标签:
http://blog.csdn.net/ysai/article/details/7468961
XP下切换输入法造成程序卡死的原因及解决方案
(by ysai)
现象:
在XP下,如果线程中创建了窗口而线程中没有消息循环,那么可能切换输入法时会造成程序卡死(某些XP下必现,跟安装盘有关)
 
原因:
线程创建一个窗口后,系统会自动创建一个Default IME窗口以便通知输入法消息(可能只有可以接收输入的窗口才会创建,未证实)
XP下切换输入法,会向所有DefaultIME窗口SendMessage告诉应用程序,当前输入法改变了
而线程窗口如果没有消息循环,则不会处理消息队列,然后卡死
 
演示代码:
- TTestThread = class(TThread)  
- private  
-   procedure ProcessMessages;  
- protected  
-   procedure Execute; override;  
- end;  
-   
- procedure TTestThread.Execute;  
- begin  
-   TTimer.Create(nil);  
-   while not Terminated do  
-   begin  
-     DoSomething;
-     
-     Sleep(1);  
-   end;  
- end;  
-   
- procedure TTestThread.ProcessMessages;  
- var  
-   Msg: TMsg;  
- begin  
-   while PeekMessage(Msg, 0, 0, 0,PM_REMOVE) then  
-   begin  
-     TranslateMessage(Msg);  
-     DispatchMessage(Msg);  
-   end;  
- end;  
 
 
程序中使用上面的线程,则在XP下切换输入法可能卡死
即使线程中加入了消息循环,如果在线程工作时DoSomething占用过多时间,也会假死
 
终极解决方案:
如果不能避免在线程中创建窗口(比如调用了某个COM组件,但COM内部创建了窗口,如ADO会创建一个ADODB.AsyncEventMessenger窗口)
则在线程创建窗口后,执行以下代码
- procedure FreeIMEWindow;  
- const  
-   IME_WINDOW_CLASS =‘IME‘;  
-   IME_WINDOW_TEXT = ‘Default IME‘;  
- var  
-   h : HWND;  
-   pid : DWORD;  
-   dh : HWND;  
- begin  
-   if GetCurrentThreadId= 主线程IDthen exit;    
-   h := FindWindow(IME_WINDOW_CLASS, IME_WINDOW_TEXT);  
-   while IsWindow(h) do  
-   begin  
-     ifGetWindowThreadProcessId(h, pid) = GetCurrentThreadId then  
-       dh  :=  h  
-     else  
-       dh  :=  0;  
-     h:=  FindWindowEx(0, h, IME_WINDOW_CLASS, IME_WINDOW_TEXT);  
-     if dh<> 0 then  
-       DestroyWindow(dh);  
-   end;  
- end;  
-   
- procedure TTestThread.Execute;  
- begin  
-   TTimer.Create(nil);  
-   FreeIMEWindow;  
-   while not Terminated do  
-   begin  
-     DoSomething;
-     Sleep(1);  
-   end;  
- end; 
 XP下切换输入法造成程序卡死的原因及解决方案
标签:
原文地址:http://www.cnblogs.com/wxc7009/p/5970111.html