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

MFC 實現 MSN/QQ 風格訊息提示視窗:拉簾式滑入 + 淡入淡出動畫

     編輯:關於VC++

專案目標

在螢幕右下角 (系統托盤區) 顯示非模態提示視窗,支援兩種動畫:

  • MSN 風格:從底部向上滑入 (拉簾式)、停留數秒、向下滑出消失
  • QQ 風格:淡入淡出 (AnimateWindow + AW_BLEND)

MSN 拉簾式動畫實現 (三階段定時器)


#define ID_TIMER_POP_WINDOW    1  // 滑入
#define ID_TIMER_DISPLAY_DELAY 2  // 停留
#define ID_TIMER_CLOSE_WINDOW  3  // 滑出

class CMsgWnd : public CWnd {
    int m_nHeight = 0;
    const int WIN_WIDTH = 300, WIN_HEIGHT = 150;

    void OnTimer(UINT nIDEvent) {
        int cx = GetSystemMetrics(SM_CXSCREEN);
        int cy = GetSystemMetrics(SM_CYSCREEN);
        RECT rcWork; SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWork, 0);
        int x = rcWork.right - WIN_WIDTH;
        int y = rcWork.bottom;

        switch (nIDEvent) {
        case ID_TIMER_POP_WINDOW: // 滑入
            if (m_nHeight <= WIN_HEIGHT) {
                ++m_nHeight;
                MoveWindow(x, y - m_nHeight, WIN_WIDTH, WIN_HEIGHT);
                Invalidate(FALSE);
            } else {
                KillTimer(ID_TIMER_POP_WINDOW);
                SetTimer(ID_TIMER_DISPLAY_DELAY, 5000, NULL); // 停留 5 秒
            }
            break;

        case ID_TIMER_DISPLAY_DELAY: // 停留結束
            KillTimer(ID_TIMER_DISPLAY_DELAY);
            SetTimer(ID_TIMER_CLOSE_WINDOW, 20, NULL);
            break;

        case ID_TIMER_CLOSE_WINDOW: // 滑出
            if (m_nHeight >= 0) {
                --m_nHeight;
                MoveWindow(x, y - m_nHeight, WIN_WIDTH, m_nHeight);
            } else {
                KillTimer(ID_TIMER_CLOSE_WINDOW);
                SendMessage(WM_CLOSE);
            }
            break;
        }
        CWnd::OnTimer(nIDEvent);
    }

    // 建立時啟動
    int OnCreate(LPCREATESTRUCT lpCS) {
        if (CWnd::OnCreate(lpCS) == -1) return -1;
        SetTimer(ID_TIMER_POP_WINDOW, 20, NULL); // 20ms/幀 ≈ 50 FPS
        return 0;
    }
};

QQ 淡入淡出實現 (AnimateWindow)


// 顯示時
AnimateWindow(GetSafeHwnd(), 1000, AW_CENTER | AW_BLEND | AW_ACTIVATE);
// 關閉時
AnimateWindow(GetSafeHwnd(), 1000, AW_HIDE | AW_CENTER | AW_BLEND);

關鍵旗標:

旗標效果
AW_BLEND淡入/淡出 (僅限最上層視窗)
AW_CENTER從中心展開/收縮
AW_SLIDE滑動 (需搭配 AW_HOR_POSITIVE 等方向旗標)
AW_ACTIVATE顯示後啟動視窗
AW_HIDE執行隱藏動畫

無閃爍繪製技巧


void CMsgWnd::OnEraseBkgnd(CDC* pDC) {
    // 不呼叫預設擦除,由 OnPaint 統一繪製背景+內容
    return TRUE;
}

void CMsgWnd::OnPaint() {
    CPaintDC dc(this);
    CRect rc; GetClientRect(&rc);
    // 雙緩衝
    CMemDC memDC(&dc, &rc);
    memDC.FillSolidRect(&rc, RGB(255, 255, 200)); // 淡黃背景
    memDC.DrawText(m_strMsg, &rc, DT_CENTER|DT_VCENTER|DT_WORDBREAK);
}

CMemDC 為 Keith Rule 經典雙緩衝類別,專案中已包含。

啟動提示視窗


void CMainFrame::ShowNotification(LPCTSTR pszMsg) {
    CMsgWnd* pWnd = new CMsgWnd();
    pWnd->CreateEx(WS_EX_TOPMOST | WS_EX_TOOLWINDOW,
        AfxRegisterWndClass(CS_SAVEBITS, LoadCursor(NULL, IDC_ARROW),
        (HBRUSH)GetStockObject(WHITE_BRUSH)),
        _T("MsgTip"), WS_POPUP, 0, 0, 300, 150, NULL, NULL);
    pWnd->SetMessage(pszMsg);
    // 視窗會自動動畫顯示並自我銷毀
}

進階建議

  • 多訊息佇列:同時顯示多個提示時,垂直堆疊並依序動畫
  • 點擊穿透:WS_EX_TRANSPARENT (需配合 WS_EX_LAYERED)
  • 高 DPI 支援:依 GetDpiForWindow 縮放尺寸與字體
  • 自訂外觀:載入 PNG 背景 (GDI+ / CImage) 實現圓角、陰影

總結

MSN 風格以 MoveWindow + 定時器實現像素級控制,適合需精確軌跡的場景;QQ 風格以系統級 AnimateWindow 一行搞定,適合快速集成。兩者均在 VC6.0+Win2000 驗證通過。

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