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

VC++ 對話方塊實作動畫圓形:定時器驅動半徑變化

     編輯:VC 教學

前言

在 MFC 對話方塊中實作簡單動畫,核心在於定時器觸發狀態更新與`OnPaint` 重繪。本文以一個會呼吸般放大縮小的彩色圓環為例,示範完整流程:建立專案、宣告變數、定時器邏輯、自訂繪圖、顏色選擇對話框整合。

一、建立專案與介面佈局

  1. AppWizard → **Dialog based** 專案 Graph。
  2. 刪除預設靜態文字與「確定」按鈕,新增按鈕 IDC_BTN_COLOR(標題「顏色」)、IDC_BTN_EXIT(標題「離開」)。
  3. ClassWizard 為對話方塊類別 `CGraphDlg` 新增訊息處理:`WM_TIMER`、`WM_PAINT`、`BN_CLICKED`(顏色/離開)、`WM_DESTROY`。

二、成員變數宣告

// CGraphDlg.h
protected:
    int  m_nRadius;      // 當前半徑
    int  m_nDirection;   // 1=放大, -1=縮小
    COLORREF m_clrCircle; // 圓環顏色
    CColorDialog m_dlgColor; // 顏色選擇對話框

三、初始化與定時器啟動

BOOL CGraphDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    m_nRadius = 50;
    m_nDirection = 1;
    m_clrCircle = RGB(255, 0, 0); // 預設紅色

    // 建立 50ms 定時器(約 20 FPS)
    if (SetTimer(1, 50, NULL) == 0)
        AfxMessageBox(_T("無法建立定時器!"));

    m_dlgColor.m_cc.rgbResult = m_clrCircle;
    return TRUE;
}

四、定時器驅動半徑變化

void CGraphDlg::OnTimer(UINT nIDEvent)
{
    if (nIDEvent == 1)
    {
        m_nRadius += m_nDirection;
        if (m_nRadius >= 100) m_nDirection = -1; // 到達上限反向
        else if (m_nRadius <= 10) m_nDirection = 1; // 到達下限反向

        Invalidate(FALSE); // 觸發 WM_PAINT,FALSE=不抹除背景(由 OnPaint 處理)
    }
    CDialog::OnTimer(nIDEvent);
}

五、自訂繪圖 OnPaint

void CGraphDlg::OnPaint()
{
    CPaintDC dc(this); // 自動 BeginPaint/EndPaint

    // 建立畫筆:實線、寬度 10、指定顏色
    CPen pen(PS_SOLID, 10, m_clrCircle);
    CPen* pOldPen = dc.SelectObject(&pen);

    // 圓環外接矩形:中心固定,半徑決定大小
    // 假設中心約在 (130, 130) 附近,依實際對話框調整
    CRect rc(130 - m_nRadius, 130 - m_nRadius, 
             130 + m_nRadius, 130 + m_nRadius);
    dc.Ellipse(&rc); // 畫圓/橢圓

    dc.SelectObject(pOldPen); // 還原畫筆
    // 不呼叫 CDialog::OnPaint(),避免重繪背景覆蓋動畫
}

六、顏色選擇與離開處理

void CGraphDlg::OnBtnColor()
{
    if (m_dlgColor.DoModal() == IDOK)
    {
        m_clrCircle = m_dlgColor.GetColor();
        Invalidate(); // 立即以新顏色重繪
    }
}

void CGraphDlg::OnBtnExit()
{
    OnOK(); // 正常關閉對話框
}

void CGraphDlg::OnDestroy()
{
    KillTimer(1); // 釋放定時器
    CDialog::OnDestroy();
}

七、執行效果與優化建議

動畫圓形示範

  • 雙緩衝防閃爍:在 `OnPaint` 使用 `CMemDC`(記憶體 DC)離屏繪圖再 `BitBlt` 到螢幕。
  • 高精度定時器:多媒體定時器 `timeSetEvent` 或 `SetTimer` 配合 `timeGetTime` 計算真實經過時間,避免 50ms 不準確導致速度波動。
  • 向量化繪圖:改用 GDI+ `Graphics::DrawEllipse` 支援抗鋸齒與透明度。
  • 參數化:將中心座標、最大/最小半徑、動畫速度做成可配置屬性。

八、結語

本範例展示了 MFC 對話方塊動畫的最小完整閉環:狀態變數 → 定時器更新 → Invalidate 觸發重繪 → OnPaint 依狀態繪圖。此模式可擴充至載入畫面旋轉圖示、進度環、波形圖等多種動態視覺元素,是 MFC 開發者必備的基礎技能。

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