[PATCH] Implement OleCreatePropertyFrame (try 3)

Geoffrey Hausheer winedevel9605 at phracturedblue.com
Mon Jan 18 10:28:49 CST 2010


This patch implements OleCreatePropertyFrame() and
OleCreatePropertyFrameIndirect().

Third try includes more comments from Piotr Caban.  Mostly fixing how
the frame size is calculated as well as making the IPropertyPageSite
implementation into a proper COM object.

Ge
-------------- next part --------------
commit 034701acf71abdef4b3c45bf38920a26db32e7ed
Author: Geoffrey Hausheer <winedevel9605 at phracturedblue.com>
Date:   Mon Jan 18 08:17:02 2010 -0800

    Implement OleCreatePropertyFrame and OleCreatePropertyFrameIndirect

diff --git a/dlls/oleaut32/Makefile.in b/dlls/oleaut32/Makefile.in
index a8ab7b4..d304257 100644
--- a/dlls/oleaut32/Makefile.in
+++ b/dlls/oleaut32/Makefile.in
@@ -17,6 +17,7 @@ C_SRCS = \
 	oleaut.c \
 	olefont.c \
 	olepicture.c \
+	olepropframe.c \
 	recinfo.c \
 	regsvr.c \
 	safearray.c \
diff --git a/dlls/oleaut32/olepropframe.c b/dlls/oleaut32/olepropframe.c
new file mode 100644
index 0000000..b424181
--- /dev/null
+++ b/dlls/oleaut32/olepropframe.c
@@ -0,0 +1,353 @@
+/*
+ *	OleCreatePropertyFrame
+ *
+ *	Copyright 2010	Geoffrey Hausheer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#define COBJMACROS
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+
+#include "winerror.h"
+#include "windef.h"
+#include "winbase.h"
+#include "winnls.h"
+#include "winreg.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "lzexpand.h"
+
+#include "wine/unicode.h"
+#include "objbase.h"
+#include "typelib.h"
+#include "wine/debug.h"
+#include "variant.h"
+#include "wine/list.h"
+#include "ocidl.h"
+#include "prsht.h"
+#include "olectl.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(olepropframe);
+
+typedef struct
+{
+    const IPropertyPageSiteVtbl* lpVtbl;
+    LCID lcid;
+    LONG ref;
+} OLEPropertyPageSite;
+
+typedef struct {
+    struct {
+         DLGTEMPLATE dlg;
+         WORD menu;
+         WORD class;
+         WORD caption;
+    } dialog;
+    IPropertyPageSite *pps;
+    IPropertyPage  *propPage;
+} OLEPropertyFrame;
+
+static INT_PTR CALLBACK prop_sheet_proc(HWND hwnd, UINT msg, WPARAM wparam,
+                                      LPARAM lparam)
+{
+
+    switch(msg)
+    {
+    case WM_INITDIALOG:
+      {
+        RECT rect;
+        HRESULT result;
+        PROPSHEETPAGEW *psp = (PROPSHEETPAGEW *)lparam; 
+        OLEPropertyFrame *opf = (OLEPropertyFrame *)psp->lParam;
+
+        TRACE("(%p, %s, %ld, %p)\n", hwnd, "WM_INITDIALOG",
+              wparam, opf->propPage);
+        ZeroMemory(&rect, sizeof(rect));
+        GetClientRect(hwnd, &rect);
+        result = IPropertyPage_Activate(opf->propPage, hwnd, &rect, TRUE);
+        if(result == S_OK) {
+            result = IPropertyPage_Show(opf->propPage, SW_SHOW);
+            if(result == S_OK) {
+                SetWindowLongPtrW(hwnd, DWLP_USER, (LONG)opf);
+            }
+        }
+        break;
+      }
+    case WM_DESTROY:
+      {
+        OLEPropertyFrame *opf = (OLEPropertyFrame *)GetWindowLongPtrW(hwnd, DWLP_USER);
+        if(opf) {
+            IPropertyPage_Show(opf->propPage, SW_HIDE);
+            IPropertyPage_Deactivate(opf->propPage);
+            SetWindowLongPtrW(hwnd, DWLP_USER, (LONG)NULL);
+        }
+        break;
+      }
+    case WM_NOTIFY:
+      {
+        OLEPropertyFrame *opf = (OLEPropertyFrame *)GetWindowLongPtrW(hwnd, DWLP_USER);
+        NMHDR *nmhdr = (NMHDR *)lparam;
+        if(! opf)
+          break;
+
+        switch(nmhdr->code)
+        {
+        case PSN_APPLY:
+            TRACE("(%p, %s, %s)\n", hwnd, "WM_NOTIFY", "PSN_APPLY");
+            IPropertyPage_Apply(opf->propPage);
+            return TRUE;
+        default:
+            TRACE("(%p, %s, %d)\n", hwnd, "WM_NOTIFY", nmhdr->code);
+            return FALSE;
+        }
+      }
+    default:
+        TRACE("(%p, %d, %ld, %p)\n", hwnd, msg, wparam, (void *)lparam);
+    }
+    return FALSE;
+}
+
+/******************************************************************************/
+static ULONG WINAPI PPS_AddRef(IPropertyPageSite* iface)
+{
+    OLEPropertyPageSite *this = (OLEPropertyPageSite *)iface;
+    TRACE("(%p)->(ref=%d)\n", this, this->ref);
+    return InterlockedIncrement(&this->ref);
+}
+
+static ULONG WINAPI PPS_Release(IPropertyPageSite* iface)
+{
+    HRESULT hr;
+    OLEPropertyPageSite *this = (OLEPropertyPageSite *)iface;
+
+    /* Decrease the reference count for current interface */
+    hr = InterlockedDecrement(&this->ref);
+    TRACE("(%p)->(ref=%d)\n", this, hr);
+    if (hr == 0) {
+        HeapFree(GetProcessHeap(),0,this);
+    }
+    return hr;
+}
+    
+static HRESULT WINAPI PPS_QueryInterface(
+    IPropertyPageSite*  iface,
+    REFIID  riid,
+    void**  ppvObject)
+{
+    TRACE("(%p) riid: %s\n",iface, debugstr_guid(riid));
+
+    if(ppvObject == NULL)
+        return E_INVALIDARG;
+
+    if(IsEqualGUID(&IID_IUnknown, riid)
+        || IsEqualGUID(&IID_IPropertyPageSite, riid))
+    {
+        *ppvObject = iface;
+    } else {
+        *ppvObject = NULL;
+        return E_NOINTERFACE;
+    }
+    PPS_AddRef((IPropertyPageSite*)iface);
+    return S_OK;
+}
+
+static HRESULT WINAPI PPS_OnStatusChange(IPropertyPageSite *iface, DWORD dwFlags)
+{
+    FIXME("(%p, %d)", iface, dwFlags);
+    return S_OK;
+}
+
+static HRESULT WINAPI PPS_GetLocaleID(IPropertyPageSite *iface, LCID *pLocaleID)
+{
+    OLEPropertyPageSite *pps = (OLEPropertyPageSite *)iface;
+    TRACE("(%p, %p)", iface, pLocaleID);
+    if(pLocaleID == NULL)
+        return E_POINTER;
+
+    *pLocaleID = pps->lcid;
+    return S_OK;
+}
+
+static HRESULT WINAPI PPS_GetPageContainer(IPropertyPageSite* iface, IUnknown** ppUnk)
+{
+    TRACE("(%p, %p)", iface, ppUnk);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI PPS_TranslateAccelerator(IPropertyPageSite* iface, MSG *pMsg)
+{
+    TRACE("(%p, %p)", iface, pMsg);
+    return E_NOTIMPL;
+}
+
+IPropertyPageSiteVtbl PPS_Vtbl = {
+    PPS_QueryInterface,
+    PPS_AddRef,
+    PPS_Release,
+    PPS_OnStatusChange,
+    PPS_GetLocaleID,
+    PPS_GetPageContainer,
+    PPS_TranslateAccelerator
+};
+
+static IPropertyPageSite *PPS_create(LCID lcid)
+{
+    OLEPropertyPageSite *this;
+    this = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+                     sizeof(OLEPropertyPageSite));
+    this->ref = 1;
+    this->lcid = lcid;
+    this->lpVtbl = &PPS_Vtbl;
+    return (IPropertyPageSite *)this;
+}
+/******************************************************************************/
+HRESULT WINAPI OleCreatePropertyFrameIndirect(LPOCPFIPARAMS lpParams)
+{
+    PROPSHEETHEADERW propSheet;
+    PROPSHEETPAGEW psp;
+    PROPPAGEINFO pPageInfo;
+    HPROPSHEETPAGE *hpsp;
+    OLEPropertyFrame *opf;
+    int page;
+    HRESULT result;
+    HFONT font = GetStockObject(DEFAULT_GUI_FONT);
+    HDC hdc = GetDC(NULL);
+    LONG xBaseUnit, yBaseUnit;
+
+    TRACE("(%p)\n** OCPFIPARAMS **\ncbStructSize\t%d\nhWndOwner\t%p\nx\t\t%d\n"
+          "y\t\t%d\nlpszCaption\t%p\ncObjects\t%d\nlplpUnk\t\t%p\ncPages\t%d\n"
+          "lpPages\t%p\nlcid\t\t%x\ndispidInitialProperty\t%d\n",
+          lpParams, lpParams->cbStructSize, lpParams->hWndOwner, lpParams->x,
+          lpParams->y,
+          lpParams->lpszCaption, lpParams->cObjects, lpParams->lplpUnk,
+          lpParams->cPages, lpParams->lpPages, (int)lpParams->lcid,
+          lpParams->dispidInitialProperty);
+
+    if(lpParams->dispidInitialProperty) {
+        FIXME("dispidInitialProperty is not yet implemented\n");
+    }
+
+    ZeroMemory(&propSheet, sizeof(propSheet));
+
+    propSheet.dwSize = sizeof(propSheet);
+    propSheet.dwFlags = PSH_PROPTITLE;
+    
+    propSheet.pszCaption = lpParams->lpszCaption;
+
+    hpsp = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+                     lpParams->cPages * sizeof(HPROPSHEETPAGE));
+    opf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+                     lpParams->cPages * sizeof(OLEPropertyFrame));
+
+    propSheet.u3.phpage = hpsp;
+
+    ZeroMemory(&psp, sizeof(psp));
+    psp.dwSize=sizeof(psp);
+    psp.dwFlags = PSP_DLGINDIRECT | PSP_USETITLE;
+    psp.pfnDlgProc = prop_sheet_proc;
+
+    /* Calculate average character width fo converting pixels to dialog units */
+    font = SelectObject(hdc, font);
+    xBaseUnit = GdiGetCharDimensions( hdc, NULL, &yBaseUnit );
+
+    for(page = 0; page < lpParams->cPages;  page++) {
+        result = CoCreateInstance(&lpParams->lpPages[page],NULL,
+                                  CLSCTX_INPROC_SERVER,&IID_IPropertyPage,
+                                  (void**)&opf[page].propPage);
+        if(result != S_OK) {
+            continue;
+        }
+        opf[page].pps = PPS_create(lpParams->lcid);
+
+        result = IPropertyPage_SetPageSite(opf[page].propPage, opf[page].pps);
+        IPropertyPageSite_Release(opf[page].pps);
+
+        if(result != S_OK) {
+            continue;
+        }
+        result = IPropertyPage_GetPageInfo(opf[page].propPage, &pPageInfo);
+        if(result != S_OK) {
+            continue;
+        }
+        result = IPropertyPage_SetObjects(opf[page].propPage,
+                               lpParams->cObjects, lpParams->lplpUnk);
+        if(result != S_OK) {
+            continue;
+        }
+        opf[page].dialog.dlg.cx = MulDiv(pPageInfo.size.cx, 4, xBaseUnit);
+        opf[page].dialog.dlg.cy = MulDiv(pPageInfo.size.cy, 8, yBaseUnit);
+
+        psp.u.pResource = (DLGTEMPLATE *)&opf[page].dialog;
+        psp.lParam = (LPARAM) &opf[page];
+        psp.pszTitle = pPageInfo.pszTitle;
+        hpsp[propSheet.nPages++] = CreatePropertySheetPageW(&psp);
+    }
+    result = PropertySheetW(&propSheet);
+
+    for(page = 0; page < lpParams->cPages; page++) {
+        if(opf[page].propPage) {
+            IPropertyPage_SetPageSite(opf[page].propPage, NULL);
+            IPropertyPage_Release(opf[page].propPage);
+        }
+    }
+    HeapFree(GetProcessHeap(), 0, hpsp);
+    HeapFree(GetProcessHeap(), 0, opf);
+    if(result == -1)
+        return E_UNEXPECTED;
+    return S_OK;
+}
+
+HRESULT WINAPI OleCreatePropertyFrame(
+    HWND hWndOwner,
+    UINT x,
+    UINT y, 
+    LPCOLESTR lpszCaption,
+    ULONG cObjects,
+    LPUNKNOWN *ppUnk,
+    ULONG cPages,
+    LPCLSID pPageClsID,
+    LCID lcid,
+    DWORD dwReserved,
+    LPVOID pvReserved)
+{
+    OCPFIPARAMS ocpf;
+
+    ocpf.cbStructSize =  sizeof(OCPFIPARAMS);
+    ocpf.hWndOwner    = hWndOwner;
+    ocpf.x            = x;
+    ocpf.y            = y;
+    ocpf.lpszCaption  = lpszCaption;
+    ocpf.cObjects     = cObjects;
+    ocpf.lplpUnk      = ppUnk;
+    ocpf.cPages       = cPages;
+    ocpf.lpPages      = pPageClsID;
+    ocpf.lcid         = lcid;
+    ocpf.dispidInitialProperty = 0;
+
+    return OleCreatePropertyFrameIndirect(&ocpf);
+}
+
diff --git a/dlls/oleaut32/stubs.c b/dlls/oleaut32/stubs.c
index d87e76e..164be38 100644
--- a/dlls/oleaut32/stubs.c
+++ b/dlls/oleaut32/stubs.c
@@ -32,25 +32,3 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(ole);
 
-/***********************************************************************
- * OleCreatePropertyFrameIndirect (OLEAUT32.416)
- */
-HRESULT WINAPI OleCreatePropertyFrameIndirect( LPOCPFIPARAMS lpParams)
-{
-	FIXME("(%p), not implemented (olepro32.dll)\n",lpParams);
-	return S_OK;
-}
-
-/***********************************************************************
- * OleCreatePropertyFrame (OLEAUT32.417)
- */
-HRESULT WINAPI OleCreatePropertyFrame(
-    HWND hwndOwner, UINT x, UINT y, LPCOLESTR lpszCaption,ULONG cObjects,
-    LPUNKNOWN* ppUnk, ULONG cPages, LPCLSID pPageClsID, LCID lcid,
-    DWORD dwReserved, LPVOID pvReserved )
-{
-	FIXME("(%p,%d,%d,%s,%d,%p,%d,%p,%x,%d,%p), not implemented (olepro32.dll)\n",
-		hwndOwner,x,y,debugstr_w(lpszCaption),cObjects,ppUnk,cPages,
-		pPageClsID, (int)lcid,dwReserved,pvReserved);
-	return S_OK;
-}


More information about the wine-patches mailing list