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.