heberoxx 发表于 2015-5-17 09:30:07

【搜集整理】Win7下 directshow 窗口模式退出全屏后黑屏

  Win7下 directshow 窗口模式退出全屏后黑屏,使用的方法是put_FullScreenMode,据说是因为win7的桌面组合效果导致的。
  解决方法:改为无窗口或仿真全屏。



HRESULT PlayVideo::PutFullScreen(HWND ghApp)
{
    HRESULT hr=S_OK;
   
    if (!bFullscreen)
    {
    // Save current message drain
      pVidWin->get_MessageDrain((OAHWND)NULL);
      // Set message drain to application main window
      pVidWin->put_MessageDrain((OAHWND) ghApp);
      pVidWin->put_Owner( (OAHWND) NULL);
      pVidWin->put_WindowStyle(0);
      pVidWin->put_WindowStyleEx(WS_EX_TOPMOST | WS_POPUP);
      pVidWin->SetWindowPosition(0,0,GetSystemMetrics(SM_CXSCREEN),
                        GetSystemMetrics(SM_CYSCREEN));//全屏显示
      bFullscreen = TRUE;
    }
    else
    {
      pVidWin->put_MessageDrain((OAHWND)NULL);
      pVidWin->put_Visible(OAFALSE);
      pVidWin->put_Owner((OAHWND)Owner);
      pVidWin->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS|WS_CLIPCHILDREN);
      pVidWin->SetWindowForeground(OATRUE);
      OnSize();//调整视频窗口大小
      bFullscreen = FALSE;
    }
    return hr;
}


void PlayVideo::OnSize()
{
    HWND hwnd;
    CWnd *pcwnd;
    CRect rect;
    pVidWin->get_Owner((OAHWND*)&hwnd);
    pcwnd=CWnd::FromHandle(hwnd);
    pcwnd->GetClientRect(&rect);
    pVidWin->SetWindowPosition(rect.left ,rect.top ,
                  rect.right ,rect.bottom );
}
  http://blog.iyunv.com/watzds/article/details/6618594#
  http://social.msdn.microsoft.com/Forums/en-US/windowsdirectshowdevelopment/thread/b8bf047d-8353-4b32-89a5-776bec85cb17/
  Using Windowless Mode
  http://msdn.microsoft.com/en-us/library/dd407299(VS.85).aspx
  About Video Rendering in DirectShow
  http://msdn.microsoft.com/en-us/library/dd373407(VS.85).aspx
  http://alax.info/blog/tag/directshow



HRESULT ToggleFullScreen(void)
{
    HRESULT hr=S_OK;
    LONG lMode;
    static HWND hDrain=0;
    // Don't bother with full-screen for audio-only files
    if ((g_bAudioOnly) || (!pVW))
      return S_OK;
    CComPtr pVideoRender;
    LIF(GetVideoRenderer(pGB, pVideoRender));

    if (FALSE == g_bFullscreen)
    {
      // Save current message drain
      LIF(pVW->get_MessageDrain((OAHWND *) &hDrain));
      //Switch into the FullScren mode.

      RECT rcMonitor = {};
      LIF(GetCurrentMonitorSize(rcMonitor, pVideoRender));
      // Switch to full-screen mode
      LIF(pVW->put_Visible(OAFALSE));
      LIF(pVW->put_Owner( (OAHWND) NULL));
      LIF(pVW->put_WindowStyle(0));
      LIF(pVW->put_WindowStyleEx(WS_EX_TOPMOST | WS_POPUP));
LIF(pVW->SetWindowPosition(rcMonitor.left, rcMonitor.top, rcMonitor.right - rcMonitor.left, rcMonitor.bottom - rcMonitor.top));
      LIF(CorrectAspectRatio(pVideoRender));
      LIF(pVW->put_Visible(OATRUE));
      // Set message drain to application main window
      LIF(pVW->put_MessageDrain((OAHWND) ghApp));
      g_bFullscreen = TRUE;
    }
    else
    {
      // Switch back to windowed mode

      LIF(pVW->put_Visible(OAFALSE));
      LIF(pVW->put_Owner((OAHWND)ghApp));
      LIF(pVW->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS));
      LIF(pVW->put_WindowStyleEx(0));

      RECT client={};
      GetClientRect(ghApp, &client);
      LIF(pVW->SetWindowPosition(client.left, client.top, client.right, client.bottom));

      LIF(CorrectAspectRatio(pVideoRender));
      // Undo change of message drain
      LIF(pVW->put_MessageDrain((OAHWND) hDrain));
      LIF(pVW->put_Visible(OATRUE));
      // Reset video window
      LIF(pVW->SetWindowForeground(-1));
      // Reclaim keyboard focus for player application
      UpdateWindow(ghApp);
      SetForegroundWindow(ghApp);
      SetFocus(ghApp);
      g_bFullscreen = FALSE;
    }
    return hr;
}
And are help functions:
HRESULT GetVideoRenderer(IGraphBuilder *pGraphBuilder, CComPtr& pVideoRender)
{
    pVideoRender.Release();
    CheckPointer(pGraphBuilder, E_POINTER);
    HRESULT                  hr = S_FALSE;   //The renderer is not found.
    CComPtr   pEnum;
    CComPtr    pFilter;
    ULONG               ulFetched = 0;
    // Get filter enumerator
    hr = pGraphBuilder->EnumFilters(&pEnum);
    if (FAILED(hr)){
      return hr;
    }
    hr = pEnum->Reset();
    if (FAILED(hr)){
      return hr;
    }
    // Enumerate all filters in the graph
    while( (pEnum->Next(1, &pFilter, &ulFetched) == S_OK))
    {
      CComPtr pIBasicVideo;
      hr = pFilter->QueryInterface(IID_IBasicVideo, reinterpret_cast(&pIBasicVideo));
      if(SUCCEEDED(hr))
      {
            pVideoRender = pFilter;
            return S_OK;
      }
      pFilter.Release();
    }
    return E_NOTIMPL;
}
HRESULT GetCurrentMonitorSize(RECT& rcMonitor,CComPtr& pVideoRender)
{
    CheckPointer(pVideoRender, E_POINTER);
    HRESULT hr = S_OK;
    CComPtr pVMRMonitorConfig9;
    hr = pVideoRender ->QueryInterface(IID_IVMRMonitorConfig9, reinterpret_cast(&pVMRMonitorConfig9));
    if(SUCCEEDED(hr))
    {
      VMR9MonitorInfo vMonInfo = {};            // Array of VMR9MonitorInfo structures.
      DWORD            dwNumMonitors = 0;            // Number of attached monitors.
      UINT            dwCutrrentMonitorIndex = 0;
      LIF( pVMRMonitorConfig9->GetAvailableMonitors(vMonInfo, 16, &dwNumMonitors) );
      rcMonitor = vMonInfo.rcMonitor;
    }
    else
    {
      CComPtr pVMRMonitorConfig;
      hr = pVideoRender->QueryInterface(IID_IVMRMonitorConfig, reinterpret_cast(&pVMRMonitorConfig));
      if(FAILED(hr)){
            return hr;
      }
      VMRMONITORINFO    vMonInfo = {};            // Array of VMRMONITORINFO structures.
      DWORD            dwNumMonitors = 0;            // Number of attached monitors.
      UINT            dwCutrrentMonitorIndex = 0;
      LIF( pVMRMonitorConfig->GetAvailableMonitors(vMonInfo, 16, &dwNumMonitors) );
      rcMonitor = vMonInfo.rcMonitor;
    }
    return S_OK;
}
HRESULT CorrectAspectRatio(CComPtr& pVideoRender)
{
    CheckPointer(pVideoRender, E_POINTER);
    HRESULT hr = S_OK;
    CComPtr pIVMRAspectRatioControl9;
    hr = pVideoRender ->QueryInterface(IID_IVMRAspectRatioControl9, reinterpret_cast(&pIVMRAspectRatioControl9));
    if(SUCCEEDED(hr))
    {
      LIF( pIVMRAspectRatioControl9->SetAspectRatioMode(VMR_ARMODE_LETTER_BOX) );
    }
    else
    {
      CComPtr pIVMRAspectRatioControl;
      hr = pVideoRender ->QueryInterface(IID_IVMRAspectRatioControl, reinterpret_cast(&pIVMRAspectRatioControl));
      if(FAILED(hr)){
            return hr;
      }
      LIF( pIVMRAspectRatioControl->SetAspectRatioMode(VMR_ARMODE_LETTER_BOX) );
    }
    return S_OK;
}
  IVideoWindow FullScreen Vista Issues
  http://social.msdn.microsoft.com/forums/en-US/windowsdirectshowdevelopment/thread/cd515f32-87f4-4726-a07d-f995fa521e1f/
  1. DirectX Summer 2004 SDK has the most samples (recommended for this and other reasons on my site):
    C:\DXSDK\9_0\Samples\C++\DirectShow\Players\PlayWnd
2.VMR7 and VMR9 are not obsolete.However, some of us have written our own custom renderers because the stock renderers have limitations that we cannot live with.EVR has its limitations too.
3.The full screen vs. creating a borderless window the size of the screen comes up from time to time.I prefer the latter because fullscreen mode has issues.In the old days, when graphics cards had more problems stretching video in windowed mode, it was good to have fullscreen alternative.
  http://tmhare.mvps.org/
  
页: [1]
查看完整版本: 【搜集整理】Win7下 directshow 窗口模式退出全屏后黑屏