参考TLabeledEdit控件,我写了一个 TControl+TcxDBTreeList(类似树枝型的DBGrid),这样一个组合控件。
目的是,通过TControl控件点一下鼠标后,后者能下拉显示出来……基本类似TComboBox的下拉效果。
基本都ok了,唯独TControl.OnMouseDown事件的赋值不是在设定属性的时候,而是在调试界面上代码给的。
我尝试了GetWindowLong来截获消息。是TWinControl的时候是可以的。如果是TLabel之类的图形控件的时候,就没有Handle可抓。
我只是想捕获TControl的WM_LBUTTONDOWN,有什么办法吗?
以下贴出,主要结构代码。
目的是,通过TControl控件点一下鼠标后,后者能下拉显示出来……基本类似TComboBox的下拉效果。
基本都ok了,唯独TControl.OnMouseDown事件的赋值不是在设定属性的时候,而是在调试界面上代码给的。
我尝试了GetWindowLong来截获消息。是TWinControl的时候是可以的。如果是TLabel之类的图形控件的时候,就没有Handle可抓。
我只是想捕获TControl的WM_LBUTTONDOWN,有什么办法吗?
以下贴出,主要结构代码。
TCustomDuoDBTreeList = class(TcxCustomDBTreeList)
private
FDropListControl: TControl;
FOldProc:TFarProc;
procedure SetDropListControl(const Value: TControl);
protected
procedure DropListProc(var Msg: TMessage);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property DropListControl:TControl read FDropListControl write SetDropListControl;
end;
procedure TCustomDuoDBTreeList.SetDropListControl(const Value: TControl);
var pp:TPoint;f:TCustomForm;//p:Pointer;
begin
FDropListControl := Value;
// FOldProc:=Pointer(FDropListControl.WindowProc);
// FDropListControl.WindowProc:=DropListProc;
// if FDropListControl is TWinControl then
// begin
// FOldProc:=Pointer(GetWindowLong((FDropListControl as TWinControl).Handle,GWL_WNDPROC));
// p:=MakeObjectInstance(DropListProc);
// SetWindowLong((FDropListControl as TWinControl).Handle,GWL_WNDPROC,LongInt(p));
// end;
end;procedure TCustomDuoDBTreeList.DropListProc(var Msg: TMessage);
begin
case Msg.Msg of
WM_LBUTTONDOWN:ShowMessage('鼠标按下');
else
Msg.Result:=DefWindowProc((FDropListControl as TWinControl).Handle,Msg.Msg,Msg.WParam,Msg.LParam);// 其它消息做默认处理
end;
end;
private
F_Handle:integer; Procedure WriteSqlLog(const Str:String);
f_Handle:=classes.AllocateHWnd(wndProc);
classes.DeallocateHWnd(F_Handle);
procedure TSqlFuns.WndProc(var Msg: TMessage);
begin
if Msg.Msg = MSG_RECV_DATA then //转发消息到调用窗口
begin
.......
end
else
DefWindowProc(F_Handle, Msg.Msg, Msg.wParam, Msg.lParam);
end;
我早几天也碰到这问题,不过我的是把控件拉到非客户区去了,结果 CM_MOUSELEAVE类消息可以响应, WM_LBUTTONDOWN类的消息响应不到。
鼠标按一下它们,我就ShowList。
请注意一下结构。
TCustomDuoDBTreeList = class(TcxCustomDBTreeList)
private
FDropListControl: TControl;我要的是FDropListControl的消息,而不是TCustomDuoDBTreeList的消息。也可能是我理解错了。
请多一点指示。
愿意加分。
然后是 TWMParentNotify
仔细研究一下,估计就有戏了。
待解决后赠分。
用GetWindowLong截获消息是不是舍近求远了?你直接重载TControl的Click方法不就行了?
至于,你说的那个可以直接转换一下应该
自己定义一个OnMouseDown事件,用来覆盖原来的事件就可以了
property OnMouseDown: TMouseEvent read GetOnMouseDown write SetOnMouseDown;procedure GetOnMouseDown;
begin
result := Label.OnMouseDown;
end;procedure SetOnMouseDown(DownEvent: TMouseEvent);
begin
Label.OnMouseDown : DownEvent;
end;
FTargetHWND:HWND;//保存DropDown的Handle
FTargetProc:TFarProc;//保存DropDown的原有WndProc
//Assign控件的时候
if not (csSubComponent in FDropListControl.ComponentStyle) then
begin
if FDropListControl is TWinControl then
FTargetWCtrl:=(FDropListControl as TWinControl)
else
FTargetWCtrl:=FDropListControl.Parent;
FTargetHWND:=FTargetWCtrl.Handle;
FTargetProc:=Pointer(GetWindowLong(FTargetHWND,GWL_WNDPROC));
{$WARN SYMBOL_DEPRECATED OFF}
p:=MakeObjectInstance(DropListProc);
{$WARN SYMBOL_DEPRECATED ON}
SetWindowLong(FTargetHWND,GWL_WNDPROC,LongInt(p));
end;
//点击目标控件,使我的TreeList下拉
procedure TCustomDuoDBTreeList.DropListProc(var Msg: TMessage);
function IsControlMouseMsg(var Message: TWMMouse): Boolean;
var Control:TControl;P:TPoint;
begin
Control:=FTargetWCtrl.ControlAtPos(SmallPointToPoint(Message.Pos), False);
Result := False;
if Control <> nil then
begin
P.X := Message.XPos - Control.Left;
P.Y := Message.YPos - Control.Top;
Message.Result := Control.Perform(Message.Msg, Message.Keys, Longint(PointToSmallPoint(P)));
Result := True;
end;
end;
begin
Msg.Result:=CallWindowProc(FTargetProc,FTargetHWND,Msg.Msg,Msg.WParam,Msg.LParam);
case Msg.Msg of
WM_LBUTTONDOWN:begin
if IsControlMouseMsg(TWMMouse(Msg)) then
self.DoDropDown
else if FDropListControl=FTargetWCtrl then
self.DoDropDown;
end;
end;
end;destructor TCustomDuoDBTreeList.Destroy;
begin
if Assigned(FTargetProc) then SetWindowLong(FTargetHWND,GWL_WNDPROC,LongInt(FTargetProc));
inherited;
end;
//这里稍微说明一下,我有可能设置Button(TWinControl),也有可能设置成Label(TControl)
//前者的消息很好理解,而后者,其实消息是在它的Parent上的。所以,FTargetHWND是Parent.Handle
//只要截获到了消息,想干嘛就干嘛。
//谢谢各位D友。我的多选树枝,和多选下拉树枝同时完成了。