http://demo.netfoucs.com/autumn20080101/article/details/9032093

由SendMessageTimeout想到的。SendMessageTimeout 和 SendMessage

|2013-06-05 16:32 |939人阅读

 
分类: MFC2011-04-17 20:32 1774人阅读 评论(0) 收藏 举报

SendMessageTimeout 和 SendMessage

闲来无事,查找下如何实现修改注册表立即生效的功能。下面举个例子:比如修改光盘为不自动运行,如果单单通过写注册项修改NoDriveTypeAutorun属性,则要使其生效必须重起电脑,但是TweakUI就可以立即生效,到网上查发现必须先通知Windows外壳更新信息。

最后去MSDN查了一下SendMessageTimeOut,觉得可以一试,结果还真成功了,呵呵
下面是我修改系统 Policy 设置后实现立即生效的方法:
SendMessageTimeout(HWND_BROADCAST,WM_SETTINGCHANGE,NULL,(LPARAM)(LPTSTR)lpD­ata,SMTO_NORMAL,1000,&dwResult);

LRESULT WINAPI SendMessageTimeout(

  __in       HWND hWnd,

  __in       UINT Msg,

  __in       WPARAM wParam,

  __in       LPARAM lParam,

  __in       UINT fuFlags,

  __in       UINT uTimeout,

  __out_opt  PDWORD_PTR lpdwResult

);

 

参数说明:

.常量 HWND_BROADCAST, "65535"
.常量 SMTO_NORMAL, "0"
.常量 WM_SETTINGCHANGE, "26"

.DLL命令 SendMessageTimeout, 整数型, "user32", "SendMessageTimeoutA", , 
     .参数 hWnd, 整数型, , 要接收消息的一个窗口的句柄
     .参数 Msg, 整数型, , 消息的标识符
     .参数 wParam, 整数型, , 由消息决定
     .参数 lParam, 整数型, , 由消息决定
     .参数 fuFlags, 整数型, , 下述常数的一个或多个;SMTO_ABORTIFHUNG:如目标进程挂起,则函数立即返回;SMTO_BLOCK:除非函数返回,否则调用线程不能处理消息;SMTO_NORMAL:允许调用线程处理消息,同时保持函数继续执行
     .参数 uTimeout, 整数型, , 超时值,采用毫秒为单位
     .参数 lpdwResult, 整数型, 传址, 用于装载函数结果的一个变量;

这个API函数可以帮你通知底层应用程序更新注册表中 Policies 和 Enviroment 相关的所有注册项。

 

在这里不得不得说下,SendMessageTimeout 的功能。

MSDN:

Sends the specified message to one or more windows.

SendMessageTimeout并不是简单在SendMessage加上Timeout的功能。MSDN上面有一段文字是这样说的
If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine. If the specified window was created by a different thread, the system switches to that thread and calls the appropriate window procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code. The sending thread is blocked until the receiving thread processes the message. However, the sending thread will process incoming nonqueued messages while waiting for its message to be processed. To prevent this, use SendMessageTimeout with SMTO_BLOCK set. For more information on nonqueued messages, see Nonqueued Messages. 
SendMessage : 如果指定窗口由调用线程创建,那么窗口过程会被当成一个子程序立即调用。如果指定窗口由另外一个线程创建,那么系统会切换到那个线程,并且调用合适的窗口过程。在线程之间传递的消息仅仅当接收线程执行message retrieval code才会被处理。发送线程会被堵塞直到接收线程处理完消息。但是,发送线程在等待的同时会处理收到的nonqueued messages 。为了阻止这一点,使用带有SMTO_BLOCK参数 的SendMessageTimeout .

我遇到这个问题,我调用SendMessage向另外一个线程窗口发message,本来以为他会一直block住,但是他却调用了另外一个消息的处理程序,导致了行为不正确。所以一定要小心使用SendMessage发给其他线程的窗口。

修改了一下:pWnd->SendMessage(MSG_LOG_MESSAGE, nMsgType, (LPARAM)(LPCTSTR)m_cstrMessage);
改成了
HWND hWnd = pWnd->GetSafeHwnd();
::SendMessageTimeout(hWnd,MSG_LOG_MESSAGE, nMsgType, (LPARAM)(LPCTSTR)m_cstrMessage,SMTO_BLOCK,15000,0);
解决了这个bug.