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

MFC 分割視窗限制分割條移動範圍:重寫 OnMouseMove 實現固定最小寬度

     編輯:關於VC++

需求:CSplitterWnd 分割單文檔視窗為左右兩欄,左欄需設定**最小寬度 228 像素**,防止使用者拖曳分割條過度壓縮左側視圖。MFC 無內建屬性支援,通過重寫 OnMouseMove 攔截拖曳邏輯輕鬆實現。

解決方案:自訂分割視窗類別

1. 繼承 CSplitterWnd


class CMySplitter : public CSplitterWnd
{
    DECLARE_DYNCREATE(CMySplitter)
protected:
    virtual void OnMouseMove(UINT nFlags, CPoint point);
};

2. 重寫 OnMouseMove 限制範圍


void CMySplitter::OnMouseMove(UINT nFlags, CPoint point)
{
    // point 為螢幕座標,需轉換為客戶區座標
    ScreenToClient(&point);
    
    // 限制分割條 X 座標範圍:左欄最小 228、最大 600 (視總寬而定)
    if (point.x < 228 || point.x > 600) {
        // 超出範圍:傳遞給 CWnd 預設處理 (不移動分割條)
        CWnd::OnMouseMove(nFlags, point);
    } else {
        // 範圍內:呼叫基類實作執行實際分割
        CSplitterWnd::OnMouseMove(nFlags, point);
    }
}

關鍵點:

  • ScreenToClient 轉換座標系,point.x 即為分割條目標位置。
  • 範圍值可依視窗總寬動態計算:minX = 228; maxX = GetTotalWidth() - minRightWidth。
  • 呼叫 CWnd::OnMouseMove 而非 CSplitterWnd::OnMouseMove 即可「吃掉」拖曳事件,分割條保持原位。

3. 主框架建立分割視窗


// MainFrm.h
protected:
    CMySplitter m_wndSplitter;

// MainFrm.cpp
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT, CCreateContext* pContext)
{
    if (!m_wndSplitter.CreateStatic(this, 1, 2)) // 1列2行
        return FALSE;
    
    if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CLeftView), 
            CSize(228, 100), pContext) ||  // 初始寬度 228
        !m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CDataEditView), 
            CSize(100, 100), pContext)) {
        m_wndSplitter.DestroyWindow();
        return FALSE;
    }
    return TRUE;
}

進階擴充:動態範圍、比例鎖定、雙向限制


void CMySplitter::OnMouseMove(UINT nFlags, CPoint point)
{
    ScreenToClient(&point);
    
    CRect rectClient;
    GetClientRect(&rectClient);
    int totalWidth = rectClient.Width();
    
    int minLeft = 228;
    int minRight = 150;
    int maxLeft = totalWidth - minRight;
    
    // 可選:鎖定比例 (如左欄固定 30%)
    // int lockedPos = totalWidth * 30 / 100;
    // if (abs(point.x - lockedPos) > tolerance) point.x = lockedPos;
    
    if (point.x < minLeft) point.x = minLeft;
    if (point.x > maxLeft) point.x = maxLeft;
    
    CSplitterWnd::OnMouseMove(nFlags, point);
}

替代方案比較

適用場景

  • 左側導航樹/屬性面板需保證最小可見寬度
  • 右側編輯區需保留最小操作空間
  • 雙欄比例鎖定 (如 3:7) 防止使用者誤調

總結

單一方法重寫 OnMouseMove 即可精確控制 CSplitterWnd 分割條移動範圍,無需 Hook、子類化或複雜訊息處理。配合動態計算 min/max 可適應視窗縮放、DPI 變化。完整 Demo 專案含左右視圖、分割條範圍即時顯示標籤,請下載附件。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
方法優點缺點
重寫 OnMouseMove (本文)簡單、無副作用、即時生效需自行計算座標範圍
處理 WM_SIZING系統級攔截CSplitterWnd 內部不送 WM_SIZING 給分割條
GetMinMaxInfo標準視窗尺寸限制僅對框架視窗有效,分割條不受影響
CSplitterWnd::SetColumnInfo設定理想/最小寬度僅作為 CreateView 參考,拖曳時不強制執行