使用視窗模式
[與此頁面相關的功能 DirectShow是舊版功能。 它已被 MediaPlayer、 IMFMediaEngine和 Media Foundation 中的音訊/視訊擷取取代。 這些功能已針對Windows 10和Windows 11進行優化。 Microsoft 強烈建議新程式碼盡可能使用 MediaPlayer、 IMFMediaEngine 和 音訊/視訊擷取 ,而不是 DirectShow。 Microsoft 建議使用舊版 API 的現有程式碼盡可能重寫為使用新的 API。
注意
舊版 影片轉譯器篩選 一律使用視窗模式。 VMR-7 和 VMR-9 篩選預設會使用視窗模式,但也支援無視窗模式。
在視窗模式中,視訊轉譯器會在其繪製視訊畫面的位置建立自己的視窗。 除非您另有指定,否則此視窗是具有本身框線和標題列的最上層視窗。 不過,大部分時候,您會將視訊視窗附加至應用程式視窗,讓影片整合到您的應用程式 UI 中。 此時,您需要進行下列步驟:
- 查詢 IVideoWindow。
- 設定父視窗。
- 設定新的視窗樣式。
- 將視訊視窗置於擁有者視窗內。
- 通知WM_MOVE訊息的視訊視窗。
查詢 IVideoWindow
開始播放之前,請查詢 IVideoWindow 介面的 Filter Graph 管理員:
IVideoWindow *pVidWin = NULL;
pGraph->QueryInterface(IID_IVideoWindow, (void **)&pVidWin);
設定父視窗
若要設定父視窗,請使用應用程式視窗的控制碼呼叫 IVideoWindow::p ut_Owner 方法。 此方法採用 OAHWND類型的變數,因此請將控制碼轉換成此類型:
pVidWin->put_Owner((OAHWND)hwnd);
設定新視窗樣式
呼叫 IVideoWindow::p ut_WindowStyle 方法來變更視訊視窗的樣式:
pVidWin->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS);
WS_CHILD旗標會將視窗設定為子視窗,而WS_CLIPSIBLINGS旗標可防止視窗繪製在另一個子視窗的工作區內。
放置視訊視窗
若要設定視訊相對於應用程式視窗工作區的位置,請呼叫 IVideoWindow::SetWindowPosition 方法。 這個方法會採用矩形,指定視訊視窗的左邊緣、上邊緣、寬度和高度。 例如,下列程式碼會延展視訊視窗,以符合父視窗的整個工作區:
RECT rc;
GetClientRect(hwnd, &rc);
pVidWin->SetWindowPosition(0, 0, rc.right, rc.bottom);
若要取得視訊的原生大小,請在篩選圖形管理員上呼叫 IBasicVideo::GetVideoSize 方法。 您可以使用該資訊來調整影片,並保留正確的外觀比例。
回應WM_MOVE訊息
為了獲得最佳效能,您應該在圖形暫停時,每當視窗移動時通知視訊轉譯器。 呼叫 IVideoWindow::NotifyOwnerMessage 方法來轉送WM_MOVE訊息:
// (Inside your WindowProc)
case WM_MOVE:
pVidWin->NotifyOwnerMessage((OAHWND)hWnd, msg, wParam, lParam);
break;
如果轉譯器使用硬體重迭,此通知會導致轉譯器更新重迭位置。 (VMR-9 不使用重迭,因此如果您使用 VMR-9.) ,則不需要呼叫此方法
清除
在應用程式結束之前,請停止圖形,並將視訊視窗的擁有者重設為 Null。 否則,視窗訊息可能會傳送至錯誤的視窗,這可能會造成錯誤。 此外,隱藏視訊視窗,或者您可能會立即在畫面上看到影片影像閃爍:
pControl->Stop();
pVidWin->put_Visible(OAFALSE);
pVidWin->put_Owner(NULL);
注意
如果視訊視窗的父系是主應用程式視窗的子視窗, (換句話說,如果視訊視窗是子) 的子系,您應該使用 CoCreateInstance 建立視訊視窗,並將它新增至圖形,而不是讓 Filter Graph Manager 在 Intelligent Connect期間新增視訊轉譯器。 這可確保視訊視窗和子視窗同時重新繪製。 否則,子視窗可能會繪製在視訊視窗上。
相關主題