972 lines
32 KiB
C
972 lines
32 KiB
C
|
/*
|
||
|
* OLE2UI.C
|
||
|
*
|
||
|
* Contains initialization routines and miscellaneous API implementations for
|
||
|
* the OLE 2.0 User Interface Support Library.
|
||
|
*
|
||
|
* Copyright (c)1992 Microsoft Corporation, All Right Reserved
|
||
|
*/
|
||
|
|
||
|
#define STRICT 1
|
||
|
|
||
|
#include "ole2ui.h"
|
||
|
#include "common.h"
|
||
|
#include "utility.h"
|
||
|
#include "resimage.h"
|
||
|
#include "iconbox.h"
|
||
|
#include <commdlg.h>
|
||
|
|
||
|
#define WINDLL 1 // make far pointer version of stdargs.h
|
||
|
#include <stdarg.h>
|
||
|
|
||
|
// NOTE: If this code is being compiled for a DLL, then we need to define
|
||
|
// our OLE2UI debug symbols here (with the OLEDBGDATA_MAIN macro). If we're
|
||
|
// compiling for a static LIB, then the application we link to must
|
||
|
// define these symbols -- we just need to make an external reference here
|
||
|
// (with the macro OLEDBGDATA).
|
||
|
|
||
|
#ifdef DLL_VER
|
||
|
OLEDBGDATA_MAIN(TEXT("OLE2UI"))
|
||
|
#else
|
||
|
OLEDBGDATA
|
||
|
#endif
|
||
|
|
||
|
//The DLL instance handle shared amongst all dialogs.
|
||
|
HINSTANCE ghInst;
|
||
|
|
||
|
//Registered messages for use with all the dialogs, registered in LibMain
|
||
|
UINT uMsgHelp=0;
|
||
|
UINT uMsgEndDialog=0;
|
||
|
UINT uMsgBrowse=0;
|
||
|
UINT uMsgChangeIcon=0;
|
||
|
UINT uMsgFileOKString=0;
|
||
|
UINT uMsgCloseBusyDlg=0;
|
||
|
|
||
|
//Clipboard formats used by PasteSpecial
|
||
|
UINT cfObjectDescriptor;
|
||
|
UINT cfLinkSrcDescriptor;
|
||
|
UINT cfEmbedSource;
|
||
|
UINT cfEmbeddedObject;
|
||
|
UINT cfLinkSource;
|
||
|
UINT cfOwnerLink;
|
||
|
UINT cfFileName;
|
||
|
|
||
|
// local function prototypes
|
||
|
BOOL CALLBACK EXPORT PromptUserDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam);
|
||
|
BOOL CALLBACK EXPORT UpdateLinksDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam);
|
||
|
|
||
|
|
||
|
// local definition
|
||
|
#define WM_U_UPDATELINK WM_USER
|
||
|
|
||
|
|
||
|
// local structure definition
|
||
|
typedef struct tagUPDATELINKS
|
||
|
{
|
||
|
LPOLEUILINKCONTAINER lpOleUILinkCntr; // pointer to Link Container
|
||
|
UINT cLinks; // total number of links
|
||
|
UINT cUpdated; // number of links updated
|
||
|
DWORD dwLink; // pointer to link
|
||
|
BOOL fError; // error flag
|
||
|
LPTSTR lpszTitle; // caption for dialog box
|
||
|
} UPDATELINKS, *PUPDATELINKS, FAR *LPUPDATELINKS;
|
||
|
|
||
|
|
||
|
/*
|
||
|
* OleUIInitialize
|
||
|
*
|
||
|
* NOTE: This function should only be called by your application IF it is
|
||
|
* using the static-link version of this library. If the DLL version is
|
||
|
* being used, this function is automatically called from the OLE2UI DLL's
|
||
|
* LibMain.
|
||
|
*
|
||
|
* Purpose:
|
||
|
* Initializes the OLE UI Library. Registers the OLE clipboard formats
|
||
|
* used in the Paste Special dialog, registers private custom window
|
||
|
* messages, and registers window classes of the "Result Image"
|
||
|
* and "Icon Box" custom controls used in the UI dialogs.
|
||
|
*
|
||
|
* Parameters:
|
||
|
*
|
||
|
* hInstance HINSTANCE of the module where the UI library resources
|
||
|
* and Dialog Procedures are contained. If you are calling
|
||
|
* this function yourself, this should be the instance handle
|
||
|
* of your application.
|
||
|
*
|
||
|
* hPrevInst HINSTANCE of the previous application instance.
|
||
|
* This is the parameter passed in to your WinMain. For
|
||
|
* the DLL version, this should always be set to zero (for
|
||
|
* WIN16 DLLs).
|
||
|
*
|
||
|
* lpszClassIconBox
|
||
|
* LPTSTR containing the name you assigned to the symbol
|
||
|
* SZCLASSICONBOX (this symbol is defined in UICLASS.H
|
||
|
* which is generated in the MAKEFILE).
|
||
|
*
|
||
|
* This name is used as the window class name
|
||
|
* when registering the IconBox custom control used in the
|
||
|
* UI dialogs. In order to handle mutliple apps running
|
||
|
* with this library, you must make this name unique to your
|
||
|
* application.
|
||
|
*
|
||
|
* For the DLL version: Do NOT call this function directly
|
||
|
* from your application, it is called automatically from
|
||
|
* the DLL's LibMain.
|
||
|
*
|
||
|
* For the static library version: This should be set to
|
||
|
* the symbol SZCLASSICONBOX. This symbol is defined in
|
||
|
* UICLASS.H.
|
||
|
*
|
||
|
* lpszClassResImage
|
||
|
* LPTSTR containing the name you assigned to the symbol
|
||
|
* SZCLASSRESULTIMAGE. See the description of
|
||
|
* lpszClassIconBox above for more info.
|
||
|
*
|
||
|
* Return Value:
|
||
|
* BOOL TRUE if initialization was successful.
|
||
|
* FALSE if either the "Magic Number" did not verify, or one of
|
||
|
* the window classes could not be registered. If the
|
||
|
* "Magic Number" did not verify, then the resources
|
||
|
* in your module are of a different version than the
|
||
|
* ones you compiled with.
|
||
|
*/
|
||
|
|
||
|
STDAPI_(BOOL) OleUIInitialize(HINSTANCE hInstance,
|
||
|
HINSTANCE hPrevInst,
|
||
|
LPTSTR lpszClassIconBox,
|
||
|
LPTSTR lpszClassResImage)
|
||
|
{
|
||
|
HRSRC hr;
|
||
|
HGLOBAL hg;
|
||
|
LPWORD lpdata;
|
||
|
|
||
|
OleDbgOut1(TEXT("OleUIInitialize called.\r\n"));
|
||
|
ghInst=hInstance;
|
||
|
|
||
|
// Verify that we have the correct resources added to our application
|
||
|
// by checking the "VERIFICATION" resource with the magic number we've
|
||
|
// compiled into our app.
|
||
|
|
||
|
OutputDebugString(TEXT("Entering OleUIInitialize\n"));
|
||
|
|
||
|
if ((hr = FindResource(hInstance, TEXT("VERIFICATION"), RT_RCDATA)) == NULL)
|
||
|
goto ResourceLoadError;
|
||
|
|
||
|
if ((hg = LoadResource(hInstance, hr)) == NULL)
|
||
|
goto ResourceLoadError;
|
||
|
|
||
|
if ((lpdata = (LPWORD)LockResource(hg)) == NULL)
|
||
|
goto ResourceLockError;
|
||
|
|
||
|
if ((WORD)*lpdata != (WORD)OLEUI_VERSION_MAGIC)
|
||
|
goto ResourceReadError;
|
||
|
|
||
|
// OK, resource versions match. Contine on.
|
||
|
UnlockResource(hg);
|
||
|
FreeResource(hg);
|
||
|
OleDbgOut1(TEXT("OleUIInitialize: Resource magic number verified.\r\n"));
|
||
|
|
||
|
// Register messages we need for the dialogs. If
|
||
|
uMsgHelp =RegisterWindowMessage(SZOLEUI_MSG_HELP);
|
||
|
uMsgEndDialog =RegisterWindowMessage(SZOLEUI_MSG_ENDDIALOG);
|
||
|
uMsgBrowse =RegisterWindowMessage(SZOLEUI_MSG_BROWSE);
|
||
|
uMsgChangeIcon=RegisterWindowMessage(SZOLEUI_MSG_CHANGEICON);
|
||
|
uMsgFileOKString = RegisterWindowMessage(FILEOKSTRING);
|
||
|
uMsgCloseBusyDlg = RegisterWindowMessage(SZOLEUI_MSG_CLOSEBUSYDIALOG);
|
||
|
|
||
|
// Register Clipboard Formats used by PasteSpecial dialog.
|
||
|
cfObjectDescriptor = RegisterClipboardFormat(CF_OBJECTDESCRIPTOR);
|
||
|
cfLinkSrcDescriptor= RegisterClipboardFormat(CF_LINKSRCDESCRIPTOR);
|
||
|
cfEmbedSource = RegisterClipboardFormat(CF_EMBEDSOURCE);
|
||
|
cfEmbeddedObject = RegisterClipboardFormat(CF_EMBEDDEDOBJECT);
|
||
|
cfLinkSource = RegisterClipboardFormat(CF_LINKSOURCE);
|
||
|
cfOwnerLink = RegisterClipboardFormat(CF_OWNERLINK);
|
||
|
cfFileName = RegisterClipboardFormat(CF_FILENAME);
|
||
|
|
||
|
if (!FResultImageInitialize(hInstance, hPrevInst, lpszClassResImage))
|
||
|
{
|
||
|
OleDbgOut1(TEXT("OleUIInitialize: FResultImageInitialize failed. Terminating.\r\n"));
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (!FIconBoxInitialize(hInstance, hPrevInst, lpszClassIconBox))
|
||
|
{
|
||
|
OleDbgOut1(TEXT("OleUIInitialize: FIconBoxInitialize failed. Terminating.\r\n"));
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
|
||
|
ResourceLoadError:
|
||
|
OleDbgOut1(TEXT("OleUIInitialize: ERROR - Unable to find version verification resource.\r\n"));
|
||
|
return FALSE;
|
||
|
|
||
|
ResourceLockError:
|
||
|
OleDbgOut1(TEXT("OleUIInitialize: ERROR - Unable to lock version verification resource.\r\n"));
|
||
|
FreeResource(hg);
|
||
|
return FALSE;
|
||
|
|
||
|
ResourceReadError:
|
||
|
OleDbgOut1(TEXT("OleUIInitialize: ERROR - Version verification values did not compare.\r\n"));
|
||
|
|
||
|
{TCHAR buf[255];
|
||
|
wsprintf(buf, TEXT("resource read 0x%X, my value is 0x%X\n"), (WORD)*lpdata, (WORD)OLEUI_VERSION_MAGIC);
|
||
|
OutputDebugString(buf);
|
||
|
}
|
||
|
|
||
|
UnlockResource(hg);
|
||
|
FreeResource(hg);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* OleUIUnInitialize
|
||
|
*
|
||
|
* NOTE: This function should only be called by your application IF it is using
|
||
|
* the static-link version of this library. If the DLL version is being used,
|
||
|
* this function is automatically called from the DLL's LibMain.
|
||
|
*
|
||
|
* Purpose:
|
||
|
* Uninitializes OLE UI libraries. Deletes any resources allocated by the
|
||
|
* library.
|
||
|
*
|
||
|
* Return Value:
|
||
|
* BOOL TRUE if successful, FALSE if not. Current implementation always
|
||
|
* returns TRUE.
|
||
|
*/
|
||
|
|
||
|
|
||
|
STDAPI_(BOOL) OleUIUnInitialize()
|
||
|
{
|
||
|
IconBoxUninitialize();
|
||
|
ResultImageUninitialize();
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* OleUIAddVerbMenu
|
||
|
*
|
||
|
* Purpose:
|
||
|
* Add the Verb menu for the specified object to the given menu. If the
|
||
|
* object has one verb, we directly add the verb to the given menu. If
|
||
|
* the object has multiple verbs we create a cascading sub-menu.
|
||
|
*
|
||
|
* Parameters:
|
||
|
* lpObj LPOLEOBJECT pointing to the selected object. If this
|
||
|
* is NULL, then we create a default disabled menu item.
|
||
|
*
|
||
|
* lpszShortType LPTSTR with short type name (AuxName==2) corresponding
|
||
|
* to the lpOleObj. if the string is NOT known, then NULL
|
||
|
* may be passed. if NULL is passed, then
|
||
|
* IOleObject::GetUserType will be called to retrieve it.
|
||
|
* if the caller has the string handy, then it is faster
|
||
|
* to pass it in.
|
||
|
*
|
||
|
* hMenu HMENU in which to make modifications.
|
||
|
*
|
||
|
* uPos Position of the menu item
|
||
|
*
|
||
|
* uIDVerbMin UINT ID value at which to start the verbs.
|
||
|
* verb_0 = wIDMVerbMin + verb_0
|
||
|
* verb_1 = wIDMVerbMin + verb_1
|
||
|
* verb_2 = wIDMVerbMin + verb_2
|
||
|
* etc.
|
||
|
* uIDVerbMax UINT maximum ID value allowed for object verbs.
|
||
|
* if uIDVerbMax==0 then any ID value is allowed
|
||
|
*
|
||
|
* bAddConvert BOOL specifying whether or not to add a "Convert" item
|
||
|
* to the bottom of the menu (with a separator).
|
||
|
*
|
||
|
* idConvert UINT ID value to use for the Convert menu item, if
|
||
|
* bAddConvert is TRUE.
|
||
|
*
|
||
|
* lphMenu HMENU FAR * of the cascading verb menu if it's created.
|
||
|
* If there is only one verb, this will be filled with NULL.
|
||
|
*
|
||
|
*
|
||
|
* Return Value:
|
||
|
* BOOL TRUE if lpObj was valid and we added at least one verb
|
||
|
* to the menu. FALSE if lpObj was NULL and we created
|
||
|
* a disabled default menu item
|
||
|
*/
|
||
|
|
||
|
STDAPI_(BOOL) OleUIAddVerbMenu(LPOLEOBJECT lpOleObj,
|
||
|
LPTSTR lpszShortType,
|
||
|
HMENU hMenu,
|
||
|
UINT uPos,
|
||
|
UINT uIDVerbMin,
|
||
|
UINT uIDVerbMax,
|
||
|
BOOL bAddConvert,
|
||
|
UINT idConvert,
|
||
|
HMENU FAR *lphMenu)
|
||
|
{
|
||
|
LPPERSISTSTORAGE lpPS=NULL;
|
||
|
LPENUMOLEVERB lpEnumOleVerb = NULL;
|
||
|
OLEVERB oleverb;
|
||
|
LPUNKNOWN lpUnk;
|
||
|
LPTSTR lpszShortTypeName = lpszShortType;
|
||
|
LPTSTR lpszVerbName = NULL;
|
||
|
HRESULT hrErr;
|
||
|
BOOL fStatus;
|
||
|
BOOL fIsLink = FALSE;
|
||
|
BOOL fResult = TRUE;
|
||
|
BOOL fAddConvertItem = FALSE;
|
||
|
int cVerbs = 0;
|
||
|
UINT uFlags = MF_BYPOSITION;
|
||
|
static BOOL fFirstTime = TRUE;
|
||
|
static TCHAR szBuffer[OLEUI_OBJECTMENUMAX];
|
||
|
static TCHAR szNoObjectCmd[OLEUI_OBJECTMENUMAX];
|
||
|
static TCHAR szObjectCmd1Verb[OLEUI_OBJECTMENUMAX];
|
||
|
static TCHAR szLinkCmd1Verb[OLEUI_OBJECTMENUMAX];
|
||
|
static TCHAR szObjectCmdNVerb[OLEUI_OBJECTMENUMAX];
|
||
|
static TCHAR szLinkCmdNVerb[OLEUI_OBJECTMENUMAX];
|
||
|
static TCHAR szUnknown[OLEUI_OBJECTMENUMAX];
|
||
|
static TCHAR szEdit[OLEUI_OBJECTMENUMAX];
|
||
|
static TCHAR szConvert[OLEUI_OBJECTMENUMAX];
|
||
|
|
||
|
*lphMenu=NULL;
|
||
|
|
||
|
// Set fAddConvertItem flag
|
||
|
if (bAddConvert & (idConvert != 0))
|
||
|
fAddConvertItem = TRUE;
|
||
|
|
||
|
// only need to load the strings the 1st time
|
||
|
if (fFirstTime) {
|
||
|
if (0 == LoadString(ghInst, IDS_OLE2UIEDITNOOBJCMD,
|
||
|
(LPTSTR)szNoObjectCmd, OLEUI_OBJECTMENUMAX))
|
||
|
return FALSE;
|
||
|
if (0 == LoadString(ghInst, IDS_OLE2UIEDITLINKCMD_1VERB,
|
||
|
(LPTSTR)szLinkCmd1Verb, OLEUI_OBJECTMENUMAX))
|
||
|
return FALSE;
|
||
|
if (0 == LoadString(ghInst, IDS_OLE2UIEDITOBJECTCMD_1VERB,
|
||
|
(LPTSTR)szObjectCmd1Verb, OLEUI_OBJECTMENUMAX))
|
||
|
return FALSE;
|
||
|
|
||
|
if (0 == LoadString(ghInst, IDS_OLE2UIEDITLINKCMD_NVERB,
|
||
|
(LPTSTR)szLinkCmdNVerb, OLEUI_OBJECTMENUMAX))
|
||
|
return FALSE;
|
||
|
if (0 == LoadString(ghInst, IDS_OLE2UIEDITOBJECTCMD_NVERB,
|
||
|
(LPTSTR)szObjectCmdNVerb, OLEUI_OBJECTMENUMAX))
|
||
|
return FALSE;
|
||
|
|
||
|
if (0 == LoadString(ghInst, IDS_OLE2UIUNKNOWN,
|
||
|
(LPTSTR)szUnknown, OLEUI_OBJECTMENUMAX))
|
||
|
return FALSE;
|
||
|
|
||
|
if (0 == LoadString(ghInst, IDS_OLE2UIEDIT,
|
||
|
(LPTSTR)szEdit, OLEUI_OBJECTMENUMAX))
|
||
|
return FALSE;
|
||
|
|
||
|
if ( (0 == LoadString(ghInst, IDS_OLE2UICONVERT,
|
||
|
(LPTSTR)szConvert, OLEUI_OBJECTMENUMAX)) && fAddConvertItem)
|
||
|
return FALSE;
|
||
|
|
||
|
fFirstTime = FALSE;
|
||
|
}
|
||
|
|
||
|
// Delete whatever menu may happen to be here already.
|
||
|
DeleteMenu(hMenu, uPos, uFlags);
|
||
|
|
||
|
if (!lpOleObj)
|
||
|
goto AVMError;
|
||
|
|
||
|
if (! lpszShortTypeName) {
|
||
|
// get the Short form of the user type name for the menu
|
||
|
OLEDBG_BEGIN2(TEXT("IOleObject::GetUserType called\r\n"))
|
||
|
hrErr = CallIOleObjectGetUserTypeA(
|
||
|
lpOleObj,
|
||
|
USERCLASSTYPE_SHORT,
|
||
|
(LPTSTR FAR*)&lpszShortTypeName
|
||
|
);
|
||
|
OLEDBG_END2
|
||
|
|
||
|
if (NOERROR != hrErr) {
|
||
|
OleDbgOutHResult(TEXT("IOleObject::GetUserType returned"), hrErr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// check if the object is a link (it is a link if it support IOleLink)
|
||
|
hrErr = lpOleObj->lpVtbl->QueryInterface(
|
||
|
lpOleObj,
|
||
|
&IID_IOleLink,
|
||
|
(LPVOID FAR*)&lpUnk
|
||
|
);
|
||
|
if (NOERROR == hrErr) {
|
||
|
fIsLink = TRUE;
|
||
|
OleStdRelease(lpUnk);
|
||
|
}
|
||
|
|
||
|
// Get the verb enumerator from the OLE object
|
||
|
OLEDBG_BEGIN2(TEXT("IOleObject::EnumVerbs called\r\n"))
|
||
|
hrErr = lpOleObj->lpVtbl->EnumVerbs(
|
||
|
lpOleObj,
|
||
|
(LPENUMOLEVERB FAR*)&lpEnumOleVerb
|
||
|
);
|
||
|
OLEDBG_END2
|
||
|
|
||
|
if (NOERROR != hrErr) {
|
||
|
OleDbgOutHResult(TEXT("IOleObject::EnumVerbs returned"), hrErr);
|
||
|
}
|
||
|
|
||
|
if (!(*lphMenu = CreatePopupMenu()))
|
||
|
goto AVMError;
|
||
|
|
||
|
// loop through all verbs
|
||
|
while (lpEnumOleVerb != NULL) { // forever
|
||
|
hrErr = lpEnumOleVerb->lpVtbl->Next(
|
||
|
lpEnumOleVerb,
|
||
|
1,
|
||
|
(LPOLEVERB)&oleverb,
|
||
|
NULL
|
||
|
);
|
||
|
if (NOERROR != hrErr)
|
||
|
break; // DONE! no more verbs
|
||
|
|
||
|
/* OLE2NOTE: negative verb numbers and verbs that do not
|
||
|
** indicate ONCONTAINERMENU should NOT be put on the verb menu
|
||
|
*/
|
||
|
if (oleverb.lVerb < 0 ||
|
||
|
! (oleverb.grfAttribs & OLEVERBATTRIB_ONCONTAINERMENU)) {
|
||
|
|
||
|
/* OLE2NOTE: we must still free the verb name string */
|
||
|
if (oleverb.lpszVerbName)
|
||
|
OleStdFree(oleverb.lpszVerbName);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// we must free the previous verb name string
|
||
|
if (lpszVerbName)
|
||
|
OleStdFreeString(lpszVerbName, NULL);
|
||
|
|
||
|
CopyAndFreeOLESTR(oleverb.lpszVerbName, &lpszVerbName);
|
||
|
|
||
|
if ( 0 == uIDVerbMax ||
|
||
|
(uIDVerbMax >= uIDVerbMin+(UINT)oleverb.lVerb) ) {
|
||
|
fStatus = InsertMenu(
|
||
|
*lphMenu,
|
||
|
(UINT)-1,
|
||
|
MF_BYPOSITION | (UINT)oleverb.fuFlags,
|
||
|
uIDVerbMin+(UINT)oleverb.lVerb,
|
||
|
(LPTSTR)lpszVerbName
|
||
|
);
|
||
|
if (! fStatus)
|
||
|
goto AVMError;
|
||
|
|
||
|
cVerbs++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Add the separator and "Convert" menu item.
|
||
|
if (fAddConvertItem) {
|
||
|
|
||
|
if (0 == cVerbs) {
|
||
|
LPTSTR lpsz;
|
||
|
|
||
|
// if object has no verbs, then use "Convert" as the obj's verb
|
||
|
lpsz = lpszVerbName = OleStdCopyString(szConvert, NULL);
|
||
|
uIDVerbMin = idConvert;
|
||
|
|
||
|
// remove "..." from "Convert..." string; it will be added later
|
||
|
if (lpsz) {
|
||
|
while(*lpsz && *lpsz != TEXT('.'))
|
||
|
lpsz++;
|
||
|
*lpsz = TEXT('\0');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (cVerbs > 0) {
|
||
|
fStatus = InsertMenu(*lphMenu,
|
||
|
(UINT)-1,
|
||
|
MF_BYPOSITION | MF_SEPARATOR,
|
||
|
(UINT)0,
|
||
|
(LPCTSTR)NULL);
|
||
|
if (! fStatus)
|
||
|
goto AVMError;
|
||
|
}
|
||
|
|
||
|
/* add convert menu */
|
||
|
fStatus = InsertMenu(*lphMenu,
|
||
|
(UINT)-1,
|
||
|
MF_BYPOSITION,
|
||
|
idConvert,
|
||
|
(LPCTSTR)szConvert);
|
||
|
if (! fStatus)
|
||
|
goto AVMError;
|
||
|
|
||
|
cVerbs++;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Build the appropriate menu based on the number of verbs found
|
||
|
*
|
||
|
* NOTE: Localized verb menus may require a different format.
|
||
|
* to assist in localization of the single verb case, the
|
||
|
* szLinkCmd1Verb and szObjectCmd1Verb format strings start
|
||
|
* with either a '0' (note: NOT '\0'!) or a '1':
|
||
|
* leading '0' -- verb type
|
||
|
* leading '1' -- type verb
|
||
|
*/
|
||
|
|
||
|
if (cVerbs == 0) {
|
||
|
|
||
|
// there are NO verbs (not even Convert...). set the menu to be
|
||
|
// "<short type> &Object/Link" and gray it out.
|
||
|
wsprintf(
|
||
|
szBuffer,
|
||
|
(fIsLink ? (LPTSTR)szLinkCmdNVerb:(LPTSTR)szObjectCmdNVerb),
|
||
|
(lpszShortTypeName ? lpszShortTypeName : (LPTSTR) TEXT(""))
|
||
|
);
|
||
|
uFlags |= MF_GRAYED;
|
||
|
|
||
|
#if defined( OBSOLETE )
|
||
|
//No verbs. Create a default using Edit as the verb.
|
||
|
LPTSTR lpsz = (fIsLink ? szLinkCmd1Verb : szObjectCmd1Verb);
|
||
|
|
||
|
if (*lpsz == TEXT('0')) {
|
||
|
wsprintf(szBuffer, lpsz+1, (LPSTR)szEdit,
|
||
|
(lpszShortTypeName ? lpszShortTypeName : (LPTSTR) TEXT(""))
|
||
|
);
|
||
|
}
|
||
|
else {
|
||
|
wsprintf(szBuffer, lpsz+1,
|
||
|
(lpszShortTypeName ? lpszShortTypeName : (LPTSTR) TEXT("")),
|
||
|
(LPTSTR)szEdit
|
||
|
);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
fResult = FALSE;
|
||
|
DestroyMenu(*lphMenu);
|
||
|
*lphMenu = NULL;
|
||
|
|
||
|
}
|
||
|
else if (cVerbs == 1) {
|
||
|
//One verb without Convert, one item.
|
||
|
LPTSTR lpsz = (fIsLink ? szLinkCmd1Verb : szObjectCmd1Verb);
|
||
|
|
||
|
if (*lpsz == TEXT('0')) {
|
||
|
wsprintf(szBuffer, lpsz+1, lpszVerbName,
|
||
|
(lpszShortTypeName ? lpszShortTypeName : (LPTSTR) TEXT(""))
|
||
|
);
|
||
|
}
|
||
|
else {
|
||
|
wsprintf(szBuffer, lpsz+1,
|
||
|
(lpszShortTypeName ? lpszShortTypeName : (LPTSTR) TEXT("")),
|
||
|
lpszVerbName
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// if only "verb" is "Convert..." then append the ellipses
|
||
|
if (fAddConvertItem)
|
||
|
lstrcat(szBuffer, TEXT("..."));
|
||
|
|
||
|
DestroyMenu(*lphMenu);
|
||
|
*lphMenu=NULL;
|
||
|
}
|
||
|
else {
|
||
|
|
||
|
//Multiple verbs or one verb with Convert, add the cascading menu
|
||
|
wsprintf(
|
||
|
szBuffer,
|
||
|
(fIsLink ? (LPTSTR)szLinkCmdNVerb:(LPTSTR)szObjectCmdNVerb),
|
||
|
(lpszShortTypeName ? lpszShortTypeName : (LPTSTR) TEXT(""))
|
||
|
);
|
||
|
uFlags |= MF_ENABLED | MF_POPUP;
|
||
|
uIDVerbMin=(UINT)*lphMenu;
|
||
|
}
|
||
|
|
||
|
if (!InsertMenu(hMenu, uPos, uFlags, uIDVerbMin, (LPTSTR)szBuffer))
|
||
|
|
||
|
AVMError:
|
||
|
{
|
||
|
InsertMenu(hMenu, uPos, MF_GRAYED | uFlags,
|
||
|
uIDVerbMin, (LPTSTR)szNoObjectCmd);
|
||
|
#if defined( OBSOLETE )
|
||
|
HMENU hmenuDummy = CreatePopupMenu();
|
||
|
|
||
|
InsertMenu(hMenu, uPos, MF_GRAYED | MF_POPUP | uFlags,
|
||
|
(UINT)hmenuDummy, (LPTSTR)szNoObjectCmd);
|
||
|
#endif
|
||
|
fResult = FALSE;
|
||
|
}
|
||
|
|
||
|
if (lpszVerbName)
|
||
|
OleStdFreeString(lpszVerbName, NULL);
|
||
|
if (!lpszShortType && lpszShortTypeName)
|
||
|
OleStdFreeString(lpszShortTypeName, NULL);
|
||
|
if (lpEnumOleVerb)
|
||
|
lpEnumOleVerb->lpVtbl->Release(lpEnumOleVerb);
|
||
|
return fResult;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* PromptUserDlgProc
|
||
|
* -----------------
|
||
|
*
|
||
|
* Purpose:
|
||
|
* Dialog procedure used by OleUIPromptUser(). Returns when a button is
|
||
|
* clicked in the dialog box and the button id is return.
|
||
|
*
|
||
|
* Parameters:
|
||
|
* hDlg
|
||
|
* iMsg
|
||
|
* wParam
|
||
|
* lParam
|
||
|
*
|
||
|
* Returns:
|
||
|
*
|
||
|
*/
|
||
|
BOOL CALLBACK EXPORT PromptUserDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
switch (iMsg) {
|
||
|
case WM_INITDIALOG:
|
||
|
{
|
||
|
LPTSTR lpszTitle;
|
||
|
TCHAR szBuf[256];
|
||
|
TCHAR szFormat[256];
|
||
|
va_list *parglist;
|
||
|
|
||
|
if (!lParam) {
|
||
|
EndDialog(hDlg, -1);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// lParam is really a va_list *. We called va_start and va_end in
|
||
|
// the function that calls this.
|
||
|
//
|
||
|
|
||
|
parglist = (va_list *) lParam;
|
||
|
|
||
|
lpszTitle = va_arg(*parglist, LPTSTR);
|
||
|
SetWindowText(hDlg, lpszTitle);
|
||
|
|
||
|
GetDlgItemText(hDlg, ID_PU_TEXT,(LPTSTR)szFormat,sizeof(szFormat)/sizeof(TCHAR));
|
||
|
wvsprintf((LPTSTR)szBuf, (LPTSTR)szFormat, *parglist);
|
||
|
|
||
|
|
||
|
SetDlgItemText(hDlg, ID_PU_TEXT, (LPTSTR)szBuf);
|
||
|
return TRUE;
|
||
|
}
|
||
|
case WM_COMMAND:
|
||
|
EndDialog(hDlg, wParam);
|
||
|
return TRUE;
|
||
|
|
||
|
default:
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/* OleUIPromptUser
|
||
|
* ---------------
|
||
|
*
|
||
|
* Purpose:
|
||
|
* Popup a dialog box with the specified template and returned the
|
||
|
* response (button id) from the user.
|
||
|
*
|
||
|
* Parameters:
|
||
|
* nTemplate resource number of the dialog
|
||
|
* hwndParent parent of the dialog box
|
||
|
* ... title of the dialog box followed by argument list
|
||
|
* for the format string in the static control
|
||
|
* (ID_PU_TEXT) of the dialog box.
|
||
|
* The caller has to make sure that the correct number
|
||
|
* and type of argument are passed in.
|
||
|
*
|
||
|
* Returns:
|
||
|
* button id selected by the user (template dependent)
|
||
|
*
|
||
|
* Comments:
|
||
|
* the following message dialog boxes are supported:
|
||
|
*
|
||
|
* IDD_LINKSOURCEUNAVAILABLE -- Link source is unavailable
|
||
|
* VARARG Parameters:
|
||
|
* None.
|
||
|
* Used for the following error codes:
|
||
|
* OLE_E_CANT_BINDTOSOURCE
|
||
|
* STG_E_PATHNOTFOUND
|
||
|
* (sc >= MK_E_FIRST) && (sc <= MK_E_LAST) -- any Moniker error
|
||
|
* any unknown error if object is a link
|
||
|
*
|
||
|
* IDD_SERVERNOTFOUND -- server registered but NOT found
|
||
|
* VARARG Parameters:
|
||
|
* LPSTR lpszUserType -- user type name of object
|
||
|
* Used for the following error codes:
|
||
|
* CO_E_APPNOTFOUND
|
||
|
* CO_E_APPDIDNTREG
|
||
|
* any unknown error if object is an embedded object
|
||
|
*
|
||
|
* IDD_SERVERNOTREG -- server NOT registered
|
||
|
* VARARG Parameters:
|
||
|
* LPSTR lpszUserType -- user type name of object
|
||
|
* Used for the following error codes:
|
||
|
* REGDB_E_CLASSNOTREG
|
||
|
* OLE_E_STATIC -- static object with no server registered
|
||
|
*
|
||
|
* IDD_LINKTYPECHANGED -- class of link source changed since last binding
|
||
|
* VARARG Parameters:
|
||
|
* LPSTR lpszUserType -- user type name of ole link source
|
||
|
* Used for the following error codes:
|
||
|
* OLE_E_CLASSDIFF
|
||
|
*
|
||
|
* IDD_LINKTYPECHANGED -- class of link source changed since last binding
|
||
|
* VARARG Parameters:
|
||
|
* LPSTR lpszUserType -- user type name of ole link source
|
||
|
* Used for the following error codes:
|
||
|
* OLE_E_CLASSDIFF
|
||
|
*
|
||
|
* IDD_OUTOFMEMORY -- out of memory
|
||
|
* VARARG Parameters:
|
||
|
* None.
|
||
|
* Used for the following error codes:
|
||
|
* E_OUTOFMEMORY
|
||
|
*
|
||
|
*/
|
||
|
int EXPORT FAR CDECL OleUIPromptUser(int nTemplate, HWND hwndParent, ...)
|
||
|
{
|
||
|
int nRet;
|
||
|
va_list arglist;
|
||
|
LPARAM lParam;
|
||
|
|
||
|
//
|
||
|
// We want to pass the variable list of arguments to PrompUserDlgProc,
|
||
|
// but we can't just pass arglist because arglist is not always the
|
||
|
// same size as an LPARAM (e.g. on Alpha va_list is a structure).
|
||
|
// So, we pass the a pointer to the arglist instead.
|
||
|
//
|
||
|
|
||
|
va_start(arglist, hwndParent);
|
||
|
lParam = (LPARAM) &arglist;
|
||
|
|
||
|
nRet = DialogBoxParam(ghInst, MAKEINTRESOURCE(nTemplate), hwndParent,
|
||
|
PromptUserDlgProc, lParam);
|
||
|
|
||
|
va_end(arglist);
|
||
|
|
||
|
return nRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/* UpdateLinksDlgProc
|
||
|
* ------------------
|
||
|
*
|
||
|
* Purpose:
|
||
|
* Dialog procedure used by OleUIUpdateLinks(). It will enumerate all
|
||
|
* all links in the container and updates all automatic links.
|
||
|
* Returns when the Stop Button is clicked in the dialog box or when all
|
||
|
* links are updated
|
||
|
*
|
||
|
* Parameters:
|
||
|
* hDlg
|
||
|
* iMsg
|
||
|
* wParam
|
||
|
* lParam pointer to the UPDATELINKS structure
|
||
|
*
|
||
|
* Returns:
|
||
|
*
|
||
|
*/
|
||
|
BOOL CALLBACK EXPORT UpdateLinksDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
LPUPDATELINKS FAR* lplpUL = NULL;
|
||
|
HANDLE gh;
|
||
|
static BOOL fAbort = FALSE;
|
||
|
|
||
|
//Process the temination message
|
||
|
if (iMsg==uMsgEndDialog)
|
||
|
{
|
||
|
gh = RemoveProp(hDlg, STRUCTUREPROP);
|
||
|
if (NULL!=gh) {
|
||
|
GlobalUnlock(gh);
|
||
|
GlobalFree(gh);
|
||
|
}
|
||
|
EndDialog(hDlg, wParam);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
switch (iMsg) {
|
||
|
case WM_INITDIALOG:
|
||
|
{
|
||
|
gh=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,sizeof(LPUPDATELINKS));
|
||
|
SetProp(hDlg, STRUCTUREPROP, gh);
|
||
|
|
||
|
if (NULL==gh)
|
||
|
{
|
||
|
PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_GLOBALMEMALLOC,0L);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
fAbort = FALSE;
|
||
|
lplpUL = (LPUPDATELINKS FAR*)GlobalLock(gh);
|
||
|
|
||
|
if (lplpUL) {
|
||
|
*lplpUL = (LPUPDATELINKS)lParam;
|
||
|
SetWindowText(hDlg, (*lplpUL)->lpszTitle);
|
||
|
SetTimer(hDlg, 1, UPDATELINKS_STARTDELAY, NULL);
|
||
|
return TRUE;
|
||
|
} else {
|
||
|
PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_GLOBALMEMALLOC,0L);
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
case WM_TIMER:
|
||
|
KillTimer(hDlg, 1);
|
||
|
gh = GetProp(hDlg, STRUCTUREPROP);
|
||
|
|
||
|
if (NULL!=gh) {
|
||
|
// gh was locked previously, lock and unlock to get lplpUL
|
||
|
lplpUL = GlobalLock(gh);
|
||
|
GlobalUnlock(gh);
|
||
|
}
|
||
|
if (! fAbort && lplpUL)
|
||
|
PostMessage(hDlg, WM_U_UPDATELINK, 0, (LPARAM)(*lplpUL));
|
||
|
else
|
||
|
PostMessage(hDlg,uMsgEndDialog,OLEUI_CANCEL,0L);
|
||
|
|
||
|
return 0;
|
||
|
|
||
|
case WM_COMMAND: // Stop button
|
||
|
fAbort = TRUE;
|
||
|
SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L);
|
||
|
return TRUE;
|
||
|
|
||
|
case WM_U_UPDATELINK:
|
||
|
{
|
||
|
HRESULT hErr;
|
||
|
int nPercent;
|
||
|
RECT rc;
|
||
|
TCHAR szPercent[5]; // 0% to 100%
|
||
|
HBRUSH hbr;
|
||
|
HDC hDC;
|
||
|
HWND hwndMeter;
|
||
|
MSG msg;
|
||
|
DWORD dwUpdateOpt;
|
||
|
LPUPDATELINKS lpUL = (LPUPDATELINKS)lParam;
|
||
|
|
||
|
lpUL->dwLink=lpUL->lpOleUILinkCntr->lpVtbl->GetNextLink(
|
||
|
lpUL->lpOleUILinkCntr,
|
||
|
lpUL->dwLink
|
||
|
);
|
||
|
|
||
|
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||
|
if (! IsDialogMessage(hDlg, &msg)) {
|
||
|
TranslateMessage(&msg);
|
||
|
DispatchMessage(&msg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (fAbort)
|
||
|
return FALSE;
|
||
|
|
||
|
if (!lpUL->dwLink) { // all links processed
|
||
|
SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
hErr = lpUL->lpOleUILinkCntr->lpVtbl->GetLinkUpdateOptions(
|
||
|
lpUL->lpOleUILinkCntr,
|
||
|
lpUL->dwLink,
|
||
|
(LPDWORD)&dwUpdateOpt
|
||
|
);
|
||
|
|
||
|
if ((hErr == NOERROR) && (dwUpdateOpt == OLEUPDATE_ALWAYS)) {
|
||
|
|
||
|
hErr = lpUL->lpOleUILinkCntr->lpVtbl->UpdateLink(
|
||
|
lpUL->lpOleUILinkCntr,
|
||
|
lpUL->dwLink,
|
||
|
FALSE, // fMessage
|
||
|
FALSE // ignored
|
||
|
);
|
||
|
lpUL->fError |= (hErr != NOERROR);
|
||
|
lpUL->cUpdated++;
|
||
|
|
||
|
nPercent = lpUL->cUpdated * 100 / lpUL->cLinks;
|
||
|
if (nPercent <= 100) { // do NOT advance % beyond 100%
|
||
|
// update percentage
|
||
|
wsprintf((LPTSTR)szPercent, TEXT("%d%%"), nPercent);
|
||
|
SetDlgItemText(hDlg, ID_PU_PERCENT, (LPTSTR)szPercent);
|
||
|
|
||
|
// update indicator
|
||
|
hwndMeter = GetDlgItem(hDlg, ID_PU_METER);
|
||
|
GetClientRect(hwndMeter, (LPRECT)&rc);
|
||
|
InflateRect((LPRECT)&rc, -1, -1);
|
||
|
rc.right = (rc.right - rc.left) * nPercent / 100 + rc.left;
|
||
|
hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
|
||
|
if (hbr) {
|
||
|
hDC = GetDC(hwndMeter);
|
||
|
if (hDC) {
|
||
|
FillRect(hDC, (LPRECT)&rc, hbr);
|
||
|
ReleaseDC(hwndMeter, hDC);
|
||
|
}
|
||
|
DeleteObject(hbr);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||
|
if (! IsDialogMessage(hDlg, &msg)) {
|
||
|
TranslateMessage(&msg);
|
||
|
DispatchMessage(&msg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PostMessage(hDlg, WM_U_UPDATELINK, 0, lParam);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/* OleUIUpdateLink
|
||
|
* ---------------
|
||
|
*
|
||
|
* Purpose:
|
||
|
* Update all links in the Link Container and popup a dialog box which
|
||
|
* shows the progress of the updating.
|
||
|
* The process is stopped when the user press Stop button or when all
|
||
|
* links are processed.
|
||
|
*
|
||
|
* Parameters:
|
||
|
* lpOleUILinkCntr pointer to Link Container
|
||
|
* hwndParent parent window of the dialog
|
||
|
* lpszTitle title of the dialog box
|
||
|
* cLinks total number of links
|
||
|
*
|
||
|
* Returns:
|
||
|
* TRUE all links updated successfully
|
||
|
* FALSE otherwise
|
||
|
*/
|
||
|
STDAPI_(BOOL) OleUIUpdateLinks(LPOLEUILINKCONTAINER lpOleUILinkCntr, HWND hwndParent, LPTSTR lpszTitle, int cLinks)
|
||
|
{
|
||
|
LPUPDATELINKS lpUL = (LPUPDATELINKS)OleStdMalloc(sizeof(UPDATELINKS));
|
||
|
BOOL fError;
|
||
|
|
||
|
OleDbgAssert(lpOleUILinkCntr && hwndParent && lpszTitle && (cLinks>0));
|
||
|
OleDbgAssert(lpUL);
|
||
|
|
||
|
lpUL->lpOleUILinkCntr = lpOleUILinkCntr;
|
||
|
lpUL->cLinks = cLinks;
|
||
|
lpUL->cUpdated = 0;
|
||
|
lpUL->dwLink = 0;
|
||
|
lpUL->fError = FALSE;
|
||
|
lpUL->lpszTitle = lpszTitle;
|
||
|
|
||
|
DialogBoxParam(ghInst, MAKEINTRESOURCE(IDD_UPDATELINKS),
|
||
|
hwndParent, UpdateLinksDlgProc, (LPARAM)lpUL);
|
||
|
|
||
|
fError = lpUL->fError;
|
||
|
OleStdFree((LPVOID)lpUL);
|
||
|
|
||
|
return !fError;
|
||
|
}
|