## Control the Video Playback Window from C++

This article walks through a simple C++ program designed to demonstrate one way to play movies in a particular playback window. It is based on the PlayMovieInWindow function code taken from the InWindow.cpp file, which is available in the InWindow sample in the Samples\ds\player directory. This function is based on the Playfile sample, but has been expanded to show how an application can control the size and style of the video playback window.

See these related sections if you want to play back media files or display a property page:

- Play a Movie from C++ — demonstrates the basic code for playing back a media file.
- Adding Media Seeking — shows the code needed to seek to a particular location in the media file.
- Display a Filter's Property Page from C++ — demonstrates how to display a filter's property page, so the user can change how media files are played back.

Perform the following steps to play a video file in a particular window from within C/C++. You don't necessarily have to perform the steps in the order presented.

1. Include the necessary headers.

         #include <windows.h>
         #include <mmsystem.h>
         #include <streams.h>
         #include "inwindow.h"

2. Define a windows message constant and the HELPER_RELEASE macro, which will be used to release the interfaces from the WndMainProc callback (see the InWindow code for generic window code).

        #define WM_GRAPHNOTIFY  WM_USER+13
        #define HELPER_RELEASE(x) { if (x) x->Release(); x = NULL; }

3. Declare variables.

        HWND      ghApp;
        HINSTANCE ghInst;
        HRESULT   hr;
        LONG      evCode;
        LONG      evParam1;
        LONG      evParam2;
        RECT      grc;

   The ghApp variable is the handle of window to notify when the graph signals an event. The ghInst variable is the HINSTANCE of the window. The evCode variable will hold the event code, and the evParam1 and evParam2 variables will hold the event parameters. The grc variable will hold the coordinates of the parent window's client area.

4. Declare and initialize the necessary interfaces. The reference count of the interfaces is automatically incremented on initialization, so you don't need to call the IUnknown::AddRef method on them. For this example, you need only the four interfaces shown in the following code. For more information, see the documentation for the IMediaEventEx, IGraphBuilder, IMediaControl, and IVideoWindow interfaces.

         IGraphBuilder *pigb  = NULL;
         IMediaControl *pimc  = NULL;
         IMediaEventEx *pimex = NULL;
         IVideoWindow  *pivw  = NULL;

5. Define the function and declare variables. The szFile parameter is the name of the video file that will be played.

       void PlayMovieInWindow (LPCTSTR szFile)
           {

6. Create a Unicode (wide character) string from the input file name.

               WCHAR wFile[MAX_PATH];
               MultiByteToWideChar( CP_ACP, 0, szFile, -1, wFile, MAX_PATH );

7. Instantiate the filter graph manager, asking for the IGraphBuilder interface.

               hr = CoCreateInstance(CLSID_FilterGraph,
               NULL,
               CLSCTX_INPROC_SERVER,
               IID_IGraphBuilder,
               (void **)&pigb);

8. Query for the IMediaControl interface (provides the methods to run, pause, and stop the playback), the IMediaEventEx interface (so you can receive event notifications), and the IVideoWindow interface to hide the window when the movie is finished playing.

          pigb->QueryInterface(IID_IMediaControl, (void **)&pimc);
          pigb->QueryInterface(IID_IMediaEventEx, (void **)&pimex);
          pigb->QueryInterface(IID_IVideoWindow, (void **)&pivw);

9. Ask the filter graph manager to build the filter graph that renders the input file. This does not play the media file. (When you play the file with Run, the filter graph will automatically render the input file's media type. You do not have to specify a renderer filter.)

          hr = pigb->RenderFile(wFile, NULL);

10. Set the ownership of the playback window. This sets ghApp as the owning parent.

           pivw->put_Owner((OAHWND)ghApp);

11. Set the style of the video window. This step is very important, and you must specify the WS_CHILD, WS_CLIPCHILDREN, and WS_CLIPSIBLINGS flags.

           pivw->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);

12. Get the coordinates of the parent window's client area.

           GetClientRect(ghApp, &grc);

13. Set the playback window's position within parent's client area. In this case, the playback window fills the client area. If the video being played is smaller than the playback window it will be stretched to fit the window. If the video is larger, it will be compressed to fit the window.

           pivw->SetWindowPosition(grc.left, grc.top, grc.right, grc.bottom);

14. Start playing the media file.

           hr = pimc->Run();

The InWindow sample uses the same GetClipFileName function to get the movie to be played and the same the WinMain function to create the window as the Playfile sample.

The InWindow WndMainProc callback function is similar to the Playfile WndMainProc used to handle the filter graph messages and release the interfaces when necessary, with one important difference. The WndMainProc function in InWindow calls the IVideoWindow::put_Owner method with a NULL value for its parameter. You must do this before releasing the IGraphBuilder interface and before the video window is destroyed. Otherwise, messages will continue to be sent to the video playback window but it will have no parent to forward the messages to, so errors will likely occur.

    pivw->put_Owner(NULL);

© 1997 Microsoft Corporation. All rights reserved. Terms of Use.