dcsimg

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

WEBINAR:
On-Demand

Desktop-as-a-Service Designed for Any Cloud ? Nutanix Frame


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

  • There are no comments yet. Be the first to comment!

  • You must have javascript enabled in order to post comments.

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

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date