讲到Window通讯我们就一定会提到消息, 而对于消息通讯的方法大家也一定会说PostMessage, SendMessage. 是的,两个消息发送方法目的都是一样, 但达到的效果以及对系统的稳定性其实是不一样的,我们先分析一下PostMessage,它发送的消息入消息队列,这样的消息仅将消息放入到窗体消息队列后返回,什么时候执行调用者是不知道的所以我们通常称其为异步消息或非阻塞式消息同时此方法不保证窗体收到此消息,SendMessage 发送的消息不入消息队列而是直接调用窗体过程函数, 窗体过程处理完消息后返回即调用与被调之间是同步的也称之为阴塞式消息。 这两个函数各有千秋,各有不足,比如我们软件开发时可能有这样的需求,消息发送时像PostMessage一样放到队列就返回,但又要像SendMessage一样等执行后完通知我,或过一段时间返回通知结果. Windows 系统为了的确有类拟这样的函数.
一、我们下面将学习除PostMessage, SendMessage以外的消息通讯函数:
1. BOOL SendMessageCallback(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, SENDASYNCPROC lpCallBack, ULONG_PTR dwData)
本函数像PostMessage一样发送一个消息到目标窗体后返回,当目标窗体过程函数处理完消息后通过回调函数返回结果
2. LRESULT SendMessageTimeout(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, UINT fuFlags, UINT uTimeout, PDWORD_PTR lpdwResult)
本函数和SendMessage一样发送消息到目标窗体,若目标窗体在uTimeOut的时间内返回此函数立即返回,否则uTimeOut时间到后返回
3. BOOL SendNotifyMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
该函数将指定的消息发送到一个窗口。如果该窗口是由调用线程创建的;此函数为该窗口调用窗口程序,并等待窗口程序处理完消息后再返回。如果该窗口是由不同的线程创建的,此函数
将消息传给该窗口程序,并立即返回,不等待窗口程序处理完消息。
二、代码演示
DWORD CALLBACK ThreadProc(LPVOID lpData)
{
HWND hMainWnd = *(HWND*)lpData;
TCHAR szTmp[128];
DWORD dwRes= 0;
for (int ii = 0; ii < sizeof(Info) / sizeof(*Info); ii++)
{
switch (ii)
{
case 0: PostMessage(hMainWnd, WM_TEST, Info[ii].nParam, 0); break;
case 1: SendMessageCallback(hMainWnd, WM_TEST, Info[ii].nParam, 0, TestMsgProc, 0); break;
case 2: SendNotifyMessage(hMainWnd, WM_TEST, Info[ii].nParam, 0); break;
case 3: SendMessageTimeout(hMainWnd, WM_TEST, Info[ii].nParam, 0, 0, 1000, &dwRes); break;
case 4: break; //SendMessage(hMainWnd, WM_TEST, Info[ii].nParam, 0); break;
//case 5: SendMessage(hMainWnd, WM_TEST, Info[ii].nParam, 0); break;
}
OutputDebugString(_T("\n===================================================\n"));
_stprintf(szTmp, _T("Create thread to here(%s), spend time: %d wparam = %d\n"),
Info[ii].szSendWay, GetTickCount() - dwTickCount, Info[ii].nParam);
//_tcscat(szContext, szTmp);
OutputDebugString(szTmp);
}
return 0;
}
{
if (5 == wParam)
{
OutputDebugString(szContext);
}
Sleep(2000);
TCHAR szTmp[128];
_stprintf(szTmp, _T("Recieve this message from \"%s\" sent, wparam: %d \n"), Info[wParam].szSendWay, wParam);
OutputDebugString(szTmp);
//_tcscat(szContext, szTmp);
return 100;
}
程序创建了一个线程,在线程中使用不同的消息发送函数向主窗体发送WM_TEST消息,并将设定了一个值作为参数用于标识不同发送方法. 看看OutputView结果:
分析结果我们可以看出: 1. PostMessage, SendMessageCallBack, SendNotifyMessage 发送函数没有花费什么时间,都几乎发送就返回了;
2. 而SendMessateTimeout 发了1秒多, 实际上这个函数要2秒才能执行完, 但并没有执行完就timeout了。
3. SendMessageCallBack 发送成功后, 而了许久后才调了回调函数将结果返回.