![](/img/trans.png)
[英]MFC dialog-based app with tab control - Visual Studio bugs/restrictions make recommended path impossible?
[英]MFC's dialog-based app title bar highlighting visual artifacts on Windows 10 (i.e. bugs in CDialogEx)
我設法復制你的問題並找到了一個快速解決方案。 您需要將WM_ACTIVATE消息處理程序添加到主對話框中,注釋掉基類OnActivate並將其修改為:
void CMFCApplication1Dlg::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
//CDialogEx::OnActivate(nState, pWndOther, bMinimized);
// TODO: Add your message handler code here
this->Default();
}
需要CWnd :: Default調用以保持默認按鈕的活動/非活動可視化。
好的,盡管我很欣賞@VuVirt的解決方案,但它並沒有完全刪除VS2017中基於對話框的默認解決方案中提供的所有錯誤。 它解決了標題欄焦點問題,但在繼續開發我的項目時,我遇到了另一個錯誤。 所以我將它從我的評論中復制並粘貼到他的答案中:
那里還有一些搞砸了。 我不確定它是否與此修復有關。 例如:如果你創建一個按鈕,然后在其處理程序中嘗試執行:CFileDialog d(TRUE,NULL,NULL,OFN_HIDEREADONLY | OFN_EXPLORER,NULL,this); d.DoModal(); 打開文件選擇器對話框。 打開文件選擇器時,關閉它並查看父MFC對話框窗口的標題欄是否恢復活動狀態。 在我的情況下,它一直處於非活動狀態,直到我點擊Windows任務欄然后再回到那個MFC應用程序。
在我的頭撞到牆上試圖看看那里發生了什么后,我決定嘗試@ zett42在我原來的問題的評論中提出的早期解決方案(即用CDialog替換CDialogEx)並且它有效! 所有的錯誤都消失了!
所以這是我的判決: CDialogEx
是錯誤的。
解決方案非常簡單:當您創建一個新的基於對話框的項目時,使用項目范圍的查找和替換(在編輯菜單中)並用CDialog
替換所有出現的CDialogEx
。 就是這樣。 (我嘗試使用VS2017的重構工具,但它搞砸了並沒有全部替換它。這樣簡單的搜索和替換工作。)
如果你認為沒有CDialogEx
就會缺少某些功能,那么你就不會。 它所做的一切(除了引入錯誤)是它為對話框添加了背景圖像和顏色。
因此,在MS修復模板中那些明顯的錯誤之前,我堅持使用這種方法。
這似乎是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
早期問題的補丁。 但它會在其他地方引起問題,例如在CDialogEx
使用CFileDialog
時
建議的解決方案:
修改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
保持OnNcActivate
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.