首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

MFC 視窗鎖定技巧:禁止移動、調整大小、分割條拖曳、系統選單操作

     編輯:關於VC++

某些專用應用(如自助終端機、工業控制介面、考試系統)需鎖定視窗狀態,防止使用者移動、調整大小、最大化/最小化、拖曳分割條。本文系統性解決 MFC SDI/MDI 應用程式的視窗鎖定問題,涵蓋非客戶區點擊測試、系統選單清理、狀態列大小控制桿移除、分割視窗鎖定等完整方案。

核心原理:WM_NCHITTEST 攔截

Windows 透過 WM_NCHITTEST 判斷滑鼠位於視窗哪個非客戶區(標題列、邊框、按鈕等)。預設處理返回 HTCAPTION(標題列)、HTLEFT/HTRIGHT(邊框)等代碼,觸發移動/調整大小。重寫此訊息,將不想要的代碼映射為 HTBORDER(不可調整的邊框),即可阻擋操作,同時保持視窗可被點擊激活。


UINT CMainFrame::OnNcHitTest(CPoint point)
{
    UINT hit = CFrameWnd::OnNcHitTest(point);
    static BYTE DisallowCodes[] = {
        HTLEFT, HTRIGHT, HTTOP, HTBOTTOM,
        HTTOPLEFT, HTTOPRIGHT, HTBOTTOMLEFT, HTBOTTOMRIGHT,
        HTSIZE, HTCAPTION
    };
    for (BYTE code : DisallowCodes) {
        if (hit == code) return HTBORDER;
    }
    return hit;
}

系統選單清理

移除「移動」、「大小」、「最小化」、「最大化」、「還原」等選單項:


static UINT BadCommands[] = {
    SC_SIZE, SC_MOVE, SC_MINIMIZE, SC_MAXIMIZE, SC_RESTORE, 0
};
CMenu* pSysMenu = GetSystemMenu(FALSE);
for (int i = 0; BadCommands[i]; i++) {
    pSysMenu->RemoveMenu(BadCommands[i], MF_BYCOMMAND);
}

標題列按鈕移除


BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
    cs.style &= ~(WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
    return CFrameWnd::PreCreateWindow(cs);
}

狀態列大小控制桿移除

狀態列右下角的三角形控制桿由 WS_THICKFRAME 風格決定。在建立狀態列前暫時移除此風格,建立完成後恢復:


int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1;

    ModifyStyle(WS_THICKFRAME, 0);          // 移除粗框架
    m_wndStatusBar.Create(this);            // 建立狀態列(無控制桿)
    ModifyStyle(0, WS_THICKFRAME);          // 恢復粗框架

    return 0;
}

原理:MFC 在 CStatusBar::Create() 時檢查視窗風格決定是否建立大小控制桿。欺騙 MFC 可一次解決,事後無 API 可動態移除控制桿。

分割視窗鎖定

自訂 CSplitterWnd 衍生類別,重寫滑鼠訊息直接返回:


class CMySplitterWnd : public CSplitterWnd {
    void OnLButtonDown(UINT, CPoint) { return; }  // 禁止拖曳
    void OnMouseMove(UINT, CPoint) { return; }    // 禁止游標變更
    // DoKeyboardSplit 由選單命令觸發,直接從選單移除「視窗|分割」即可
};

對應 CSplitterWnd 原始碼邏輯:

  • OnLButtonDown → HitTest() → StartTracking()
  • OnMouseMove → 設定分割游標(雙向箭頭)

完整鎖定檢查清單

操作途徑阻擋方法
標題列拖曳移動WM_NCHITTEST 映射 HTCAPTION → HTBORDER
邊框拖曳調整大小WM_NCHITTEST 映射 HTLEFT/HTRIGHT/HTSIZE 等 → HTBORDER
最大化/最小化按鈕PreCreateWindow 移除 WS_MINIMIZEBOX/WS_MAXIMIZEBOX
系統選單命令OnCreate 移除 SC_MOVE/SC_SIZE/SC_MINIMIZE/SC_MAXIMIZE/SC_RESTORE
狀態列大小控制桿建立狀態列前暫時移除 WS_THICKFRAME
分割條拖曳CSplitterWnd 衍生類重寫 OnLButtonDown/OnMouseMove
鍵盤分割命令資源編輯器移除「視窗|分割」選單項

注意事項

  • 過度限制視窗操作會嚴重損害使用者體驗,僅限專用場景使用
  • Dialog-based 應用同樣適用 WM_NCHITTEST 技巧
  • 多顯示器環境下 HTBORDER 行為一致
  • 若需保留特定功能(如最小化),從 DisallowCodes 移除對應代碼即可

結語

透過 WM_NCHITTEST 攔截非客戶區點擊、清理系統選單、欺騙狀態列建立邏輯、重寫分割視窗滑鼠處理,可構建完全鎖定的 MFC 主視窗。這套方案在工業自動化、資訊安全終端、公開資訊查詢系統等領域經實戰驗證可靠。完整範例程式碼請參考附件專案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved