Ich habe dieses sehr seltsame Problem, bei dem ein Fenster scheint, seinen Inhalt zu löschen und es nach dem Löschen nicht neu zu zeichnen. Dieser Dialog ist von CDHtmlDialog
abgeleitet, was ich für einen Teil des Problems halte. Es gibt eine Art von nicht-deterministischer Codeausführung, die dazu führt, dass Code in bestimmten Fällen vor anderen ausgeführt wird und in anderen umgekehrt.Warum sollte ein Dialog seinen Inhalt löschen, ohne ihn zu aktualisieren?
Message-Handler, die beteiligt sind, sind:
BEGIN_MESSAGE_MAP(CCalcDrillDownDlg, CDHtmlDialog)
ON_WM_PAINT()
END_MESSAGE_MAP()
BEGIN_EVENTSINK_MAP(CCalcDrillDownDlg, CDHtmlDialog)
ON_EVENT(CCalcDrillDownDlg, AFX_IDC_BROWSER, 250 /* BeforeNavigate2 */, _OnBeforeNavigate2b, VTS_DISPATCH VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PBOOL)
END_EVENTSINK_MAP()
Die OnInitDialog()
Funktion ist wie folgt:
BOOL CCalcDrillDownDlg::OnInitDialog()
{
SetHostFlags(DOCHOSTUIFLAG_FLAT_SCROLLBAR);
CDHtmlDialog::OnInitDialog(); // << will eventually call _OnBeforeNavigate2b()
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
LoadFromResource(IDR_CALC_DRILLDOWN); // << will eventually call _OnBeforeNavigate2b()
CString title = getStr2Ptr(22574);
SetWindowText(title);
ShowWindow(SW_SHOW);
return TRUE; // return TRUE unless you set the focus to a control
}
Dies ist die OnPaint()
Funktion ist:
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();
}
}
ich nicht habe setzen der Inhalt der _OnBeforeNavigate2b()
Funktion, wie es scheint, nicht zu ha habe etwas mit dem Neuzeichnen zu tun.
So scheint es, dass manchmal der Dialoginhalt vor dem Aufruf von CCalcDrillDownDlg::OnPaint()
irgendwie gemalt wird. Wenn dies geschieht, löscht der Aufruf von CDHtmlDialog::OnPaint()
den Inhalt aus dem Fenster.
Andere Zeiten, die Inhalte sind nicht auf dem Fenster vor dem Aufruf CCalcDrillDownDlg::OnPaint()
gemalt. Wenn das passiert, wird der Aufruf von CDHtmlDialog::OnPaint()
wahrscheinlich noch den Inhalt des Fensters löschen, das noch nicht gemalt wurde, und dann irgendwann nach dem Aufruf von CCalcDrillDownDlg::OnPaint()
wird es neu gezeichnet.
Spy ++ erfasst keine Nachrichten, wenn das System das Fenster ordnungsgemäß neu erstellt, daher habe ich die von dieser Frage generierten Nachrichten entfernt.
Hat jemand eine Idee, wie das Neuzeichnen durchgeführt wird und warum die Bestellung manchmal foobarred wird?
bearbeiten
Hier ist der Inhalt der IDR_CALC_DRILLDOWN
Ressource:
<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
Weitere Untersuchungen zu zeigen scheint, dass die CDHtmlDialog Klasse (oder eine Basisklasse davon) zeichnen das Fenster, unabhängig davon, ob meine CCalcDrillDownDlg::OnPaint()
CDHtmlDialog::OnPaint()
ruft oder nicht, was einfach komisch und nicht intuitiv ist. :(
Es scheint auch, dass dies möglicherweise threading-bezogen ist, da dies davon abhängt, wie lange es dauert, um das Fenster zu rendern. Wenn es eine kurze Zeit dauert, zeigt es fein. Wenn es eine halbe dauert Sekunde oder mehr, es vermasselt.
im Moment bin ich eine Abhilfe verwenden, wo ich eine m_bRepaint
Flagge in der Klasse haben, die zunächst auf true
gesetzt. nach CCalcDrillDownDlg::OnPaint()
Aufruf und es ist nicht ikonischen, überprüfe ich die flag und erzwinge eine Größenänderung Dies ist nicht optimal, da es ein anfängliches Flimmern verursacht, aber es stellt zumindest sicher, dass der Inhalt des Fensters gezeichnet wird
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;
}
Die Verwendung von Invalidate()
funktioniert nicht.Ich muss es auf etwas anderes als seine gegenwärtige Größe ändern und es zurück ändern.
Diese CDHtmlDialog
Klasse ist ein PITA zu arbeiten, und ich würde niemandem empfehlen, es zu verwenden, wenn sie die Wahl haben.
Ohne [mcve] können wir nur raten. – theB
@theB, wenn ich das tun könnte, wäre ich prolly fertig. Einige mögliche Vorschläge wären nett. – Adrian
Wenn Sie kein [mcve] bereitstellen können, geben Sie bitte das entsprechende Code-Snippet an. –