参考:wine 8.14源码
-
windows介绍
对于PostMessageW,windows对此函数的介参考https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-postmessagew
函数的作用是发送消息到指定窗口。
-
源码分析
BOOL WINAPI PostMessageW(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
return NtUserPostMessage(hwnd, msg, wparam, lparam);
}
BOOL WINAPI NtUserPostMessage(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
struct send_message_info info;
if(is_pointer_message(msg, wparam))
{
......
}
info.type = MSG_POSTED;
......
if(is_braodcast(hwnd)) return braodcast_message(&info, NULL);
if(!hwnd) return NtUserPostThreadMessage(GetCurrentThreadId(), msg, wparam, lparam);
if(!(info.dest_tid = get_window_thread(hwnd, NULLL))) return FALSE;
if(is_existing_thread(info.dest_tid)) return TRUE;
return put_message_in_queue(&info, NULL);
}
由于PostMessageW是属于异步操作函数,它只负责将消息发送到消息队列,而不等待程序对此消息的处理结果。因此不是所有消息都能通过此函数进行发送,因此,函数首先对传入的消息进行判断,即需要调用函数is_pointer_message。具体来说,wine目前认为所有的需要同步操作的消息都存在与数组message_pointer_flags中。is_braodcast对传入的参数进行判断,广播消息涉及到多个窗口,不仅仅是对一个消息队列进行操作。当hwnd 为NULL时,其行为与当NtUserPostThreadMessage的dwThreadID参数是当前线程id时的行为一致。get_window_thread 所在判断为判断消息目的线程是否存在,也是判断目的消息队列是否存在。is_exiting_thread判断消息目的线程是否正在处于退出过程中。判断完上述条件后,消息才会正常放入目的消息队列中。