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

VC++ MFC 繪圖程式入門:滑鼠事件處理與四種 DC 使用方式比較

     編輯:VC 教學

前言

MFC 繪圖核心在於取得裝置內容(DC)並呼叫 GDI 函式。本文以「滑鼠拖曳畫直線」為例,說明 WM_LBUTTONDOWN/WM_LBUTTONUP/WM_MOUSEMOVE 訊息處理,並比較四種取得 DC 的方式優缺點。

滑鼠訊息處理架構


// View 類別成員
CPoint m_ptOrigin;  // 起始點
BOOL   m_bDrawing;  // 是否正在繪圖

// 滑鼠按下:記錄起點
void CMyView::OnLButtonDown(UINT nFlags, CPoint point)
{
    m_ptOrigin = point;
    m_bDrawing = TRUE;
    SetCapture(); // 捕捉滑鼠,確保 MouseMove/Up 仍送達此視窗
    CView::OnLButtonDown(nFlags, point);
}

// 滑鼠移動:連續畫線
void CMyView::OnMouseMove(UINT nFlags, CPoint point)
{
    if (m_bDrawing) {
        CClientDC dc(this); // 即時繪製到螢幕
        dc.MoveTo(m_ptOrigin);
        dc.LineTo(point);
        m_ptOrigin = point; // 更新起點為上一終點
    }
    CView::OnMouseMove(nFlags, point);
}

// 滑鼠釋放:結束繪圖
void CMyView::OnLButtonUp(UINT nFlags, CPoint point)
{
    if (m_bDrawing) {
        m_bDrawing = FALSE;
        ReleaseCapture();
        // 這裡可將最終線段存入資料結構,以便重繪
    }
    CView::OnLButtonUp(nFlags, point);
}

四種 DC 取得方式比較

方式程式碼特點適用場景
1. 全域 APIHDC hdc = ::GetDC(m_hWnd); ... ::ReleaseDC(m_hWnd, hdc);最底層,需手動管理釋放非 MFC 專案、特殊需求
2. CDC::GetDC/ReleaseDCCDC* pDC = GetDC(); ... ReleaseDC(pDC);MFC 封裝,指標需手動釋放短暫繪圖、回呼函式中
3. CClientDC (RAII)CClientDC dc(this); // 建構時 GetDC,解構時 ReleaseDC**推薦**:自動管理生命週期,僅限客戶區OnMouseMove、OnPaint 外的即時繪圖
4. CWindowDCCWindowDC dc(this); // 含非客戶區(標題列、邊框)可繪製整個視窗區域非客戶區繪圖、桌面視窗
5. CPaintDCCPaintDC dc(this); // 僅限 OnPaint,自動 BeginPaint/EndPaint**唯一合法**用於 WM_PAINT 回應OnPaint 重繪

關鍵差異:即時繪圖 vs. 持久化

  • 即時回饋:OnMouseMove 中用 CClientDC 直接畫到螢幕,使用者拖曳時看到線條跟隨。
  • 持久化:滑鼠釋放時將線段座標存入 CArray<LINE>,OnPaint 中遍歷陣列重繪所有線條,確保視窗最小化/遮蔽後恢復正確。

持久化資料結構與 OnPaint 範例


struct LINE { CPoint ptFrom, ptTo; };
CArray m_lines;

void CMyView::OnLButtonUp(UINT nFlags, CPoint point)
{
    if (m_bDrawing) {
        m_bDrawing = FALSE;
        ReleaseCapture();
        LINE ln; ln.ptFrom = m_ptOrigin; ln.ptTo = point;
        m_lines.Add(ln);
        Invalidate(); // 觸發 WM_PAINT 重繪
    }
    CView::OnLButtonUp(nFlags, point);
}

void CMyView::OnDraw(CDC* pDC)
{
    for (int i = 0; i < m_lines.GetSize(); ++i) {
        pDC->MoveTo(m_lines[i].ptFrom);
        pDC->LineTo(m_lines[i].ptTo);
    }
}

進階:雙緩衝消除拖曳閃爍

參考《VC++ 雙緩衝繪圖消除閃爍》一文,在 OnDraw 使用 CMemDC(或自行建立相容 DC/點陣圖)一次性 BitBlt 到螢幕。

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