那postmessage 跨域和sendmessage有又什么区别

高手进,关于PostMessage和SendMessage的问题
作者:用户
浏览:102 次
我做了2个程序A和B,A发消息,B接收A:[DllImport("User32.dll",EntryPoint="SendMessage")]privatestaticexternintSendMes
问题描述我做了2个程序A和B,A发消息,B接收A:[DllImport("User32.dll",EntryPoint="SendMessage")]privatestaticexternintSendMessage(inthWnd,//目标窗口的handleintMsg,//消息intwParam,//第一个消息参数refCOPYDATASTRUCTlParam//第二个消息参数);[DllImport("User32.dll",EntryPoint="FindWindow")]privatestaticexternintFindWindow(stringlpClassName,stringlpWindowName);publicstructCOPYDATASTRUCT{publicIntPtrdwDpublicintcbD[MarshalAs(UnmanagedType.LPStr)]publicstringlpD}constintWM_COPYDATA=0x004A;publicForm1(){InitializeComponent();}privatevoidbutton1_Click(objectsender,EventArgse){intWINDOW_HANDLER=FindWindow(null,@"FrmReceive");if(WINDOW_HANDLER!=0){byte[]sarr=System.Text.Encoding.Default.GetBytes(textBox1.Text);intlen=sarr.LCOPYDATASTRUCTcds.dwData=(IntPtr)100;cds.lpData=textBox1.Tcds.cbData=len+1;SnedMessage(WINDOW_HANDLER,WM_COPYDATA,0,refcds);}B:publicstructCOPYDATASTRUCT{publicIntPtrdwDpublicintcbD[MarshalAs(UnmanagedType.LPStr)]publicstringlpD}constintWM_COPYDATA=0x004A;publicreceive(){InitializeComponent();}protectedoverridevoidDefWndProc(refMessagem){if(m.Msg==WM_COPYDATA){COPYDATASTRUCTmystr=newCOPYDATASTRUCT();Typemytype=mystr.GetType();mystr=(COPYDATASTRUCT)m.GetLParam(mytype);switch(mystr.dwData.ToString()){case"100":textBox1.Text=mystr.lpDcase"200":textBox2.Text=mystr.lpD}}base.DefWndProc(refm);}}现在用SendMessage测试成功,但把SendMessage改成PostMessage后,消息就无法传递了想请问下,如果要用PostMessage的话,应该怎么改呢?解决方案解决方案二:PostMessage消息发出后不等消息函数处理完就执行它的下一语句SendMessage消息发出后阻塞等消息函数处理完执行它的下一语句其他地方没有区别的解决方案三:引用1楼jinjazz的回复:PostMessage消息发出后不等消息函数处理完就执行它的下一语句SendMessage消息发出后阻塞等消息函数处理完执行它的下一语句其他地方没有区别的是的,因为我现在是SERVER发给CLIENT,所以想用PostMessage,但上面代码改成PostMessage后,消息就是发不过解决方案四:mark解决方案五:试试WM_SETTEXT作为参数解决方案六:引用4楼jinjazz的回复:试试WM_SETTEXT作为参数不行,WM_SETTEXT作为参数是设置标题的....解决方案七:SendMessage把消息直接发送到窗口,并调用此窗口的相应消息处理函数,等消息处理函数结束后SendMessage才返回!SendMessage发送的消息不进入系统的消息队列;SendMessage函数有返回值PostMessage将消息发送到与创建窗口的线程相关联的消息队列后立即返回;PostMessage函数没有返回值;我用PostMessage把消息发到B后,B怎么去获得这个消息呢?解决方案八:顶上去,高手来解答下吧
【云栖快讯】红轴机械键盘、无线鼠标等753个大奖,先到先得,云栖社区首届博主招募大赛9月21日-11月20日限时开启,为你再添一个高端技术交流场所&&
稳定可靠、可弹性伸缩的在线数据库服务,全球最受欢迎的开源数据库之一
6款热门基础云产品6个月免费体验;2款产品1年体验;1款产品2年体验
弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率
开发者常用软件,超百款实用软件一站式提供查看: 3552|回复: 12
关于SendMessage和PostMessage的两个个问题
阅读权限50
结帖率: (9/12)
一、SendMessage 和Message的第2个参数是怎么得到的?&&为什么513是按下左键,514是抬起左键等等?为什么百度查的都是WM_LBUTTONDOWN这种格式的,而里是数值?
二、SendMessage 和PostMessage的第3个和第4个参数是怎么确定的? 比如SendMessage (句柄, 513, 0,坐标),0代表什么?1又代表什么?234等等
好吧,第一个问题参考一楼
第二个问题:第三个参数和第四个参数对于不同的消息意义也不一样,比如在WM_LBUTTONDOWN消息里wParam表示鼠标左键按下时的组合键信息,lParam则包含了鼠标点击的坐标,而在WM_CLOSE里这两个参数都没有被用到。对于不同的消息wParam和lParam表示的意义具体要查看msdn。直接搜索常量就可以看到具体的参数具体的值
回答提醒:如果本帖被关闭无法回复,您有更好的答案帮助楼主解决,请发表至
可获得加分喔。友情提醒:本版被采纳的主题可在
帖子申请荣誉值,获得 1点 荣誉值,荣誉值可兑换终身vip用户组哦。快捷通道: →
阅读权限10
好吧,第一个问题参考一楼
第二个问题:第三个参数和第四个参数对于不同的消息意义也不一样,比如在WM_LBUTTONDOWN消息里wParam表示鼠标左键按下时的组合键信息,lParam则包含了鼠标点击的坐标,而在WM_CLOSE里这两个参数都没有被用到。对于不同的消息wParam和lParam表示的意义具体要查看msdn。直接搜索常量就可以看到具体的参数具体的值
您可以选择打赏方式支持他
阅读权限50
SendMessage 和PostMessage的第2个参数是怎么得到的?& &&&微软提供的API函数 可以在MSDN查询
为什么513是按下左键,514是抬起左键等等?为什么百度查的都是WM_LBUTTONDOWN这种格式的,而易语言里是数值?& && & 513 ,514是微软规定的,百度查的是其他变成个语言预设了常量,同样也是数值。
第二不懂,懂英文 可以看MSDN/en-us/library/msv=VS.85%29.aspx复制代码
您可以选择打赏方式支持他
阅读权限50
结帖率: (9/12)
Pewl 发表于
SendMessage 和PostMessage的第2个参数是怎么得到的?& &&&微软提供的API函数 可以在MSDN查询
为什么5 ...
谢谢,希望能有更完善的回答
您可以选择打赏方式支持他
阅读权限50
结帖率: (9/12)
人工置顶 走一个
您可以选择打赏方式支持他
阅读权限50
结帖率: (9/12)
置顶置顶走走走
您可以选择打赏方式支持他
阅读权限50
结帖率: (9/12)
这道题怎么那么难,不知道难倒了多少模块少年
您可以选择打赏方式支持他
阅读权限50
结帖率: (9/12)
要要切克闹
您可以选择打赏方式支持他
阅读权限160
WM_LBUTTONDOWN&&,看来LZ不懂什么是常量,Wm开头是Windows Message 简写!
您可以选择打赏方式支持他
阅读权限20
结帖率: (3/5)
查手册即可
您可以选择打赏方式支持他
精易论坛 - 有你更精彩 /1
一步步开发出自己的HOOK框架、自己ARM代码的VM模型、自己的ARM虚拟指令集等
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
揭阳精易科技有限公司申明:我公司所有的培训课程版权归精易所有,任何人以任何方式翻录、盗版、破解本站培训课程,我们必将通过法律途径解决!
公司简介:揭阳市揭东区精易科技有限公司致力于易语言教学培训/易语言学习交流社区的建设与软件开发,多年来为中小企业编写过许许多多各式软件,并把多年积累的开发经验逐步录制成视频课程供学员学习,让学员全面系统化学习易语言编程,少走弯路,减少对相关技术的研究与摸索时间,从而加快了学习进度!
防范网络诈骗,远离网络犯罪
违法和不良信息举报电话,QQ: ,,邮箱:@
Powered by
粤公网安备 25sendmessage与postmessage的区别
一、函数功能
该函数将指定的消息发送到一个或多个窗口。此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回。而函数PostMessage不同,将一个消息寄送到一个线程的消息队列后立即返回。
二、函数原型
SendMessage函数的原型为
LRESULT SendMessage(
& HWND hWnd,
& UINT Msg,
& WPARAM wParam,
& LPARAM lParam
hWnd:其窗口程序将接收消息的窗口的句柄。
Msg:指定被发送的消息。
wParam:指定附加的消息指定信息。
IParam:指定附加的消息指定信息。
返回值:返回值指定消息处理的结果,依赖于所发送的消息
WPARAM 和 LPARAM 两个附加参数,可以传递一些附加信息,由于它们是long
型的,所以只能传递数字,如果想要传递字符串之类的则需要使用指针,即字符串的地址。
三、同一进程里发送消息
1.发送消息
void CSendMessageDlg::OnBnClickeonSend()
CString* msg = new CString("发送的字符串");
::SendMessage(m_hWnd,WM_USER+1,0,(LPARAM)msg);
2.添加消息响应函数
(1)SendMessageDlg.h 添加
afx_msg HRESULT OnClickBtn1(WPARAM,LPARAM);
(2)SendMessageDlg.cpp
BEGIN_MESSAGE_MAP
END_MESSAGE_MAP()中间
ON_MESSAGE(WM_USER+1,OnClickBtnSend)
(3)实现函数
HRESULT CSendMessageDlg::OnClickBtn1(WPARAM wParam,LPARAM lParam)
CString* rmsg = (CString*)lP
MessageBox(*rmsg);
return TRUE;
3.点击发送,响应消息
四、不同进程发送消息传递字符串
1.两个进程间
(1)两个不同的进程不能用上面的方法,当然只发送消息是可以的。
(2)两个进程由于使用的是相互独立的两个虚拟内存空间,同一地址对不同的进程来说并不一定指向同一物理内存,内容也就不一定一样,因此不同进程无法通过传地址的方式传递字符串(但是同一进程下的不同线程是可以的)
2.解决办法
发送WM_COPYDATA消息在进程间传送数据
(1)发送消息
The exchange of data is performed by finding the other
application (using FindWindow) and sending a WM_COPYDATA message to
that window
使用FindWindow找到窗口,然后发送WM_COPYDATA消息,字符串附加到COPYDATASTRUCT 结构体
LRESULT copyDataR
CWnd *pOtherWnd = CWnd::FindWindow(NULL, strWindowTitle);
if (pOtherWnd)
COPYDATASTRUCT
cpd.dwData = 0;
cpd.cbData = strDataToSend.GetLength();
cpd.lpData = (void*)strDataToSend.GetBuffer(cpd.cbData);
copyDataResult = pOtherWnd-&SendMessage(WM_COPYDATA,
(WPARAM)AfxGetApp()-&m_pMainWnd-&GetSafeHwnd(),
(LPARAM)&cpd);
strDataToSend.ReleaseBuffer();
// copyDataResult has value returned by other app
AfxMessageBox("Unable to find other app.");
(2)添加消息
The other app should handle the WM_COPYDATA message in the
following manner
BEGIN_MESSAGE_MAP(CMyWnd, CWnd)
//{{AFX_MSG_MAP(CMyWnd)
ON_WM_COPYDATA()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
(3)消息处理
BOOL CMyWnd::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
CString strRecievedText = (LPCSTR) (pCopyDataStruct-&lpData);
return CMyWnd::OnCopyData(pWnd, pCopyDataStruct);
五、PostMessage&
和SendMessage的区别
PostMessage&
和SendMessage的区别主要在于是否等待其他程序消息处理。
PostMessage只是把消息放入队列,不管其他程序是否处理都返回,然后继续执行
SendMessage必须等待其他程序处理消息后才返回,继续执行。这两个函数的返回值也不同,SendMessage的返回值表示其他程序处理消息后的返回值
PostMessage的返回值表示PostMessage函数执行是否正确
六、引用申明
引用到csdn还有codeproject上的部分代码和部分话语,具体链接也存档后忘记了,谢谢作者。
我自己的内容欢迎随便修改转载使用。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。&&& 本文将使用C++语言,在MFC框架的配合下给出PostMessage、SendMessage等的使用方式与使用不当造成的后果(讨论均针对自定义的消息进行)。如有什么错误,欢迎指正。
写过Windows程序的同学都知道PostMessage、SendMessage的区别,PostMessage函数调用发送之后,立即返回,不等待消息处理完成。而SendMessage则让调用的线程处于阻塞(BLOCk)状态,直到消息处理完成。
&&&&&&&正由于这两个函数的区别导致了如下想法:
&&&&&&&想法1:PostMessage立即返回,在程序中,处理界面显示(如处理进度条、滚动条等)时使用PostMessage,不会影响程序的用户体验。
&&&&&&&想法2:在程序中全用PostMessage,放弃SendMessage,好处:PostMessage是立即返回的,可以不影响程序的正常流程,就算在消息处理函数中卡死了,也不影响主线程的运行。
&&&&&&&起初&学习&到了这些想法,以为受益匪浅,但经过一段时间之后,发现此两种想法都是不可取的。
&&&&&&&分析想法1:
&&&&&&&这里可分为两点:
1)&&在主线程中Post消息,以处理进度条显示(用WM_MY_TEST的参数WPARAM、LPARAM来处理进度条的显示)
代码:code_1
#define&WM_MY_TEST&(WM_USER&+ 100)
void&CMyDlg::OnBnClickedOk()
&&&&&int&nParam1&= 0;
&&&&&int&nParam2&= 0;
&&&&&for&(int&nIndex&= 0;&nIndex&& 1000;&nIndex++)
&&&&&&&&&// Do other things
&&&&&&&&&//&&
&&&&&&&&&nParam1++;
&&&&&&&&&nParam2++;
&&&&&&&&&PostMessage(WM_MY_TEST, (WPARAM)&nParam1, (LPARAM)&nParam2);
&&&&&//OnOK();
LRESULT&CMyDlg::OnMyTest(WPARAM&wParam,&LPARAM&lParam)
&&&&&static&int&nTimes&= 0;
&&&&&CString&strOutP
&&&&&int*&pParam1&= (int*)wP
&&&&&int*&pParam2&= (int*)lP
&&&&&nTimes++;
&&&&&strOutPut.Format(_T("%s%d&&&%s%d&%s%d"),
&&&&&&&&&_T("Param1 = "), *pParam1,
&&&&&&&&&_T("Param2 = "), *pParam2,
&&&&&&&&&_T("RealTimes = "),&nTimes);
&&&&&OutputDebugString(strOutPut);
&&&&&return&0;
code_1将运行的结果:
Param1 = 0 Param2 = 0 RealTimes = 1
Param1 = 0 Param2 = 0 RealTimes = 2
Param1 = 0 Param2 = 0 RealTimes = 3
Param1 = 0 Param2 = 0 RealTimes = 1000
结果远不如我们所料,表现为PostMessage多次发送时,2~1000的消息参数全被冲掉了。用pParam1、pParam2来处理进度条的话,后果可想而知(进度条根本没动)。如果将上面的PostMessage改为SendMessage,结果如下:
Param1 = 1 Param2 = 1 RealTimes = 1
Param1 = 2 Param2 = 2 RealTimes = 2
Param1 = 3 Param2 = 3 RealTimes = 3
Param1 = 1000 Param2 = 1000 RealTimes = 1000
可见,稳定的输出了需要的内容,可以很好的控制。
在此情况下(主线程中Post消息时),不仅没有改善用户体验,反而更差了。
不可以频繁使用PostMessage发送同一个消息,除非保证上一次发送的消息被处理完成(这如何保证???),这还不如直接用SendMessage。
当然OnMyTest函数可能是这样的:
LRESULT&CMyDlg::OnMyTest(WPARAM&wParam,&LPARAM&lParam)
&&&&&static&int&nTimes&= 0;
&&&&&CString&strOutP
&&&&&int*&pParam1&= (int*)wP
&&&&&int*&pParam2&= (int*)lP
&&&&&nTimes++;
&&&&&strOutPut.Format(_T("%s%d&&&%s%d&%s%d"),
&&&&&&&&&_T("Param1 = "), *pParam1,
&&&&&&&&&_T("Param2 = "), *pParam2,
&&&&&&&&&_T("RealTimes = "),&nTimes);
&&&&&OutputDebugString(strOutPut);
&&&&&//&大量访问网络,磁盘等低速操作
&&&&&return&0;
在这种情况下,如果用SendMessage的话,用户体验将会大大下降,甚至导致程序无法响应。于是有人提出了使用PostMessage,这样程序不会无法响应,最多显示不正确罢了。乍一看,提议似乎还不错,至少程序正常运行了。但是,这些网络访问、磁盘读写等操作为什么要放到界面的代码中呢?界面、代码分离才是合理的,因此可以认定,访问网络、磁盘读写等操作不应该放到这里来处理。
2)&&在非主线程中Post消息,以处理进度条显示(用WM_MY_TEST的参数WPARAM、LPARAM来处理进度条的显示)
代码:code_2
DWORD&WINAPI&ThreadProc(&LPVOID&lpParam&)
&&&&&CMyDlg&*pThis&= (CMyDlg&*)lpP
&&&&&int&nParam1&= 0;
&&&&&int&nParam2&= 0;
&&&&&for&(int&nIndex&= 0;&nIndex&& 1000;&nIndex++)
&&&&&&&&&nParam1++;
&&&&&&&&&nParam2++;
&&&&&&&&&pThis-&PostMessage(WM_MY_TEST, (WPARAM)&(nParam1), (LPARAM)&(nParam2));
&&&&&return&0;
void&CMyDlg::OnBnClickedOk()
&&&&&HANDLE&hThread&=&CreateThread(NULL,
&&&&&&&&&0,
&&&&&&&&&ThreadProc,&
&&&&&&&&&(void*)this,
&&&&&&&&&0,
&&&&&&&&&NULL);
&&&&&//OnOK();
LRESULT&CMyDlg::OnMyTest(WPARAM&wParam,&LPARAM&lParam)
&&&&&static&int&nTimes&= 0;
&&&&&CString&strOutP
&&&&&int*&pParam1&= (int*)wP
&&&&&int*&pParam2&= (int*)lP
&&&&&nTimes++;
&&&&&strOutPut.Format(_T("%s%d&&&%s%d&%s%d"),
&&&&&&&&&_T("Param1 = "), *pParam1,
&&&&&&&&&_T("Param2 = "), *pParam2,
&&&&&&&&&_T("RealTimes = "),&nTimes);
&&&&&OutputDebugString(strOutPut);
&&&&&return&0;
code_2的运行结果:
(程序直接崩溃了)
线程函数不等待WM_MY_TEST的返回,循环1000次之后直接退出了,这导致栈上的变量nParam1、nParam2被释放,然后OnMyTest处理的时候,nParam1、nParam2的地址已经无效了,导致崩溃。SendMessage则不会出现此类情况。
代码:code_2(2)
DWORD&WINAPI&ThreadProc(&LPVOID&lpParam&)
&&&&&CqwerDlg&*pThis&= (CqwerDlg&*)lpP
&&&&&int&*nParam1&=&NULL;
&&&&&int&*nParam2&=&NULL;
&&&&&nParam1&=&new&
&&&&&nParam2&=&new&
&&&&&for&(int&nIndex&= 0;&nIndex&& 1000;&nIndex++)
&&&&&&&&&*nParam1&=&nI
&&&&&&&&&*nParam2&=&nI
&&&&&&&&&pThis-&PostMessage(WM_MY_TEST, (WPARAM)nParam1, (LPARAM)nParam2);
&&&&&return&0;
由于堆内存没有被释放,所以程序没有崩溃,在我的机器上运行结果为:
Param1 = 27 Param2 = 27 RealTimes = 1
Param1 = 117 Param2 = 117 RealTimes = 2
Param1 = 162 Param2 = 162 RealTimes = 3
Param1 = 218 Param2 = 218 RealTimes = 4
Param1 = 272 Param2 = 272 RealTimes = 5
Param1 = 312 Param2 = 312 RealTimes = 6
Param1 = 353 Param2 = 353 RealTimes = 7
Param1 = 391 Param2 = 391 RealTimes = 8
Param1 = 431 Param2 = 431 RealTimes = 9
程序执行非常不稳定,每次结构都不同,当然也不能用这些数据了。当把两个new int放到for循环中,执行结果是稳定的,但这样的代码晦涩难懂。在这里用PostMessage没有任何好处,所以建议使用SendMessage。
&&&&&&&分析想法2:
&&&&&&&1)&&已知一个线程处理了A,由于其他需要,此线程还需要处理B(必须在A完成之后)。需要新加入代码来实现,以前的代码为:
代码:code_3
DWORD&WINAPI&ThreadProc(LPVOID&lpParam)
&&&&&HWND&hWnd&= (HWND)lpP
&&&&&// Do some things
&&&&&::PostMessage(hWnd,&WM_MUST_DO_THING_A, 0, 0);
&&&&&return&0;
LRESULT&CMyDlg::OnMustDoThingA(WPARAM&wParam,&LPARAM&lParam)
&&&&&Do some things for A
&&&&&Do some things for B&&&//&费解,这是A的处理函数!!!
我们可以多加个消息,WM_MUST_DO_THING_B,然后用PostMessage发送,哦,不能这样,B一定要在A完成之后,现在唯一的处理方式只有对B的处理加入到A的消息处理函数中,这将导致费解的代码。如果在原来的线程函数中PostMessage为SendMessage,则不会如此。
&&&&如果A、B是不相关联的两个操作,为了以后扩展,也不该用PostMessage,这种情况下应该多创建一个线程进行处理。
2)&&对于需要处理的比较重要的操作(这些可能导致卡死):
LRESULT&CMyDlg::OnDoThing(WPARAM&wParam,&LPARAM&lParam)
&&&&Things To do. //&这里可能会卡死,但又必须处理
在这种情况下,建议使用SendMessageTimeout,当等待一段时间后,消息仍然没有处理完成,则程序放弃操作继续运行。
&&&&3)对于所有无关紧要的操作:
&&&&这些操作包括:清理磁盘临时文件等等,这些操作有没正常处理,程序并不关心,在这种情况下,则可使用PostMessage、
终上所述,我们得到如下结论:
1、&&PostMessage不能频繁的发送同一个消息,除非保证上次Post过的消息处理完成。
2、&&如果用SendMessage导致应用程序用户体验下降,应该检查消息处理函数,而不仅仅简单改为PostMessage。
3、&&如果消息是程序必须处理的,则不能使用PostMessage。
4、&&如果消息是程序必须处理,而又有可能导致程序卡死,则使用SendMessageTimeout。
5、&&如果消息是无关紧要的,则可以建议使用PostMessage。
6、&&对于WM_HOTKEY&等Windows特定的消息,则只能使用PostMessage(未在本文中说明)。
参考:http://blog.csdn.net/xt_xiaotian/article/details/2778689
Views(...) Comments()

我要回帖

更多关于 postmessage 跨域 的文章

 

随机推荐