## Display a Filter's Property Page from C++

This article walks through a simple C++ program designed to demonstrate how to request a filter to display its property page. It is based on the MPegProp function code in the MPegProp.cpp file, which you can find in the MPegProp sample in the Samples\ds\player directory.

This code displays the property page of the MPEG video decoder. This filter has a property page that enables you to play MPEG files in color or monochrome. You can see this filter's property page by opening the Filter Graph Editor, choosing the Insert Filters command from the Graph menu, selecting MPEG Video Decoder from the DirectShow Filters list, and clicking the Insert Filters button. After you've inserted the filter, right-click anywhere on it to display its property page.

See these related sections if you want to play back media files or specify the video playback window:

- 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.
- Control the Video Playback Window 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 control the MPEG video decoder's property page in 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 "playfile.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 MPegProp 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;

   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.

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;
         IFilterGraph  *pifg  = NULL;
         IBaseFilter   *pifPP = NULL;
         ISpecifyPropertyPages *pispp = NULL;

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

          void MpegProp (LPSTR 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. Use a window to capture graph signal events. This not only improves performance, but allows your application to run in any threading model.

           pimex->SetNotifyWindow((OAHWND)ghApp, WM_GRAPHNOTIFY, 0);

    The window specified by ghApp will handle messages in response to all events from the graph. If an event occurs, DirectShow posts a WM_GRAPHNOTIFY message to the window.

11. Query for the IFilterGraph interface. Through IFilterGraph, you will retrieve a pointer to the IBaseFilter interface on the MPEG Video Codec filter. The easiest way to find the single MPEG video codec in the graph is through IFilterGraph::FindFilterByName.

          pigb->QueryInterface(IID_IFilterGraph, (void **)&pifg);

12. Use FindFilterByName to find the MPEG Video Codec. This method returns a pointer (&pifPP) to the IBaseFilter interface on the MPEG Video Codec.

           hr = pifg->FindFilterByName(L"MPEG Video Codec", &pifPP);

13. Retrieve the ISpecifyPropertyPages interface for the MPEG Video Codec. This filter has a property page that enables you to play MPEG files in color or monochrome.

           pif->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pispp);

14. Allocate a counted array of GUIDs for the property page. The ISpecifyPropertyPages::GetPages method uses the COM CAUUID structure to receive an array of CLSIDs from the filter for each of its property pages. The structure has two members, cElems, which holds the number of property pages, and pElems, which points to an array holding the property page CLSIDs.

           CAUUID caGUID;

15. Using the pointer to the MPEG Video Decoder filter's property page, pispp, call the COM ISpecifyPropertyPages::GetPages method to fill the caGUID structure with a counted array of UUIDs, where each UUID specifies a property page CLSID.

           pispp->GetPages(&caGUID);

16. Release the ISpecifyPropertyPages interface.

          HELPER_RELEASE(pispp);

17. Create a modal dialog box to display the MPEG Video Decoder filter's property page. This dialog box appears before the video is played, enabling the user to choose to play back in color or monochrome.

           OleCreatePropertyFrame(NULL,
                    0,
                    0,
                    L"Filter",          // Caption for the dialog box
                    1,                  // Number of filters
                    (IUnknown **)&pifPP,  // Pointer to the filter whose property
                                        // Pages are being displayed. This can
                                        // be an array of pointers if more than
                                        // one filter's property pages are to
                                        // be displayed. Note that only
                                        // properties common to all the filters
                                        // can be displayed on the same modal
                                        // dialog.
                    caGUID.cElems,      // Number of property pages
                    caGUID.pElems,      // Pointer to property page CLSIDs
                    0,
                    0,
                    NULL);

18. Release the IBaseFilter interface.

          HELPER_RELEASE(pifPP);

The MPegProp sample uses the same WndMainProc callback function to handle the filter graph messages, 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. These are all generic windows functions.

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