Как переключить состояние выбора выбранного (сфокусированного) элемента с помощью TListView с отключенным MultiSelect?

У меня есть TListView с MultiSelect установленным на False.

Я хочу переключить состояние выбора выбранного в данный момент элемента. Я имею в виду, отменить выбор элемента, который в данный момент выбран (в фокусе). Но разрешить переключение выделения (фокуса) на другой элемент. Тот же переключатель, который вы можете увидеть при включенном MultiSelect и нажатии Ctrl+Click на выбранном элементе.

Я попробовал событие OnChanging, но полностью потерялся из-за повторного входа в метод.

Наконец-то я сделал очень уродливый обходной путь с событием OnEditing, например:

procedure TForm1.CMUnselectItems(var Message: TMessage);
var
  Item: TListItem;
begin
  Item := ListView1.Selected;
  if Assigned(Item) then
  begin
    ListView1.Selected := nil;
    ListView1.ItemFocused := nil;
  end;
end;

procedure TForm1.ListView1Editing(Sender: TObject; Item: TListItem;
  var AllowEdit: Boolean);
begin
  AllowEdit := False;
  PostMessage(Self.Handle, CM_UnselectItems, 0, 0);
end;

Есть ли элегантный способ сделать это?


person zig    schedule 18.06.2017    source источник
comment
Возможно, ожидая в сообщении WM_NOTIFY уведомления NM_CLICK, в структуре NMITEMACTIVATE проверьте и измените член uNewState (флаги LVIS_FOCUSED и LVIS_SELECTED). Вопрос в том, отправляется ли это уведомление даже тогда, когда пользователь нажимает на один и тот же элемент через долгое время (когда на самом деле не происходит никаких изменений). Не могу проверить сейчас.   -  person Victoria    schedule 18.06.2017
comment
@Victoria, NM_CLICK не дает действительных uNewState/uOldState. он отправляется каждый раз, когда пользователь щелкает элемент. однако никакой особой информации нет. кажется, что единственный способ - LVN_ITEMCHANGING, но я не могу понять, как с этим бороться. может быть задействован таймер, который дважды запускает это уведомление, если элемент уже выбран (я не уверен).   -  person zig    schedule 18.06.2017
comment
Правильно ли вы замаскировали флаги (в этих сообщениях всегда проверяйте состояния). Если это так, то вы все равно можете выполнить LVM_GETITEMSTATE и LVM_SETITEMSTATE.   -  person Victoria    schedule 18.06.2017
comment
stackoverflow.com/a/23570100   -  person Sertac Akyuz    schedule 18.06.2017
comment
Я не предлагал LVN_ITEMCHANGING уведомление, потому что оно отправляется для элемента, который выбирается, а также для элемента, который не выбран.   -  person Victoria    schedule 18.06.2017