SendMessage、PostMessage原理(1)本文讲解SendMessage、PostMessage两个函数的实现原理,分为三个步骤进行讲解,分别适合初级、中级、高级程序员进行理解,三个步骤分别为: 1、SendMessage、PostMessage的运行机制。 2、SendMessage、PostMessage的运行内幕。 3、SendMessage、PostMessage的内部实现。 注:理解这篇文章之前,必须先了解Windows的消息循环机制。
1、SendMessage、PostMessage的运行机制 我们先来看最简单的。 SendMessage可以理解为,SendMessage函数发送消息,等待消息处理完成后,SendMessage才返回。稍微深入一点,是等待窗口处理函数返回后,SendMessage就返回了。 PostMessage可以理解为,PostMessage函数发送消息,不等待消息处理完成,立刻返回。稍微深入一点,PostMessage只管发送消息,消息有没有被送到则并不关心,只要发送了消息,便立刻返回。 对于写一般Windows程序的程序员来说,能够这样理解也就足够了。但SendMessage、PostMessage真的是一个发送消息等待、一个发送消息不等待吗?具体细节,下面第2点将会讲到。
2、SendMessage、PostMessage的运行内幕 在写一般Windows程序时,如上第1点讲到的足以应付,其实我们可以看看MSDN来确定SendMessage、PostMessage的运行内幕。 在MSDN中,SendMessage解释如为:The SendMessage function sends the specified message to a window or windows. It calls the window procedure for the specified window and does not return until the window procedure has processed the message. 翻译成中文为:SendMessage函数将指定的消息发到窗口。它调用特定窗口的窗口处理函数,并且不会立即返回,直到窗口处理函数处理了这个消息。 再看看PostMessage的解释:The PostMessage function places (posts) a message in the message queue associated with the thread that created the specified window and returns without waiting for the thread to process the message. 翻译成中文为:PostMessage函数将一个消息放入与创建这个窗口的消息队列相关的线程中,并立刻返回不等待线程处理消息。 仔细看完MSDN解释,我们了解到,SendMessage的确是发送消息,然后等待处理完成返回,但发送消息的方法为直接调用消息处理函数(即WndProc函数),按照函数调用规则,肯定会等消息处理函数返回之后,SendMessage才返回。而PostMessage却没有发送消息,PostMessage是将消息放入消息队列中,然后立刻返回,至于消息何时被处理,PostMessage完全不知道,此时只有消息循环知道被PostMessage的消息何时被处理了。 至此我们拨开了一层疑云,原来SendMessage只是调用我们的消息处理函数,PostMessage只是将消息放到消息队列中。下一节将会更深入这两个函数,看看Microsoft究竟是如何实现这两个函数的。
3、SendMessage、PostMessage的内部实现 Windows内部运行原理、机制往往是我们感兴趣的东西,而这些东西又没有被文档化,所以我们只能使用Microsoft提供的工具自己研究了。 首先,在基本Win32工程代码中,我们可以直接看到消息处理函数、消息循环,所以建立一个基本Win32工程(本篇文章使用VS2005),为了看到更多信息,我们需要进行设置,让VS2005载入Microsoft的Symbol(pdb)文件[1]。为了方便,去除了一些多余的代码,加入了两个菜单,ID分别为:IDM_SENDMESSAGE、IDM_POSTMESSAGE。如下列出经过简化后的必要的代码。 消息循环: Ln000:while (GetMessage(&msg, NULL, 0, 0)) Ln001:{ Ln002: TranslateMessage(&msg); Ln003: DispatchMessage(&msg); Ln004:}
消息处理函数: Ln100:LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) Ln101:{ Ln102: int wmId, wmEvent; Ln103: switch (message) Ln104: { Ln105: case WM_COMMAND: Ln106: wmId = LOWORD(wParam); Ln107: wmEvent = HIWORD(wParam); Ln108: switch (wmId) Ln109: { Ln110: case IDM_EXIT: Ln111: DestroyWindow(hWnd); Ln112: break; Ln113: case IDM_SENDMESSAGE: Ln114: SendMessage(hWnd, WM_SENDMESSAGE, 0, 0); Ln115: break; Ln116: case IDM_POSTMESSAGE: Ln117: PostMessage(hWnd, WM_POSTMESSAGE, 0, 0); Ln118: break; Ln119: default: Ln120: return DefWindowProc(hWnd, message, wParam, lParam); Ln121: } Ln122: break; Ln123: Ln124: case WM_SENDMESSAGE: Ln125: MessageBox(hWnd, L"SendMessage", L"Prompt", MB_OK); Ln126: break; Ln127: Ln128: case WM_POSTMESSAGE: Ln129: MessageBox(hWnd, L"PostMessage", L"Prompt", MB_OK); Ln130: break; Ln131: Ln132: case WM_DESTROY: Ln133: PostQuitMessage(0); Ln134: Ln135: default: Ln136: return DefWindowProc(hWnd, message, wParam, lParam); Ln137: } Ln138: return 0; Ln139:} |
|
来自: Qin Hantang > 《工作、技术》