simulate OnIdle in MFC ActiveX control

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 + 0x12 0x34 0x56 ));
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.

你可能感兴趣的:(simulate OnIdle in MFC ActiveX control)