У меня возникает эта очень странная проблема, когда окно, кажется, стирает его содержимое, а не перерисовывает его после его стирания. Этот диалог получен от CDHtmlDialog
, который, я думаю, является частью проблемы. Существует какое-то неиндексинированное выполнение кода, приводящее к тому, что некоторый код выполняется до других в некоторых случаях, а наоборот - в других.Зачем было удалять содержимое без обновления?
обработчики сообщений, которые участвуют являются:
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()
OnInitDialog()
функция выглядит следующим образом:
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
}
Это OnPaint()
функция:
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();
}
}
Я не поставил содержимое функции _OnBeforeNavigate2b()
, как представляется, не га что-нибудь связанное с системой перерисовки.
Так что, похоже, что иногда содержимое диалогового окна будет как-то окрашено до вызова CCalcDrillDownDlg::OnPaint()
. Если это произойдет, вызов CDHtmlDialog::OnPaint()
уничтожит содержимое окна.
В других случаях содержимое не окрашивается в окно перед вызовом CCalcDrillDownDlg::OnPaint()
. Если это произойдет, то вызов CDHtmlDialog::OnPaint()
, вероятно, по-прежнему будет вычищать содержимое из окна, которое еще не было нарисовано, а затем после вызова CCalcDrillDownDlg::OnPaint()
оно перерисовывается.
Spy ++ не записывает никаких сообщений, когда система правильно перерисовывает окно, поэтому я удалил сообщения, созданные из этого вопроса.
Есть ли у кого-нибудь идеи относительно того, как выполняется перерисовка, и почему заказ иногда становится foobarred?
Редактировать
Вот содержимое IDR_CALC_DRILLDOWN
ресурса:
<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
Дальнейшие исследования, кажется, показывают, что класс CDHtmlDialog (или базовый класс их) будет рисовать в окне, независимо от того, звонит ли мой CCalcDrillDownDlg::OnPaint()
CDHtmlDialog::OnPaint()
или нет, что просто странно и не интуитивно. :(
Кроме того, похоже, что это связано с потоками, поскольку это, похоже, зависит от того, сколько времени потребуется для визуализации окна. Если это занимает короткое время, оно отображает штраф. Если это занимает половину второй или более, он щурит.
на данный момент, я использую обходной путь, где у меня есть m_bRepaint
флага в классе, который изначально установлен на true
. После вызова CCalcDrillDownDlg::OnPaint()
и это не культовое, я проверить флаг и принудительное изменение размера.Это не оптимально, поскольку оно вызывает начальное мерцание, но по крайней мере оно гарантирует, что содержимое окна будет нарисовано.
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;
}
Использование Invalidate()
не работает.Я должен изменить его размер на другой, чем текущий размер, и изменить его размер.
Этот класс CDHtmlDialog
является PITA для работы, и я бы не рекомендовал никому его использовать, если у них есть выбор.
Без [mcve] мы можем только догадываться. – theB
@theB, если бы я мог это сделать, я бы сделал это. Некоторые возможные предложения были бы приятными. – Adrian
Если вы не можете предоставить [mcve], предоставьте соответствующий фрагмент кода. –