SAMPLE: Opropsheet.exe Create a Modeless OLE Property Sheet Using MFCID: Q234545
|
The OLE API OleCreatePropertyFrame() is used to create a modal property sheet displaying the property pages supported by a given object. This API does not support modeless creation. There is no equivalent API for creating a modeless OLE property sheet. This article explains how to create one using MFC.
Opropsheet.exe is a self extracting archive that contains a Visual C++ 6.0 workspace (Opropsheet.dsw). This workspace contains two projects, CTRL and PROPCLI. The CTRL project is an ATL full control. This control supports two OLE property pages, the system-provided stock color and a custom property page called PropPageCustom. The PROPCLI project is an MFC dialog box-based client application for the CTRL control. This project also contains the code for the modeless property sheet. After invoking the property sheet, you can change properties and see the control get updated; because it is modeless, you can leave it active and return to the main UI.
The following file is available for download from the Microsoft
Software Library. Click the file name below to download the file:
Opropsheet.exeRelease Date: Jul-23-1999
Q119591 How to Obtain Microsoft Support Files from Online ServicesTo create a modeless OLE Property Sheet, you need to write your own property frame and property page site. This is not a trivial task because you also need to implement the rest of what OleCreatePropertyFrame gives you, that is, a parent dialog box with a tab control (the property sheet), display and hiding of property pages, navigation between pages and the property sheet, creation and destruction of the property page objects, and implementation of IPropertyPageSite.
BOOL COlePropSheet::Create(CWnd* pParentWnd, DWORD dwStyle, DWORD dwExStyle)
{
ASSERT(m_pUnkServer != NULL);
// Get number of property pages that reside in object.
ISpecifyPropertyPages * lpSPP;
HRESULT hRes = m_pUnkServer->QueryInterface(IID_ISpecifyPropertyPages, (LPVOID*)&lpSPP);
if( FAILED( hRes ) )
AfxThrowOleException( hRes );
CAUUID cauuid;
lpSPP->GetPages(&cauuid);
m_iPageCnt = cauuid.cElems;
lpSPP->Release();
for (UINT i = 0; i < m_iPageCnt; i++)
{
// Create CPropertyPages and Property page sites.
COlePropPage * pPage = new COlePropPage(cauuid.pElems[i], m_pUnkServer);
if (pPage == NULL)
return FALSE;
m_pageArray.Add(pPage);
AddPage((COlePropPage*)m_pageArray[i]);
}
return CPropertySheet::Create(pParentWnd, dwStyle, dwExStyle);
}
COlePropPage::COlePropPage(CLSID clsidPage, LPUNKNOWN lpUnkPage) : CPropertyPage(COlePropPage::IDD),
m_clsidPage(clsidPage), m_pObject(lpUnkPage)
{
HRESULT hRes = E_FAIL;
m_pPropPage=NULL;
try {
// Create COM Property page and get IPropertyPage interface.
hRes = CoCreateInstance( m_clsidPage, NULL, CLSCTX_INPROC, IID_IPropertyPage, (void**)&m_pPropPage );
if( FAILED( hRes ) )
AfxThrowOleException( hRes );
hRes = m_pPropPage->SetPageSite( (IPropertyPageSite*) GetInterface( &IID_IPropertyPageSite ) );
if( FAILED( hRes ) )
AfxThrowOleException( hRes );
hRes = m_pPropPage->SetObjects( 1, &m_pObject );
if( FAILED( hRes ) )
AfxThrowOleException( hRes );
IMalloc *pIMalloc;
if (FAILED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
AfxThrowOleException(E_FAIL);
PROPPAGEINFO* pPPI = (PROPPAGEINFO*) pIMalloc->Alloc(sizeof(PROPPAGEINFO));
pPPI->cb = sizeof(PROPPAGEINFO);
hRes = m_pPropPage->GetPageInfo(pPPI);
m_strCaption.Format("%S", pPPI->pszTitle);
m_psp.pszTitle = m_strCaption;
m_psp.dwFlags |= PSP_USETITLE;
pIMalloc->Free(pPPI);
pIMalloc->Release();
}
catch (COleException * e)
{
throw (e);
}
file://{{AFX_DATA_INIT(COlePropPage)
// <B>NOTE</B>: The ClassWizard adds member initialization here
file://}}AFX_DATA_INIT
}
// Parent COM Property page to placeholder page,
// add WS_EX_CONTROLPARENT to COM property page.
BOOL COlePropPage::OnInitDialog()
{
CPropertyPage::OnInitDialog();
HRESULT hRes = E_FAIL;
try {
// Activate COM property page and parent to placeholder page.
CRect pgrect;
GetWindowRect(&pgrect);
ScreenToClient(pgrect);
hRes = m_pPropPage->Activate( GetSafeHwnd(), pgrect, TRUE );
if( FAILED( hRes ) )
AfxThrowOleException( hRes );
hRes = m_pPropPage->Show( SW_SHOW );
if( FAILED( hRes ) )
AfxThrowOleException( hRes );
} catch (COleException * e)
{
throw (e);
}
// Add WS_EX_CONTROLPARENT style to property page
// necessary to allow tabbing from page to sheet.
// Get COM Prop Page.
CWnd * pWnd = GetWindow(GW_CHILD);
CString str;
::GetClassName(pWnd->GetSafeHwnd(), str.GetBuffer(128), 128);
str.ReleaseBuffer();
if (str == (CString)"#32770") // #32770 is dialog class name
pWnd->ModifyStyleEx(0,WS_EX_CONTROLPARENT,0);
return TRUE; // Return TRUE unless you set the focus to a control.
}
Q103788 Creating a modeless dialog box with MFC libraries
Q117500 Using Accelerators with MFC Modeless Dialog
m_pModelessSheet = new CModelessOPS(m_ctrl.GetControlUnknown(),
_T("Modeless Ole Property Sheet"));
m_pModelessSheet->Create();
With the exception of the additional parameter in the property sheet constructor, this is exactly how you would create a "normal" modeless property sheet.Q146916 How to Create a Modeless CPropertySheet With Standard Buttons
Visual C++ documentation: TN038: MFC/OLE IUnknown Implementation.
Visual C++ documentation: Tom's Handy Dandy MFC/COM/MIDL Recipe Book for Creating Custom Interfaces.
For additional information, please see the following
articles in the Microsoft Knowledge Base:
Q103788 Creating a modeless dialog box with MFC libraries
Q117500 Using Accelerators with MFC Modeless Dialog
Q146916 How to Create a Modeless CPropertySheet With Standard ButtonsMSDN, see "Inside OLE": The Property Page Site: IPropertyPageSite
© Microsoft Corporation 1999, All Rights Reserved.
Contributions by Mike Francis, Microsoft Corporation
Additional query words: CPropertySheet IPropertyPage IPropertyPageSite WS_EX_CONTROLPARENT ISpecifyPropertyPages
Keywords : kbfile kbole kbsample kbActiveX kbCtrl kbDlg kbMFC kbVC500 kbVC600 kbDSupport kbGrpMFCATL
Version : winnt:5.0,6.0
Platform : winnt
Issue type :
Last Reviewed: July 23, 1999