brent's hut

simulate OnIdle in MFC ActiveX control

There are two ways to do this, one is simple, another is complicated but more powerful.

Method A:
::SetWindowsHookEx(WH_FOREGROUNDIDLE, YourIdleProc, AfxGetInstanceHandle(), GetCurrentThreadId());

Method B (my way):
 1 static HHOOK s_hGetMsgHook = NULL;
 2 
 3 LRESULT FAR PASCAL GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
 4 {
 5     AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
 6 
 7     LPMSG lpMsg = (LPMSG) lParam;
 8     if( (nCode >= 0&& PM_REMOVE == wParam)
 9     {
10         //your code here. maybe to deal with hot-keys, accelerators ...
11         //see http://support.microsoft.com/kb/187988
12 
13         //my code to simulate OnIdle
14         static BOOL bIdle = FALSE;
15         CWinApp* pApp = AfxGetApp();
16         if(!bIdle && pApp->IsIdleMessage(lpMsg))
17             bIdle = TRUE;
18         
19         if(bIdle)
20         {
21             MSG msgPeek = {0};
22             if(!::PeekMessage(&msgPeek, NULL, NULL, NULL, PM_NOREMOVE))
23             {
24                 VERIFY(PostMessage(AfxGetMainWnd()->GetSafeHwnd(), WM_USER+0x120x340x56));
25             }
26         }
27 
28         if(lpMsg->hwnd == AfxGetMainWnd()->GetSafeHwnd() &&
29             lpMsg->message == WM_USER+0x12 && lpMsg->wParam == 0x34 && lpMsg->lParam == 0x56)
30         {
31             lpMsg->message = WM_NULL;
32             lpMsg->lParam = 0L;
33             lpMsg->wParam = 0L;
34 
35             pApp->OnIdle(0);
36             bIdle = FALSE;
37         }
38     }
39 
40     return ::CallNextHookEx(s_hGetMsgHook, nCode, wParam, lParam);
41 }
42 
43 int CYourOleControl::OnCreate(LPCREATESTRUCT lpCreateStruct) 
44 {
45     //...
46     
47     if(NULL == s_hGetMsgHook)
48         s_hGetMsgHook = ::SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, AfxGetInstanceHandle(), GetCurrentThreadId());
49 }
50 
51 void CYourOleControl::OnDestroy() 
52 {
53     //...
54     
55     ::UnhookWindowsHookEx(s_hGetMsgHook);
56     s_hGetMsgHook = NULL;
57 
58     COleControl::OnDestroy();
59 }

Method A is far more simple, but with Method B:

1) You can override CWinApp::IsIdleMessage to filter some special messages, such as a frequent timer which will not affect what you want to do in CWinApp::OnIdle. Because timer will affect message queue and if you don't filter it, OnIdle will be called every time after the timer is invoked.

2) Sometimes your action in OnIdle will affect message queue inevitably, thus you will get a infinite loop: OnIdle->the special messages in message queue->OnIdle->... But with Method B, with SPY++ you can find the special messages, and filter them in IsIdleMessage.

posted on 2010-04-15 15:49 brent 阅读(1655) 评论(0)  编辑 收藏 引用 所属分类: C++WindowsWeb


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理