標準 CStatusBar 不支援直接加入子控制項。本文介紹將按鈕/編輯控制項作為狀態列「姊妹視窗」加入主框架的技巧,並附贈 Windows 2000 環境下終止螢幕保護程式的解決方案。
控制項不是狀態列的子視窗,而是與狀態列、工具列、視圖同層的主框架子視窗。透過 OnSize 手動定位即可。
// CMainFrame 成員
CButton m_wndBtnAbout; // ID_APP_ABOUT,自動連結 Help→About 命令
// OnCreate 中建立
m_wndBtnAbout.Create("About", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
CRect(0,0,0,0), this, ID_APP_ABOUT);
// OnSize 中定位(填入狀態列被壓縮的空間)
void CMainFrame::OnSize(UINT nType, int cx, int cy) {
CFrameWnd::OnSize(nType, cx, cy);
RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);
CRect rc; m_wndStatusBar.GetItemRect(0, &rc); // 取得第一個窗格矩形
m_wndBtnAbout.MoveWindow(&rc); // 按鈕填滿該窗格
}
// MFC 硬編碼邏輯
if (pParentWnd->GetStyle() & WS_THICKFRAME)
dwStyle |= SBARS_SIZEGRIP;
有 WS_THICKFRAME 時強制加入調整把手,導致按鈕左側出現多餘把手。
ModifyStyle(WS_THICKFRAME, 0); // 關閉厚邊框
m_wndStatusBar.Create(this); // 建立狀態列(不加把手)
ModifyStyle(0, WS_THICKFRAME); // 還原厚邊框
雖屬「業餘手法」但有效。正式做法可衍生 CMyStatusBar 重寫 Create。
// ID_VIEW_STATUS_BAR 命令處理
void CMainFrame::OnViewStatusBar() {
CFrameWnd::OnViewStatusBar();
m_wndBtnAbout.ShowWindow(m_wndStatusBar.IsWindowVisible() ? SW_SHOW : SW_HIDE);
}
WM_ERASEBKGND 填補中間空白COLOR_3DFACEOnCmdMsg 轉發命令至父視窗Win2000 引入桌面隔離,螢幕保護程式運行於 "Screen-Saver" 桌面,GetActiveWindow/GetForegroundWindow 找不到視窗。
HDESK hDesk = OpenDesktop("Screen-saver", 0, FALSE, GENERIC_ALL);
if (hDesk) {
EnumDesktopWindows(hDesk, EnumProc, 0);
CloseDesktop(hDesk);
}
BOOL CALLBACK EnumProc(HWND hwnd, LPARAM lParam) {
PostMessage(hwnd, WM_CLOSE, 0, 0);
return TRUE;
}
int cx = GetSystemMetrics(SM_CXSCREEN);
int cy = GetSystemMetrics(SM_CYSCREEN);
// 多螢幕支援
int vcx = GetSystemMetrics(SM_CXVIRTUALSCREEN);
int vcy = GetSystemMetrics(SM_CYVIRTUALSCREEN);
狀態列擴充採用「姊妹視窗 + OnSize 定位」模式,解決 MFC 硬編碼限制。螢幕保護程式終止需理解桌面隔離架構。GetSystemMetrics 是取得系統尺寸的萬用鑰匙,建議徹底掌握其參數變化。