I have a (large) application that works perfectly under XP. When I run it under Windows 7 the "File Edit View..." menu in my application flickers when everything is otherwise idle.
I have traced this down to SetTimer and its associated OnTimer function. OnTimer usually does nothing, so I have commented out everything leaving this:
Code:
void MyView::OnTimer(UINT nIDEvent) { }
I have also changed the SetTimer call to give one tick every five seconds.
I now see the same behaviour: the File menu is very briefly greyed-out every five seconds, leading to the flicker. Nothing else in the window is exhibiting this flicker.
So, I have a call to a null function every five seconds that manages to affect a menu.
The call to the base class was in the original code that was commented out. Putting it back in makes no difference.
WM_INITMENUPOPUP messages are not mentioned in the code.
OnUpdate is handled for all of the menu items. Interestingly, commenting out the code for the File update stops the flicker.
It seems this is getting called each time the timer ticks, but why?
OnUpdate is handled for all of the menu items. Interestingly, commenting out the code for the File update stops the flicker.
It seems this is getting called each time the timer ticks, but why?
IIRC, the OnUpdate functions are called each time the message loop is idle (i.e. all messages have been processed). It could be that the code in your OnUpdate functions is too slow. Maybe you could refactor the code such that you store the state that you need in these functions and update the state whenever it changes.
E.g. in your main frame class you have a bool m_IsCalculating and you have a menu item called 'Calculate' that you update as
Whenever you start a calculation (in a worker thread, of course) you set the bool to true and when the calculation is complete you set it back to false.
Cheers, D Drmmr
Please put [code][/code] tags around your code to preserve indentation and make it more readable.
As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky
That's essentially what I have. Unfortunately the simple call to Enable resulted in the menu never being re-enabled,
so the code grew other stuff and that is probably causing the problem. I can inhibit it in most cases, so that's what I shall do.
So whenever the message loop empties, all sorts of stuff is called 'just in case'?
Does anyone else get the feeling that all of this is very ad hoc and not well designed?
The flickering comes when the LastRunning tests are removed, clearly caused by DrawMenuBar.
Removing the call on DrawMenuBar altogether results in the File menu item remaining greyed-out even when Running becomes false until the cursor moves over it.
Why do you update the item in the menu bar (and redraw the whole bar as well) from within the message handler for some submenu item?
It will only be called in response on the user action like clinking on the menu item in the menu bar!
Perhaps, you'd implement something like what was suggested in this thread?
The thread you reference seems to be suggesting what I am already doing.
Unless I've missed something, the handler is not only called when the user clicks a menu item; as discussed earlier it is called when the message loop becomes empty.
I'm not sure where submenu items appeared from; the item in question is a handler for 'File' in the main menu.
The event that causes the menu item to be enabled is not a user action but something external.
The code in its current form is the result of a long and tedious process to get something to work. I would much prefer a simpler solution, but this is the only thing that I have found to give acceptable results.
No, OnUpdate... message handlers for menu items are called from within the CFrameWnd::OnInitMenuPopup message handler (if OnUpdate... for the the submenu items exist). See http://www.microsoft.com/msj/0299/c/c0299.aspx
For ControlBars (toolbar, statusbar, ...) OnUpdate... handler are called from OnIdle.
So whenever the message loop empties, all sorts of stuff is called 'just in case'?
Does anyone else get the feeling that all of this is very ad hoc and not well designed?
Not 'just in case', it is called when necessary. I was inaccurate about the call to OnUpdate....
As Victor said, OnUpdate... for a submenu item is only called when that menu is opened (and, thus, the item becomes visible). See this for more info: http://social.msdn.microsoft.com/For...-5795ebdaf7d8/
Cheers, D Drmmr
Please put [code][/code] tags around your code to preserve indentation and make it more readable.
As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky
The flickering comes when the LastRunning tests are removed, clearly caused by DrawMenuBar.
Removing the call on DrawMenuBar altogether results in the File menu item remaining greyed-out even when Running becomes false until the cursor moves over it.
Ok, so this is the handler function for the (top-level) File menu item, right? Then all you should need is the call to pCmdUI->Enable(...).
Whenever you change Running, you may need to call DrawMenuBar to make 100% sure that the menu will be updated. It will also be updated after the user moves the mouse and OnIdle is called again.
You are changing Running only from the main thread, right? Not from a worker thread?
Taking a step back, my main question now is: why do you want to disable the File menu? As a user I can understand not being able to open, save or close a file while the application is busy, but why should I not be allowed to open the File menu?
Cheers, D Drmmr
Please put [code][/code] tags around your code to preserve indentation and make it more readable.
As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky
Bookmarks