关于SendMessage和PostMessage,近4个月的困惑

bestxy 2010-08-18 02:31:57
原以为很简单的问题,花了近4个月的时间,一直没能很好地解决,纠结ing

据说SendMessage是发消息并等待消息的处理结果,然后再执行一下句;
PostMessage是把消息放到消息队列里就返回继续执行下一句。

实际上,经过多次试验,向别的程序发送消息,不管是::SendMessage还是::PostMessage,后面不跟一个Sleep(n)或者别的延时,都可能返回0,下一句得以继续执行,而此时目标程序可能接到了消息,也可能没接到;只有n足够大的时候,才能保证目标程序正确收到消息。

也就是说,向目标程序的特定文本框发送一个字符串,标准方式是:
for i := 0 to Length(cStr)-1 do
begin
PostMessage(hCtrlHandle,WM_CHAR,Wparam(cStr[i]),1);
Sleep(iDelay);
Application.ProcessMessages;
end;
或者:
SendMessage(hCtrlHandle,WM_SETTEXT,0,sStr);
Sleep(iDelay);

好吧,这样也挺不错的。问题是,iDelay 应该取多少呢?

iDelay<=600的时候,我的程序在T4400双核CPU、2G内存的本本上运行得很好,但放到1.5G单核CPU、1G内存的台式机上,发送消息就经常失败了:(

如何才能根据CPU的主频自动计算出延时值iDelay,既保证消息发送成功,又尽量避免多余的延时时间?
...全文
1113 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
bestxy 2011-12-12
  • 打赏
  • 举报
回复
TO: MM22GG
不好意思,很久没上CSDN。我在发此贴之前就分别用VC和DELPHI实现了这个程序的基本功能,能批量转换格式、缩小JPEG文件大小、放缩和旋转图片,没继续完善了。不知你动手做了没有,我的程序叫JPEGSliming,发到你邮箱去了,试用后请反馈意见,谢谢
MM22GG 2011-01-11
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 bestxy 的回复:]

先感谢各位大大。

也许这个问题我没说清楚。

我的程序是这样的:先调用CreateProcess在后台打开画图(MSPAINT.EXE),然后循环以下步骤,处理一批图像文件:
A、调出“打开”对话框;
B、自动选择打开文件类型;
C、自动填入文件名;
D、自动执行“打开”按钮的功能;
E、调出“另存为”对话框;
F、自动选择“保存类型”为JPEG;
G、自动填入文件名;
……
[/Quote]
你设计的这个程序实现了么,最近在处理相册图片时,也想到了该功能,如果没有发现人实现的话,打算自己编码实现并发出来跟大家共享.
如果你的实现了,不知道可否拿来与大家分享?谢谢.
mm22gg@163.com
bestxy 2010-08-18
  • 打赏
  • 举报
回复
大家的热心回答让我很感动,再次谢谢。不过还请各位大大先看清帖子再回答。毕竟这个问题偶已经研究了三个多月,再菜也可以说颇有心得了。

TO pornographer & lvxinjian_cn:
就是这种情况,所以要Sleep让出CPU并等待对方处理。问题就是如何判断这个Sleep等待的时间值。

TO xxd_qd & tylin_124 & smallfishff & test_machine:
你们说的都对,近4个月的时间,这些我都一一检查、试验、验证过了,只有发送WM_SETTEXT或者WM_CHAR消息的时候才会出现问题。

TO ljhnew:
是找到的另一个进程中CEdit控件的句柄,已经判断无误了。

TO m_tornado:
MSPAINT.EXE当然不是自己的程序,没办法直接调用该函数(其实办法也有,那些太麻烦了)

TO MildSong:
"不管是用PostMessage循环发WM_CHAR消息,还是用SendMessage直接发送WM_SETTEXT消息"
当然不是自定义消息啦。还有,如果是参数的问题,肯定不会使用Sleep(n)且“只有n足够大的时候,才能保证目标程序正确收到消息。”

TO aa65433:
setwindowtext函数,设置编辑框的内容只对当前进程有效,不能设置另一个进程中的CEdit文本。

TO VisualEleven:
MSDN官方的帮助已经反复看了数百遍,麻烦大大不要再复制粘贴,以免浪费您的宝贵时间。

MildSong 2010-08-18
  • 打赏
  • 举报
回复
PostMessage 和 SendMessage经常被使用,没遇到过搂主的问题
怀疑是参数的问题,比如 如果传递的是用户自定义消息,而消息ID定义小于 WM_USER
aa65433 2010-08-18
  • 打赏
  • 举报
回复
试验下 直接获得CEdit的句柄,然后用setwindowtext函数,设置编辑框的内容
lvxinjian_cn 2010-08-18
  • 打赏
  • 举报
回复
建议你从消息队列思路来想,消息有可能发出去了,但是程序并没有空闲时间来处理这个思路。只是建议
bestxy 2010-08-18
  • 打赏
  • 举报
回复
先感谢各位大大。

也许这个问题我没说清楚。

我的程序是这样的:先调用CreateProcess在后台打开画图(MSPAINT.EXE),然后循环以下步骤,处理一批图像文件:
A、调出“打开”对话框;
B、自动选择打开文件类型;
C、自动填入文件名;
D、自动执行“打开”按钮的功能;
E、调出“另存为”对话框;
F、自动选择“保存类型”为JPEG;
G、自动填入文件名;
H、自动执行“保存”按钮的功能;

简单的说,就是后台调用XP自带的画图程序批量进行图像文件格式转换。在步骤A-H中,大量用到了PostMessage和SendMessage,比如调用画图的菜单打开对话框、选择下拉列表框、填入文件名等等。
hCtrlHandle是内存变量,用于保存目标控件的句柄;该句柄是用FindWindowEx找到的。


多次试验的结果,如果不是发送文本到CEdit控件,比如操纵菜单、选择下拉列表框的选项等,是不需要Sleep,但向CEdit控件填入文件名,不管是用PostMessage循环发WM_CHAR消息,还是用SendMessage直接发送WM_SETTEXT消息,都需要Sleep(n),而且n必须达到一定的大小,否则CEdit控件的内容就会为空。

显然,这个问题不是SendMessage和PostMessage引起的,而是两个不同进程之间同步的问题。因为MSPAINT.EXE是外部程序,没有源码,所以只能用延时等待来实现进程之间的同步。问题是如何测算延时量,才能在不同主频的电脑都保证进程之间的同步?

PS:还有个奇怪的问题,每次发送文本失败,用GetLastError取得的错误代码,都是“无效的句柄”,但句柄是事先用FindWindowEx找到并且检验过的。
Eleven 2010-08-18
  • 打赏
  • 举报
回复
SendMessage()
The return value specifies the result of the message processing; it depends on the message sent.
pornographer 2010-08-18
  • 打赏
  • 举报
回复
messagebox还有类似于windows消息忙等情况似乎都能阻塞message的

注意点
tylin_124 2010-08-18
  • 打赏
  • 举报
回复
确实在PostMessage和SendMessage后面不需要延时处理,两个函数的不同非常明确,SendMessage等待消息处理完成才返回,PostMessage直接返回.在多线程程序中,建议做好共享对象的互斥访问,感觉会不会是这方面的问题.
xxd_qd 2010-08-18
  • 打赏
  • 举报
回复
几乎从未遇到过这种情况(要么是遇到过我没注意?),至少在我所编写过的程序中,大量使用PostMessage和SendMessage,没有发生过什么让我想不通的奇怪现象。实际上,我写的程序中有很多关键代码都是靠这些消息传递来实现的,如果有问题的话,那这些程序早崩溃了。顺便说一句,我从没有在这两个函数后面用过Sleep。

另外,不要说MFC,即使Windows的很多机制也都是用这两个实现的(比如各种控件),照你的说法,岂不是谁都无法保证你什么时候会不会收到消息了?所以,我觉得还是你的代码有别的方面的问题,不要光盯着这两个函数。SendMessage的返回值是对方的消息处理函数所返回的值,如果对方返回零,SendMessage自然也返回0,这并不表示调用失败。至于PostMessage,如果返回0的话,那你GetLastError看看究竟什么原因失败。
smallfishff 2010-08-18
  • 打赏
  • 举报
回复
很少有这样情况的.
SendMessage 与 PostMessage都具可靠性.当然也有很小机率会失败.对于MFC程式封装的API也是使用这两个函数来实现消息传递.若像你那样描述....MFC程式在老机子上就频繁不工作?
bestxy 2010-08-18
  • 打赏
  • 举报
回复
ColdMooon说得好,我是钻牛角了。结了吧
m_tornado 2010-08-18
  • 打赏
  • 举报
回复
你要是在不放心,就直接调用该函数好了,还发什么消息~
test_machine 2010-08-18
  • 打赏
  • 举报
回复
PostMessage确实有时可能收不到消息,但SendMessage应该是有保证的,我觉得可能是出在参数传递的这一部分,您有没有试过不传递参数时,不用Sleep函数能不能接收到消息,我在使用中好像没有遇到这样的!比如要加Sleep
ljhnew 2010-08-18
  • 打赏
  • 举报
回复
hCtrlHandle?是啥控件?它是一个单独线程运行的控件吗?如果有个窗口存在,该句柄是否有效,最好在发送前判断。
smallfishff 2010-08-18
  • 打赏
  • 举报
回复

PostMessage(hCtrlHandle,WM_CHAR,Wparam(cStr[i]),1);
换成这样行不?
SendMessage (hCtrlHandle, WM_CHAR, "x", 0);

然后你可以单独使用
SendMessage(hCtrlHandle,WM_SETTEXT,0,sStr);获取那个程式的其它控件的文本咯.
如果不成功再使用同样的方法获取另外一个程式的控件文本....这样排除下看看是什么问题.
ColdMooon 2010-08-18
  • 打赏
  • 举报
回复
很简单,除非有特殊的需要,统统用PostMessage。
至于延时的问题,灵敏度和可靠性本来就是一对矛盾,在你不知道mspaint的源码情况下。就算知道也没多大用。
比如,一个高配置的机器600ms一般就够用了,但当他开着3个BT,2个高清电影,还开着杀毒软件时,6000毫秒也不一定够用。
wolffan3150 2010-08-18
  • 打赏
  • 举报
回复
消息有可能发出去了,但是程序并没有空闲时间来处理这个思路


bestxy 2010-08-18
  • 打赏
  • 举报
回复
如果哪位大大有空,不妨写一段循环内的的代码让偶参考,不胜感激。



[Quote=引用 10 楼 bestxy 的回复:]
先感谢各位大大。

也许这个问题我没说清楚。

我的程序是这样的:先调用CreateProcess在后台打开画图(MSPAINT.EXE),然后循环以下步骤,处理一批图像文件:
A、调出“打开”对话框;
B、自动选择打开文件类型;
C、自动填入文件名;
D、自动执行“打开”按钮的功能;
E、调出“另存为”对话框;
F、自动选择“保存类型”为JPEG;
G、自动填入文件名;
……
[/Quote]

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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