NT4/private/ole2ui32/objprop.cpp
2020-09-30 17:12:29 +02:00

1336 lines
53 KiB
C++

/*
* OBJPROP.CPP
*
* Implements the OleUIObjectProperties function which invokes the complete
* Object Properties dialog.
*
* Copyright (c)1992 Microsoft Corporation, All Right Reserved
*/
#include "precomp.h"
#include "common.h"
#include "utility.h"
#include "iconbox.h"
#include "resimage.h"
#include <stddef.h>
OLEDBGDATA
// Internally used structure
typedef struct tagGNRLPROPS
{
// Keep this item first as the Standard* functions depend on it here.
LPOLEUIGNRLPROPS lpOGP; // Original structure passed.
UINT nIDD; // IDD of dialog (used for help info)
CLSID clsidNew; // new class ID (if conversion done)
} GNRLPROPS, *PGNRLPROPS, FAR* LPGNRLPROPS;
typedef struct tagVIEWPROPS
{
// Keep this item first as the Standard* functions depend on it here.
LPOLEUIVIEWPROPS lpOVP; // Original structure passed.
UINT nIDD; // IDD of dialog (used for help info)
BOOL bIconChanged;
int nCurrentScale;
BOOL bRelativeToOrig;
DWORD dvAspect;
} VIEWPROPS, *PVIEWPROPS, FAR* LPVIEWPROPS;
typedef struct tagLINKPROPS
{
// Keep this item first as the Standard* functions depend on it here.
LPOLEUILINKPROPS lpOLP; // Original structure passed.
UINT nIDD; // IDD of dialog (used for help info)
DWORD dwUpdate; // original update mode
LPTSTR lpszDisplayName;// new link source
ULONG nFileLength; // file name part of source
} LINKPROPS, *PLINKPROPS, FAR* LPLINKPROPS;
// Internal function prototypes
// OBJPROP.CPP
/*
* OleUIObjectProperties
*
* Purpose:
* Invokes the standard OLE Object Properties dialog box allowing the user
* to change General, View, and Link properties of an OLE object. This
* dialog uses the new Windows 95 tabbed dialogs.
*
* Parameters:
* lpOP LPOLEUIObjectProperties pointing to the in-out structure
* for this dialog.
*
* Return Value:
* UINT One of the following codes, indicating success or error:
* OLEUI_SUCCESS Success
* OLEUI_ERR_STRUCTSIZE The dwStructSize value is wrong
*
*/
static UINT WINAPI ValidateObjectProperties(LPOLEUIOBJECTPROPS);
static UINT WINAPI PrepareObjectProperties(LPOLEUIOBJECTPROPS);
STDAPI_(UINT) OleUIObjectProperties(LPOLEUIOBJECTPROPS lpOP)
{
#ifdef UNICODE
return (InternalObjectProperties(lpOP, TRUE));
#else
return (InternalObjectProperties(lpOP, FALSE));
#endif
}
UINT InternalObjectProperties(LPOLEUIOBJECTPROPS lpOP, BOOL fWide)
{
// Validate Parameters
UINT uRet = ValidateObjectProperties(lpOP);
if (OLEUI_SUCCESS != uRet)
return uRet;
if (NULL == lpOP->lpObjInfo)
{
return(OLEUI_OPERR_OBJINFOINVALID);
}
if (IsBadReadPtr(lpOP->lpObjInfo, sizeof(IOleUIObjInfo)))
{
return(OLEUI_OPERR_OBJINFOINVALID);
}
if (lpOP->dwFlags & OPF_OBJECTISLINK)
{
if (NULL == lpOP->lpLinkInfo)
{
return(OLEUI_OPERR_LINKINFOINVALID);
}
if (IsBadReadPtr(lpOP->lpLinkInfo, sizeof(IOleUILinkInfo)))
{
return(OLEUI_OPERR_LINKINFOINVALID);
}
}
// Fill Missing values in lpPS
LPPROPSHEETHEADER lpPS = (LPPROPSHEETHEADER)lpOP->lpPS;
LPPROPSHEETPAGE lpPP = (LPPROPSHEETPAGE)lpPS->ppsp;
uRet = PrepareObjectProperties(lpOP);
if (OLEUI_SUCCESS != uRet)
return uRet;
LPTSTR lpszShortType = NULL;
lpOP->lpObjInfo->GetObjectInfo(lpOP->dwObject, NULL, NULL,
NULL, &lpszShortType, NULL);
if (lpszShortType == NULL)
return OLEUI_ERR_OLEMEMALLOC;
TCHAR szCaption[256];
if (lpPS->pszCaption == NULL)
{
TCHAR szTemp[256];
LoadString(_g_hOleStdResInst,
(lpOP->dwFlags & OPF_OBJECTISLINK) ?
IDS_LINKOBJECTPROPERTIES : IDS_OBJECTPROPERTIES,
szTemp, sizeof(szTemp));
wsprintf(szCaption, szTemp, lpszShortType);
#ifdef UNICODE
if (!fWide)
{
// We're going to actually call the ANSI version of PropertySheet,
// so we need to store the caption as an ANSI string.
lstrcpy(szTemp, szCaption);
WTOA((char *)szCaption, szTemp, 256);
}
#endif
lpPS->pszCaption = szCaption;
}
OleStdFree(lpszShortType);
// Invoke the property sheet
int nResult = StandardPropertySheet(lpOP->lpPS, fWide);
// Cleanup any temporary memory allocated during the process
if (lpPP == NULL)
{
OleStdFree((LPVOID)lpOP->lpPS->ppsp);
lpOP->lpPS->ppsp = NULL;
}
// map PropertPage return value to OLEUI_ return code
if (nResult < 0)
uRet = OLEUI_OPERR_PROPERTYSHEET;
else if (nResult == 0)
uRet = OLEUI_CANCEL;
else
uRet = OLEUI_OK;
return uRet;
}
/////////////////////////////////////////////////////////////////////////////
// Validation code
static UINT WINAPI ValidateGnrlProps(LPOLEUIGNRLPROPS lpGP)
{
OleDbgAssert(lpGP != NULL);
if (lpGP->cbStruct != sizeof(OLEUIGNRLPROPS))
return OLEUI_ERR_CBSTRUCTINCORRECT;
if (lpGP->lpfnHook && IsBadCodePtr((FARPROC)lpGP->lpfnHook))
return OLEUI_ERR_LPFNHOOKINVALID;
return OLEUI_SUCCESS;
}
static UINT WINAPI ValidateViewProps(LPOLEUIVIEWPROPS lpVP)
{
OleDbgAssert(lpVP != NULL);
if (lpVP->cbStruct != sizeof(OLEUIVIEWPROPS))
return OLEUI_ERR_CBSTRUCTINCORRECT;
if (lpVP->lpfnHook && IsBadCodePtr((FARPROC)lpVP->lpfnHook))
return OLEUI_ERR_LPFNHOOKINVALID;
return OLEUI_SUCCESS;
}
static UINT WINAPI ValidateLinkProps(LPOLEUILINKPROPS lpLP)
{
OleDbgAssert(lpLP != NULL);
if (lpLP->cbStruct != sizeof(OLEUILINKPROPS))
return OLEUI_ERR_CBSTRUCTINCORRECT;
if (lpLP->lpfnHook && IsBadCodePtr((FARPROC)lpLP->lpfnHook))
return OLEUI_ERR_LPFNHOOKINVALID;
return OLEUI_SUCCESS;
}
static UINT WINAPI ValidateObjectProperties(LPOLEUIOBJECTPROPS lpOP)
{
// Validate LPOLEUIOBJECTPROPS lpOP
if (lpOP == NULL)
return OLEUI_ERR_STRUCTURENULL;
if (IsBadWritePtr(lpOP, sizeof(OLEUIOBJECTPROPS)))
return OLEUI_ERR_STRUCTUREINVALID;
// Validate cbStruct field of OLEUIOBJECTPROPS
if (lpOP->cbStruct != sizeof(OLEUIOBJECTPROPS))
return OLEUI_ERR_CBSTRUCTINCORRECT;
// Validate "sub" property pointers
if (lpOP->lpGP == NULL || lpOP->lpVP == NULL ||
((lpOP->dwFlags & OPF_OBJECTISLINK) && lpOP->lpLP == NULL))
return OLEUI_OPERR_SUBPROPNULL;
if (IsBadWritePtr(lpOP->lpGP, sizeof(OLEUIGNRLPROPS)) ||
IsBadWritePtr(lpOP->lpVP, sizeof(OLEUIVIEWPROPS)) ||
((lpOP->dwFlags & OPF_OBJECTISLINK) &&
IsBadWritePtr(lpOP->lpLP, sizeof(OLEUILINKPROPS))))
return OLEUI_OPERR_SUBPROPINVALID;
// Validate property sheet data pointers
LPPROPSHEETHEADER lpPS = lpOP->lpPS;
if (lpPS == NULL)
return OLEUI_OPERR_PROPSHEETNULL;
if (IsBadWritePtr(lpPS, sizeof(PROPSHEETHEADER)))
return OLEUI_OPERR_PROPSHEETINVALID;
DWORD dwSize = lpPS->dwSize;
if (dwSize < sizeof(PROPSHEETHEADER))
return OLEUI_ERR_CBSTRUCTINCORRECT;
// If links specified, validate "sub" link property pointer
if (lpOP->dwFlags & OPF_OBJECTISLINK)
{
if (lpPS->ppsp != NULL && lpPS->nPages < 3)
return OLEUI_OPERR_PAGESINCORRECT;
}
else
{
if (lpPS->ppsp != NULL && lpPS->nPages < 2)
return OLEUI_OPERR_PAGESINCORRECT;
}
if (lpPS->ppsp != NULL &&
IsBadWritePtr((PROPSHEETPAGE*)lpPS->ppsp,
lpPS->nPages * sizeof(PROPSHEETPAGE)))
{
return OLEUI_OPERR_INVALIDPAGES;
}
// not setting PSH_PROPSHEETPAGE is not supported
if (lpOP->dwFlags & OPF_NOFILLDEFAULT)
{
if (!(lpPS->dwFlags & PSH_PROPSHEETPAGE))
return OLEUI_OPERR_NOTSUPPORTED;
}
else if (lpPS->dwFlags != 0)
{
return OLEUI_OPERR_NOTSUPPORTED;
}
// Sanity check any pages provided
for (UINT nPage = 0; nPage < lpPS->nPages; nPage++)
{
LPPROPSHEETPAGE lpPP = (PROPSHEETPAGE*)&lpPS->ppsp[nPage];
if (lpPP->dwSize != sizeof(PROPSHEETPAGE))
return OLEUI_ERR_CBSTRUCTINCORRECT;
if (lpPP->pfnDlgProc != NULL)
return OLEUI_OPERR_DLGPROCNOTNULL;
if (lpPP->lParam != 0)
return OLEUI_OPERR_LPARAMNOTZERO;
}
// validate individual prop page structures
UINT uRet = ValidateGnrlProps(lpOP->lpGP);
if (uRet != OLEUI_SUCCESS)
return uRet;
uRet = ValidateViewProps(lpOP->lpVP);
if (uRet != OLEUI_SUCCESS)
return uRet;
if ((lpOP->dwFlags & OPF_OBJECTISLINK) && lpOP->lpLP != NULL)
{
uRet = ValidateLinkProps(lpOP->lpLP);
if (uRet != OLEUI_SUCCESS)
return uRet;
}
return OLEUI_SUCCESS;
}
/////////////////////////////////////////////////////////////////////////////
// GnrlPropsDialogProc and helpers
// takes a DWORD add commas etc to it and puts the result in the buffer
LPTSTR AddCommas(DWORD dw, LPTSTR pszResult, UINT nMax)
{
NUMBERFMT numberFmt;
numberFmt.NumDigits = 0;
numberFmt.LeadingZero = 0;
TCHAR szSep[5];
GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SGROUPING, szSep, sizeof(szSep));
numberFmt.Grouping = Atol(szSep);
GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, szSep, sizeof(szSep));
numberFmt.lpDecimalSep = numberFmt.lpThousandSep = szSep;
numberFmt.NegativeOrder= 0;
TCHAR szTemp[64];
wsprintf(szTemp, TEXT("%lu"), dw);
GetNumberFormat(LOCALE_USER_DEFAULT, 0, szTemp, &numberFmt, pszResult, nMax);
return pszResult;
}
const short pwOrders[] = {IDS_BYTES, IDS_ORDERKB, IDS_ORDERMB, IDS_ORDERGB, IDS_ORDERTB};
/* converts numbers into short formats
* 532 -> 523 bytes
* 1340 -> 1.3KB
* 23506 -> 23.5KB
* -> 2.4MB
* -> 5.2GB
*/
LPTSTR ShortSizeFormat64(__int64 dw64, LPTSTR szBuf)
{
int i;
UINT wInt, wLen, wDec;
TCHAR szTemp[10], szOrder[20], szFormat[5];
if (dw64 < 1000)
{
wsprintf(szTemp, TEXT("%d"), DWORD(dw64));
i = 0;
}
else
{
for (i = 1; i < (sizeof(pwOrders)/sizeof(pwOrders))-1
&& dw64 >= 1000L * 1024L; dw64 >>= 10, i++)
; /* do nothing */
wInt = DWORD(dw64 >> 10);
AddCommas(wInt, szTemp, sizeof(szTemp)/sizeof(TCHAR));
wLen = lstrlen(szTemp);
if (wLen < 3)
{
wDec = DWORD(dw64 - (__int64)wInt * 1024L) * 1000 / 1024;
// At this point, wDec should be between 0 and 1000
// we want get the top one (or two) digits.
wDec /= 10;
if (wLen == 2)
wDec /= 10;
// Note that we need to set the format before getting the
// intl char.
lstrcpy(szFormat, TEXT("%02d"));
szFormat[2] = '0' + 3 - wLen;
GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL,
szTemp+wLen, sizeof(szTemp)-wLen);
wLen = lstrlen(szTemp);
wLen += wsprintf(szTemp+wLen, szFormat, wDec);
}
}
LoadString(_g_hOleStdResInst, pwOrders[i], szOrder, sizeof(szOrder));
wsprintf(szBuf, szOrder, (LPSTR)szTemp);
return szBuf;
}
LPTSTR WINAPI ShortSizeFormat(DWORD dw, LPTSTR szBuf)
{
return ShortSizeFormat64((__int64)dw, szBuf);
}
BOOL FGnrlPropsRefresh(HWND hDlg, LPGNRLPROPS lpGP)
{
// get object information and fill in default fields
LPOLEUIOBJECTPROPS lpOP = lpGP->lpOGP->lpOP;
LPOLEUIOBJINFO lpObjInfo = lpOP->lpObjInfo;
// get object's icon
HGLOBAL hMetaPict;
lpObjInfo->GetViewInfo(lpOP->dwObject, &hMetaPict, NULL, NULL);
if (hMetaPict != NULL)
{
HICON hIcon = OleUIMetafilePictExtractIcon(hMetaPict);
SendDlgItemMessage(hDlg, IDC_GP_OBJECTICON, STM_SETICON,
(WPARAM)hIcon, 0);
}
OleUIMetafilePictIconFree(hMetaPict);
// get type, short type, location, and size of object
DWORD dwObjSize;
LPTSTR lpszLabel = NULL;
LPTSTR lpszType = NULL;
LPTSTR lpszShortType = NULL;
LPTSTR lpszLocation = NULL;
lpObjInfo->GetObjectInfo(lpOP->dwObject, &dwObjSize, &lpszLabel,
&lpszType, &lpszShortType, &lpszLocation);
// set name, type, and size of object
SetDlgItemText(hDlg, IDC_GP_OBJECTNAME, lpszLabel);
SetDlgItemText(hDlg, IDC_GP_OBJECTTYPE, lpszType);
SetDlgItemText(hDlg, IDC_GP_OBJECTLOCATION, lpszLocation);
TCHAR szTemp[128];
if (dwObjSize == (DWORD)-1)
{
LoadString(_g_hOleStdResInst, IDS_OLE2UIUNKNOWN, szTemp, 64);
SetDlgItemText(hDlg, IDC_GP_OBJECTSIZE, szTemp);
}
else
{
// get the master formatting string
TCHAR szFormat[64];
LoadString(_g_hOleStdResInst, IDS_OBJECTSIZE, szFormat, 64);
// format the size in two ways (short, and with commas)
TCHAR szNum1[20], szNum2[32];
ShortSizeFormat(dwObjSize, szNum1);
AddCommas(dwObjSize, szNum2, 32);
FormatString2(szTemp, szFormat, szNum1, szNum2);
// set the control's text
SetDlgItemText(hDlg, IDC_GP_OBJECTSIZE, szTemp);
}
// enable/disable convert button as necessary
BOOL bEnable = TRUE;
if (lpOP->dwFlags & (OPF_OBJECTISLINK|OPF_DISABLECONVERT))
bEnable = FALSE;
else
{
CLSID clsid; WORD wFormat;
lpObjInfo->GetConvertInfo(lpOP->dwObject, &clsid, &wFormat, NULL, NULL, NULL);
bEnable = OleUICanConvertOrActivateAs(clsid, FALSE, wFormat);
}
StandardEnableDlgItem(hDlg, IDC_GP_CONVERT, bEnable);
// cleanup temporary info strings
OleStdFree(lpszLabel);
OleStdFree(lpszType);
OleStdFree(lpszShortType);
OleStdFree(lpszLocation);
return TRUE;
}
BOOL FGnrlPropsInit(HWND hDlg, WPARAM wParam, LPARAM lParam)
{
// Copy the structure at lParam into our instance memory.
HFONT hFont;
LPGNRLPROPS lpGP = (LPGNRLPROPS)LpvStandardInit(hDlg, sizeof(GNRLPROPS), &hFont);
// LpvStandardInit send a termination to us already.
if (NULL == lpGP)
return FALSE;
LPPROPSHEETPAGE lpPP = (LPPROPSHEETPAGE)lParam;
LPOLEUIGNRLPROPS lpOGP = (LPOLEUIGNRLPROPS)lpPP->lParam;
lpGP->lpOGP = lpOGP;
lpGP->nIDD = IDD_GNRLPROPS;
// If we got a font, send it to the necessary controls.
if (NULL != hFont)
{
SendDlgItemMessage(hDlg, IDC_GP_OBJECTNAME, WM_SETFONT, (WPARAM)hFont, 0L);
SendDlgItemMessage(hDlg, IDC_GP_OBJECTTYPE, WM_SETFONT, (WPARAM)hFont, 0L);
SendDlgItemMessage(hDlg, IDC_GP_OBJECTLOCATION, WM_SETFONT, (WPARAM)hFont, 0L);
SendDlgItemMessage(hDlg, IDC_GP_OBJECTSIZE, WM_SETFONT, (WPARAM)hFont, 0L);
}
// Initialize the controls
FGnrlPropsRefresh(hDlg, lpGP);
// Call the hook with lCustData in lParam
UStandardHook((PVOID)lpGP, hDlg, WM_INITDIALOG, wParam, lpOGP->lCustData);
return TRUE;
}
BOOL CALLBACK GnrlPropsDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
// Declare Win16/Win32 compatible WM_COMMAND parameters.
COMMANDPARAMS(wID, wCode, hWndMsg);
// This will fail under WM_INITDIALOG, where we allocate it.
UINT uHook = 0;
LPGNRLPROPS lpGP = (LPGNRLPROPS)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uHook);
// If the hook processed the message, we're done.
if (0 != uHook)
return (BOOL)uHook;
// Get pointers to important info
LPOLEUIGNRLPROPS lpOGP = NULL;
LPOLEUIOBJECTPROPS lpOP = NULL;
LPOLEUIOBJINFO lpObjInfo = NULL;
if (lpGP != NULL)
{
lpOGP = lpGP->lpOGP;
if (lpOGP != NULL)
{
lpObjInfo = lpOGP->lpOP->lpObjInfo;
lpOP = lpOGP->lpOP;
}
}
switch (iMsg)
{
case WM_INITDIALOG:
FGnrlPropsInit(hDlg, wParam, lParam);
return TRUE;
case WM_COMMAND:
switch (wID)
{
case IDC_GP_CONVERT:
{
// Call up convert dialog to obtain new CLSID
OLEUICONVERT cv; memset(&cv, 0, sizeof(cv));
cv.cbStruct = sizeof(cv);
cv.dwFlags |= CF_CONVERTONLY;
if (lpOP->dwFlags & OPF_SHOWHELP)
cv.dwFlags |= CF_SHOWHELPBUTTON;
cv.clsidConvertDefault = lpGP->clsidNew;
cv.dvAspect = DVASPECT_CONTENT;
lpObjInfo->GetObjectInfo(lpOP->dwObject,
NULL, NULL, &cv.lpszUserType, NULL, NULL);
lpObjInfo->GetConvertInfo(lpOP->dwObject,
&cv.clsid, &cv.wFormat, &cv.clsidConvertDefault,
&cv.lpClsidExclude, &cv.cClsidExclude);
cv.fIsLinkedObject =
(lpOGP->lpOP->dwFlags & OPF_OBJECTISLINK);
if (cv.clsidConvertDefault != CLSID_NULL)
cv.dwFlags |= CF_SETCONVERTDEFAULT;
cv.hWndOwner = GetParent(GetParent(hDlg));
// allow caller to hook the convert structure
uHook = UStandardHook(lpGP, hDlg, uMsgConvert, 0, (LPARAM)&cv);
if (0 == uHook)
{
uHook = (OLEUI_OK == OleUIConvert(&cv));
SetFocus(hDlg);
}
// check to see dialog results
if (uHook != 0 && (cv.dwFlags & CF_SELECTCONVERTTO))
{
lpGP->clsidNew = cv.clsidNew;
SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
}
}
return TRUE;
}
break;
case PSM_QUERYSIBLINGS:
SetWindowLong(hDlg, DWL_MSGRESULT, 0);
switch (wParam)
{
case OLEUI_QUERY_GETCLASSID:
*(CLSID*)lParam = lpGP->clsidNew;
SetWindowLong(hDlg, DWL_MSGRESULT, 1);
return TRUE;
case OLEUI_QUERY_LINKBROKEN:
FGnrlPropsRefresh(hDlg, lpGP);
return TRUE;
}
break;
case WM_NOTIFY:
switch (((NMHDR*)lParam)->code)
{
case PSN_HELP:
PostMessage(GetParent(GetParent(hDlg)), uMsgHelp,
(WPARAM)hDlg, MAKELPARAM(IDD_GNRLPROPS, 0));
break;
case PSN_APPLY:
// apply changes if changes made
if (lpGP->clsidNew != CLSID_NULL)
{
// convert the object -- fail the apply if convert fails
if (NOERROR != lpObjInfo->ConvertObject(lpOP->dwObject,
lpGP->clsidNew))
{
SetWindowLong(hDlg, DWL_MSGRESULT, 1);
return TRUE;
}
lpGP->clsidNew = CLSID_NULL;
}
SetWindowLong(hDlg, DWL_MSGRESULT, 0);
PostMessage(GetParent(hDlg), PSM_CANCELTOCLOSE, 0, 0);
return TRUE;
}
break;
case WM_DESTROY:
{
HICON hIcon = (HICON)SendDlgItemMessage(hDlg, IDC_GP_OBJECTICON,
STM_GETICON, 0, 0);
if (hIcon != NULL)
DestroyIcon(hIcon);
StandardCleanup((PVOID)lpGP, hDlg);
}
return TRUE;
}
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// ViewPropsDialogProc and helpers
void EnableDisableScaleControls(LPVIEWPROPS lpVP, HWND hDlg)
{
LPOLEUIVIEWPROPS lpOVP = lpVP->lpOVP;
BOOL bEnable = !(lpOVP->dwFlags & VPF_DISABLESCALE) &&
SendDlgItemMessage(hDlg, IDC_VP_ASICON, BM_GETCHECK, 0, 0) == 0;
StandardEnableDlgItem(hDlg, IDC_VP_SPIN, bEnable);
StandardEnableDlgItem(hDlg, IDC_VP_PERCENT, bEnable);
StandardEnableDlgItem(hDlg, IDC_VP_SCALETXT, bEnable);
bEnable = bEnable && !(lpOVP->dwFlags & VPF_DISABLERELATIVE);
StandardEnableDlgItem(hDlg, IDC_VP_RELATIVE, bEnable);
}
BOOL FViewPropsInit(HWND hDlg, WPARAM wParam, LPARAM lParam)
{
// Copy the structure at lParam into our instance memory.
LPVIEWPROPS lpVP = (LPVIEWPROPS)LpvStandardInit(hDlg, sizeof(VIEWPROPS));
// LpvStandardInit send a termination to us already.
if (NULL == lpVP)
return FALSE;
LPPROPSHEETPAGE lpPP = (LPPROPSHEETPAGE)lParam;
LPOLEUIVIEWPROPS lpOVP = (LPOLEUIVIEWPROPS)lpPP->lParam;
lpVP->lpOVP = lpOVP;
lpVP->nIDD = IDD_VIEWPROPS;
// get object information and fill in default fields
LPOLEUIOBJECTPROPS lpOP = lpOVP->lpOP;
LPOLEUIOBJINFO lpObjInfo = lpOP->lpObjInfo;
// initialize icon and scale variables
HGLOBAL hMetaPict;
DWORD dvAspect;
int nCurrentScale;
lpObjInfo->GetViewInfo(lpOP->dwObject, &hMetaPict,
&dvAspect, &nCurrentScale);
SendDlgItemMessage(hDlg, IDC_VP_ICONDISPLAY, IBXM_IMAGESET,
0, (LPARAM)hMetaPict);
lpVP->nCurrentScale = nCurrentScale;
lpVP->dvAspect = dvAspect;
// Initialize the result image
SendDlgItemMessage(hDlg, IDC_VP_RESULTIMAGE,
RIM_IMAGESET, RESULTIMAGE_EDITABLE, 0L);
// Initialize controls
CheckRadioButton(hDlg, IDC_VP_EDITABLE, IDC_VP_ASICON,
dvAspect == DVASPECT_CONTENT ? IDC_VP_EDITABLE : IDC_VP_ASICON);
SendDlgItemMessage(hDlg, IDC_VP_RELATIVE, BM_SETCHECK,
(lpOVP->dwFlags & VPF_SELECTRELATIVE) != 0, 0L);
if (!(lpOVP->dwFlags & VPF_DISABLESCALE))
SetDlgItemInt(hDlg, IDC_VP_PERCENT, nCurrentScale, FALSE);
lpVP->bRelativeToOrig = SendDlgItemMessage(hDlg, IDC_VP_RELATIVE,
BM_GETCHECK, 0, 0) != 0;
// Setup up-down control as buddy to IDC_VP_PERCENT
HWND hWndSpin = CreateWindowEx(0, UPDOWN_CLASS, NULL,
WS_CHILD|UDS_SETBUDDYINT|UDS_ARROWKEYS|UDS_ALIGNRIGHT, 0, 0, 0, 0,
hDlg, (HMENU)IDC_VP_SPIN, _g_hOleStdInst, NULL);
if (hWndSpin != NULL)
{
SendMessage(hWndSpin, UDM_SETRANGE, 0,
MAKELPARAM(lpOVP->nScaleMax, lpOVP->nScaleMin));
SendMessage(hWndSpin, UDM_SETPOS, 0, nCurrentScale);
SendMessage(hWndSpin, UDM_SETBUDDY,
(WPARAM)GetDlgItem(hDlg, IDC_VP_PERCENT), 0);
ShowWindow(hWndSpin, SW_SHOW);
}
EnableDisableScaleControls(lpVP, hDlg);
// Call the hook with lCustData in lParam
UStandardHook((PVOID)lpVP, hDlg, WM_INITDIALOG, wParam, lpOVP->lCustData);
return TRUE;
}
BOOL CALLBACK ViewPropsDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
// Declare Win16/Win32 compatible WM_COMMAND parameters.
COMMANDPARAMS(wID, wCode, hWndMsg);
// This will fail under WM_INITDIALOG, where we allocate it.
UINT uHook = 0;
LPVIEWPROPS lpVP = (LPVIEWPROPS)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uHook);
// If the hook processed the message, we're done.
if (0 != uHook)
return (BOOL)uHook;
// Get pointers to important info
LPOLEUIVIEWPROPS lpOVP = NULL;
LPOLEUIOBJECTPROPS lpOP = NULL;
LPOLEUIOBJINFO lpObjInfo = NULL;
if (lpVP != NULL)
{
lpOVP = lpVP->lpOVP;
if (lpOVP != NULL)
{
lpObjInfo = lpOVP->lpOP->lpObjInfo;
lpOP = lpOVP->lpOP;
}
}
switch (iMsg)
{
case WM_INITDIALOG:
FViewPropsInit(hDlg, wParam, lParam);
return TRUE;
case WM_COMMAND:
switch (wID)
{
case IDC_VP_ASICON:
case IDC_VP_EDITABLE:
EnableDisableScaleControls(lpVP, hDlg);
SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
return TRUE;
case IDC_VP_CHANGEICON:
{
// Call up Change Icon dialog to obtain new icon
OLEUICHANGEICON ci; memset(&ci, 0, sizeof(ci));
ci.cbStruct = sizeof(ci);
ci.dwFlags = CIF_SELECTCURRENT;
ci.hWndOwner = GetParent(GetParent(hDlg));
ci.hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg, IDC_VP_ICONDISPLAY,
IBXM_IMAGEGET, 0, 0L);
// get classid to look for (may be new class if conversion applied)
SendMessage(GetParent(hDlg), PSM_QUERYSIBLINGS,
OLEUI_QUERY_GETCLASSID, (LPARAM)&ci.clsid);
lpObjInfo->GetConvertInfo(lpOP->dwObject,
&ci.clsid, NULL, NULL, NULL, NULL);
if (lpOP->dwFlags & OPF_SHOWHELP)
ci.dwFlags |= CIF_SHOWHELP;
// allow the caller to hook the change icon
uHook = UStandardHook(lpVP, hDlg, uMsgChangeIcon, 0, (LPARAM)&ci);
if (0 == uHook)
{
uHook = (OLEUI_OK == OleUIChangeIcon(&ci));
SetFocus(hDlg);
}
if (0 != uHook)
{
// apply the changes
SendDlgItemMessage(hDlg, IDC_VP_ICONDISPLAY, IBXM_IMAGESET, 1,
(LPARAM)ci.hMetaPict);
lpVP->bIconChanged = TRUE;
SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
}
}
return TRUE;
case IDC_VP_PERCENT:
case IDC_VP_RELATIVE:
SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
return TRUE;
}
break;
case WM_VSCROLL:
SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
break;
case PSM_QUERYSIBLINGS:
SetWindowLong(hDlg, DWL_MSGRESULT, 0);
switch (wParam)
{
case OLEUI_QUERY_LINKBROKEN:
if (!lpVP->bIconChanged)
{
// re-init icon, since user hasn't changed it
HGLOBAL hMetaPict;
lpObjInfo->GetViewInfo(lpOP->dwObject, &hMetaPict, NULL, NULL);
SendDlgItemMessage(hDlg, IDC_VP_ICONDISPLAY, IBXM_IMAGESET,
1, (LPARAM)hMetaPict);
}
return TRUE;
}
break;
case WM_NOTIFY:
switch (((NMHDR*)lParam)->code)
{
case PSN_HELP:
PostMessage(GetParent(GetParent(hDlg)), uMsgHelp,
(WPARAM)hDlg, MAKELPARAM(IDD_VIEWPROPS, 0));
break;
case PSN_APPLY:
{
HGLOBAL hMetaPict = NULL;
int nCurrentScale = -1;
DWORD dvAspect = (DWORD)-1;
BOOL bRelativeToOrig = FALSE;
// handle icon change
if (lpVP->bIconChanged)
{
hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg,
IDC_VP_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L);
lpVP->bIconChanged = FALSE;
}
// handle scale changes
if (IsWindowEnabled(GetDlgItem(hDlg, IDC_VP_PERCENT)))
{
// parse the percentage entered
BOOL bValid;
nCurrentScale = GetDlgItemInt(hDlg, IDC_VP_PERCENT, &bValid, FALSE);
if (!bValid)
{
PopupMessage(GetParent(hDlg), IDS_VIEWPROPS,
IDS_INVALIDPERCENTAGE, MB_OK|MB_ICONEXCLAMATION);
// cancel the call
SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
return TRUE;
}
// normalize range
int nScaleMin, nScaleMax;
if (lpOVP->nScaleMin > lpOVP->nScaleMax)
{
nScaleMin = lpOVP->nScaleMax;
nScaleMax = lpOVP->nScaleMin;
}
else
{
nScaleMin = lpOVP->nScaleMin;
nScaleMax = lpOVP->nScaleMax;
}
// check range for validity
if (nCurrentScale < nScaleMin || nCurrentScale > nScaleMax)
{
// format appropriate message
TCHAR szCaption[128];
LoadString(_g_hOleStdResInst, IDS_VIEWPROPS, szCaption, 128);
TCHAR szFormat[128];
LoadString(_g_hOleStdResInst, IDS_RANGEERROR, szFormat, 128);
TCHAR szTemp[256], szNum1[32], szNum2[32];
wsprintf(szNum1, _T("%d"), lpOVP->nScaleMin);
wsprintf(szNum2, _T("%d"), lpOVP->nScaleMax);
FormatString2(szTemp, szFormat, szNum1, szNum2);
MessageBox(GetParent(hDlg), szTemp, szCaption, MB_OK|MB_ICONEXCLAMATION);
// and cancel the call
SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
return TRUE;
}
// otherwise scale is in correct range
bRelativeToOrig =
SendDlgItemMessage(hDlg, IDC_VP_RELATIVE, BM_GETCHECK, 0, 0) != 0;
if (nCurrentScale != lpVP->nCurrentScale ||
bRelativeToOrig != lpVP->bRelativeToOrig)
{
lpVP->nCurrentScale = nCurrentScale;
lpVP->bRelativeToOrig = bRelativeToOrig;
}
}
// handle aspect changes
if (SendDlgItemMessage(hDlg, IDC_VP_ASICON, BM_GETCHECK, 0, 0L))
dvAspect = DVASPECT_ICON;
else
dvAspect = DVASPECT_CONTENT;
if (dvAspect == lpVP->dvAspect)
dvAspect = (DWORD)-1;
else
{
lpVP->dvAspect = dvAspect;
bRelativeToOrig = 1;
}
lpObjInfo->SetViewInfo(lpOP->dwObject, hMetaPict, dvAspect,
nCurrentScale, bRelativeToOrig);
}
SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_NOERROR);
PostMessage(GetParent(hDlg), PSM_CANCELTOCLOSE, 0, 0);
return TRUE;
}
break;
case WM_DESTROY:
SendDlgItemMessage(hDlg, IDC_VP_ICONDISPLAY, IBXM_IMAGEFREE, 0, 0);
StandardCleanup((PVOID)lpVP, hDlg);
return TRUE;
}
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// LinkPropsDialogProc and helpers
static BOOL IsNullTime(const FILETIME* lpFileTime)
{
FILETIME fileTimeNull = { 0, 0 };
return CompareFileTime(&fileTimeNull, lpFileTime) == 0;
}
static BOOL SetDlgItemDate(HWND hDlg, int nID, const FILETIME* lpFileTime)
{
if (IsNullTime(lpFileTime))
return FALSE;
// convert UTC file time to system time
FILETIME localTime;
FileTimeToLocalFileTime(lpFileTime, &localTime);
SYSTEMTIME systemTime;
FileTimeToSystemTime(&localTime, &systemTime);
TCHAR szDate[80];
GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systemTime,
NULL, szDate, sizeof(szDate));
SetDlgItemText(hDlg, nID, szDate);
return TRUE;
}
static BOOL SetDlgItemTime(HWND hDlg, int nID, const FILETIME* lpFileTime)
{
if (IsNullTime(lpFileTime))
return FALSE;
// convert UTC file time to system time
FILETIME localTime;
FileTimeToLocalFileTime(lpFileTime, &localTime);
SYSTEMTIME systemTime;
FileTimeToSystemTime(&localTime, &systemTime);
if (systemTime.wHour || systemTime.wMinute || systemTime.wSecond)
{
TCHAR szTime[80];
GetTimeFormat(LOCALE_USER_DEFAULT, 0, &systemTime,
NULL, szTime, sizeof(szTime));
SetDlgItemText(hDlg, nID, szTime);
}
return TRUE;
}
BOOL FLinkPropsInit(HWND hDlg, WPARAM wParam, LPARAM lParam)
{
// Copy the structure at lParam into our instance memory.
HFONT hFont;
LPLINKPROPS lpLP = (LPLINKPROPS)LpvStandardInit(hDlg, sizeof(LINKPROPS), &hFont);
// LpvStandardInit send a termination to us already.
if (NULL == lpLP)
return FALSE;
LPPROPSHEETPAGE lpPP = (LPPROPSHEETPAGE)lParam;
LPOLEUILINKPROPS lpOLP = (LPOLEUILINKPROPS)lpPP->lParam;
lpLP->lpOLP = lpOLP;
lpLP->nIDD = IDD_LINKPROPS;
// If we got a font, send it to the necessary controls.
if (NULL != hFont)
{
// Do this for as many controls as you need it for.
SendDlgItemMessage(hDlg, IDC_LP_LINKSOURCE, WM_SETFONT, (WPARAM)hFont, 0);
SendDlgItemMessage(hDlg, IDC_LP_DATE, WM_SETFONT, (WPARAM)hFont, 0);
SendDlgItemMessage(hDlg, IDC_LP_TIME, WM_SETFONT, (WPARAM)hFont, 0);
}
// general "Unknown" string for unknown items
TCHAR szUnknown[64];
LoadString(_g_hOleStdResInst, IDS_OLE2UIUNKNOWN, szUnknown, 64);
// get object information and fill in default fields
LPOLEUIOBJECTPROPS lpOP = lpOLP->lpOP;
LPOLEUILINKINFO lpLinkInfo = lpOP->lpLinkInfo;
FILETIME lastUpdate; memset(&lastUpdate, 0, sizeof(lastUpdate));
lpLinkInfo->GetLastUpdate(lpOP->dwLink, &lastUpdate);
// initialize time and date static text
if (IsNullTime(&lastUpdate))
{
// time and date are unknown
SetDlgItemText(hDlg, IDC_LP_DATE, szUnknown);
SetDlgItemText(hDlg, IDC_LP_TIME, szUnknown);
}
else
{
// time and date are known
SetDlgItemDate(hDlg, IDC_LP_DATE, &lastUpdate);
SetDlgItemTime(hDlg, IDC_LP_TIME, &lastUpdate);
}
// initialize source display name
LPTSTR lpszDisplayName;
lpLinkInfo->GetLinkSource(lpOP->dwLink, &lpszDisplayName,
&lpLP->nFileLength, NULL, NULL, NULL, NULL);
SetDlgItemText(hDlg, IDC_LP_LINKSOURCE, lpszDisplayName);
OleStdFree(lpszDisplayName);
// initialize automatic/manual update field
DWORD dwUpdate;
lpLinkInfo->GetLinkUpdateOptions(lpOP->dwLink, &dwUpdate);
CheckRadioButton(hDlg, IDC_LP_AUTOMATIC, IDC_LP_MANUAL,
dwUpdate == OLEUPDATE_ALWAYS ? IDC_LP_AUTOMATIC : IDC_LP_MANUAL);
lpLP->dwUpdate = dwUpdate;
// Call the hook with lCustData in lParam
UStandardHook((PVOID)lpLP, hDlg, WM_INITDIALOG, wParam, lpOLP->lCustData);
return TRUE;
}
BOOL CALLBACK LinkPropsDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
// Declare Win16/Win32 compatible WM_COMMAND parameters.
COMMANDPARAMS(wID, wCode, hWndMsg);
// This will fail under WM_INITDIALOG, where we allocate it.
UINT uHook = 0;
LPLINKPROPS lpLP = (LPLINKPROPS)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uHook);
// If the hook processed the message, we're done.
if (0 != uHook)
return (BOOL)uHook;
// Get pointers to important info
LPOLEUILINKPROPS lpOLP = NULL;
LPOLEUIOBJECTPROPS lpOP = NULL;
LPOLEUILINKINFO lpLinkInfo;
if (lpLP != NULL)
{
lpOLP = lpLP->lpOLP;
if (lpOLP != NULL)
{
lpLinkInfo = lpOLP->lpOP->lpLinkInfo;
lpOP = lpOLP->lpOP;
}
}
switch (iMsg)
{
case WM_INITDIALOG:
FLinkPropsInit(hDlg, wParam, lParam);
return TRUE;
case WM_COMMAND:
switch (wID)
{
case IDC_LP_OPENSOURCE:
// force update
SendMessage(GetParent(hDlg), PSM_APPLY, 0, 0);
// launch the object
lpLinkInfo->OpenLinkSource(lpOP->dwLink);
// close the dialog
SendMessage(GetParent(hDlg), WM_COMMAND, IDOK, 0);
break;
case IDC_LP_UPDATENOW:
{
// force update
SendMessage(GetParent(hDlg), PSM_APPLY, 0, 0);
// update the link via container provided callback
if (lpLinkInfo->UpdateLink(lpOP->dwLink, TRUE, FALSE) != NOERROR)
break;
// since link was updated, update the time/date display
SYSTEMTIME systemTime; GetSystemTime(&systemTime);
FILETIME localTime; SystemTimeToFileTime(&systemTime, &localTime);
FILETIME lastUpdate; LocalFileTimeToFileTime(&localTime, &lastUpdate);
lpLinkInfo->GetLastUpdate(lpOP->dwLink, &lastUpdate);
SetDlgItemDate(hDlg, IDC_LP_DATE, &lastUpdate);
SetDlgItemTime(hDlg, IDC_LP_TIME, &lastUpdate);
// modification that cannot be undone
SendMessage(GetParent(hDlg), PSM_CANCELTOCLOSE, 0, 0);
}
break;
case IDC_LP_BREAKLINK:
{
UINT uRet = PopupMessage(GetParent(hDlg), IDS_LINKPROPS,
IDS_CONFIRMBREAKLINK, MB_YESNO|MB_ICONQUESTION);
if (uRet == IDYES)
{
// cancel the link turning it into a picture
lpLinkInfo->CancelLink(lpOP->dwLink);
// allow other pages to refresh
lpOP->dwFlags &= ~OPF_OBJECTISLINK;
SendMessage(GetParent(hDlg), PSM_QUERYSIBLINGS,
OLEUI_QUERY_LINKBROKEN, 0);
// remove the links page (since this is no longer a link)
SendMessage(GetParent(hDlg), PSM_REMOVEPAGE, 2, 0);
}
}
break;
case IDC_LP_CHANGESOURCE:
{
// get current source in OLE memory
UINT nLen = GetWindowTextLength(GetDlgItem(hDlg, IDC_LP_LINKSOURCE));
LPTSTR lpszDisplayName = (LPTSTR)OleStdMalloc((nLen+1) * sizeof(TCHAR));
GetDlgItemText(hDlg, IDC_LP_LINKSOURCE, lpszDisplayName, nLen+1);
if (lpszDisplayName == NULL)
break;
// fill in the OLEUICHANGESOURCE struct
OLEUICHANGESOURCE cs; memset(&cs, 0, sizeof(cs));
cs.cbStruct = sizeof(cs);
cs.hWndOwner = GetParent(GetParent(hDlg));
cs.dwFlags = CSF_ONLYGETSOURCE;
if (lpOP->dwFlags & OPF_SHOWHELP)
cs.dwFlags |= CSF_SHOWHELP;
cs.lpOleUILinkContainer = lpLinkInfo;
cs.dwLink = lpOP->dwLink;
cs.lpszDisplayName = lpszDisplayName;
cs.nFileLength = lpLP->nFileLength;
// allow the Change Souce dialog to be hooked
UINT uRet = UStandardHook(lpLP, hDlg, uMsgChangeSource, 0,
(LPARAM)&cs);
if (!uRet)
{
uRet = (OLEUI_OK == OleUIChangeSource(&cs));
SetFocus(hDlg);
}
if (uRet)
{
OleStdFree(lpLP->lpszDisplayName);
lpLP->lpszDisplayName = cs.lpszDisplayName;
lpLP->nFileLength = cs.nFileLength;
SetDlgItemText(hDlg, IDC_LP_LINKSOURCE, lpLP->lpszDisplayName);
OleStdFree(cs.lpszTo);
OleStdFree(cs.lpszFrom);
SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
}
}
break;
case IDC_LP_MANUAL:
case IDC_LP_AUTOMATIC:
SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
break;
}
break;
case WM_NOTIFY:
switch (((NMHDR*)lParam)->code)
{
case PSN_HELP:
PostMessage(GetParent(GetParent(hDlg)), uMsgHelp,
(WPARAM)hDlg, MAKELPARAM(IDD_LINKPROPS, 0));
break;
case PSN_APPLY:
{
// update link update options first
DWORD dwUpdate;
if (SendDlgItemMessage(hDlg, IDC_LP_AUTOMATIC, BM_GETCHECK, 0, 0))
dwUpdate = OLEUPDATE_ALWAYS;
else
dwUpdate = OLEUPDATE_ONCALL;
if (dwUpdate != lpLP->dwUpdate)
lpLinkInfo->SetLinkUpdateOptions(lpOP->dwLink, dwUpdate);
// set the link source
if (lpLP->lpszDisplayName != NULL)
{
// try setting with validation first
ULONG chEaten;
if (NOERROR != lpLinkInfo->SetLinkSource(lpOP->dwLink,
lpLP->lpszDisplayName, lpLP->nFileLength, &chEaten,
TRUE))
{
UINT uRet = PopupMessage(GetParent(hDlg), IDS_LINKPROPS,
IDS_INVALIDSOURCE, MB_ICONQUESTION|MB_YESNO);
if (uRet == IDYES)
{
// user wants to correct the link source
SetWindowLong(hDlg, DWL_MSGRESULT, 1);
return TRUE;
}
// user doesn't care if link source is bogus
lpLinkInfo->SetLinkSource(lpOP->dwLink,
lpLP->lpszDisplayName, lpLP->nFileLength, &chEaten,
FALSE);
}
OleStdFree(lpLP->lpszDisplayName);
lpLP->lpszDisplayName = NULL;
}
}
SetWindowLong(hDlg, DWL_MSGRESULT, 0);
PostMessage(GetParent(hDlg), PSM_CANCELTOCLOSE, 0, 0);
return TRUE;
}
break;
case WM_DESTROY:
if (lpLP != NULL)
{
OleStdFree(lpLP->lpszDisplayName);
lpLP->lpszDisplayName = NULL;
}
StandardCleanup((PVOID)lpLP, hDlg);
return TRUE;
default:
if (lpOP != NULL && lpOP->lpPS->hwndParent && iMsg == uMsgBrowseOFN)
{
SendMessage(lpOP->lpPS->hwndParent, uMsgBrowseOFN, wParam, lParam);
}
break;
}
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// Property Page initialization code
struct PROPPAGEDATA
{
UINT nTemplateID;
UINT nTemplateID4;
DLGPROC pfnDlgProc;
size_t nPtrOffset;
};
#define PTR_OFFSET(x) offsetof(OLEUIOBJECTPROPS, x)
static PROPPAGEDATA pageData[3] =
{
{ IDD_GNRLPROPS,IDD_GNRLPROPS4, GnrlPropsDialogProc, PTR_OFFSET(lpGP), },
{ IDD_VIEWPROPS,IDD_VIEWPROPS, ViewPropsDialogProc, PTR_OFFSET(lpVP), },
{ IDD_LINKPROPS,IDD_LINKPROPS4, LinkPropsDialogProc, PTR_OFFSET(lpLP), },
};
#undef PTR_OFFSET
static UINT WINAPI PrepareObjectProperties(LPOLEUIOBJECTPROPS lpOP)
{
// setup back pointers from page structs to sheet structs
lpOP->lpGP->lpOP = lpOP;
lpOP->lpVP->lpOP = lpOP;
if ((lpOP->dwFlags & OPF_OBJECTISLINK) && lpOP->lpLP != NULL)
lpOP->lpLP->lpOP = lpOP;
// pre-init GNRLPROPS struct
LPOLEUIGNRLPROPS lpGP = lpOP->lpGP;
// get ready to initialize PROPSHEET structs
LPPROPSHEETHEADER lpPS = lpOP->lpPS;
LPPROPSHEETPAGE lpPPs = (LPPROPSHEETPAGE)lpPS->ppsp;
UINT nMaxPage = (lpOP->dwFlags & OPF_OBJECTISLINK ? 3 : 2);
// setting OPF_NOFILLDEFAULT allows you to control almost everything
if (!(lpOP->dwFlags & OPF_NOFILLDEFAULT))
{
// get array of 3 PROPSHEETPAGE structs if not provided
if (lpPS->ppsp == NULL)
{
lpPS->nPages = nMaxPage;
lpPPs = (LPPROPSHEETPAGE)
OleStdMalloc(nMaxPage * sizeof(PROPSHEETPAGE));
if (lpPPs == NULL)
return OLEUI_ERR_OLEMEMALLOC;
memset(lpPPs, 0, nMaxPage * sizeof(PROPSHEETPAGE));
lpPS->ppsp = lpPPs;
}
// fill in defaults for lpPS
lpPS->dwFlags |= PSH_PROPSHEETPAGE;
if (lpPS->hInstance == NULL)
lpPS->hInstance = _g_hOleStdResInst;
// fill Defaults for Standard Property Pages
for (UINT nPage = 0; nPage < nMaxPage; nPage++)
{
LPPROPSHEETPAGE lpPP = &lpPPs[nPage];
PROPPAGEDATA* pPageData = &pageData[nPage];
if (lpPP->dwSize == 0)
lpPP->dwSize = sizeof(PROPSHEETPAGE);
if (lpPP->hInstance == NULL)
lpPP->hInstance = _g_hOleStdResInst;
UINT nIDD = bWin4 ?
pPageData->nTemplateID4 : pPageData->nTemplateID;
if (lpPP->pszTemplate == NULL)
lpPP->pszTemplate = MAKEINTRESOURCE(nIDD);
}
}
// fill Property Page info which cannot be overridden
for (UINT nPage = 0; nPage < nMaxPage; nPage++)
{
LPPROPSHEETPAGE lpPP = &lpPPs[nPage];
PROPPAGEDATA* pPageData = &pageData[nPage];
lpPP->pfnDlgProc = pPageData->pfnDlgProc;
lpPP->lParam = (LONG)
*(OLEUIGNRLPROPS**)((LPBYTE)lpOP + pPageData->nPtrOffset);
}
return OLEUI_SUCCESS;
}
/////////////////////////////////////////////////////////////////////////////