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\n", 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 ); }这里面的函数涉及到了更底层的调用,等以后理解深刻了再分析吧。