I have a suggestion for how to make the CMessageLoop class more useful. So what is wrong with current implementation?
I have a program where I use the CMainFrame::OnIdle event to handle ribbon/ menu/toolbar states - basically extending the UIUpdateToolBar function generated by the Wizard. In my implementation I send a window user message (WM_QUERYINTERFACE) to underlying windows. To my surprise, the OnIdle event newer stops coming (if I don’t send messages, it does). The reason for this is that CMessageLoop::IsIdleMessage consider my WM_QUERYINTERFACE to be a GUI changing message and turns idle on (CMessageLoop::bDoIdle = TRUE).
Ok, that’s easy to fix – override CMessageLoop::IsIdleMessage and add my message to the no- idle-messages. But no, IsIdleMessage is static! It cannot be overridden!
In my suggestion I have removed the function CMessageLoop::Run. I have also removed virtual on PreTranslateMessage and OnIdle – turning this class into a concrete base class with no vtable. Finally I renamed the class to CMessageLoopBase (e.g.). This implies that the class CAppModule must be changes as well (it must refer to CMessageLoopBase and not CMessageLoop).
I have then created a new template class CMessageLoopT, containing a slight modification of CMessageLoop::Run.
And finally a concrete class CMessageLoop, the default message loop class.
Here is an example of use:
*class CMyMessageLoop
: public CMessageLoopT<cmymessageloop>
{
public:
BOOL IsIdleMessage(MSG</cmymessageloop> pMsg)
{
if (!super::IsIdleMessage(pMsg))
return FALSE;
switch (pMsg->message)
{
case WM_QUERYINTERFACE:
case WM_KICKIDLE:
case WM_TIMER:
case 0x8002:
return FALSE;
}
return TRUE;
}
} theLoop;
_Module.AddMessageLoop(&theLoop);
So what are pros and cons?
Pros:
Cons:
Anonymous
View and moderate all "feature-requests Discussion" comments posted by this user
Mark all as spam, and block user from posting to "Feature Requests"
Opps, wrong file attached above.
This proposal is excellent and in the spirit of WTL design. I would gladly use it, but... it would require code changes in code emitted by the AppWizard (use of CMessageLoopBase ptr instead of CMessageLoop ptr). It would require changes in all existing projects. It would also break all custom message loop implementations.
Because of that I went the other way and made IsIdleMessage() virtual. Now it is easy to override it in a derived class. It will cost us one more vtable entry. Before we were always trying to avoid that, but I think that now we can be a bit more generous.
Note: Be careful with idle processing, it can easily slow down the app.
Commit: https://sourceforge.net/p/wtl/git/ci/6cf1e60ab290ec5660297b14942e432b6b18878f/