Это, похоже, ошибка в CDialogImpl::OnActivate
и CDialogImpl::OnNcActivate
:
void CDialogImpl::OnNcActivate(BOOL& bActive)
{
if (m_Dlg.m_nFlags & WF_STAYACTIVE)
bActive = TRUE;
if (!m_Dlg.IsWindowEnabled())
bActive = FALSE;
}
void CDialogImpl::OnActivate(UINT nState, CWnd* pWndOther)
{
m_Dlg.m_nFlags &= ~WF_STAYACTIVE;
CWnd* pWndActive = (nState == WA_INACTIVE) ? pWndOther : &m_Dlg;
if (pWndActive != NULL)
{
BOOL bStayActive = (pWndActive->GetSafeHwnd() == m_Dlg.GetSafeHwnd()
|| pWndActive->SendMessage(WM_FLOATSTATUS, FS_SYNCACTIVE));
if (bStayActive)
m_Dlg.m_nFlags |= WF_STAYACTIVE;
}
else
{
m_Dlg.SendMessage(WM_NCPAINT, 1);
}
}
Это означает, что CDialogEx
может оставаться активным, например,когда отображается CMFCPopupMenu
.
Но m_Dlg.SendMessage(WM_NCPAINT, 1)
является подозрительным вызовом.Использование не соответствует документации для WM_NCPAINT
:
Параметры
wParam
Дескриптор области обновления окна.Область обновления ограничена рамкой окна.
lParam
Этот параметр не используется.
Кроме того, OnNcActivate
имеет переопределение на основеIsWindowEnabled()
.Похоже, это исправление для исправления более ранней проблемы в OnActivate
.Но это вызывает проблемы в других местах, например, при использовании CFileDialog
в CDialogEx
Предлагаемое решение:
Измените CDialogEx::OnActivate
, чтобы запустить процедуру по умолчанию.Или измените его так, чтобы оно вызывало перерисовку.
BOOL CDialogEx::OnNcActivate(BOOL active)
{
if(m_nFlags & WF_STAYACTIVE)
active = TRUE;
return(BOOL)DefWindowProc(WM_NCACTIVATE, active, 0L);
}
void CDialogEx::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
Default();
}
или
void CDialogEx::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
Default();
//save the previous flag
UINT previous_flag = m_nFlags;
m_nFlags &= ~WF_STAYACTIVE;
// Determine if this window should be active or not:
CWnd* pWndActive = (nState == WA_INACTIVE) ? pWndOther : this;
if(pWndActive != NULL)
{
BOOL bStayActive = pWndActive->GetSafeHwnd() == GetSafeHwnd() ||
pWndActive->SendMessage(WM_FLOATSTATUS, FS_SYNCACTIVE);
if(bStayActive)
m_nFlags |= WF_STAYACTIVE;
}
if(previous_flag != m_nFlags && previous_flag & WF_STAYACTIVE)
{
//if the flag is changed,
//and if WF_STAYACTIVE was previously set,
//then OnNcActivate had handled it wrongly, do it again
SendMessage(WM_NCACTIVATE, FALSE); //<- less wrong!
}
}
Это должно работать, например, с CMFCPopupMenu
.Меню MFC откроется без отключения диалога.
Я не уверен, для чего нужен SendMessage(WM_FLOATSTATUS, FS_SYNCACTIVE)
, я не смог его протестировать ... Если это необходимо, кажется, код можно добавить на OnNcActivate
, а затем OnActivate
остается один.