I had a very strange problem when a window seems to erase its contents, rather than redrawing it after erasing it. This dialog is derived from CDHtmlDialog , which I think is part of the problem. There is some kind of uninterrupted code execution that leads to some code being executed before others in some cases, and vice versa in others.
Message handlers that are involved:
BEGIN_MESSAGE_MAP(CCalcDrillDownDlg, CDHtmlDialog) ON_WM_PAINT() END_MESSAGE_MAP() BEGIN_EVENTSINK_MAP(CCalcDrillDownDlg, CDHtmlDialog) ON_EVENT(CCalcDrillDownDlg, AFX_IDC_BROWSER, 250 , _OnBeforeNavigate2b, VTS_DISPATCH VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PBOOL) END_EVENTSINK_MAP()
The OnInitDialog() function is as follows:
BOOL CCalcDrillDownDlg::OnInitDialog() { SetHostFlags(DOCHOSTUIFLAG_FLAT_SCROLLBAR); CDHtmlDialog::OnInitDialog();
This is the OnPaint() function:
void CCalcDrillDownDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDHtmlDialog::OnPaint(); } }
I did not put the contents of the _OnBeforeNavigate2b() function, since it has nothing to do with the redraw system.
So what happens is that sometimes the contents of the dialog will somehow be colored before calling CCalcDrillDownDlg::OnPaint() . If this happens, calling CDHtmlDialog::OnPaint() wipe the contents from the window.
In other cases, the content is not painted on the window before calling CCalcDrillDownDlg::OnPaint() . If this happens, then calling CDHtmlDialog::OnPaint() will probably wipe the contents from a window that has not been painted yet, and then, after calling CCalcDrillDownDlg::OnPaint() , it will be redrawn.
Spy ++ does not record any messages when the system correctly redraws the window, so I deleted messages created from this question.
Does anyone have any ideas on how redrawing is done and why the order sometimes gets foobarred?
Edit
Here is the contents of the IDR_CALC_DRILLDOWN resource:
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Calculation Drilldown</title> <style type="text/css"> body { overflow-y: auto; font-family: arial, Helvetica, sans-serif; font-size: 90%; } a:link { color: black; } a:visited { color: black; } table { border-collapse: collapse; } tr.runcache td { background-color: #B5B5B5; color: black; } tr.runcache td a:link { color: black; } tr.runcache td a:visited { color: black; } tr.tracker td { background-color: white; color: black; } tr.tracker td a:link { color: black; } tr.tracker td a:visited { color: black; } td.numericvalue { text-align: right; } tr.paramTitle td { background-color: #4A4A4A; color: white; } tr.resultTitle td { background-color: #4A4A4A; color: white; } tr.resultTitle td a:link { color: white; } tr.resultTitle td a:visited { color: white; } tr.param td { background-color: white; color: black; } tr.param td a:link { color: black; } tr.param td a:visited { color: black; } span.selection { background-color: #EBEBEB; } </style> </head> <body> <div id="calculation"></div> <div id="details" style="padding-left: 0.1in; display: none;"></div> </body> </html>
Edit # 2
Further research shows that the CDHtmlDialog class (or its base class) will draw a window regardless of whether my CCalcDrillDownDlg::OnPaint() CDHtmlDialog::OnPaint() or not, which is just weird and unintuitive. :(
It also seems to be related to threads, as it depends on how long it takes to render the window. If it takes a short time, it displays normally. If it takes half a second or more, it drags on.
m_bRepaint now I'm using a workaround where I have the m_bRepaint flag in the class originally set to true . When calling CCalcDrillDownDlg::OnPaint() and is not signed, I check the flag and force it to resize. This is not optimal since it causes an initial flicker, but at least it ensures that the contents of the window are drawn.
if (!m_bRepaint) { CDHtmlDialog::OnPaint(); } else { CRect winRect; GetWindowRect(&winRect); SetWindowPos(NULL, 0, 0, winRect.Width() - 1, winRect.Height(), SWP_NOMOVE | SWP_NOZORDER); SetWindowPos(NULL, 0, 0, winRect.Width() , winRect.Height(), SWP_NOMOVE | SWP_NOZORDER); m_bRepaint = false; }
Using Invalidate() does not work. I have to resize it to some other than the current size, and resize it.
This CDHtmlDialog class is PITA to work with, and I would not recommend anyone use it if they have a choice.