如何给Button加上单击事件?
procedure TForm1.Button1Click(Sender: TObject);
var h,hButton1:HWND;
begin
WinExec('mstsc',1);
Sleep(1000);
h:=FindWindow(0,'远程桌面连接');
if h=0 then exit;
hButton1:=CreateWindow('Button','取数据',WS_VISIBLE or WS_CHILD or BS_PUSHLIKE or BS_TEXT,0,0,74,24,h,0,0,nil);
end;
上面的代码所实现的功能是打开一个“远程桌面连接”,然后在该窗体上添加一个按扭。
我的问题是:如何给这个按扭加上单击事件?例如单击时弹出一句 ShowMessage('你好!') ?
我目前可以用鼠标钩子做到,我的方法是在钩住鼠标抬起事件,抬起时判断鼠标位置所在的句柄是不是我创建的Button句柄。
可能还会有其它方法。我希望求到的答案不是用鼠标构子(但可以用其它类型钩子)。
当然,直接在自己的窗体上建一个按扭写好事件后,再设置按扭的父句柄,这应该是最简单的方法。但这个是有缺陷的(单击按扭时会使原窗体“远程桌面连接”失去焦点)。
etomahawk一直在消息处理上让我比较佩服,所以该贴向他提问了。但大家也可以回答,如果答案有多种,我会给贴子加分,每种都可以得100分。
[解决办法]
实现一个提示框是可以的,但没什么大意义,关键是你需要的处理是否能用这种方式达到。
unit Unit23;interfaceuses Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,dialogs,StdCtrls;type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); procedure MyClick(sender: TObject); private public end;var Form1: TForm1;implementation {$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);var f: TForm; h: hwnd;begin WinExec('mstsc',1); Sleep(1000); h:=FindWindow(0,'远程桌面连接'); if h=0 then exit; F := Tform.Create(self); f.Tag := self.Handle ; f.Width := 74; f.Height := 24; f.BorderStyle := bsNone; with TButton.Create(F) do begin Caption := '取数据'; left := 0; Top := 0 ; Width := 74; Height :=24; Parent := F; OnClick := MyClick; end; f.ParentWindow := h; f.Show;end;procedure TForm1.MyClick(sender: TObject);var H: HWND; //远程连接窗口的handlebegin H := 0; if (sender <> nil) and (sender is TButton) and (TButton(sender).Parent.ParentWindow > 0) then H := (TButton(sender).Parent).ParentWindow; //获取远程连接窗口的handle Windows.MessageBox(h, '新按钮点击', '', MB_OK); //以下可以处理H所指向的远程连接窗口相关事情end;end.
[解决办法]
刚看到,写了一个,测试一下。
LS的,记住按钮是创建到其他程序的窗体上的,是不同进程的,你的代码只会产生一个异常。
CSDN怎么这样啊,上传我找了半天才找到,好不容易上传了,用看不到上传了的文件。
到我上传的资源里去看看吧。
利用了消息HOOK, 由于是全局HOOK,使用了一个dll。
主单元:
procedure InstallHook; stdcall; external 'Hook.dll';
procedure TForm1.Button1Click(Sender: TObject);
begin
InstallHook;
end;
DLL 工程:
library Hook;uses SysUtils, Windows, Messages, Classes;var g_hBtn : HWND = 0; g_hHook: HHook = 0; g_hWin : HWND = 0;{$R *.res}function MsgFilter(nCode: Integer; wPar: WPARAM; lPar: LPARAM): LResult; stdcall;begin if (PCWPRETSTRUCT(lPar)^.message = WM_COMMAND) then begin // 在这里验证是否为我们自己创建的按钮被按下了 if (GetWindowLong(PCWPRETSTRUCT(lPar)^.lParam, GWL_USERDATA) = PCWPRETSTRUCT(lPar)^.lParam) then begin // 这里写你的按钮消息处理过程代码 MessageBox(0, '按钮按下!', '信息提示', MB_OK + MB_ICONINFORMATION); end; end; Result:= CallNextHookEx(g_hHook, nCode, wPar, lPar);end;procedure InstallHook; stdcall;begin WinExec('mstsc',1); Sleep(1000); // 我用的是英文版的操作系统,所以这里进行了修改 g_hWin:=FindWindow(nil, 'Remote Desktop Connection');//'远程桌面连接'); if g_hWin = 0 then exit; // 创建一个按钮 g_hBtn:=CreateWindow('Button','取数据', WS_VISIBLE or WS_CHILD or BS_PUSHLIKE or BS_TEXT, 0, 0, 74, 24, g_hWin, 0, 0, nil); // 把自己的句柄保存到用户数据中,以便收到WM_COMMAND消息后进行验证 // 至于这里为什么要保存起来,自己考虑考虑 SetWindowLong(g_hBtn, GWL_USERDATA, Integer(g_hBtn)); g_hHook:= SetWindowsHookEx(WH_CALLWNDPROCRET, @MsgFilter, HInstance, GetWindowThreadProcessId(g_hWin)); // 检查钩子是否成功挂接 if g_hHook = 0 then begin MessageBox(0, PChar(Format('Hook failed: %d', [GetLastError])), 'ERROR', MB_OK); end;end;exports InstallHook;beginend.