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

視頻啟動封面實現:MCIWnd 窗口子類化攔截鼠標點擊關閉

     編輯:VC++

需求與挑戰

應用啟動時播放視頻作為 Splash Screen,需支持:

  1. 視頻播放結束自動關閉進入主界面。
  2. 用戶點擊視頻區域可隨時跳過。

難點:MCIWnd 窗口內部封裝了鼠標消息處理,宿主無法直接捕獲其客戶區點擊事件。

解決方案:窗口子類化

使用 SetWindowLong(GWL_WNDPROC) 替換 MCIWnd 窗口過程,攔截 WM_LBUTTONDOWN 設置全局標志,其餘消息調用原窗口過程。

核心實現步驟

1. 全局標志與視頻窗口句柄

// App 類
class CMyApp : public CWinApp {
public:
    bool m_CanClose = false; // 是否允許關閉視頻窗口
};

// View 類成員
HWND m_VideoWnd = NULL;      // 視頻窗口句柄
long m_VideoLength = 0;      // 視頻總長度 (毫秒)
WNDPROC OldProc = NULL;      // 原窗口過程地址

2. 構造函數創建視頻窗口

CMyView::CMyView() {
    CString file = _T("D:\\Video\\Cover.avi");
    m_VideoWnd = MCIWndCreate(GetSafeHwnd(), AfxGetInstanceHandle(),
                              WS_POPUP | WS_VISIBLE | MCIWNDF_NOPLAYBAR | MCIWNDF_NOMENU,
                              file);
    // 居中顯示
    RECT rc; GetWindowRect(m_VideoWnd, &rc);
    int sx = (GetSystemMetrics(SM_CXSCREEN) - (rc.right - rc.left)) / 2;
    int sy = (GetSystemMetrics(SM_CYSCREEN) - (rc.bottom - rc.top)) / 2;
    SetWindowPos(m_VideoWnd, HWND_TOPMOST, sx, sy, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE);
}

3. OnInitialUpdate 子類化並播放

void CMyView::OnInitialUpdate() {
    CView::OnInitialUpdate();
    OldProc = (WNDPROC)GetWindowLong(m_VideoWnd, GWL_WNDPROC);
    SetWindowLong(m_VideoWnd, GWL_WNDPROC, (LONG)NewProc); // 替換窗口過程

    m_VideoLength = MCIWndGetLength(m_VideoWnd);
    MCIWndPlay(m_VideoWnd);
    SetTimer(1, 20, NULL); // 20ms 輪詢
}

4. 定時器檢查退出條件

void CMyView::OnTimer(UINT nIDEvent) {
    CMyApp* pApp = (CMyApp*)AfxGetApp();
    if (MCIWndGetPosition(m_VideoWnd) >= m_VideoLength || pApp->m_CanClose) {
        KillTimer(1);
        MCIWndDestroy(m_VideoWnd);
        AfxGetMainWnd()->ShowWindow(SW_SHOWMAXIMIZED); // 顯示主窗口
        return;
    }
    CView::OnTimer(nIDEvent);
}

5. 新窗口過程攔截左鍵

LRESULT CALLBACK NewProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    if (msg == WM_LBUTTONDOWN) {
        CMyApp* pApp = (CMyApp*)AfxGetApp();
        pApp->m_CanClose = true; // 設置標志,定時器將關閉視頻
    }
    return CallWindowProc(OldProc, hWnd, msg, wParam, lParam); // 其餘轉發
}

關鍵技術點

  • MCIWndCreate 參數:MCIWNDF_NOPLAYBAR 隱藏控制欄,MCIWNDF_NOMENU 隱藏右鍵菜單,實現全屏沉浸體驗。
  • 子類化時機:必須在 MCIWndCreate 之後、MCIWndPlay 之前完成,確保攔截生效。
  • 線程安全:m_CanClose 僅在 UI 線程讀寫,無需鎖;若跨線程需用 InterlockedExchange 或原子操作。
  • 資源清理:MCIWndDestroy 釋放視頻窗口及 MCI 設備,避免句柄泄漏。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved