MFC用PostMessage传递消息

时间:2021-02-14 09:23:19

1.自定义消息ID。

#define WM_MY_MESSAGE (WM_USER+100)         WM_USER为windows系统为非系统消息保留的ID,这里至少要用100,因为其它控件的消息会占用一部分。

2. 定义消息处理函数。

消息处理函数为消息目标类的成员函数。首先应该在.h 文件中声明。这里以主窗口类为例,主窗口类名 CMainDialog,则首先在CMainDialog.h声明消息处理函数。

protected:

afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);

3.在CMainDialog.cpp中实现消息处理函数

LPESULT CMainDialog::OnMyMessage(WPARAM wParam, LPARAM lParam) 

// TODO: 处理用户自定义消息 
... 
return 0; 
}

4.在CMainDialog.cpp中映射消息ID和消息处理函数

BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) 
ON_WM_CREATE() 
ON_WM_TIMER() 
ON_MESSAGE(WM_MY_MESSAGE, OnMyMessage) 
//}}AFX_MSG_MAP 
END_MESSAGE_MAP()

在创建线程的时候将主窗口句柄作为参数传入线程,就可以用 PostMessage传递消息了。

SendMessage函数功能描述:将指定的消息发送到一个或多个窗口。此函数为指定的窗口调用窗口过程,直到窗口过程处理完消息后才返回。

Postmessage函数则是将消息放入消息队列里,并立即返回。

常见问题

1)使用SendMessage来实现剪切、复制和粘贴

1 SendMessage(hwnd, WM_COPY, 0, 0);
2 SendMessage(hwnd, WM_CUT, 0, 0);
3 SendMessage(hwnd, WM_PASTE, 0, 0);

2)SendMessage与PostMessage的区别

PostMessage将消息放入消息队列后马上返回,而SendMessage直到窗口过程处理完消息后才返回。

3)SendMessage发送WM_COPYDATA消息在进程间传送数据

WM_COPYDATA消息主要目的是允许在进程间传递少量只读数据。SDK文档推荐用户使用SendMessage()函数,接收方在数据复制完成前不返回,这样发送方就不可能删除和修改数据。

例如:

1 std:string strData = "VC知识库 VCKBASE.COM";
2 COPYDATASTRUCT cds;
3 cds.dwData = 0;
4 cds.cbData = strData.Length();
5 cds.lpData = strData.c_str();
6 ::SendMessage(hwnd, WM_COPYDATA, NULL, (LPARAM)&cds);

3、PostThreadMessage有时会失败,报1444错误(Invalid thread identifier. ),其实这不一定是线程不存在的原因,也有可能是线程不存在消息队列(message queue)造成的。事实上,并不是每个thread都有message queue,那如何让thread具有呢? 答案是,至少调用message相关的function一次,比如GetMessage,PeekMessage。

4、如果是postthreadmessage动态分配的memory给另外一个thread,要注意内存的正确释放。并且PostThreadMessage不能够post WM_COPYDATE之类的同步消息,否则会报错!

5、最好不要使用PostThreadMessage post message给一个窗口,使用PostMessage替代。

1    #include <windows.h>
#include <cstdio>
#include <process.h>
#define MY_MSG WM_USER+100
const int MAX_INFO_SIZE = ;
HANDLE hStartEvent; // thread start event
// thread function
unsigned __stdcall fun(void *param)
{
printf("thread fun start \n");
MSG msg;
PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
if(!SetEvent(hStartEvent)) //set thread start event
{
printf("set start event failed,errno:%d\n",::GetLastError());
return ;
} while(true)
{
if(GetMessage(&msg,,,)) //get msg from message queue
{
switch(msg.message)
{
case MY_MSG:
char * pInfo = (char *)msg.wParam;
printf("recv %s\n",pInfo);
delete[] pInfo;
break;
}
}
};
return ;
}
int main()
{
HANDLE hThread;
unsigned nThreadID;
hStartEvent = ::CreateEvent(,FALSE,FALSE,); //create thread start event
if(hStartEvent == )
{
printf("create start event failed,errno:%d\n",::GetLastError());
return ;
}
//start thread
hThread = (HANDLE)_beginthreadex( NULL, , &fun, NULL, , &nThreadID );
if(hThread == )
{
printf("start thread failed,errno:%d\n",::GetLastError());
CloseHandle(hStartEvent);
return ;
}
//wait thread start event to avoid PostThreadMessage return errno:1444
::WaitForSingleObject(hStartEvent,INFINITE);
CloseHandle(hStartEvent);
int count = ;
while(true)
{
char* pInfo = new char[MAX_INFO_SIZE]; //create dynamic msg
sprintf(pInfo,"msg_%d",++count);
if(!PostThreadMessage(nThreadID,MY_MSG,(WPARAM)pInfo,))//post thread msg
{
printf("post message failed,errno:%d\n",::GetLastError());
delete[] pInfo;
}
::Sleep();
}
CloseHandle(hThread);
return ;
}