共用方式為


使用視窗模式

[與此頁面相關聯的功能,DirectShow是舊版功能。 它已被 MediaPlayerIMFMediaEngine和媒體基金會的音訊/視訊擷取取代。 這些功能已針對 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 介面:

IVideoWindow *pVidWin = NULL;
pGraph->QueryInterface(IID_IVideoWindow, (void **)&pVidWin);

設定父視窗

若要設定父視窗,請使用應用程式視窗的句柄呼叫 IVideoWindow::put_Owner 方法。 此方法會採用類型為 OAHWND的變數,因此請將這個 handle 轉換為這種類型:

pVidWin->put_Owner((OAHWND)hwnd);

設定新視窗樣式

呼叫 IVideoWindow::put_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);

若要取得視訊的原生大小,請在 Filter Graph 管理員上呼叫 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 來建立視訊視窗,並將其加入到圖表中,而不是在 Intelligent Connect期間讓 Filter Graph Manager 自動添加視訊渲染器。 這可確保視訊視窗和子視窗同時重新繪製。 否則,子視窗可能會覆蓋在視訊視窗上。

 

視訊渲染