Using IMediaEventEx::SetNotifyWindow

This page shows you how to know when the playback ends using window messages. The previous samples used MessageBox, or WaitForCompletion to block until the MPEG file reaches to an end. This sample might be a better way if you are using MFC. Please note that error handling codes are omitted to keep the sample code simple.

Sample code

The following sample code shows how to receive window messages.


#include <afxwin.h>

#include <dshow.h>

#define	FILENAME L"c:\\DXSDK\\Samples\\Media\\butterfly.mpg"

#define	WM_GRAPH_NOTIFY		(WM_APP + 1)

class CMainWin : public CFrameWnd
{
public:
	CMainWin();
	~CMainWin();
	DECLARE_MESSAGE_MAP()

private:
	IGraphBuilder *pGraphBuilder;
	IMediaControl *pMediaControl;
	IMediaEventEx *pMediaEventEx;
	IVideoWindow *pVideoWindow;

	bool bRunning;

protected:
	afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
	LRESULT OnGraphNotify(WPARAM wParam, LPARAM lParam);
};

CMainWin::CMainWin()
{
 Create(NULL, "Sample");

 bRunning = false;
 CoInitialize(NULL);
}

CMainWin::~CMainWin()
{
 if (pMediaEventEx != NULL) {
	pMediaEventEx->Release();
 }

 if (pMediaControl != NULL) {
	pMediaControl->Release();
 }

 if (pVideoWindow != NULL) {
	pVideoWindow->Release();
 }

 if (pGraphBuilder != NULL) {
	pGraphBuilder->Release();
 }

 CoUninitialize();
}

void
CMainWin::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
 if (bRunning == false) {
	CoCreateInstance(CLSID_FilterGraph,
		NULL,
		CLSCTX_INPROC,
		IID_IGraphBuilder,
		(LPVOID *)&pGraphBuilder);

	pGraphBuilder->QueryInterface(IID_IMediaControl,
		(LPVOID *)&pMediaControl);

	pGraphBuilder->QueryInterface(IID_IMediaEventEx,
		(LPVOID *)&pMediaEventEx);
	pMediaEventEx->SetNotifyWindow((OAHWND)GetSafeHwnd(),
					WM_GRAPH_NOTIFY, NULL);

	pMediaControl->RenderFile(FILENAME);

	pGraphBuilder->QueryInterface(IID_IVideoWindow,
		(LPVOID *)&pVideoWindow);
	pVideoWindow->put_Owner((OAHWND)GetSafeHwnd());

	pVideoWindow->put_WindowStyle(WS_CHILD|WS_CLIPSIBLINGS);

	RECT rect;
	GetClientRect(&rect);
	pVideoWindow->SetWindowPosition(0, 0,
				rect.right - rect.left,
				rect.bottom - rect.top);

	pVideoWindow->put_Visible(OATRUE);
	pVideoWindow->SetWindowForeground(OATRUE);

	pMediaControl->Run();

	bRunning = true;
 }
}

// called when the event is triggered
LRESULT
CMainWin::OnGraphNotify(WPARAM wParam, LPARAM lParam)
{
 long evCode;
 LONG param1, param2;

 // Get all events
 while (SUCCEEDED(pMediaEventEx->GetEvent(&evCode,
					&param1, &param2, 0))) {
	pMediaEventEx->FreeEventParams(evCode, param1, param2);

	switch (evCode) {
		case EC_COMPLETE:
			// playback complete
			MessageBox("EC_COMPLETE");
			break;
	}
 }

 return NOERROR;
}

class CApp : public CWinApp
{
public:
	BOOL InitInstance();
};

BOOL CApp::InitInstance()
{
 m_pMainWnd = new CMainWin;
 m_pMainWnd->ShowWindow(m_nCmdShow);
 m_pMainWnd->UpdateWindow();

 return true;
}

BEGIN_MESSAGE_MAP(CMainWin, CFrameWnd)
	ON_WM_CHAR()
	ON_MESSAGE(WM_GRAPH_NOTIFY, OnGraphNotify)
END_MESSAGE_MAP()

CApp App;

This sample first displays a window. When a key is pressed, MPEG file playback starts. When the MPEG file playback completes, OnGraphNotify is called. OnGraphNotify will display "EC_COMPLETE" using MessageBox. After the MessageBox message is showed, this sample will do nothing. Please press "X" on the sample window, and kill the sample application.

The essential points of this sample are,

  • Getting pointer to IMediaEventEx interface
  • Defining the value of the window event. This sample defined WM_GRAPH_NOTIFY.
  • Setting the window (OAHWND) for the notification using SetNotifyWindow().
  • Setting an event handler using ON_MESSAGE().
  • Getting event using IMediaEventEx::GetEvent().

Since IMediaEventEx inherits IMediaEvent interface, IMediaEvent::GetEvent() can be used from IMediaEventEx *pMediaEventEx.

Please note that this sample omits a lot of things. It is not practical at all. When you write your own application, please be careful about how you save/use IMediaEventEx objects etc.

  

Copyright (C) GeekPage.JP. All rights reserved.