使用SendMessage发送鼠标点击事件,为何需要发送两次

wfxyjx 2011-07-11 10:19:40
为了测试使用SendMessage发送鼠标消息模拟鼠标点击,我做了一个测试程序,就一个对话框,中间一个按钮,点击后会弹出一个MessageBox,显示一句话“发生点击”。然后又写了另外一个程序,来给这个测试程序发送鼠标点击消息。代码如下:

HWND hand_game = FindWindow(NULL,TEXT("测试文件"));
HWND hand_button = FindWindowEx(hand_game,NULL,TEXT("Button"),TEXT("点击"));//得到按钮的句柄

SendMessage(hand_button,WM_LBUTTONDOWN,0,MAKELPARAM(46,12));
SendMessage(hand_button,WM_LBUTTONUP,0,MAKELPARAM(46,12));

上述代码是实现发送的程序中的一个按钮的响应代码,点击这个发送按钮后,发现测试程序中的按钮得到了焦点,但是为弹出MessageBox……再次点击发送消息的程序中的按钮,这次测试程序弹出了MessageBox,经测试发下,只有两次单击发送消息,或者将代码改成下面的样子:

HWND hand_game = FindWindow(NULL,TEXT("测试文件"));
HWND hand_button = FindWindowEx(hand_game,NULL,TEXT("Button"),TEXT("点击"));//得到按钮的句柄

SendMessage(hand_button,WM_LBUTTONDOWN,0,MAKELPARAM(46,12));
SendMessage(hand_button,WM_LBUTTONUP,0,MAKELPARAM(46,12));
//发送两次:
SendMessage(hand_button,WM_LBUTTONDOWN,0,MAKELPARAM(46,12));
SendMessage(hand_button,WM_LBUTTONUP,0,MAKELPARAM(46,12));

才能正常弹出MessageBox……用SPY++监视按钮得到的消息,发现结果都是正常的……小弟十分不解,望高手解释下!

平台:Visual C++6.0 Windows 7 Ultimate
...全文
3829 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
0Mouse 2014-01-25
  • 打赏
  • 举报
回复
今天我在VB中也碰到了这个问题。我要关闭运行某个软件之初弹出的“每日提示”对话框,思路就是通过发送关闭消息给该对话框的“关闭”按钮。通过spy++已确定“关闭”按钮是该对话框的子窗口,而且不存在下一级窗口。成功关闭的方案也就是前辈们提出的两种:
(1)使用两次sendmessage发送关闭消息(第一次设置为前台窗口,第二次执行关闭行为)。
(2)先用SetForegroundWindow将“关闭”按钮窗口设置为前台窗口,再用sendmessage发送关闭消息。
受益了,感谢前辈们!:-)
flyshow01 2011-09-16
  • 打赏
  • 举报
回复
前置和焦点都较麻烦,可以先在坐标处放开鼠标,再使用单击,这样不用把窗口位置调来调去的
wfxyjx 2011-07-13
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 tandyt 的回复:]
估计是第一次发送,是用来激活接收的窗口为活动窗口,第二次发送才是让已经激活的活动窗口来执行消息操作吧。。。。。
[/Quote]
只是有一点不解,我第一次点了发送消息,对方成为活动窗口,可是我再次点击发送消息按钮时,对方的活动窗口状态应该就取消了吧。这样我不断点发送消息,实质上不就是在不断设置对方为活动窗口吗?
wfxyjx 2011-07-13
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 visualeleven 的回复:]
模拟按钮点击可以发送WM_COMMAND消息,通知码为BN_CLICKED

C/C++ code
HWND hand_game = FindWindow(NULL,TEXT("测试文件"));
HWND hand_button = FindWindowEx(hand_game,NULL,TEXT("Button"),TEXT("点击"));//得到按钮的句柄
int nId = Get……
[/Quote]
我主要是知道为什么sendmessage为何会失效,好像很多人都是靠这种方法软模拟的。再说WM_COMMAND得需要控件ID的,有的时候点击不是控件诶,这样岂不会失效。
youhao1999 2011-07-13
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 tandyt 的回复:]
估计是第一次发送,是用来激活接收的窗口为活动窗口,第二次发送才是让已经激活的活动窗口来执行消息操作吧。。。。。
[/Quote]
+1
还没淹死的鱼 2011-07-13
  • 打赏
  • 举报
回复
啊o,学习一下
wfxyjx 2011-07-13
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 xiaoc1026 的回复:]
sendmessage之前 SetForegroundWindow 试试?
[/Quote]
加上这个有效了,但是有几个疑问:
1.我之前试过SendMessage前加过SetFocus,是无效的,这个和SetForegroundWindow有什么区别呢?MSDN上说SetForegroundWindow 是将创建目标窗口的线程调到前台,然后接受输入,听上去和SetFocus差不多啊。
2.另一个疑问是,我的两次sendmessage应该是被分作了两次使用了吧,第一次用来将目标窗口调到前台,第二次才实现单击。我们实际操作时只要单击一次,是Windows在处理鼠标单击的时候,帮我们做了SetForegroundWindow这个过程。我这样说对么?
3.最后一个,我是两次单击发送消息按钮,对方才响应一次。如果我第二点说的对的话,那么我在第一次发送消息后,目标窗口调到前台。然而我再次单击发送消息,前台岂不是又回到了发送程序,则我这样一直SendMessage,应该只是不断的将目标窗口调到前台啊,何以对方还能响应一次呢?

乞解答!
Eleven 2011-07-13
  • 打赏
  • 举报
回复
模拟按钮点击可以发送WM_COMMAND消息,通知码为BN_CLICKED
HWND hand_game = FindWindow(NULL,TEXT("测试文件"));
HWND hand_button = FindWindowEx(hand_game,NULL,TEXT("Button"),TEXT("点击"));//得到按钮的句柄
int nId = GetDlgCtrlID(hand_button);
::PostMessage(hand_game, WM_COMMAND, MAKEWPARAM(nId, BN_CLICKED), (LPARAM)hand_button);
wfxyjx 2011-07-13
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 vann1982 的回复:]
down up 间加个延时有没有效果啊?
[/Quote]
这个也加过的,sleep到1000毫秒都没用的
wfxyjx 2011-07-13
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 simoreg 的回复:]
用PostMessage试试
[/Quote]
嗯,我之前试过的,效果不变,依然得发送两次
wfxyjx 2011-07-13
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 gemmo 的回复:]
引用 11 楼 wfxyjx 的回复:
引用 4 楼 xiaoc1026 的回复:
sendmessage之前 SetForegroundWindow 试试?

加上这个有效了,但是有几个疑问:
1.我之前试过SendMessage前加过SetFocus,是无效的,这个和SetForegroundWindow有什么区别呢?MSDN上说SetForegroundWindow 是将创建目标窗……
[/Quote]
高手你好,看了你的帖子明白了不少,但是对于第三点,我还有一些疑问,就是说我第一次单击发送程序的按钮后,接收方程序的线程被提到前台,然而我再次第二次单击发送程序的发送按钮时,发送者窗口的线程岂不会由于接受鼠标消息而被调到前台吗?这样接受窗口的线程应该又被调到后台了吧。对于线程什么时候调到前台,什么时候调到后台,请说一下可以吗,或者有什么资料给个链接也行。
gemmo 2011-07-13
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 wfxyjx 的回复:]
引用 4 楼 xiaoc1026 的回复:
sendmessage之前 SetForegroundWindow 试试?

加上这个有效了,但是有几个疑问:
1.我之前试过SendMessage前加过SetFocus,是无效的,这个和SetForegroundWindow有什么区别呢?MSDN上说SetForegroundWindow 是将创建目标窗口的线程调到前台,然后接受输入,听上去和S……
[/Quote]
1.-->每个gui线程都有自己的活动窗口,而目前被用户点中那个线程活动窗口叫前台窗口(或叫前景窗口)。而创建前台窗口的线程叫做前台线程(或叫前景线程),前台线程拥有比其它非前景线程更高的优先级,会被windows操作系统优先处理。
SetFocus可以是前台窗口或者是前台窗口的子窗口(控件)。所以可能无效。
2.-->支持你的推断
3.-->你已经把窗口设为前景线程了,就可以接收消息并处理了。并不会一直做设为前景线程的动作。你可以试试,sendmessage到该窗口,然后SetForegroundWindow 另外一个窗口,继续sendmessage到该窗口验证下。
以上个人观点。供参考。
simoreg 2011-07-12
  • 打赏
  • 举报
回复
用PostMessage试试
TandyT 2011-07-12
  • 打赏
  • 举报
回复
估计是第一次发送,是用来激活接收的窗口为活动窗口,第二次发送才是让已经激活的活动窗口来执行消息操作吧。。。。。
vann1982 2011-07-12
  • 打赏
  • 举报
回复
down up 间加个延时有没有效果啊?
见习学术士 2011-07-12
  • 打赏
  • 举报
回复
sendmessage之前 SetForegroundWindow 试试?
wfxyjx 2011-07-12
  • 打赏
  • 举报
回复
难道没有人知道吗。。。。。。
wfxyjx 2011-07-11
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 zwfgdlc 的回复:]
C/C++ code
SendMessage(hand_button,BM_CLICK,0,0);

行不行?
[/Quote]
试了下,和我那发送两次的SendMessage一个效果,也就是说得点两次测试程序才弹一次点击提示……
zwfgdlc 2011-07-11
  • 打赏
  • 举报
回复
SendMessage(hand_button,BM_CLICK,0,0);

行不行?

16,552

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Creator Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧