In this article, I want to show a simple workaround for a bug in the MFC Feature Pack, and explain how I arrived at the solution.
When you open the attached application and move your mouse, you will notice that the folder icon of the first edit control flickers heavily.
To find the cause of this problem, I used WinSpector, but Spy++ works as well. Open up Spy++ and show the messages sent to the first edit control. When you move the mouse above the control, you will see many
So let's look up the MFC source code, to find out what the
CMFCEditBrowseCtrl does with the
WM_NCPAINT-Message. The code is located in the file afxeditbrowsectrl.cpp.
OnDrawBrowseButton(&dc, rect, m_bIsButtonPressed, m_bIsButtonHighlighted);
Stepping further into
OnDrawBrowseButton we arive at
CMFCVisualManagerWindows::OnDrawBrowseButton (located in afxvisualmanagerwindows.cpp)
So everythime, the button is drawn via
WM_NCPAINT, the visualmanager first erases the area, and then redraws everything. This causes the flickering.
Many methods of MFC-Feature Pack classes are declared
virtual, so to workaround this issue, we can easily add our own, customized implementation instead.
Using the Code
To remove the flicker, replace the
CMFCEditBrowseCtrl with this fixed implementation:
class CMFCEditBrowseCtrlNoFlicker : public CMFCEditBrowseCtrl
void OnDrawBrowseButton(CDC* pDC, CRect rect, BOOL bIsButtonPressed, BOOL bIsButtonHot) override
CMemDC dc(*pDC, rect);
__super::OnDrawBrowseButton(&dc.GetDC(), rect, bIsButtonPressed, bIsButtonHot);
In this implementation, we use a
CMemDC, i.e., we buffer all drawing commands. So technically, the button is still erased and redrawn many times, but since only the final result is drawn on the screen, the flickering is gone.
- 2018-04-03: First version (skip drawing when flags did not change)
- 2018-04-16: Updated implementation with CMemDC (fixes missing redraw after minimizing the application)