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

VC++ 自繪按鈕播放 AVI 動畫:CAnimateCtrl 與 OwnerDraw 結合實現動態介面

     編輯:關於VC++

前言

在遊戲選單、三維軟體工具列中常見「滑鼠移過按鈕播放微動畫」的效果。MFC CAnimateCtrl 封裝了 Windows 動畫控制項,支援無聲、未壓縮或 RLE 壓縮的 AVI 檔案/資源。本文示範如何將 CAnimateCtrl 嵌入 CButton 衍生類,在 WM_MOUSEMOVE 觸發播放,打造專業級動態按鈕。

一、動畫控制項基礎:CAnimateCtrl

建立樣式組合

DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_BORDER | ACS_AUTOPLAY | ACS_CENTER | ACS_TRANSPARENT;
樣式說明
ACS_CENTER動畫置中,控制項尺寸固定不隨動畫大小變化
ACS_TRANSPARENT背景透明(不繪製動畫背景色)
ACS_AUTOPLAY開啟後自動循環播放

核心成員函數

函數用途
Open(LPCTSTR lpszFileName) / Open(UINT nID)從檔案/資源開啟 AVI
Play(UINT nFrom, UINT nTo, UINT nRep)播放:起始幀/結束幀/重複次數 (-1=無限)
Seek(UINT nTo)靜態顯示指定幀
Stop()停止播放
Close()關閉並釋放記憶體

AVI 檔案限制

  • 必須無聲(無音軌)。
  • 未壓縮或 RLE 壓縮。
  • 調色板固定不變。
  • 256 色 AVI 播放效果接近 16 色(系統預設調色板限制),高品質需改用 MCI/DirectShow。

二、CAviButton 類別設計

類別宣告

class CAviButton : public CButton
{
public:
    CAviButton();
    UINT m_nAviID;           // AVI 資源 ID
    CAnimateCtrl m_animCtrl; // 內嵌動畫控制項
    BOOL m_bPlaying;         // 播放狀態旗標

    void LoadAvi(UINT nID);
    void DrawButton(CDC* pDC, UINT nState, CRect rect); // 繪製按鈕邊框/背景

    virtual void DrawItem(LPDRAWITEMSTRUCT lpDIS); // OwnerDraw 入口
    virtual BOOL Create(LPCTSTR, LPCTSTR, DWORD, const RECT&, CWnd*, UINT, CCreateContext* = NULL);

protected:
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    DECLARE_MESSAGE_MAP()
};

訊息映射與滑鼠觸發播放


BEGIN_MESSAGE_MAP(CAviButton, CButton)
    ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()

void CAviButton::OnMouseMove(UINT nFlags, CPoint point)
{
    ClientToScreen(&point);
    CRect rcWnd; GetWindowRect(&rcWnd);
    BOOL bOver = rcWnd.PtInRect(point);

    if (bOver && IsWindowEnabled()) {
        if (::IsWindow(m_animCtrl.m_hWnd) && !m_bPlaying) {
            m_animCtrl.Play(0, -1, 1); // 播放一次
            m_bPlaying = TRUE;
            SetCapture(); // 捕捉滑鼠以便偵測移出
        }
    } else {
        m_bPlaying = FALSE;
        ReleaseCapture();
    }
    CButton::OnMouseMove(nFlags, point);
}

DrawItem:建立動畫控制項並繪製按鈕外觀

void CAviButton::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
    CRect rcClient; GetClientRect(&rcClient);

    // 首次建立動畫控制項(填滿按鈕客戶區)
    if (!::IsWindow(m_animCtrl.m_hWnd)) {
        m_animCtrl.Create(WS_CHILD | WS_VISIBLE, rcClient, this, 0);
        m_animCtrl.Open(m_nAviID); // 開啟並顯示第一幀
    }

    CDC* pDC = CDC::FromHandle(lpDIS->hDC);
    UINT nState = lpDIS->itemState;
    DrawButton(pDC, nState, rcClient); // 自繪 3D 邊框/背景
}

DrawButton:經典 3D 按鈕繪製(按下/彈起視覺差異)

void CAviButton::DrawButton(CDC* pDC, UINT nState, CRect rect)
{
    COLORREF clrTopLeft, clrBottomRight, clrEdge;
    if (nState & ODS_SELECTED) { // 按下態
        clrTopLeft = RGB(0,0,0); clrBottomRight = RGB(128,128,128); clrEdge = RGB(128,128,128);
    } else { // 正常態
        clrTopLeft = RGB(255,255,255); clrBottomRight = RGB(128,128,128); clrEdge = RGB(0,0,0);
    }

    CPen penTL(PS_SOLID, 1, clrTopLeft), penBR(PS_SOLID, 1, clrBottomRight), penEdge(PS_SOLID, 1, clrEdge);
    CPen* pOld = pDC->SelectObject(&penTL);
    // 左上邊框
    pDC->MoveTo(1, rect.Height()-1); pDC->LineTo(1,1); pDC->LineTo(rect.Width()-1,1);
    pDC->MoveTo(0, rect.Height()-1); pDC->LineTo(0,0); pDC->LineTo(rect.Width()-1,0);
    pDC->SelectObject(&penBR);
    // 右下邊框
    pDC->MoveTo(rect.Width()-1,0); pDC->LineTo(rect.Width()-1,rect.Height()-1); pDC->LineTo(0,rect.Height()-1);
    pDC->MoveTo(rect.Width()-2,1); pDC->LineTo(rect.Width()-2,rect.Height()-2); pDC->LineTo(0,rect.Height()-2);
    pDC->SelectObject(&penEdge); // 外框
    pDC->SelectObject(pOld);
}

三、對話框整合與資源準備

  1. 資源編輯器:插入 AVI 檔案 → 資源類型 AVI → ID 為 IDR_AVI。
  2. 對話框編輯器:放置 Button → 屬性 Owner Draw = True → 類別向導建立 CAviButton 變數 m_aviBtn。
  3. OnInitDialog 中載入資源:m_aviBtn.LoadAvi(IDR_AVI);

四、執行效果

AVI 動畫按鈕效果圖

滑鼠移入按鈕區域 → 播放 AVI 動畫一次;移出 → 停止並釋放捕捉。

五、擴展應用建議

  • 工具列按鈕動畫: 同理可將 CAnimateCtrl 嵌入 CToolBar 自定按鈕(TBSTYLE_CUSTOMERASE)。
  • 狀態列區域動畫: 在狀態列特定格內播放狀態指示動畫。
  • 循環待機動畫: 使用 ACS_AUTOPLAY + Play(0,-1,-1) 實現持續播放的載入指示器。

結語

CAnimateCtrl + OwnerDraw Button 是實現輕量級 AVI 動畫按鈕的經典組合。關鍵在於 DrawItem 中延遲建立動畫控制項(確保視窗句柄有效),以及 WM_MOUSEMOVE + SetCapture/ReleaseCapture 精確控制播放生命週期。受限於 AVI 格式限制,現代專案建議改用 CMFCToolBarButton + GIF/APNG 解碼庫實現更豐富的動態介面。

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