首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

MFC OnSize 實現自動縮放:控件重定位與繪圖映射兩大模式

     編輯:程式設計疑難解答

核心思路

在 OnSize 中實現自動縮放,根據視圖類型選擇兩種模式之一:

模式一:對話框/表單視圖 → 控件重定位


void CMyDialog::OnSize(UINT nType, int cx, int cy) {
    CDialogEx::OnSize(nType, cx, cy);
    if (nType == SIZE_MINIMIZED) return;
    
    // 記錄初始尺寸(OnInitDialog 中初始化)
    if (m_origWidth == 0) { m_origWidth = cx; m_origHeight = cy; return; }
    
    double ratioX = (double)cx / m_origWidth;
    double ratioY = (double)cy / m_origHeight;
    
    // 重定位每個控件
    RepositionCtrl(IDC_EDIT1, ratioX, ratioY, ANCHOR_LEFT | ANCHOR_RIGHT | ANCHOR_TOP);
    RepositionCtrl(IDC_LIST1, ratioX, ratioY, ANCHOR_ALL);
    RepositionCtrl(IDC_BUTTON_OK, ratioX, ratioY, ANCHOR_RIGHT | ANCHOR_BOTTOM);
}

void CMyDialog::RepositionCtrl(int nID, double rX, double rY, DWORD anchor) {
    CWnd* pWnd = GetDlgItem(nID);
    if (!pWnd) return;
    
    CRect rect;
    pWnd->GetWindowRect(&rect);
    ScreenToClient(&rect);
    
    // 根據錨點計算新位置
    if (anchor & ANCHOR_LEFT)   rect.left   = (int)(rect.left * rX);
    if (anchor & ANCHOR_RIGHT)  rect.right  = (int)(rect.right * rX);
    if (anchor & ANCHOR_TOP)    rect.top    = (int)(rect.top * rY);
    if (anchor & ANCHOR_BOTTOM) rect.bottom = (int)(rect.bottom * rY);
    
    // 水平/垂直居中錨點邏輯可擴展
    pWnd->MoveWindow(&rect);
}

模式二:繪圖視圖 (CView) → 映射模式繪圖


void CMyView::OnSize(UINT nType, int cx, int cy) {
    CView::OnSize(nType, cx, cy);
    Invalidate(TRUE); // 觸發重繪
}

void CMyView::OnDraw(CDC* pDC) {
    CRect rect;
    GetClientRect(&rect);
    
    // 方法 A:映射模式(推薦)
    pDC->SetMapMode(MM_ANISOTROPIC);
    pDC->SetWindowExt(1000, 1000);      // 邏輯座標系基準
    pDC->SetViewportExt(rect.Width(), rect.Height());
    pDC->SetViewportOrg(0, 0);
    
    // 繪製代碼使用 0-1000 邏輯座標
    DrawMyGraphics(pDC);
    
    // 方法 B:手動縮放
    // double sx = rect.Width() / 1000.0;
    // double sy = rect.Height() / 1000.0;
    // pDC->Ellipse((int)(100*sx), (int)(100*sy), (int)(300*sx), (int)(300*sy));
}

關鍵區別對照

場景OnSize 中操作核心 API
對話框控件佈局計算比例 → MoveWindow 控件GetWindowRect, ScreenToClient, MoveWindow
視圖繪圖縮放Invalidate 觸發重繪SetMapMode, SetWindowExt, SetViewportExt

常見坑點

  1. 忘記 Invalidate() 導致繪圖視圖縮放後不重繪。
  2. 在 OnDraw 中調用 MoveWindow 觸發無限重繪循環。
  3. 最小化時 cx/cy=0 導致除零錯誤,需 if (cx==0||cy==0) return;。
  4. 高 DPI 下需配合 SetProcessDpiAwareness 獲取正確物理像素尺寸。

掌握「佈局用 MoveWindow,繪圖用映射模式」這一核心原則,即可在 OnSize 中正確實現各類自動縮放需求。

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