MFC 預設浮動工具列會在標題列顯示「關閉」按鈕 (系統選單)。若需求不允許使用者關閉特定工具列,必須在浮動狀態下移除父框架視窗 (CMiniFrameWnd) 的 WS_SYSMENU 風格。本文提供一個優雅的 CToolBarEx 派生類實現方案,自動偵測浮動狀態並動態切換關閉按鈕顯示。
→
圖一:預設有關閉按鈕 → 圖二:移除關閉按鈕後
WM_WINDOWPOSCHANGED 判斷浮動狀態為何不用 WM_SIZE?因為浮動工具列移動位置不一定觸發 Size,但 WM_WINDOWPOSCHANGED 只要位置、大小、Z 序任一改變必觸發。利用 CControlBar::IsFloating() 判斷浮動,透過 m_pDockBar->GetParent() 取得 CMiniFrameWnd 指標,修改其風格。
CToolBarExclass CToolBarEx : public CToolBar
{
BOOL m_bMenuRemoved = FALSE; // 標記是否已移除系統選單
protected:
afx_msg void OnWindowPosChanged(WINDOWPOS* lpwndpos);
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(CToolBarEx, CToolBar)
ON_WM_WINDOWPOSCHANGED()
END_MESSAGE_MAP()
void CToolBarEx::OnWindowPosChanged(WINDOWPOS* lpwndpos)
{
CToolBar::OnWindowPosChanged(lpwndpos);
if (IsFloating()) // 浮動狀態
{
if (m_pDockBar && !m_bMenuRemoved) // 有停靠條且未處理過
{
CWnd* pParent = m_pDockBar->GetParent(); // 取得 CMiniFrameWnd
if (pParent && pParent->IsKindOf(RUNTIME_CLASS(CMiniFrameWnd)))
{
pParent->ModifyStyle(WS_SYSMENU, 0, 0); // 移除系統選單風格
m_bMenuRemoved = TRUE;
}
}
}
else if (m_bMenuRemoved) // 重新停靠回主框架
{
m_bMenuRemoved = FALSE; // 重置標記,下次浮動再處理
}
}
CToolBar 改為 CToolBarEx。EnableDocking(CBRS_ALIGN_ANY) + CBRS_SIZE_DYNAMIC)。m_bMenuRemoved,確保再次浮動時能正確處理 (避免 CMiniFrameWnd 重用導致風格殘留)。m_pDockBar、GetParent()、IsKindOf,防止空指標或類型錯誤崩潰。