Осуществление OnStateIconClick в TListView

Тема в разделе "Delphi", создана пользователем WinHack, 24 ноя 2016.

  1. WinHack
    Управление TListView в Delphi отображает список пунктов в столбцах с заголовками столбца и подпунктами вертикально или горизонтально с маленькими или большими иконками / изображениями.

    Каждый элемент в представлении списка может иметь иконку рядом с собой. Список иконок определяется свойством SmallImages (или LargeImages). Далее, свойство StateImages определяет дополнительные изображения, которые будут отображаться рядом с каждым элементом в представлении списка.

    Каждый элемент в списке Items может быть связан с изображением, устанавливая его свойство StateIndex. Изображение состояния появляется слева от нормального пункта списка.

    1. Стиль Radio для выбора пунктов


    Допустим, нужен способ позволить пользователю Выбирать / Отмечать / Помечать один элемент из списка. Не получается использовать свойство Selected, поскольку может быть такая ситуация, когда один пункт должен быть Выбран, тогда как другой Отмечен.

    Свойство CheckBoxes не помогает. CheckBoxes позволяет отмечать несколько пунктов одновременно.

    Но нужно создать кое-что, подобно RadioGroup, где только один пункт списка будет отмечен одновременно.

    А также некоторые пункты были бы non-chekable.

    И вот что нужно сделать:

    1. Использовать StateIndex элемента, чтобы отобразить радиокнопку, подобно изображению для элемента.
    2. Обработать событие OnClick, чтобы осуществить OnStateImageClick.
    3. Вывести полужирный шрифт для отмеченного пункта.
    Код:
    // карта позиций изображения состояния в TImageList
    const
      lisSelected = 5;
      lisNotSelected = 4;
      lisNonSelectable = -1;
    
    // дескрипторы ListView OnClick
    procedure TlvForm.lvClick(Sender: TObject);
    var
      hts : THitTests;
      lvCursosPos : TPoint;
      li, lii : TListItem;
    begin
      inherited;
    
       // Позиция курсора мыши, связанного с ListView
       lvCursosPos := lv.ScreenToClient(Mouse.CursorPos) ;
    
       // Где щелкнули?
       hts := lv.GetHitTestInfoAt(lvCursosPos.X, lvCursosPos.Y);
    
       // Находимся на пункте state-clicked
       if htOnStateIcon in hts then
       begin
         li := lv.GetItemAt(lvCursosPos.X, lvCursosPos.Y);
         if Assigned(li) then
         begin
           if li.StateIndex = lisNonSelectable then Exit;
    
           for lii in lv.Items do
            if lii.StateIndex <> lisNonSelectable then lii.StateIndex := lisNotSelectd;
    
           li.StateIndex := lisSelected;
         end;
       end;
    end;
    
    // ListView AdvancedCustomDrawItem
    procedure TlvForm.lvAdvancedCustomDrawItem(Sender: TCustomListView;
      Item: TListItem; State: TCustomDrawState; Stage: TCustomDrawStage;
      var DefaultDraw: Boolean);
    begin
      if Assigned(Item) then
      begin
        if Item.StateIndex = lisSelected then
          Sender.Canvas.Font.Style := [fsBold]
        else
          Sender.Canvas.Font.Style := [];
      end;
    end;
    В событии OnClick ScreenToClient конвертирует координаты позиции мыши в координаты TListView. GetHitTestInfoAt определяет какие элементы списка находятся под мышью. Если пользователь нажал на значок состояния, включается htOnStateIcon в результате GetHitTestInfoAt.

    Ну все, пробуйте...