If you are targeting Vista or later, TLama's obvious answer. If not, check the box in the header control and not in the list box (again, when TLama commented on the question). The checkbox will send notifications to its parent, the header control, so you need to subclass it. Working sample:
type TForm1 = class(TForm) ListView1: TListView; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private FListHeaderWnd: HWND; FListHeaderChk: TCheckBox; FSaveListHeaderWndProc, FListHeaderWndProc: Pointer; procedure ListHeaderWndProc(var Msg: TMessage); end; var Form1: TForm1; implementation uses commctrl; {$R *.dfm} function GetCheckSize: TPoint; // from checklst.pas begin with TBitmap.Create do try Handle := LoadBitmap(0, PChar(OBM_CHECKBOXES)); Result.X := Width div 4; Result.Y := Height div 3; finally Free; end; end; procedure TForm1.FormCreate(Sender: TObject); var CheckSize: TPoint; HeaderSize: TRect; begin ListView1.HandleNeeded; FListHeaderWnd := ListView_GetHeader(ListView1.Handle); FListHeaderChk := TCheckBox.Create(nil); CheckSize := GetCheckSize; FListHeaderChk.Height := CheckSize.X; FListHeaderChk.Width := CheckSize.Y; // the below won't show anything since the form is not visible yet ShowWindow(ListView1.Handle, SW_SHOWNORMAL); // otherwise header is not sized windows.GetClientRect(FListHeaderWnd, HeaderSize); FListHeaderChk.Top := (HeaderSize.Bottom - FListHeaderChk.Height) div 2; FListHeaderChk.Left := FListHeaderChk.Top; FListHeaderChk.Parent := Self; windows.SetParent(FListHeaderChk.Handle, FListHeaderWnd); FListHeaderWndProc := classes.MakeObjectInstance(ListHeaderWndProc); FSaveListHeaderWndProc := Pointer(GetWindowLong(FListHeaderWnd, GWL_WNDPROC)); SetWindowLong(FListHeaderWnd, GWL_WNDPROC, NativeInt(FListHeaderWndProc)); end; procedure TForm1.FormDestroy(Sender: TObject); begin SetWindowLong(FListHeaderWnd, GWL_WNDPROC, NativeInt(FSaveListHeaderWndProc)); classes.FreeObjectInstance(FListHeaderWndProc); FListHeaderChk.Free; end; procedure TForm1.ListHeaderWndProc(var Msg: TMessage); begin if (Msg.Msg = WM_COMMAND) and (HWND(Msg.LParam) = FListHeaderChk.Handle) and (Msg.WParamHi = BN_CLICKED) then begin FListHeaderChk.Checked := not FListHeaderChk.Checked; // code that checks/clears all items end; Msg.Result := CallWindowProc(FSaveListHeaderWndProc, FListHeaderWnd, Msg.Msg, Msg.WParam, Msg.LParam); end;
Note that if you have “ColumnClick” installed, it looks awkward that the checkbox does not “click” the title button when you click on it.
Sertac akyuz
source share