MFC 預設浮動工具列 (拖離主框架) 右上角會有「關閉」按鈕 (系統選單)。某些應用需移除此按鈕防止使用者誤關。本文透過繼承 `CToolBar` 實作 `CToolBarEx`,攔截視窗位置變更訊息,動態修改父視窗樣式移除 `WS_SYSMENU`。
#pragma once
class CToolBarEx : public CToolBar {
DECLARE_DYNAMIC(CToolBarEx)
public:
CToolBarEx();
virtual ~CToolBarEx();
protected:
BOOL m_bMenuRemoved; // 狀態旗標
afx_msg void OnWindowPosChanged(WINDOWPOS FAR* lpwndpos);
DECLARE_MESSAGE_MAP()
};
#include "StdAfx.h"
#include "ToolBarEx.h"
#include // CMiniFrameWnd 定義
IMPLEMENT_DYNAMIC(CToolBarEx, CToolBar)
BEGIN_MESSAGE_MAP(CToolBarEx, CToolBar)
ON_WM_WINDOWPOSCHANGED()
END_MESSAGE_MAP()
CToolBarEx::CToolBarEx() : m_bMenuRemoved(FALSE) {}
CToolBarEx::~CToolBarEx() {}
void CToolBarEx::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos) {
CToolBar::OnWindowPosChanged(lpwndpos);
// 僅在浮動狀態處理
if (IsFloating()) {
if (m_pDockBar && !m_bMenuRemoved) {
CWnd* pParent = m_pDockBar->GetParent(); // 取得 CMiniFrameWnd
if (pParent->IsKindOf(RUNTIME_CLASS(CMiniFrameWnd))) {
pParent->ModifyStyle(WS_SYSMENU, 0, 0); // 移除系統選單
m_bMenuRemoved = TRUE;
}
}
}
else if (m_bMenuRemoved) { // 重新停駐,重置旗標
m_bMenuRemoved = FALSE;
}
}
在 `MainFrm.h` 修改工具列成員型別:
#include "ToolBarEx.h"
// ...
protected:
CToolBarEx m_wndToolBar; // 原為 CToolBar
| 點 | 說明 |
|---|---|
| 為何用 WM_WINDOWPOSCHANGED | 涵蓋大小、位置、Z 序變更;WM_SIZE 僅大小變更時觸發,浮動拖曳不一定觸發 |
| IsFloating() | CControlBar 成員函式,判斷是否為浮動狀態 |
| m_pDockBar | CControlBar 成員,指向 CDockBar,浮動時其父視窗為 CMiniFrameWnd |
| ModifyStyle(WS_SYSMENU, 0) | 移除 WS_SYSMENU 樣式,即隱藏標題列與關閉按鈕 |
| m_bMenuRemoved 旗標 | 確保僅執行一次,避免重複修改;停駐時重置 |