Do not process the WM_COMMAND message to notify BN_CLICKED , the behavior that you want to have when you click by clicking the button and then dragging it outside after the click does not work otherwise. A click consists of pressing and releasing a button on a control.
Instead, you can search by clicking inside the control, and then toggle the checked state, if any. After that, you can eat the mouse message, so the control will not receive focus. But this needs to be checked in the check box procedure, and not as a list. Modified Code:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, StdCtrls; type TForm1 = class(TForm) ListView1: TListView; CheckBox1: TCheckBox; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private FListHeaderChk: TCheckBox; FSaveListHeaderChkWndProc: TWndMethod; FListHeaderWnd: HWND; procedure ListHeaderChkWndProc(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; ShowWindow(ListView1.Handle, SW_SHOWNORMAL); windows.GetClientRect(FListHeaderWnd, HeaderSize); FListHeaderChk.Top := (HeaderSize.Bottom - FListHeaderChk.Height) div 2; FListHeaderChk.Left := FListHeaderChk.Top; FListHeaderChk.Parent := Self; FListHeaderChk.TabStop := False; windows.SetParent(FListHeaderChk.Handle, FListHeaderWnd); FSaveListHeaderChkWndProc := FListHeaderChk.WindowProc; FListHeaderChk.WindowProc := ListHeaderChkWndProc; end; procedure TForm1.FormDestroy(Sender: TObject); begin FListHeaderChk.Free; end; procedure TForm1.ListHeaderChkWndProc(var Msg: TMessage); begin if (Msg.Msg = WM_MOUSEACTIVATE) and (Msg.LParamLo = HTCLIENT) then begin Msg.Result := MA_NOACTIVATEANDEAT; FListHeaderChk.Checked := not FListHeaderChk.Checked; Exit; end; FSaveListHeaderChkWndProc(Msg); end; end.
Sertac akyuz
source share