Moving a Video Window (Video Renderer Filter) by Using the Mouse

Environment: VC++, MFC, DirectX

Introduction

If you are creating your own video player and you are using a Video Renderer Filter, I guess you'll have a problem getting the HWND of the Video Window because the IVideoWindow interface of DirectShow doesn't provide you with a GetVideoWindowHandler method. To get the HWND of the Video Window and drag it with the mouse, please complete the following steps:

Step 1

The main problem of the IVideoWindow interface is that a method such as "GetVideoWindowHandler" doesn't exist. Really, I don't understand why Microsoft didn't create such a method. So, you can find the GetWindowHandle method in the IOverlay interface on the input pin (!) of the Video Renderer Filter. First, let's get the IOverlay interface:

IGraphBuilder m_pFilterGraph;
IOverlay m_pOverlay;
// here you should create a filter graph and render your video file
...
hr = m_pFilterGraph->Render(...);
...
// getting IOverlay interface.
IBaseFilter *pFilter= NULL;
IPin *pin = NULL;
if (SUCCEEDED(m_pFilterGraph->FindFilterByName(L"Video Renderer",
    &pFilter))) {
  if (SUCCEEDED(pFilter->FindPin(L"VMR Input0", &pin))) {
    if (SUCCEEDED(pin->QueryInterface(IID_IOverlay,
        (void **)&m_pOverlay))){
      pin->Release();
      pFilter->Release();
    }
  } else {
    pFilter->Release();
  }
}

Step 2

Create a window class to receive the ON_WM_LBUTTONDOWN message from your Video Window. It can be a main application window, or some hidden child window.

CVideoWindowListner : public CWnd
{
...
};
...
void CVideoWindowListner::OnLButtonDown(UINT nFlags, CPoint point)
{
  if(m_pOverlay == NULL) return;
  HWND hWnd;
  // getting HWND of Video Window
  HRESULT hr = m_pOverlay->GetWindowHandle(&hWnd);
  // move it!
  ::SendMessage(hWnd,WM_SYSCOMMAND, SC_MOVE | HTCAPTION, 0);

  CWnd::OnLButtonDown(nFlags, point);
}

Step 3

Your Video Window should send an ON_WM_LBUTTONDOWN message to the window defined in the previous step.

// this is your target window for the Video Window messages
CVideoWindowListner m_VideoWindowListner;
m_VideoWindowListner.Create(...);
...
// getting IVideoWindow interface
IVideoWindow  *pVW ;
hr = m_pFilterGraph->QueryInterface(IID_IVideoWindow,
                                       (void **)&pVW);

// specifying m_VideoWindowListner like receiver all Video Window
// messages
pVW->put_MessageDrain((OAHWND)m_VideoWindowListner.m_hWnd);

Step 4

If you want to put a Video Window to the main application window:

pVW->put_Owner((OAHWND)AfxGetApp()->m_pMainWnd->m_hWnd);
CRect rect;
rect.left = ... ;
rect.top  = ... ;
...
pVW->SetWindowPosition(rect.left, rect.top, rect.right,
                       rect.bottom);

If you want to detach the Video Window from the main window and show it separately:

pVW->put_Owner(NULL);

In both cases, m_VideoWindowListner will receive all Video Window messages!

Tip

If you have some problems with the video (blinking, or not properly repainting) in the child window: "MFC applications which place the video window in a child window must define an empty WM_ERASEBKGND message handler, or the video display area will not repaint correctly."© Microsoft: IVideoWindow Interface.



Comments

  • Please how to resizing video window

    Posted by microbit on 01/20/2006 04:57pm

    Please how to resizing video window

    • How to make this work

      Posted by hulzinator on 08/14/2007 02:38pm

      After spending some time looking into how to get events from a cstatic(picture control) that is no longer a cstatic once you give the handle to the video renderer I got this working.  Below is my code with comments I hope this helps everyone out.
      Alex Hulst
      
      You should include the header files of the class that owns the picture control & its member variable to your class that is building the filter graph it is a good idea to separate these.
      
      below are the definitions of the variables:
      CComPtr< IGraphBuilder > m_pGraph;
      
      pstatic is the member variable for the picture control
      
      //create an instance of Ivideowindow
      CComQIPtr< IVideoWindow, &IID_IVideoWindow>pWindow = m_pGraph;
      
      //basic rect
      RECT rc;
      
      //get handle of picture control
      HWND hwndPreview = pstatic->GetSafeHwnd();
      
      //get the rect from the picture control
      pstatic->GetClientRect(&rc);
      
      //make owner of cstatic(picture control) handle //ivideowindow
      hr = pWindow->put_Owner( (OAHWND) hwndPreview );
      
      //get parent of cstatic(picture control)***
      CWnd *cwndParent =pstatic->GetAncestor(GA_PARENT);
      
      //get handle of parent application or window***
      HWND hwndParent = cwndParent->GetSafeHwnd();		
      
      //post messages to the parent window that owns the //cstatic(picture control) *****most important //part
      hr=pWindow->put_MessageDrain((OAHWND)hwndParent);	
      
      //standard ivideowindow control for size & //position
      hr = pWindow->put_Left( 0 );
      
      hr = pWindow->put_Top( 0 );
      
      hr = pWindow->put_Width( rc.right - rc.left );
      
      hr = pWindow->put_Height( rc.bottom - rc.top);
      
      hr=pWindow->put_WindowStyle(WS_CHILD|WS_CLIPSIBLINGS);
      
      hr = pWindow->put_Visible( OATRUE );

      Reply
    Reply
  • Please Help To Render two or more layer Video

    Posted by abyjoyce on 09/06/2005 04:41am

    I Am in a need of VC++ code to accomodate two or more video layers in a single window Please Help Me

    Reply
  • how to select video mode

    Posted by Straw on 04/22/2004 12:22pm

    for example pal_m ,how to select video input pin

    Reply
  • Failed to find Pin

    Posted by Legacy on 10/06/2003 12:00am

    Originally posted by: Sanjay

    The following call is failing when I tried to run it under win2k. I am running DirectX 9.0 on my system.
    
    

    if (SUCCEEDED(pFilter->FindPin(L"VMR Input0", &pin)))
    {
    ----
    }

    I feel my render filter does not support this particular pin. Please let me know if there is any other way to get IID_IOverlay interface.

    Thanks.

    • Can not save a image file

      Posted by Straw on 04/22/2004 11:54am

      ImageCapture function cannot save a bmp file,please tell me why?

      Reply
    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • With JRebel, developers get to see their code changes immediately, fine-tune their code with incremental changes, debug, explore and deploy their code with ease (both locally and remotely), and ultimately spend more time coding instead of waiting for the dreaded application redeploy to finish. Every time a developer tests a code change it takes minutes to build and deploy the application. JRebel keeps the app server running at all times, so testing is instantaneous and interactive.

  • The impact of a data loss event can be significant. Real-time data is essential to remaining competitive. Many companies can no longer afford to rely on a truck arriving each day to take backup tapes offsite. For most companies, a cloud backup and recovery solution will eliminate, or significantly reduce, IT resources related to the mundane task of backup and allow your resources to be redeployed to more strategic projects. The cloud - can now be comfortable for you – with 100% recovery from anywhere all …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds