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分。
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分。
解决方案 »
- 在ListView中,如何判断是否选择了ListView的一行?
- 关于又能返回文件生成时间时,又不影响其实程序对该文件的读写的方法.
- 为什么BDE不能访问SQL Server示例数据库NorthWind的Customers表?
- 如何加密解密一个文本文件
- taideveloper(孔丙已) 或 happyzsl(学习) 请教一下!
- 感谢windwather()在我百忙之中帮我测试、修改软件
- 请大家帮忙!!!
- 急急急!!!我自己写了两个procedure,但是第一个的其中一个参数为什么不能传递给第二个???
- firemonkey的内嵌浏览器?
- 最近想开始DELPHI的开发,忘各位高手推荐好书几本???
- idftp使用代理上传文件出现 socket 10060 错误
- html 转 mht 的问题。是否有方法可以设置 CdoMHTMLFlags 属性而不需要调用CreateMHTMLBody 函数
begin
//
end;
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;type
TForm1 = class(TForm)
Button1: TButton;
procedure ButtonClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.dfm}procedure TForm1.ButtonClick(Sender: TObject);
begin
showmessage('hello');
end;procedure TForm1.FormCreate(Sender: TObject);
begin
button1.OnClick:=buttonclick;
end;end.
interface
uses 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; //远程连接窗口的handle
begin
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.
var H: HWND; //远程连接窗口的handle
begin
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所指向的远程连接窗口相关事情
SendMessage(h, WM_LBUTTONDOWN, 0, 0);
SendMessage(h, WM_LBUTTONUP, 0, 0);
SendMessage(h, WM_LBUTTONDOWN, 0, 0);
SendMessage(h, WM_LBUTTONUP, 0, 0);
end;
模拟按下没有成功?再有,如果先把远程连接程序关闭了,再关闭本程序,就会报错?
var
oldButton1WinProc: Pointer;
h, hButton1: HWND;function NewButton1WinProc(hWnd, Msg, wParam, lParam: Integer): Integer; stdcall;
begin
Result := CallWindowProc(oldButton1WinProc, hWnd, Msg, wParam, lParam);
case Msg of
WM_LBUTTONDOWN:
MessageBox(h,'你好!','提示',MB_OK);
end;
end;procedure TForm1.Button1Click(Sender: TObject);
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, GetModuleHandle(nil), nil);
//获取nButton1的WinProc,保存
oldButton1WinProc := Pointer(GetWindowLong(hButton1, GWL_WNDPROC));
//设置nButton1的WinProc为NewButton1WinProc
SetWindowLong(hButton1, GWL_WNDPROC, Integer(@NewButton1WinProc));
end;
到我上传的资源里去看看吧。利用了消息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;begin
end.
ideation_shang 的答案暂时没有发现什么缺点,是最接近我要的答案,但本贴只有100分,已经分给上面两位,所以只能再加分,因此他将得100分。
我知道各位朋友并不是在乎分的人,但我做为散分人,明白分虽然没有什么实际价值,但却是对答案认可以的一种直接表现形式。而许多时候,人其实就活在“面子”上,如果我的给分有异议可以提出,否则我就结贴了。
你说子类化会发生错误,应该是由于h,hButton1,oldButton1WinProc三个变量作用域的在Button1Click内而导致.表示歉意.
按你的说法,我做了,没有解决呀?
unit Unit1; interface
uses Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,dialogs,StdCtrls,
ExtCtrls;
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 h: hwnd;
begin
WinExec('mstsc',1);
Sleep(1000);
h:=FindWindow(nil,'远程桌面连接');
if h=0 then exit;
//F := Tform.Create(nil);
self.BorderStyle := bsNone;
with Button1 do
begin
Caption := '取数据';
left := 0;
Top := 0 ;
Width := 74;
Height :=24;
OnClick := MyClick;
end;
self.ParentWindow := h;
self.Tag := h;
self.Left:=0;
self.Top:=0;
self.Width := 74;
self.Height := 24;end;procedure TForm1.MyClick(sender: TObject);
var H: HWND; //远程连接窗口的handle
begin
H := 0;
if (sender <> nil) and (sender is TButton) and (TButton(sender).Parent.ParentWindow > 0) then
H := (TButton(sender).Parent).ParentWindow; //获取远程连接窗口的handle
MessageBox(h, '新按钮点击', '', MB_OK);
//以下可以处理H所指向的远程连接窗口相关事情
end;end.现在倒是可以先关远程窗口了,不过,form1只能结束进程才能关.是我没明白你的意思,还是我明白了.
比如下面的代码procedure TForm1.Button1Click(Sender: TObject);
var
h, hButton1: HWND;
oldButton1WinProc: Pointer;
function NewButton1WinProc(hWnd, Msg, wParam, lParam: Integer): Integer; stdcall;
begin
Result := CallWindowProc(oldButton1WinProc, hWnd, Msg, wParam, lParam);
case Msg of
WM_LBUTTONDOWN:
MessageBox(h, '你好!', '提示', MB_OK);
end;
end;
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, GetModuleHandle(nil), nil);
//获取nButton1的WinProc,保存
oldButton1WinProc := Pointer(GetWindowLong(hButton1, GWL_WNDPROC));
//设置nButton1的WinProc为NewButton1WinProc
SetWindowLong(hButton1, GWL_WNDPROC, Integer(@NewButton1WinProc));
end;