DirectShow, OleCreatePropertyFrame Issues and Button Return Codes

Build Date: 27-May-2019

When building a DirectShow app, it's usually desirable to display camera configuration property sheets, such as this one.

There's several coding issues with getting this work that appear over and over in developer forums, as follows.

  1. The call to OleCreatePropertyFrame includes X,Y coordinates that are supposed to locate the property frame, but are listed as reserved and have no effect. How do we get the Property Sheet to appear where we want?
  2. There is no obvious or perhaps no way to get the button return codes, which is what is normally done with a dialog.

Let's clarify this...

The OleCreatePropertyFrame call displays a modal dialog box, and the X, Y position is ignored. This is a known Microsoft bug. The solution is to create a new locator window (a Button class will do) in the desired place and use the new handle to locate the PropertyFrame. Remember to delete the locator window when you are done.

The PropertyFrame attaches itself to the window (which never appears) and is presented to the user at the position set when the locator window was created. Here's some sample code.

 // hwndApp is the app parent window
// mainRect is the parent window rectangle
// Some error handling is omitted for clarity

ISpecifyPropertyPages *pSpec;
 CAUUID cauuid;

 HRESULT hr = pVideoCapture->QueryInterface(IID_ISpecifyPropertyPages,(void **)&pSpec);
 hr = pSpec->GetPages(&cauuid);

 HWND hLocatorWnd = NULL;
 LPCOLESTR lpszCaption = TEXT("PiXCL Endoscope-3");

 hLocatorWnd = CreateWindow(TEXT("Button"),TEXT("Locator"),WS_POPUPWINDOW,
                    mainRect.right, mainRect.top, 20,20, hwndApp, NULL,NULL, NULL);

// The width and height (20,20) are arbitrary. 

 hr = OleCreatePropertyFrame(hLocatorWnd,
              0,0, // x,y position of the dialog box in the parent window. Ignored.
             
lpszCaption,
              1, // Number of object pointers passed
              (IUnknown **)&pVideoCapture, // An array of IUnknown pointers
               cauuid.cElems, // Number of property pages specified in cauuid.pElems
               (GUID *)cauuid.pElems, // Array of size cPages containing the CLSIDs
                                     // of each property page to display in the property sheet.
               0, // Locale, 0 is OK as default
               0, NULL); // these two are reserved items.

 // Check returned hr value as needed, then clean up.

 DestroyWindow(hLocatorWnd);

 CoTaskMemFree(cauuid.pElems);
 pSpec->Release();

The second issue, getting the button return codes, is at first glance more difficult. The OleCreatePropertyFrame call returns an HRESULT only, and even if you create and register a new window class with its own WndProc handler, you still can't get the Property Frame button return codes.

In fact, you don't need the button return codes at all. The Property Frame is a COM (a.k.a Ole) object and all message handling is done internally. All your code needs to do is handle the HRESULT.

For example, the above Video Proc Amp sheet appears while the video stream is running, and changes you make e.g. Gain are reflected in the video stream.

If you click the Cancel button, the Property Sheet object resets the original video stream values and, as you would expect, the video stream remains unchanged.

Once a change is made, the Apply button is enabled. If you click the Apply button, the changes are are written to the video stream, and the Cancel button does not cause a reversion.

Likewise, clicking the OK button, as you would expect, updates the video stream and the Property Sheet closes.

   

*****************************

Got a question on this code? Email Technical Support
 
Like us on Facebook.
 

 
Since you are here, do please have a look around the rest of our website.
 

Copyright © 2012-2019 PiXCL Automation Technologies Inc, Canada. All Rights Reserved.