SendMessage的大致流程
1、构造send_message_info结构体,然后调用send_message函数。 SendMessageA和SendMessageW的区别有两处:info.type一个是MSG_ASCII,一个是MSG_UNICODE;send_message函数的第三个参数一个为TRUE一个为FALSE。
LRESULT WINAPI SendMessageA( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
{
DWORD_PTR res = 0;
struct send_message_info info;
info.type = MSG_ASCII;
info.hwnd = hwnd;
info.msg = msg;
info.wparam = wparam;
info.lparam = lparam;
info.flags = SMTO_NORMAL;
info.timeout = 0;
info.wm_char = WMCHAR_MAP_SENDMESSAGE;
send_message( &info, &res, FALSE );
return res;
}
2、send_message
首先判断是不是广播消息,从is_broadcast函数代码来看,目的窗口句柄为HWND_BROADCAST或HWND_TOPMOST的是广播消息。对于广播消息,它使用EnumWindows通过回调函数broadcast_message_callback,将消息发给每一个窗体。
GetWindowThreadProcessId函数,通过目的窗口句柄获取窗口所在进程和线程id
如果目的窗口线程和当前发送线程相同,它直接调用窗口的回调函数。
如果是不同的线程,最终会调用到send_inter_thread_message发送线程间消息。WINPROC_CallProcAtoW这里有一次转换,目前不清楚它是什么用,它的第一个回调参数是真正发送消息的地方。
static BOOL send_message( struct send_message_info *info, DWORD_PTR *res_ptr, BOOL unicode )
{
DWORD dest_pid;
BOOL ret;
LRESULT result;
if (is_broadcast(info->hwnd))
{
EnumWindows( broadcast_message_callback, (LPARAM)info );
if (res_ptr) *res_ptr = 1;
return TRUE;
}
if (!(info->dest_tid = GetWindowThreadProcessId( info->hwnd, &dest_pid ))) return FALSE;
if (USER_IsExitingThread( info->dest_tid )) return FALSE;
SPY_EnterMessage( SPY_SENDMESSAGE, info->hwnd, info->msg, info->wparam, info->lparam );
if (info->dest_tid == GetCurrentThreadId())
{
result = call_window_proc( info->hwnd, info->msg, info->wparam, info->lparam,
unicode, TRUE, info->wm_char );
if (info->type == MSG_CALLBACK)
call_sendmsg_callback( info->callback, info->hwnd, info->msg, info->data, result );
ret = TRUE;
}
else
{
if (dest_pid != GetCurrentProcessId() && (info->type == MSG_ASCII || info->type == MSG_UNICODE))
info->type = MSG_OTHER_PROCESS;
/* MSG_ASCII can be sent unconverted except for WM_CHAR; everything else needs to be Unicode */
if (!unicode && is_unicode_message( info->msg ) &&
(info->type != MSG_ASCII || info->msg == WM_CHAR))
ret = WINPROC_CallProcAtoW( send_inter_thread_callback, info->hwnd, info->msg,
info->wparam, info->lparam, &result, info, info->wm_char );
else
ret = send_inter_thread_message( info, &result );
}
SPY_ExitMessage( SPY_RESULT_OK, info->hwnd, info->msg, result, info->wparam, info->lparam );
if (ret && res_ptr) *res_ptr = result;
return ret;
}3、send_inter_thread_message
把消息放到目标线程的消息队列,并等待消息处理完成。
static LRESULT send_inter_thread_message( const struct send_message_info *info, LRESULT *res_ptr )
{
size_t reply_size = 0;
TRACE( "hwnd %p msg %x (%s) wp %lx lp %lx
",
info->hwnd, info->msg, SPY_GetMsgName(info->msg, info->hwnd), info->wparam, info->lparam );
USER_CheckNotLock();
if (!put_message_in_queue( info, &reply_size )) return 0;
/* there"s no reply to wait for on notify/callback messages */
if (info->type == MSG_NOTIFY || info->type == MSG_CALLBACK) return 1;
wait_message_reply( info->flags );
return retrieve_reply( info, reply_size, res_ptr );
}
这里面的函数涉及到了更底层的调用,等以后理解深刻了再分析吧。声明:该文观点仅代表作者本人,入门客AI创业平台信息发布平台仅提供信息存储空间服务,如有疑问请联系rumenke@qq.com。
