题:请教:如何模拟点击一个窗口的任意一个位置?这个窗口是外部程序的一个弹出对话框。 ( 积分:10, 回复:4, 阅读:72 ) | |
来自:lkdbdlkq, 时间:2007-4-18 14:25:00, ID:3702107 |
|
这个窗口的句柄可以获得,只是窗口在整个屏幕的位置可能因为不同的显示器及而有所不同,我想模拟点击它上面的某一点(X,Y),如何入手呢?非常感谢。
来自:Mclkings, 时间:2007-5-4 15:24:59, ID:3710358 PostMessaeg 发送就可以了。
来自:dennyshao001, 时间:2007-5-4 15:31:21, ID:3710362 用消息,WM_MOVING
来自:wyxriver, 时间:2007-6-17 20:57:47, ID:3799606 模拟鼠标点击事件movent_event
来自:lkdbdlkq, 时间:2007-6-18 19:59:35, ID:3800019 接受答案了.
|
/////////////////////////////////////////////////////////////////
//先找程序外的某个标题的窗体:
function EnumWinProc(Wnd : HWND; form1 : TForm1) : Boolean; Export; {$IFDEF Win32}StdCall;{$ENDIF}
var
WinText : Array[0..255] of Char;
begin
GetWindowText(Wnd, WinText, 255);
Result := True;
if (StrPas(WinText) <> '') and (Pos('XXX ',WinText)>1) then
Form1.ListBox1.Items.Add(StrPas(WinText));
end;
//找到这个窗体,放在列表框中:
procedure TForm1.Button1Click(Sender: TObject);
begin
listbox1.Clear;
EnumWindows(@EnumWinProc, LongInt(Self));
end;
//模拟点击:
procedure TForm1.Button2Click(Sender: TObject);
var
Nhwnd:HWND;
begin
Nhwnd:=findwindow(NIL,pchar(listbox1.Items[listbox1.ItemIndex]));
//PostMessage(Nhwnd,BM_Click,100,100);
//ShowWindow(Nhwnd,sw_show);
SetForegroundWindow(Nhwnd); //这一句成功执行了
SendMessage(Nhwnd,WM_LBUTTONDOWN,400,300);
SendMessage(Nhwnd,WM_LBUTTONUP,400,300);
SetForegroundWindow(Nhwnd);
end;
end.
为了试验,我做了个标题为“XXX”的窗体程序,窗体和屏幕一样大,并投置了点击事件:
procedure TForm1.FormClick(Sender: TObject);
begin
showMessage('Clicked OK');
end;
结果发现,可以发现这个窗体的句柄,也能SetForegroundWindow,但是这个窗体并没有showMessage('Clicked OK');
哪里不对了?
来自:[xiaopei], 时间:2008-5-30 17:36:25, ID:3897798
//试试这样。
SendMessage(Nhwnd,WM_LBUTTONDOWN,0,(400 shl 16) or 300);
SendMessage(Nhwnd,WM_LBUTTONUP,0,(400 shl 16) or 300);
来自:ynduanlian, 时间:2008-5-30 17:54:34, ID:3897801
楼上的这个方法对了,可否再请讲讲如何把点击发到屏幕上的某一点,比如说像素为800*600的那一点?
//////////////////////////////////////////////////////////////////////////////////////////
程序如下,请大富翁们指教如何改正。
Handle := FindWindow('Tmainform', 'test');
if Handle <> 0 then
begin
。。。。查找别一程序的窗体句柄
BtnHandle := Handle;//已取得按钮句柄
//SendMessage(FButtonHandle, WM_LBUTTONDOWN, 0, 0);
//SendMessage(FButtonHandle, WM_LBUTTONUP, 0, 0);
PostMessage(FButtonHandle, WM_LBUTTONDOWN, 0, 0);
PostMessage(FButtonHandle, WM_LBUTTONUP, 0, 0);
//注:改成PostMessage可以跳过
//模拟点击另一程序,结果为别一程序弹出对话框,本程序就在此句停住,
//不能执行下一句模拟点击另一程序对话框的程序。
Handle := FindWindow('Tform1', 'test'); //对话框窗口查找不到正确的句柄,重点
if Handle <> 0 then
。。。。。。。。。。。。。
end;
]/////////////////////////////////////////////////////////////
应该可以,我编了一个程序定时激活一个后台应用程序的窗口,然后点击该窗口的特定区域。下面仅是部分源程序,若觉有用,我可将全部文件打包发到你的信箱里!
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls;
type
TGetDot = class(TForm)
Timer1: TTimer;
Label1: TLabel;
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
GetDot: TGetDot;
implementation
{$R *.DFM}
procedure TGetDot.Timer1Timer(Sender: TObject);
var
hCurWindow,CurActiveWindow: HWnd; // 窗口句柄
WinText: array [0..255] of char;
WinCount:Integer;
begin
WinCount:=0;
CurActiveWindow:=GetActiveWindow();
hCurWindow := GetWindow(Handle, GW_HWNDFIRST);
// 获取第一个窗口的句柄
while hCurWindow <> 0 do
begin
// 获取窗口的名称
if GetWindowText(hCurWindow, @WinText, 255)>0 then
if ( WinText='民主湖聊天室 - Microsoft Internet Explorer') then
begin
// 激活该应用程序窗口,使其在屏幕最前面
SendMessage(hCurWindow,WM_SYSCOMMAND,SC_MINIMIZE,0);
SendMessage(hCurWindow,WM_SYSCOMMAND,SC_RESTORE,0);
//将鼠标控制权转到该程序上
SetCapture(hCurWindow);
//鼠标定位到指定座标
SetCursorPos(720,475);
//产生鼠标按键事件
mouse_event(MOUSEEVENTF_LEFTDOWN+MOUSEEVENTF_LEFTUP,
720,475,0,GetMessageExtraInfo());
//给其他应用程序以事件反应时间
sleep(5000);
//获取下一窗口
hCurWindow:=GetWindow(hCurWindow, GW_HWNDNEXT);
end;
end;
来自:lycwg, 时间:2000-6-16 12:06:00, ID:266205
忘了你要不影响当前程序运行,可在处理完成后用下列方法,激活自已的窗体即可!
SendMessage(GetDot.Handle,WM_SYSCOMMAND,SC_MINIMIZE,0);
SendMessage(GetDot.Handle,WM_SYSCOMMAND,SC_RESTORE,0);
其中GetDot为自己应用程序的窗口名
/////////////////////////////////////////////////////
问题已经解决,在此,谢谢各位的帮助
我现在将代码贴出,以作参考
function EnumWindowsProc(AHWnd: HWnd; LPARAM: lParam): boolean; stdcall;
var
WndCaption: array[0..254] of char;
WndClassName: array[0..254] of char;
rtscreen: trect;
WinXY:TRect;
xy:TPoint;
begin
GetWindowText(AHWnd, @WndCaption, 254);
GetClassName(AHWnd, @WndClassName, 254);
if (pos('CashSurfers.com',wndcaption)<>0) then //用你已知的窗口标题替换这里, 找到此窗口
begin
ahwnd:=findwindowEX(ahwnd,0,pchar('TButton'),pchar('Cool!')); // 找到窗口上的按钮
GetWindowRect(AHWnd,WinXY); // 得到按钮的坐标范围
xy:=WinXY.TopLeft; // 取得按钮左上角的坐标
xy.x:=xy.x+10;
xy.y:=xy.y+10;
SetCursorPos(xy.x,xy.y); // 将Mouse定位到按钮上
Mouse_Event(MOUSEEVENTF_LEFTDown,xy.x,xy.y,0,0); // 按下左键
Mouse_Event(MOUSEEVENTF_LEFTUP, xy.x,xy.y,0,0); // 按下右键
end;
Result := True ;
end;
///////////////////////////////////////////////////////////////
一个很简单的办法:
建立一form, setwindowrgn(form.handle, createrectrgn(-1,-1,0,0), true);
setcapture(form.handle), 然后就可以用form.onmousemove, onmousedown, onmouseup等事件了, 而且窗口在屏幕上不可见(却是actived).
////////
SetForeGroundWindow(hIE); hie为句柄
不在最前面可以先SetForegroundWindow啊
根本问题是用sendmessage怎么模拟出toolbar上的按钮的click事件,而不是模拟鼠标的单击。谢谢。
另外的方法就是通过ToolBar的句柄获得类TToolBar的实例obj:= FindControl(h);,然后可以直接TToolBar(obj).Buttons[0].Click;来模拟,但是FindControl必须在目标进程内调用才能够返回正确的实例地址,所以必须写一个Hookdll,然后注入到目标进程后再FindControl获得实例后模拟Click实现。 |
|
////////
方法一 Sending a Message
1. btnevent.Perform(WM_LBUTTONDOWN, 0, 0);
2. btnevent.Perform(WM_LBUTTONUP, 0, 0);
复制代码
方法二 用按钮的事件方法
1. btnevent.Click;
复制代码
方法三 With a pressed effect:
1. {The BM_SETSTATE message is sent by an application
2. to change the highlight state of a button.
3. }
4.
5. SendMessage(btnevent.Handle, BM_SETSTATE, 1, 0);
6. btnevent.Click;
7. Sleep(100); // Some delay
8. PostMessage(btnevent.Handle, BM_SETSTATE, 0, 0);
复制代码
/////////////////////////////////////////////////////////
如果是想要在整个windows环境下面的热键
可以参看下面:
RegisterHotKey函数原型及说明:
BOOL RegisterHotKey(
HWND hWnd, // window to receive hot-key notification
int id, // identifier of hot key
UINT fsModifiers, // key-modifier flags
UINT vk // virtual-key code);
参数 id为你自己定义的一个ID值,对一个线程来讲其值必需在0x0000 - 0xBFFF范围之内,对DLL来讲其值必需在0xC000 - 0xFFFF 范围之内,在同一进程内该值必须唯一
参数 fsModifiers指明与热键联合使用按键,可取值为:MOD_ALT MOD_CONTROL MOD_WIN MOD_SHIFT
参数 vk指明热键的虚拟键码
首先(举个例子):
RegisterHotKey(handle,globaladdatom('hot key'),MOD_ALT,vk_f12);
然后在form中声明一个函数(过程):
procedure hotkey(var msg:tmessage);message wm_hotkey;
过程如下:
procedure TForm1.hotkey(var msg:tmessage);
begin
if (msg.LParamHi=VK_F12) and (msg.LParamLo=MOD_ALT) then
begin
form1.show;
SetForegroundWindow(handle);
end;
end;
这样,不管你在什么地方,窗口就会显示出来。
当然,你要GlobalDeleteAtom;
//////////////////////////////////////////////////////////////
如何用SendMessage模拟某一按钮的点击事件
2010-12-14 11:06
转载自 liu494021458
最终编辑 liu494021458
////////////////////////////////////////////////////////////////////////////////
应用程序模拟按钮点击
2010-12-13 11:32
编一个程序模拟按下计算器程序中0那个按键 以下代码获得 计算器 的各个按件的 ID 的 Caption(或Text),并放在 ListBox1 中 按下某个按钮。 HWND hWin, hChild;
|
//////////////////////////////////////////////////////////
c++模拟鼠标点击程序的实现方法
2010-12-15 10:40
模拟点击,模拟按键等功能一般都是特殊情况下的程序需求,在需要实现模拟的目标程序无源代码,不方便实现自动化的情况下,需要此类功能。比如我原来办公用到的一个管理系统,每天需要逐条审核50多条数据,每审核一条数据总会弹出一个确定对话框,这时候数据已经通过了审核,还需要什么确定,完全是画蛇添足,所以相当烦恼,这与原程序设计考虑不合理有关,此时我就通过模拟点击那个确定对话框,让必须手工点一下确定对话框由后台代码来实现。以下代码模拟点击系统自带计算器中的"7","1","9"按钮,点击后你会看到跟你用手工点击的效果一模一样。当然扩展以下代码能实现其它许多复杂的自动化功能。 HWND hWndId,hWndB1; |