首先弹出来的下拉过滤列表也是一个form
思路,在不改源代码的情况:hook,捕捉 WM_SHOWWINDOW 消息,通过源码得知窗口类名 为”TcxGridFilterPopup“
再通过句柄转得到实例,同时在本单元type 一下新的 TcxGridFilterPopup, TcxGridPopupListBox 才能访问保护起来的方法跟属性
CallWndProcHook:HHOOK; CurrentcxGridFilterPopup: TcxGridFilterPopup; pm_cxgrid_filter_choose:TPopupMenu;
initialization
initcxgrid_filter_Menus;
CallWndProcHook := SetWindowsHookEx(WH_CALLWNDPROC, @HookCallWndProc, 0, GetCurrentThreadID);
finalization
if CallWndProcHook > 0 then
UnHookWindowsHookEx(CallWndProcHook);
pm_cxgrid_filter_choose.Free;
type
TMycxGridFilterPopup = class(TcxGridFilterPopup)
end;
TMycxGridPopupListBox = class(TcxGridPopupListBox)
end;
function GetInstanceFromhWnd(const hWnd: Cardinal): TWinControl; type PObjectInstance = ^TObjectInstance; TObjectInstance = packed record Code: Byte; { 短跳转 $E8 } Offset: Integer; { CalcJmpOffset(Instance, @Block^.Code); } Next: PObjectInstance; { MainWndProc 地址 } Self: Pointer; { 控件对象地址 } end; var wc: PObjectInstance; begin Result := nil; wc := Pointer(GetWindowLong(hWnd, GWL_WNDPROC)); if wc <> nil then begin Result := wc.Self; end; end; function HookCallWndProc(code: Integer; wParam: wParam; lParam: lParam): LRESULT; stdcall; var cwp : PCwpStruct; lpClassName: array [0..MAX_PATH] of Char; tmpobjct:TWinControl; begin if code = HC_Action then begin cwp := PCwpStruct(lParam); case cwp^.message of WM_SHOWWINDOW: begin try GetClassName(cwp.hwnd, lpClassName, MAX_PATH); if lpClassName= 'TcxGridFilterPopup' then begin tmpobjct := GetInstanceFromhWnd(cwp.hwnd); if (tmpobjct <> nil) then begin if TcxGridFilterPopup(tmpobjct).PopupMenu = nil then TcxGridFilterPopup(tmpobjct).PopupMenu := pm_cxgrid_filter_choose; CurrentcxGridFilterPopup := TcxGridFilterPopup(tmpobjct); end; end; except on e:exception do Error_File(DataModule1.qry1.FieldByName('xm').AsString+ ' 添加过滤右键错误: '+ e.Message ); end; end; end; end; Result := CallNextHookEx(CallWndProcHook, code, wParam, lParam); end; procedure initcxgrid_filter_Menus; var tmpItem: TMenuItem; begin pm_cxgrid_filter_choose := TPopupMenu.Create(nil); tmpItem := TMenuItem.Create(pm_cxgrid_filter_choose); tmpItem.Caption := '全选'; tmpItem.Tag := 1; tmpItem.OnClick := MyEventClass.SetcxGridFilterListChecked; pm_cxgrid_filter_choose.Items.Add(tmpItem); tmpItem := TMenuItem.Create(pm_cxgrid_filter_choose); tmpItem.Caption := '反选'; tmpItem.Tag := 2; tmpItem.OnClick := MyEventClass.SetcxGridFilterListChecked; pm_cxgrid_filter_choose.Items.Add(tmpItem); end;
procedure TMyEventClass.SetcxGridFilterListChecked(Sender:Tobject);
var
Item: TcxCustomGridTableItem;
i,Len:integer;
FValueList: TcxGridFilterValueList;
AActiveValueIndexes: TcxGridIndexes;
MycxGridPopupListBox: TMycxGridPopupListBox;
Choose:Boolean;
begin
if CurrentcxGridFilterPopup = nil then
Exit;
Choose := TMenuItem(Sender).Tag = 1;
Item := CurrentcxGridFilterPopup.Item;
MycxGridPopupListBox := TMycxGridPopupListBox(TMycxGridFilterPopup(CurrentcxGridFilterPopup).ListBox);
case Choose of
False:
begin
Item.Filtered := False;
//要同步状态不然下拉的列表不会刷新
for i := 0 to MycxGridPopupListBox.Count -1 do
begin
if MycxGridPopupListBox.HasCheck(i) then
MycxGridPopupListBox.Checked[i] := False;
end;
end;
True:
begin
try
FValueList := Item.GridView.ViewData.CreateFilterValueList;
//获取下拉内容
Item.DataBinding.GetFilterValues(FValueList, False,True,True);
Len := 0;
for I := 0 to FValueList.Count -1 do
begin
if not (FValueList[i].Kind in [fviAll, fviCustom]) then
begin
inc(Len);
SetLength(AActiveValueIndexes, Len);
AActiveValueIndexes[Len-1] := i;
MycxGridPopupListBox.Checked[i] := False;
MycxGridPopupListBox.DoAction(i);
end;
end;
finally
FValueList.Free;
end;
end;
end;
end;
标签:tmpItem,begin,end,delphi,cxgrid,filter,右键,choose From: https://www.cnblogs.com/BTag/p/17915370.html