共用方式為


使用視窗模式

[與此頁面相關的功能 DirectShow是舊版功能。 它已被 MediaPlayerIMFMediaEngineMedia Foundation 中的音訊/視訊擷取取代。 這些功能已針對Windows 10和Windows 11進行優化。 Microsoft 強烈建議新程式碼盡可能使用 MediaPlayerIMFMediaEngine音訊/視訊擷取 ,而不是 DirectShow。 Microsoft 建議使用舊版 API 的現有程式碼盡可能重寫為使用新的 API。

注意

舊版 影片轉譯器篩選 一律使用視窗模式。 VMR-7 和 VMR-9 篩選預設會使用視窗模式,但也支援無視窗模式。

 

在視窗模式中,視訊轉譯器會在其繪製視訊畫面的位置建立自己的視窗。 除非您另有指定,否則此視窗是具有本身框線和標題列的最上層視窗。 不過,大部分時候,您會將視訊視窗附加至應用程式視窗,讓影片整合到您的應用程式 UI 中。 此時,您需要進行下列步驟:

  1. 查詢 IVideoWindow
  2. 設定父視窗。
  3. 設定新的視窗樣式。
  4. 將視訊視窗置於擁有者視窗內。
  5. 通知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期間新增視訊轉譯器。 這可確保視訊視窗和子視窗同時重新繪製。 否則,子視窗可能會繪製在視訊視窗上。

 

影片轉譯