Search code examples
listviewdelphivcldelphi-10.1-berlin

How to detect a mouse click on a TListView Group header?


I'm using Delphi 10.1 and VCL. How can I detect a click or double-click on a Group header in a TListView? Not on a Column header.


Solution

  • The answer is based on Remy and Victoria comments, with an old answer by Bummi at https://www.entwickler-ecke.de/topic_ListViewEigenschaften+Delphi+vs+C+SubItems+auslesen_110307,0.html.

    Few comments for the solution:

    1. Subclass is an option but could be implemented with Form's ListView1MouseDown event too, which is a little bit simpler.
    2. tLVHitTestInfo & LVM_HITTEST are defined in Winapi.CommCtrl.

      Uses
        Winapi.CommCtrl; // For LVM_HITTEST
      
    3. LVHT_EX_GROUP_HEADER value should be defined manually. I didn't find it inside any Delphi unit. It is the identifier that a Group header was clicked. It should be verified with LVHitTestInfo.flags. It is Valid for Windows Vista and above.

      const
        LVHT_EX_GROUP_HEADER = $10000000;
      
    4. LVHitTestInfo.iGroup Doesn't work! I don't know the reason. Originally, I thought it should be the Group index.

    The example has a form with ListView on it, the style is ViewStyle = vsReport. A mouse click on a group header will invoke a message dialog with the group index. Here is the detailed code:

        Uses Winapi.CommCtrl;
    
        procedure TForm1.ListView1MouseDown(Sender: TObject; Button: TMouseButton;
          Shift: TShiftState; X, Y: Integer);
        const
          LVHT_EX_GROUP_HEADER = $10000000; // It is Valid for Windows Vista and above.
        var
          HTI: tLVHitTestInfo; // Defined on Winapi.CommCtrl
          nGroupInx: integer;
        begin
          HTI.pt     := point(X, Y); // Add cursor position
          nGroupInx  := SendMessage(ListView1.Handle, LVM_HITTEST, -1, LPARAM(@HTI)); // Return an Item
          if nGroupInx <> -1 then // Is an Item found?
            if (HTI.flags and LVHT_EX_GROUP_HEADER) = LVHT_EX_GROUP_HEADER then // Is it a Group Header?
                ShowMessage('Clicked Group header:' + ' ' + nGroupInx.ToString);
        end;