You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2011 lines
78 KiB
2011 lines
78 KiB
/*
|
|
* INSOBJ.CPP
|
|
*
|
|
* Implements the OleUIInsertObject function which invokes the complete
|
|
* Insert Object dialog. Makes use of the OleChangeIcon function in
|
|
* ICON.CPP.
|
|
*
|
|
* Copyright (c)1993 Microsoft Corporation, All Rights Reserved
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
#include "common.h"
|
|
#include <commdlg.h>
|
|
#include <memory.h>
|
|
#include <dos.h>
|
|
#include <stdlib.h>
|
|
#include <reghelp.hxx>
|
|
#include "utility.h"
|
|
#include "resimage.h"
|
|
#include "iconbox.h"
|
|
|
|
#include "strcache.h"
|
|
|
|
OLEDBGDATA
|
|
|
|
#if USE_STRING_CACHE==1
|
|
extern CStringCache gInsObjStringCache; //defined in strcache.cpp
|
|
DWORD g_dwOldListType = 0;
|
|
#endif
|
|
|
|
// Internally used structure
|
|
typedef struct tagINSERTOBJECT
|
|
{
|
|
LPOLEUIINSERTOBJECT lpOIO; // Original structure passed.
|
|
UINT nIDD; // IDD of dialog (used for help info)
|
|
|
|
/*
|
|
* What we store extra in this structure besides the original caller's
|
|
* pointer are those fields that we need to modify during the life of
|
|
* the dialog but that we don't want to change in the original structure
|
|
* until the user presses OK.
|
|
*/
|
|
DWORD dwFlags;
|
|
CLSID clsid;
|
|
TCHAR szFile[MAX_PATH];
|
|
BOOL fFileSelected; // Enables Display As Icon for links
|
|
BOOL fAsIconNew;
|
|
BOOL fAsIconFile;
|
|
BOOL fFileDirty;
|
|
BOOL fFileValid;
|
|
UINT nErrCode;
|
|
HGLOBAL hMetaPictFile;
|
|
UINT nBrowseHelpID; // Help ID callback for Browse dlg
|
|
BOOL bObjectListFilled;
|
|
BOOL bControlListFilled;
|
|
BOOL bControlListActive;
|
|
|
|
} INSERTOBJECT, *PINSERTOBJECT, FAR *LPINSERTOBJECT;
|
|
|
|
// Internal function prototypes
|
|
// INSOBJ.CPP
|
|
|
|
void EnableChangeIconButton(HWND hDlg, BOOL fEnable);
|
|
INT_PTR CALLBACK InsertObjectDialogProc(HWND, UINT, WPARAM, LPARAM);
|
|
BOOL FInsertObjectInit(HWND, WPARAM, LPARAM);
|
|
UINT UFillClassList(HWND, UINT, LPCLSID, BOOL, BOOL);
|
|
LRESULT URefillClassList(HWND, LPINSERTOBJECT);
|
|
BOOL FToggleObjectSource(HWND, LPINSERTOBJECT, DWORD);
|
|
void UpdateClassType(HWND, LPINSERTOBJECT, BOOL);
|
|
void SetInsertObjectResults(HWND, LPINSERTOBJECT);
|
|
BOOL FValidateInsertFile(HWND, BOOL, UINT FAR*);
|
|
void InsertObjectCleanup(HWND);
|
|
static void UpdateClassIcon(HWND hDlg, LPINSERTOBJECT lpIO, HWND hList);
|
|
BOOL CALLBACK HookDlgProc(HWND, UINT, WPARAM, LPARAM);
|
|
|
|
#define IS_FILENAME_DELIM(c) ( (c) == '\\' || (c) == '/' || (c) == ':')
|
|
|
|
BOOL CALLBACK HookDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
#ifdef CHICO
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
TCHAR szTemp[MAX_PATH];
|
|
LoadString(_g_hOleStdResInst, IDS_INSERT , szTemp, MAX_PATH);
|
|
CommDlg_OpenSave_SetControlText(GetParent(hDlg), IDOK, szTemp);
|
|
return(TRUE);
|
|
default:
|
|
break;
|
|
}
|
|
#endif
|
|
return(FALSE);
|
|
}
|
|
|
|
/*
|
|
* OleUIInsertObject
|
|
*
|
|
* Purpose:
|
|
* Invokes the standard OLE Insert Object dialog box allowing the
|
|
* user to select an object source and classname as well as the option
|
|
* to display the object as itself or as an icon.
|
|
*
|
|
* Parameters:
|
|
* lpIO LPOLEUIINSERTOBJECT pointing to the in-out structure
|
|
* for this dialog.
|
|
*
|
|
* Return Value:
|
|
* UINT OLEUI_SUCCESS or OLEUI_OK if all is well, otherwise
|
|
* an error value.
|
|
*/
|
|
|
|
STDAPI_(UINT) OleUIInsertObject(LPOLEUIINSERTOBJECT lpIO)
|
|
{
|
|
HGLOBAL hMemDlg = NULL;
|
|
UINT uRet = UStandardValidation((LPOLEUISTANDARD)lpIO, sizeof(OLEUIINSERTOBJECT),
|
|
&hMemDlg);
|
|
|
|
if (OLEUI_SUCCESS != uRet)
|
|
return uRet;
|
|
|
|
//Now we can do Insert Object specific validation.
|
|
|
|
if (NULL != lpIO->lpszFile &&
|
|
(lpIO->cchFile <= 0 || lpIO->cchFile > MAX_PATH))
|
|
{
|
|
uRet = OLEUI_IOERR_CCHFILEINVALID;
|
|
}
|
|
|
|
// NULL is NOT valid for lpszFile
|
|
if (lpIO->lpszFile == NULL)
|
|
{
|
|
uRet = OLEUI_IOERR_LPSZFILEINVALID;
|
|
}
|
|
else
|
|
{
|
|
if (IsBadWritePtr(lpIO->lpszFile, lpIO->cchFile*sizeof(TCHAR)))
|
|
uRet = OLEUI_IOERR_LPSZFILEINVALID;
|
|
}
|
|
|
|
if (0 != lpIO->cClsidExclude &&
|
|
IsBadReadPtr(lpIO->lpClsidExclude, lpIO->cClsidExclude * sizeof(CLSID)))
|
|
{
|
|
uRet = OLEUI_IOERR_LPCLSIDEXCLUDEINVALID;
|
|
}
|
|
|
|
//If we have flags to create any object, validate necessary data.
|
|
if (lpIO->dwFlags & (IOF_CREATENEWOBJECT | IOF_CREATEFILEOBJECT | IOF_CREATELINKOBJECT))
|
|
{
|
|
if (NULL != lpIO->lpFormatEtc
|
|
&& IsBadReadPtr(lpIO->lpFormatEtc, sizeof(FORMATETC)))
|
|
uRet = OLEUI_IOERR_LPFORMATETCINVALID;
|
|
|
|
if (NULL != lpIO->ppvObj && IsBadWritePtr(lpIO->ppvObj, sizeof(LPVOID)))
|
|
uRet = OLEUI_IOERR_PPVOBJINVALID;
|
|
|
|
if (NULL != lpIO->lpIOleClientSite
|
|
&& IsBadReadPtr(*(VOID**)&lpIO->lpIOleClientSite, sizeof(DWORD)))
|
|
uRet = OLEUI_IOERR_LPIOLECLIENTSITEINVALID;
|
|
|
|
if (NULL != lpIO->lpIStorage
|
|
&& IsBadReadPtr(*(VOID**)&lpIO->lpIStorage, sizeof(DWORD)))
|
|
uRet = OLEUI_IOERR_LPISTORAGEINVALID;
|
|
}
|
|
|
|
if (OLEUI_ERR_STANDARDMIN <= uRet)
|
|
{
|
|
return uRet;
|
|
}
|
|
#if USE_STRING_CACHE==1
|
|
// Inform the string cache about a fresh InsertObject invocation.
|
|
gInsObjStringCache.NewCall(lpIO->dwFlags, lpIO->cClsidExclude);
|
|
#endif
|
|
|
|
//Now that we've validated everything, we can invoke the dialog.
|
|
uRet = UStandardInvocation(InsertObjectDialogProc, (LPOLEUISTANDARD)lpIO,
|
|
hMemDlg, MAKEINTRESOURCE(IDD_INSERTOBJECT));
|
|
|
|
//Stop here if we cancelled or had an error.
|
|
if (OLEUI_SUCCESS !=uRet && OLEUI_OK!=uRet)
|
|
return uRet;
|
|
|
|
/*
|
|
* If any of the flags specify that we're to create objects on return
|
|
* from this dialog, then do so. If we encounter an error in this
|
|
* processing, we return OLEUI_IOERR_SCODEHASERROR. Since the
|
|
* three select flags are mutually exclusive, we don't have to
|
|
* if...else here, just if each case (keeps things cleaner that way).
|
|
*/
|
|
|
|
lpIO->sc = S_OK;
|
|
|
|
// Check if Create New was selected and we have IOF_CREATENEWOBJECT
|
|
if ((lpIO->dwFlags & (IOF_SELECTCREATENEW|IOF_SELECTCREATECONTROL)) &&
|
|
(lpIO->dwFlags & IOF_CREATENEWOBJECT))
|
|
{
|
|
HRESULT hrErr = OleCreate(lpIO->clsid, lpIO->iid, lpIO->oleRender,
|
|
lpIO->lpFormatEtc, lpIO->lpIOleClientSite, lpIO->lpIStorage,
|
|
lpIO->ppvObj);
|
|
lpIO->sc = GetScode(hrErr);
|
|
}
|
|
|
|
// Try Create From File
|
|
if ((lpIO->dwFlags & IOF_SELECTCREATEFROMFILE))
|
|
{
|
|
if (!(lpIO->dwFlags & IOF_CHECKLINK) && (lpIO->dwFlags & IOF_CREATEFILEOBJECT))
|
|
{
|
|
HRESULT hrErr=OleCreateFromFile(CLSID_NULL, lpIO->lpszFile, lpIO->iid,
|
|
lpIO->oleRender, lpIO->lpFormatEtc, lpIO->lpIOleClientSite,
|
|
lpIO->lpIStorage, lpIO->ppvObj);
|
|
lpIO->sc = GetScode(hrErr);
|
|
}
|
|
|
|
if ((lpIO->dwFlags & IOF_CHECKLINK) && (lpIO->dwFlags & IOF_CREATELINKOBJECT))
|
|
{
|
|
HRESULT hrErr=OleCreateLinkToFile(lpIO->lpszFile, lpIO->iid,
|
|
lpIO->oleRender, lpIO->lpFormatEtc, lpIO->lpIOleClientSite,
|
|
lpIO->lpIStorage, lpIO->ppvObj);
|
|
lpIO->sc = GetScode(hrErr);
|
|
}
|
|
}
|
|
|
|
//If we tried but failed a create option, then return the appropriate error
|
|
if (S_OK != lpIO->sc)
|
|
uRet = OLEUI_IOERR_SCODEHASERROR;
|
|
|
|
return uRet;
|
|
}
|
|
|
|
/*
|
|
* InsertObjectDialogProc
|
|
*
|
|
* Purpose:
|
|
* Implements the OLE Insert Object dialog as invoked through the
|
|
* OleUIInsertObject function.
|
|
*/
|
|
|
|
INT_PTR CALLBACK InsertObjectDialogProc(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 uRet = 0;
|
|
LPINSERTOBJECT lpIO = (LPINSERTOBJECT)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uRet);
|
|
|
|
// If the hook processed the message, we're done.
|
|
if (0 != uRet)
|
|
return (BOOL)uRet;
|
|
|
|
// Process help message from Change Icon
|
|
if (iMsg == uMsgHelp)
|
|
{
|
|
if (lpIO && (lpIO->lpOIO))
|
|
PostMessage(lpIO->lpOIO->hWndOwner, uMsgHelp, wParam, lParam);
|
|
return FALSE;
|
|
}
|
|
|
|
// Process the temination message
|
|
if (iMsg == uMsgEndDialog)
|
|
{
|
|
EndDialog(hDlg, wParam);
|
|
return TRUE;
|
|
}
|
|
|
|
// The following messages do not require lpio to be non-null.
|
|
switch (iMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
return FInsertObjectInit(hDlg, wParam, lParam);
|
|
}
|
|
|
|
// The following messages DO require lpIO to be non-null, so don't
|
|
// continue processing if lpIO is NULL.
|
|
if (NULL == lpIO)
|
|
return FALSE;
|
|
|
|
switch (iMsg)
|
|
{
|
|
case WM_DESTROY:
|
|
InsertObjectCleanup(hDlg);
|
|
StandardCleanup(lpIO, hDlg);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (wID)
|
|
{
|
|
case IDC_IO_CREATENEW:
|
|
if (1 == IsDlgButtonChecked(hDlg, IDC_IO_CREATENEW))
|
|
{
|
|
FToggleObjectSource(hDlg, lpIO, IOF_SELECTCREATENEW);
|
|
SetFocus(GetDlgItem(hDlg, IDC_IO_CREATENEW));
|
|
}
|
|
break;
|
|
|
|
case IDC_IO_CREATEFROMFILE:
|
|
if (1 == IsDlgButtonChecked(hDlg, IDC_IO_CREATEFROMFILE))
|
|
{
|
|
FToggleObjectSource(hDlg, lpIO, IOF_SELECTCREATEFROMFILE);
|
|
SetFocus(GetDlgItem(hDlg, IDC_IO_CREATEFROMFILE));
|
|
}
|
|
break;
|
|
|
|
case IDC_IO_INSERTCONTROL:
|
|
if (1 == IsDlgButtonChecked(hDlg, IDC_IO_INSERTCONTROL))
|
|
{
|
|
FToggleObjectSource(hDlg, lpIO, IOF_SELECTCREATECONTROL);
|
|
SetFocus(GetDlgItem(hDlg, IDC_IO_INSERTCONTROL));
|
|
}
|
|
break;
|
|
|
|
case IDC_IO_LINKFILE:
|
|
{
|
|
BOOL fCheck=IsDlgButtonChecked(hDlg, wID);
|
|
if (fCheck)
|
|
lpIO->dwFlags |=IOF_CHECKLINK;
|
|
else
|
|
lpIO->dwFlags &=~IOF_CHECKLINK;
|
|
|
|
// Results change here, so be sure to update it.
|
|
SetInsertObjectResults(hDlg, lpIO);
|
|
UpdateClassIcon(hDlg, lpIO, NULL);
|
|
}
|
|
break;
|
|
|
|
case IDC_IO_OBJECTTYPELIST:
|
|
switch (wCode)
|
|
{
|
|
case LBN_SELCHANGE:
|
|
UpdateClassIcon(hDlg, lpIO, hWndMsg);
|
|
SetInsertObjectResults(hDlg, lpIO);
|
|
break;
|
|
|
|
case LBN_DBLCLK:
|
|
SendCommand(hDlg, IDOK, BN_CLICKED, hWndMsg);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case IDC_IO_FILEDISPLAY:
|
|
// If there are characters, enable OK and Display As Icon
|
|
if (EN_CHANGE == wCode)
|
|
{
|
|
lpIO->fFileDirty = TRUE;
|
|
lpIO->fFileValid = FALSE;
|
|
lpIO->fFileSelected = (0L != SendMessage(hWndMsg, EM_LINELENGTH, 0, 0L));
|
|
StandardEnableDlgItem(hDlg, IDC_IO_LINKFILE, lpIO->fFileSelected);
|
|
StandardEnableDlgItem(hDlg, IDC_IO_DISPLAYASICON, lpIO->fFileSelected);
|
|
EnableChangeIconButton(hDlg, lpIO->fFileSelected);
|
|
StandardEnableDlgItem(hDlg, IDOK, lpIO->fFileSelected);
|
|
}
|
|
if (EN_KILLFOCUS == wCode && NULL != lpIO)
|
|
{
|
|
if (FValidateInsertFile(hDlg, FALSE, &lpIO->nErrCode))
|
|
{
|
|
lpIO->fFileDirty = FALSE;
|
|
lpIO->fFileValid = TRUE;
|
|
UpdateClassIcon(hDlg, lpIO, NULL);
|
|
UpdateClassType(hDlg, lpIO, TRUE);
|
|
}
|
|
else
|
|
{
|
|
lpIO->fFileDirty = FALSE;
|
|
lpIO->fFileValid = FALSE;
|
|
UpdateClassType(hDlg, lpIO, FALSE);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDC_IO_DISPLAYASICON:
|
|
{
|
|
BOOL fCheck = IsDlgButtonChecked(hDlg, wID);
|
|
if (fCheck)
|
|
lpIO->dwFlags |=IOF_CHECKDISPLAYASICON;
|
|
else
|
|
lpIO->dwFlags &=~IOF_CHECKDISPLAYASICON;
|
|
|
|
// Update the internal flag based on this checking
|
|
if (lpIO->dwFlags & IOF_SELECTCREATENEW)
|
|
lpIO->fAsIconNew = fCheck;
|
|
else
|
|
lpIO->fAsIconFile = fCheck;
|
|
|
|
// Re-read the class icon on Display checked
|
|
if (fCheck)
|
|
{
|
|
if (lpIO->dwFlags & IOF_SELECTCREATEFROMFILE)
|
|
{
|
|
if (FValidateInsertFile(hDlg, TRUE,&lpIO->nErrCode))
|
|
{
|
|
lpIO->fFileDirty = FALSE;
|
|
lpIO->fFileValid = TRUE;
|
|
UpdateClassIcon(hDlg, lpIO,
|
|
GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST));
|
|
UpdateClassType(hDlg, lpIO, TRUE);
|
|
}
|
|
else
|
|
{
|
|
lpIO->fAsIconFile= FALSE;
|
|
lpIO->fFileDirty = FALSE;
|
|
lpIO->fFileValid = FALSE;
|
|
SendDlgItemMessage(hDlg, IDC_IO_ICONDISPLAY,
|
|
IBXM_IMAGESET, 0, 0L);
|
|
UpdateClassType(hDlg, lpIO, FALSE);
|
|
|
|
lpIO->dwFlags &=~IOF_CHECKDISPLAYASICON;
|
|
CheckDlgButton(hDlg, IDC_IO_DISPLAYASICON, 0);
|
|
|
|
HWND hWndEC = GetDlgItem(hDlg, IDC_IO_FILEDISPLAY);
|
|
SetFocus(hWndEC);
|
|
SendMessage(hWndEC, EM_SETSEL, 0, -1);
|
|
return TRUE;
|
|
}
|
|
}
|
|
else
|
|
UpdateClassIcon(hDlg, lpIO,
|
|
GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST));
|
|
}
|
|
|
|
// Results change here, so be sure to update it.
|
|
SetInsertObjectResults(hDlg, lpIO);
|
|
|
|
/*
|
|
* Show or hide controls as appropriate. Do the icon
|
|
* display last because it will take some time to repaint.
|
|
* If we do it first then the dialog looks too sluggish.
|
|
*/
|
|
UINT i = (fCheck) ? SW_SHOWNORMAL : SW_HIDE;
|
|
StandardShowDlgItem(hDlg, IDC_IO_ICONDISPLAY, i);
|
|
StandardShowDlgItem(hDlg, IDC_IO_CHANGEICON, i);
|
|
EnableChangeIconButton(hDlg, fCheck);
|
|
}
|
|
break;
|
|
|
|
case IDC_IO_CHANGEICON:
|
|
{
|
|
// if we're in SELECTCREATEFROMFILE mode, then we need to Validate
|
|
// the contents of the edit control first.
|
|
|
|
if (lpIO->dwFlags & IOF_SELECTCREATEFROMFILE)
|
|
{
|
|
if (lpIO->fFileDirty &&
|
|
!FValidateInsertFile(hDlg, TRUE, &lpIO->nErrCode))
|
|
{
|
|
HWND hWndEC;
|
|
lpIO->fFileValid = FALSE;
|
|
hWndEC = GetDlgItem(hDlg, IDC_IO_FILEDISPLAY);
|
|
SetFocus(hWndEC);
|
|
SendMessage(hWndEC, EM_SETSEL, 0, -1);
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
lpIO->fFileDirty = FALSE;
|
|
}
|
|
}
|
|
|
|
// Initialize the structure for the hook.
|
|
OLEUICHANGEICON ci; memset(&ci, 0, sizeof(ci));
|
|
ci.cbStruct = sizeof(ci);
|
|
ci.hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg,
|
|
IDC_IO_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L);
|
|
ci.hWndOwner= hDlg;
|
|
ci.dwFlags = CIF_SELECTCURRENT;
|
|
if (lpIO->dwFlags & IOF_SHOWHELP)
|
|
ci.dwFlags |= CIF_SHOWHELP;
|
|
|
|
HWND hList = GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST);
|
|
int iCurSel = (int)SendMessage(hList, LB_GETCURSEL, 0, 0L);
|
|
if (lpIO->dwFlags & IOF_SELECTCREATENEW)
|
|
{
|
|
LPTSTR pszString = (LPTSTR)OleStdMalloc(
|
|
OLEUI_CCHKEYMAX_SIZE + OLEUI_CCHCLSIDSTRING_SIZE);
|
|
|
|
SendMessage(hList, LB_GETTEXT, iCurSel, (LPARAM)pszString);
|
|
|
|
LPTSTR pszCLSID = PointerToNthField(pszString, 2, '\t');
|
|
CLSIDFromString(pszCLSID, &ci.clsid);
|
|
OleStdFree((LPVOID)pszString);
|
|
}
|
|
else // IOF_SELECTCREATEFROMFILE
|
|
{
|
|
TCHAR szFileName[MAX_PATH];
|
|
GetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, szFileName, MAX_PATH);
|
|
if (S_OK != GetClassFile(szFileName, &ci.clsid))
|
|
{
|
|
int istrlen = lstrlen(szFileName);
|
|
LPTSTR lpszExtension = szFileName + istrlen -1;
|
|
|
|
while (lpszExtension > szFileName &&
|
|
*lpszExtension != '.')
|
|
{
|
|
lpszExtension = CharPrev(szFileName, lpszExtension);
|
|
}
|
|
|
|
GetAssociatedExecutable(lpszExtension, ci.szIconExe, sizeof(ci.szIconExe)/sizeof(ci.szIconExe[0]));
|
|
ci.cchIconExe = lstrlen(ci.szIconExe);
|
|
ci.dwFlags |= CIF_USEICONEXE;
|
|
}
|
|
}
|
|
|
|
// Let the hook in to customize Change Icon if desired.
|
|
uRet = UStandardHook(lpIO, hDlg, uMsgChangeIcon, 0, (LPARAM)&ci);
|
|
|
|
if (0 == uRet)
|
|
uRet = (UINT)(OLEUI_OK == OleUIChangeIcon(&ci));
|
|
|
|
// Update the display and itemdata if necessary.
|
|
if (0 != uRet)
|
|
{
|
|
/*
|
|
* OleUIChangeIcon will have already freed our
|
|
* current hMetaPict that we passed in when OK is
|
|
* pressed in that dialog. So we use 0L as lParam
|
|
* here so the IconBox doesn't try to free the
|
|
* metafilepict again.
|
|
*/
|
|
SendDlgItemMessage(hDlg, IDC_IO_ICONDISPLAY,
|
|
IBXM_IMAGESET, 0, (LPARAM)ci.hMetaPict);
|
|
|
|
if (lpIO->dwFlags & IOF_SELECTCREATENEW)
|
|
SendMessage(hList, LB_SETITEMDATA, iCurSel, (LPARAM)ci.hMetaPict);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDC_IO_FILE:
|
|
{
|
|
/*
|
|
* To allow the hook to customize the browse dialog, we
|
|
* send OLEUI_MSG_BROWSE. If the hook returns FALSE
|
|
* we use the default, otherwise we trust that it retrieved
|
|
* a filename for us. This mechanism prevents hooks from
|
|
* trapping IDC_IO_BROWSE to customize the dialog and from
|
|
* trying to figure out what we do after we have the name.
|
|
*/
|
|
TCHAR szTemp[MAX_PATH];
|
|
int nChars = GetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, szTemp, MAX_PATH);
|
|
|
|
TCHAR szInitialDir[MAX_PATH];
|
|
BOOL fUseInitialDir = FALSE;
|
|
if (FValidateInsertFile(hDlg, FALSE, &lpIO->nErrCode))
|
|
{
|
|
StandardGetFileTitle(szTemp, lpIO->szFile, MAX_PATH);
|
|
int istrlen = lstrlen(lpIO->szFile);
|
|
|
|
lstrcpyn(szInitialDir, szTemp, nChars - istrlen);
|
|
fUseInitialDir = TRUE;
|
|
}
|
|
else // file name isn't valid...lop off end of szTemp to get a
|
|
// valid directory
|
|
{
|
|
TCHAR szBuffer[MAX_PATH];
|
|
lstrcpyn(szBuffer, szTemp, sizeof(szBuffer)/sizeof(TCHAR));
|
|
|
|
if ('\\' == szBuffer[nChars-1])
|
|
szBuffer[nChars-1] = '\0';
|
|
|
|
DWORD Attribs = GetFileAttributes(szBuffer);
|
|
if (Attribs != 0xffffffff &&
|
|
(Attribs & FILE_ATTRIBUTE_DIRECTORY) )
|
|
{
|
|
lstrcpy(szInitialDir, szBuffer);
|
|
fUseInitialDir = TRUE;
|
|
}
|
|
*lpIO->szFile = '\0';
|
|
}
|
|
|
|
uRet = UStandardHook(lpIO, hDlg, uMsgBrowse,
|
|
MAX_PATH, (LPARAM)(LPSTR)lpIO->szFile);
|
|
|
|
if (0 == uRet)
|
|
{
|
|
DWORD dwOfnFlags = OFN_FILEMUSTEXIST | OFN_ENABLEHOOK;
|
|
if (lpIO->lpOIO->dwFlags & IOF_SHOWHELP)
|
|
dwOfnFlags |= OFN_SHOWHELP;
|
|
|
|
uRet = (UINT)Browse(hDlg, lpIO->szFile,
|
|
fUseInitialDir ? szInitialDir : NULL, MAX_PATH,
|
|
IDS_FILTERS, dwOfnFlags, ID_BROWSE_INSERTFILE, (LPOFNHOOKPROC)HookDlgProc);
|
|
}
|
|
|
|
// Only update if the file changed.
|
|
if (0 != uRet && 0 != lstrcmpi(szTemp, lpIO->szFile))
|
|
{
|
|
SetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, lpIO->szFile);
|
|
lpIO->fFileSelected=TRUE;
|
|
|
|
if (FValidateInsertFile(hDlg, TRUE, &lpIO->nErrCode))
|
|
{
|
|
lpIO->fFileDirty = FALSE;
|
|
lpIO->fFileValid = TRUE;
|
|
UpdateClassIcon(hDlg, lpIO, NULL);
|
|
UpdateClassType(hDlg, lpIO, TRUE);
|
|
// auto set OK to be default button if valid file
|
|
SendMessage(hDlg, DM_SETDEFID,
|
|
(WPARAM)GetDlgItem(hDlg, IDOK), 0L);
|
|
SetFocus(GetDlgItem(hDlg, IDOK));
|
|
}
|
|
else // filename is invalid - set focus back to ec
|
|
{
|
|
HWND hWnd;
|
|
lpIO->fFileDirty = FALSE;
|
|
lpIO->fFileValid = FALSE;
|
|
hWnd = GetDlgItem(hDlg, IDC_IO_FILEDISPLAY);
|
|
SetFocus(hWnd);
|
|
SendMessage(hWnd, EM_SETSEL, 0, -1);
|
|
}
|
|
|
|
// Once we have a file, Display As Icon is always enabled
|
|
StandardEnableDlgItem(hDlg, IDC_IO_DISPLAYASICON, TRUE);
|
|
|
|
// As well as OK
|
|
StandardEnableDlgItem(hDlg, IDOK, TRUE);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDC_IO_ADDCONTROL:
|
|
{
|
|
TCHAR szFileName[MAX_PATH];
|
|
szFileName[0] = 0;
|
|
|
|
// allow hook to customize
|
|
uRet = UStandardHook(lpIO, hDlg, uMsgAddControl,
|
|
MAX_PATH, (LPARAM)szFileName);
|
|
|
|
if (0 == uRet)
|
|
{
|
|
DWORD dwOfnFlags = OFN_FILEMUSTEXIST | OFN_ENABLEHOOK;
|
|
if (lpIO->lpOIO->dwFlags & IOF_SHOWHELP)
|
|
dwOfnFlags |= OFN_SHOWHELP;
|
|
uRet = (UINT)Browse(hDlg, szFileName, NULL, MAX_PATH,
|
|
IDS_OCX_FILTERS, dwOfnFlags, ID_BROWSE_ADDCONTROL , (LPOFNHOOKPROC)HookDlgProc);
|
|
}
|
|
|
|
if (0 != uRet)
|
|
{
|
|
// try to register the control DLL
|
|
HINSTANCE hInst = LoadLibrary(szFileName);
|
|
if (hInst == NULL)
|
|
{
|
|
PopupMessage(hDlg, IDS_ADDCONTROL, IDS_CANNOTLOADOCX,
|
|
MB_OK | MB_ICONEXCLAMATION);
|
|
break;
|
|
}
|
|
|
|
HRESULT (FAR STDAPICALLTYPE* lpfn)(void);
|
|
(FARPROC&)lpfn = GetProcAddress(hInst, "DllRegisterServer");
|
|
if (lpfn == NULL)
|
|
{
|
|
PopupMessage(hDlg, IDS_ADDCONTROL, IDS_NODLLREGISTERSERVER,
|
|
MB_OK | MB_ICONEXCLAMATION);
|
|
FreeLibrary(hInst);
|
|
break;
|
|
}
|
|
|
|
if (FAILED((*lpfn)()))
|
|
{
|
|
PopupMessage(hDlg, IDS_ADDCONTROL, IDS_DLLREGISTERFAILED,
|
|
MB_OK | MB_ICONEXCLAMATION);
|
|
FreeLibrary(hInst);
|
|
break;
|
|
}
|
|
|
|
// cleanup the DLL from memory
|
|
FreeLibrary(hInst);
|
|
|
|
// registered successfully -- refill the list box
|
|
lpIO->bControlListFilled = FALSE;
|
|
lpIO->bObjectListFilled = FALSE;
|
|
URefillClassList(hDlg, lpIO);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDOK:
|
|
{
|
|
if ((HWND)lParam != GetFocus())
|
|
SetFocus((HWND)lParam);
|
|
|
|
// If the file name is clean (already validated), or
|
|
// if Create New is selected, then we can skip this part.
|
|
|
|
if ((lpIO->dwFlags & IOF_SELECTCREATEFROMFILE) &&
|
|
lpIO->fFileDirty)
|
|
{
|
|
if (FValidateInsertFile(hDlg, TRUE, &lpIO->nErrCode))
|
|
{
|
|
lpIO->fFileDirty = FALSE;
|
|
lpIO->fFileValid = TRUE;
|
|
UpdateClassIcon(hDlg, lpIO, NULL);
|
|
UpdateClassType(hDlg, lpIO, TRUE);
|
|
}
|
|
else // filename is invalid - set focus back to ec
|
|
{
|
|
HWND hWnd;
|
|
lpIO->fFileDirty = FALSE;
|
|
lpIO->fFileValid = FALSE;
|
|
hWnd = GetDlgItem(hDlg, IDC_IO_FILEDISPLAY);
|
|
SetFocus(hWnd);
|
|
SendMessage(hWnd, EM_SETSEL, 0, -1);
|
|
UpdateClassType(hDlg, lpIO, FALSE);
|
|
}
|
|
return TRUE; // eat this message
|
|
}
|
|
else if ((lpIO->dwFlags & IOF_SELECTCREATEFROMFILE) &&
|
|
!lpIO->fFileValid)
|
|
{
|
|
// filename is invalid - set focus back to ec
|
|
HWND hWnd;
|
|
TCHAR szFile[MAX_PATH];
|
|
|
|
if (0 != GetDlgItemText(hDlg, IDC_IO_FILEDISPLAY,
|
|
szFile, MAX_PATH))
|
|
{
|
|
OpenFileError(hDlg, lpIO->nErrCode, szFile);
|
|
}
|
|
lpIO->fFileDirty = FALSE;
|
|
lpIO->fFileValid = FALSE;
|
|
hWnd = GetDlgItem(hDlg, IDC_IO_FILEDISPLAY);
|
|
SetFocus(hWnd);
|
|
SendMessage(hWnd, EM_SETSEL, 0, -1);
|
|
UpdateClassType(hDlg, lpIO, FALSE);
|
|
return TRUE; // eat this message
|
|
}
|
|
|
|
// Copy the necessary information back to the original struct
|
|
LPOLEUIINSERTOBJECT lpOIO = lpIO->lpOIO;
|
|
lpOIO->dwFlags = lpIO->dwFlags;
|
|
|
|
if (lpIO->dwFlags & (IOF_SELECTCREATENEW|IOF_SELECTCREATECONTROL))
|
|
{
|
|
HWND hListBox = GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST);
|
|
UINT iCurSel = (UINT)SendMessage(hListBox, LB_GETCURSEL, 0, 0);
|
|
|
|
if (lpIO->dwFlags & IOF_CHECKDISPLAYASICON)
|
|
{
|
|
lpOIO->hMetaPict=(HGLOBAL)SendMessage(hListBox,
|
|
LB_GETITEMDATA, iCurSel, 0L);
|
|
|
|
/*
|
|
* Set the item data to 0 here so that the cleanup
|
|
* code doesn't delete the metafile.
|
|
*/
|
|
SendMessage(hListBox, LB_SETITEMDATA, iCurSel, 0L);
|
|
}
|
|
else
|
|
lpOIO->hMetaPict = (HGLOBAL)NULL;
|
|
|
|
TCHAR szBuffer[OLEUI_CCHKEYMAX+OLEUI_CCHCLSIDSTRING];
|
|
SendMessage(hListBox, LB_GETTEXT, iCurSel, (LPARAM)szBuffer);
|
|
|
|
LPTSTR lpszCLSID = PointerToNthField(szBuffer, 2, '\t');
|
|
CLSIDFromString(lpszCLSID, &lpOIO->clsid);
|
|
}
|
|
else // IOF_SELECTCREATEFROMFILE
|
|
{
|
|
if (lpIO->dwFlags & IOF_CHECKDISPLAYASICON)
|
|
{
|
|
// get metafile here
|
|
lpOIO->hMetaPict = (HGLOBAL)SendDlgItemMessage(
|
|
hDlg, IDC_IO_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L);
|
|
}
|
|
else
|
|
lpOIO->hMetaPict = (HGLOBAL)NULL;
|
|
}
|
|
|
|
GetDlgItemText(hDlg, IDC_IO_FILEDISPLAY,
|
|
lpIO->szFile, lpOIO->cchFile);
|
|
lstrcpyn(lpOIO->lpszFile, lpIO->szFile, lpOIO->cchFile);
|
|
SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L);
|
|
}
|
|
break;
|
|
|
|
case IDCANCEL:
|
|
SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L);
|
|
break;
|
|
|
|
case IDC_OLEUIHELP:
|
|
PostMessage(lpIO->lpOIO->hWndOwner, uMsgHelp,
|
|
(WPARAM)hDlg, MAKELPARAM(IDD_INSERTOBJECT, 0));
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if (iMsg == lpIO->nBrowseHelpID)
|
|
{
|
|
PostMessage(lpIO->lpOIO->hWndOwner, uMsgHelp,
|
|
(WPARAM)hDlg, MAKELPARAM(IDD_INSERTFILEBROWSE, 0));
|
|
}
|
|
if (iMsg == uMsgBrowseOFN &&
|
|
lpIO->lpOIO && lpIO->lpOIO->hWndOwner)
|
|
{
|
|
SendMessage(lpIO->lpOIO->hWndOwner, uMsgBrowseOFN, wParam, lParam);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CheckButton
|
|
//
|
|
// Synopsis: Handles checking the radio buttons
|
|
//
|
|
// Arguments: [hDlg] - dialog handle
|
|
// [iID] - ID of the button to check
|
|
//
|
|
// Returns: nothing
|
|
//
|
|
// History: 1-19-95 stevebl Created
|
|
//
|
|
// Notes: Used in place of CheckRadioButtons to avoid a GP fault under
|
|
// win32s that arises from IDC_IO_CREATENEW, IDC_IO_CREATEFROMFILE
|
|
// and IDC_IO_INSERTCONTROL not being contiguous.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CheckButton(HWND hDlg, int iID)
|
|
{
|
|
CheckDlgButton(hDlg, IDC_IO_CREATENEW, iID == IDC_IO_CREATENEW ? 1 : 0);
|
|
CheckDlgButton(hDlg, IDC_IO_CREATEFROMFILE, iID == IDC_IO_CREATEFROMFILE ? 1 : 0);
|
|
CheckDlgButton(hDlg, IDC_IO_INSERTCONTROL, iID == IDC_IO_INSERTCONTROL ? 1 : 0);
|
|
}
|
|
|
|
|
|
/*
|
|
* FInsertObjectInit
|
|
*
|
|
* Purpose:
|
|
* WM_INITIDIALOG handler for the Insert Object dialog box.
|
|
*
|
|
* Parameters:
|
|
* hDlg HWND of the dialog
|
|
* wParam WPARAM of the message
|
|
* lParam LPARAM of the message
|
|
*
|
|
* Return Value:
|
|
* BOOL Value to return for WM_INITDIALOG.
|
|
*/
|
|
BOOL FInsertObjectInit(HWND hDlg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
// Copy the structure at lParam into our instance memory.
|
|
HFONT hFont;
|
|
LPINSERTOBJECT lpIO = (LPINSERTOBJECT)LpvStandardInit(hDlg, sizeof(INSERTOBJECT), &hFont);
|
|
|
|
// PvStandardInit send a termination to us already.
|
|
if (NULL == lpIO)
|
|
return FALSE;
|
|
|
|
LPOLEUIINSERTOBJECT lpOIO = (LPOLEUIINSERTOBJECT)lParam;
|
|
|
|
// Save the original pointer and copy necessary information.
|
|
lpIO->lpOIO = lpOIO;
|
|
lpIO->nIDD = IDD_INSERTOBJECT;
|
|
lpIO->dwFlags = lpOIO->dwFlags;
|
|
lpIO->clsid = lpOIO->clsid;
|
|
|
|
if ((lpOIO->lpszFile) && ('\0' != *lpOIO->lpszFile))
|
|
lstrcpyn(lpIO->szFile, lpOIO->lpszFile, MAX_PATH);
|
|
else
|
|
*(lpIO->szFile) = '\0';
|
|
|
|
lpIO->hMetaPictFile = (HGLOBAL)NULL;
|
|
|
|
// If we got a font, send it to the necessary controls.
|
|
if (NULL != hFont)
|
|
{
|
|
SendDlgItemMessage(hDlg, IDC_IO_RESULTTEXT, WM_SETFONT, (WPARAM)hFont, 0L);
|
|
SendDlgItemMessage(hDlg, IDC_IO_FILETYPE, WM_SETFONT, (WPARAM)hFont, 0L);
|
|
}
|
|
|
|
// Initilize the file name display to cwd if we don't have any name.
|
|
if ('\0' == *(lpIO->szFile))
|
|
{
|
|
TCHAR szCurDir[MAX_PATH];
|
|
int nLen;
|
|
GetCurrentDirectory(MAX_PATH, szCurDir);
|
|
nLen = lstrlen(szCurDir);
|
|
if (nLen != 0 && szCurDir[nLen-1] != '\\')
|
|
lstrcat(szCurDir, _T("\\"));
|
|
SetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, szCurDir);
|
|
lpIO->fFileDirty = TRUE; // cwd is not a valid filename
|
|
}
|
|
else
|
|
{
|
|
SetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, lpIO->szFile);
|
|
if (FValidateInsertFile(hDlg, FALSE, &lpIO->nErrCode))
|
|
{
|
|
lpIO->fFileDirty = FALSE;
|
|
lpIO->fFileValid = TRUE;
|
|
}
|
|
else
|
|
{
|
|
lpIO->fFileDirty = TRUE;
|
|
lpIO->fFileValid = FALSE;
|
|
}
|
|
}
|
|
|
|
// Initialize radio button and related controls
|
|
if (lpIO->dwFlags & IOF_CHECKDISPLAYASICON)
|
|
{
|
|
if (lpIO->dwFlags & IOF_SELECTCREATENEW)
|
|
lpIO->fAsIconNew = TRUE;
|
|
else
|
|
lpIO->fAsIconFile = TRUE;
|
|
}
|
|
if (lpIO->dwFlags & IOF_SELECTCREATENEW)
|
|
CheckButton(hDlg, IDC_IO_CREATENEW);
|
|
if (lpIO->dwFlags & IOF_SELECTCREATEFROMFILE)
|
|
CheckButton(hDlg, IDC_IO_CREATEFROMFILE);
|
|
if (lpIO->dwFlags & IOF_SELECTCREATECONTROL)
|
|
CheckButton(hDlg, IDC_IO_INSERTCONTROL);
|
|
CheckDlgButton(hDlg, IDC_IO_LINKFILE, (BOOL)(0L != (lpIO->dwFlags & IOF_CHECKLINK)));
|
|
|
|
lpIO->dwFlags &=
|
|
~(IOF_SELECTCREATENEW|IOF_SELECTCREATEFROMFILE|IOF_SELECTCREATECONTROL);
|
|
FToggleObjectSource(hDlg, lpIO, lpOIO->dwFlags &
|
|
(IOF_SELECTCREATENEW|IOF_SELECTCREATEFROMFILE|IOF_SELECTCREATECONTROL));
|
|
|
|
// Show or hide the help button
|
|
if (!(lpIO->dwFlags & IOF_SHOWHELP))
|
|
StandardShowDlgItem(hDlg, IDC_OLEUIHELP, SW_HIDE);
|
|
|
|
// Show or hide the Change icon button
|
|
if (lpIO->dwFlags & IOF_HIDECHANGEICON)
|
|
DestroyWindow(GetDlgItem(hDlg, IDC_IO_CHANGEICON));
|
|
|
|
// Hide Insert Control button if necessary
|
|
if (!(lpIO->dwFlags & IOF_SHOWINSERTCONTROL))
|
|
StandardShowDlgItem(hDlg, IDC_IO_INSERTCONTROL, SW_HIDE);
|
|
|
|
// Initialize the result display
|
|
UpdateClassIcon(hDlg, lpIO, GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST));
|
|
SetInsertObjectResults(hDlg, lpIO);
|
|
|
|
// Change the caption
|
|
if (NULL!=lpOIO->lpszCaption)
|
|
SetWindowText(hDlg, lpOIO->lpszCaption);
|
|
|
|
// Hide all DisplayAsIcon related controls if it should be disabled
|
|
if (lpIO->dwFlags & IOF_DISABLEDISPLAYASICON)
|
|
{
|
|
StandardShowDlgItem(hDlg, IDC_IO_DISPLAYASICON, SW_HIDE);
|
|
StandardShowDlgItem(hDlg, IDC_IO_CHANGEICON, SW_HIDE);
|
|
StandardShowDlgItem(hDlg, IDC_IO_ICONDISPLAY, SW_HIDE);
|
|
}
|
|
|
|
lpIO->nBrowseHelpID = RegisterWindowMessage(HELPMSGSTRING);
|
|
|
|
// All Done: call the hook with lCustData
|
|
UStandardHook(lpIO, hDlg, WM_INITDIALOG, wParam, lpOIO->lCustData);
|
|
|
|
/*
|
|
* We either set focus to the listbox or the edit control. In either
|
|
* case we don't want Windows to do any SetFocus, so we return FALSE.
|
|
*/
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* URefillClassList
|
|
*
|
|
* Purpose:
|
|
* Fills the class list box with names as appropriate for the current
|
|
* flags. This function is called when the user changes the flags
|
|
* via the "exclusion" radio buttons.
|
|
*
|
|
* Note that this function removes any prior contents of the listbox.
|
|
*
|
|
* Parameters:
|
|
* hDlg HWND to the dialog box.
|
|
* lpIO pointer to LPINSERTOBJECT structure
|
|
*
|
|
* Return Value:
|
|
* LRESULT Number of strings added to the listbox, -1 on failure.
|
|
*/
|
|
LRESULT URefillClassList(HWND hDlg, LPINSERTOBJECT lpIO)
|
|
{
|
|
OleDbgAssert(lpIO->dwFlags & (IOF_SELECTCREATECONTROL|IOF_SELECTCREATENEW));
|
|
|
|
// always the same dialog ID because they are swapped
|
|
HWND hList = GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST);
|
|
|
|
// determine if already filled
|
|
BOOL bFilled;
|
|
if (lpIO->dwFlags & IOF_SELECTCREATECONTROL)
|
|
bFilled = lpIO->bControlListFilled;
|
|
else
|
|
bFilled = lpIO->bObjectListFilled;
|
|
|
|
if (!bFilled)
|
|
{
|
|
// fill the list
|
|
LPOLEUIINSERTOBJECT lpOIO = lpIO->lpOIO;
|
|
UINT uResult = UFillClassList(hList, lpOIO->cClsidExclude, lpOIO->lpClsidExclude,
|
|
(BOOL)(lpIO->dwFlags & IOF_VERIFYSERVERSEXIST),
|
|
(lpIO->dwFlags & IOF_SELECTCREATECONTROL));
|
|
|
|
// mark the list as filled
|
|
if (lpIO->dwFlags & IOF_SELECTCREATECONTROL)
|
|
lpIO->bControlListFilled = TRUE;
|
|
else
|
|
lpIO->bObjectListFilled = TRUE;
|
|
}
|
|
|
|
// return number of items now in the list
|
|
return SendMessage(hList, LB_GETCOUNT, 0, 0);
|
|
}
|
|
|
|
|
|
/*
|
|
* UFillClassList
|
|
*
|
|
* Purpose:
|
|
* Enumerates available OLE object classes from the registration
|
|
* database and fills a listbox with those names.
|
|
*
|
|
* Note that this function removes any prior contents of the listbox.
|
|
*
|
|
* Parameters:
|
|
* hList HWND to the listbox to fill.
|
|
* cIDEx UINT number of CLSIDs to exclude in lpIDEx
|
|
* lpIDEx LPCLSID to CLSIDs to leave out of the listbox.
|
|
* fVerify BOOL indicating if we are to validate existence of
|
|
* servers before putting them in the list.
|
|
*
|
|
* Return Value:
|
|
* UINT Number of strings added to the listbox, -1 on failure.
|
|
*/
|
|
|
|
UINT UFillClassList(HWND hList, UINT cIDEx, LPCLSID lpIDEx, BOOL fVerify,
|
|
BOOL fExcludeObjects)
|
|
{
|
|
OleDbgAssert(hList != NULL);
|
|
|
|
// Set the tab width in the list to push all the tabs off the side.
|
|
RECT rc;
|
|
GetClientRect(hList, &rc);
|
|
DWORD dw = GetDialogBaseUnits();
|
|
rc.right =(8*rc.right)/LOWORD(dw); //Convert pixels to 2x dlg units.
|
|
SendMessage(hList, LB_SETTABSTOPS, 1, (LPARAM)(LPINT)&rc.right);
|
|
|
|
// Clean out the existing strings.
|
|
SendMessage(hList, LB_RESETCONTENT, 0, 0L);
|
|
UINT cStrings = 0;
|
|
|
|
#if USE_STRING_CACHE==1
|
|
if (gInsObjStringCache.OKToUse() && gInsObjStringCache.IsUptodate())
|
|
{
|
|
// IsUptodate returns false if the cache is not yet populated
|
|
// or if any CLSID key changed in the registry since the last
|
|
// time the cache was populated.
|
|
|
|
LPCTSTR lpStr;
|
|
// Reset enumerator in the cache.
|
|
gInsObjStringCache.ResetEnumerator();
|
|
while ( (lpStr = gInsObjStringCache.NextString()) != NULL)
|
|
{
|
|
SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)lpStr);
|
|
cStrings++;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// Setup the cache if it was successfully initialized and
|
|
// there were no errors in a previous use.
|
|
if (gInsObjStringCache.OKToUse())
|
|
{
|
|
// Clear the string counter and enumerator.
|
|
// We will fill up the cache with strings in this round.
|
|
gInsObjStringCache.FlushCache();
|
|
}
|
|
#endif
|
|
LPTSTR pszExec = (LPTSTR)OleStdMalloc(OLEUI_CCHKEYMAX_SIZE*4);
|
|
if (NULL == pszExec)
|
|
return (UINT)-1;
|
|
|
|
LPTSTR pszClass = pszExec+OLEUI_CCHKEYMAX;
|
|
LPTSTR pszKey = pszClass+OLEUI_CCHKEYMAX;
|
|
|
|
// Open up the root key.
|
|
HKEY hKey;
|
|
LONG lRet = OpenClassesRootKey(NULL, &hKey);
|
|
if ((LONG)ERROR_SUCCESS!=lRet)
|
|
{
|
|
OleStdFree((LPVOID)pszExec);
|
|
return (UINT)-1;
|
|
}
|
|
|
|
// We will now loop over all ProgIDs and add candidates that
|
|
// pass various insertable tests to the ListBox one by one.
|
|
while (TRUE)
|
|
{
|
|
// assume not yet (for handling of OLE1.0 compat case)
|
|
BOOL bHaveCLSID = FALSE;
|
|
LPTSTR pszID = pszKey+OLEUI_CCHKEYMAX;
|
|
|
|
lRet = RegEnumKey(hKey, cStrings++, pszClass, OLEUI_CCHKEYMAX_SIZE);
|
|
if ((LONG)ERROR_SUCCESS != lRet)
|
|
break;
|
|
if (!iswalpha(pszClass[0]))
|
|
{
|
|
// avoids looking into ".ext" type entries under HKCR
|
|
continue;
|
|
}
|
|
|
|
// Cheat on lstrcat by using lstrcpy after this string, saving time
|
|
UINT cch = lstrlen(pszClass);
|
|
|
|
// Check for \NotInsertable. If this is found then this overrides
|
|
// all other keys; this class will NOT be added to the InsertObject
|
|
// list.
|
|
|
|
lstrcpy(pszClass+cch, TEXT("\\NotInsertable"));
|
|
HKEY hKeyTemp = NULL;
|
|
lRet = RegOpenKey(hKey, pszClass, &hKeyTemp);
|
|
if (hKeyTemp != NULL)
|
|
RegCloseKey(hKeyTemp);
|
|
|
|
if ((LONG)ERROR_SUCCESS == lRet)
|
|
continue; // NotInsertable IS found--skip this class
|
|
|
|
// check if ProgId says "Insertable"
|
|
lstrcpy(pszClass+cch, TEXT("\\Insertable"));
|
|
hKeyTemp = NULL;
|
|
lRet = RegOpenKey(hKey, pszClass, &hKeyTemp);
|
|
if (hKeyTemp != NULL)
|
|
RegCloseKey(hKeyTemp);
|
|
|
|
if (lRet == ERROR_SUCCESS || fExcludeObjects)
|
|
{
|
|
// ProgId says insertable (=> can't be OLE 1.0)
|
|
// See if we are displaying Objects or Controls
|
|
|
|
// Check for CLSID
|
|
|
|
lstrcpy(pszClass+cch, TEXT("\\CLSID"));
|
|
|
|
dw = OLEUI_CCHKEYMAX_SIZE;
|
|
lRet = RegQueryValue(hKey, pszClass, pszID, (LONG*)&dw);
|
|
if ((LONG)ERROR_SUCCESS != lRet)
|
|
continue; // CLSID subkey not found
|
|
bHaveCLSID = TRUE;
|
|
|
|
// CLSID\ is 6, dw contains pszID length.
|
|
cch = 6 + ((UINT)dw/sizeof(TCHAR)) - 1;
|
|
lstrcpy(pszExec, TEXT("CLSID\\"));
|
|
lstrcpy(pszExec+6, pszID);
|
|
|
|
|
|
// fExcludeObjects is TRUE for the Insert Control box.
|
|
// It's FALSE for the Insert Object box.
|
|
|
|
lstrcpy(pszExec+cch, TEXT("\\Control"));
|
|
hKeyTemp = NULL;
|
|
lRet = RegOpenKey(hKey, pszExec, &hKeyTemp);
|
|
if (hKeyTemp != NULL)
|
|
RegCloseKey(hKeyTemp);
|
|
|
|
if (!fExcludeObjects)
|
|
{
|
|
// We are listing Objects.
|
|
if (lRet == ERROR_SUCCESS)
|
|
{
|
|
// this is a control
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// We are listing controls
|
|
if (lRet != ERROR_SUCCESS)
|
|
{
|
|
// This is an Object
|
|
continue;
|
|
}
|
|
// Some generous soul at some point of time in the past
|
|
// decided that for controls it is OK to have the
|
|
// Inertable key on the clsid too. So we have to perform
|
|
// that additional check before we decide if the control
|
|
// entry should be listed or not.
|
|
|
|
lstrcpy(pszExec+cch, TEXT("\\Insertable"));
|
|
hKeyTemp = NULL;
|
|
lRet = RegOpenKey(hKey, pszExec, &hKeyTemp);
|
|
if (hKeyTemp != NULL)
|
|
RegCloseKey(hKeyTemp);
|
|
if ((LONG)ERROR_SUCCESS != lRet)
|
|
continue;
|
|
}
|
|
|
|
|
|
// This is beginning to look like a probable list candidate
|
|
|
|
// Check \LocalServer32, LocalServer, and \InprocServer
|
|
// if we were requested to (IOF_VERIFYSERVERSEXIST)
|
|
if (fVerify)
|
|
{
|
|
// Try LocalServer32
|
|
lstrcpy(pszExec+cch, TEXT("\\LocalServer32"));
|
|
dw = OLEUI_CCHKEYMAX_SIZE;
|
|
lRet = RegQueryValue(hKey, pszExec, pszKey, (LONG*)&dw);
|
|
if ((LONG)ERROR_SUCCESS != lRet)
|
|
{
|
|
// Try LocalServer
|
|
lstrcpy(pszExec+cch, TEXT("\\LocalServer"));
|
|
dw = OLEUI_CCHKEYMAX_SIZE;
|
|
lRet = RegQueryValue(hKey, pszExec, pszKey, (LONG*)&dw);
|
|
if ((LONG)ERROR_SUCCESS != lRet)
|
|
{
|
|
// Try InprocServer32
|
|
lstrcpy(pszExec+cch, TEXT("\\InProcServer32"));
|
|
dw = OLEUI_CCHKEYMAX_SIZE;
|
|
lRet = RegQueryValue(hKey, pszExec, pszKey, (LONG*)&dw);
|
|
if ((LONG)ERROR_SUCCESS != lRet)
|
|
{
|
|
// Try InprocServer
|
|
lstrcpy(pszExec+cch, TEXT("\\InProcServer"));
|
|
dw = OLEUI_CCHKEYMAX_SIZE;
|
|
lRet = RegQueryValue(hKey, pszExec, pszKey, (LONG*)&dw);
|
|
if ((LONG)ERROR_SUCCESS != lRet)
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!DoesFileExist(pszKey, OLEUI_CCHKEYMAX))
|
|
continue;
|
|
|
|
} //fVerify
|
|
|
|
// Get the readable name for the server.
|
|
// We'll needed it for the listbox.
|
|
|
|
*(pszExec+cch) = 0; //Remove \\*Server
|
|
|
|
dw = OLEUI_CCHKEYMAX_SIZE;
|
|
lRet = RegQueryValue(hKey, pszExec, pszKey, (LONG*)&dw);
|
|
if ((LONG)ERROR_SUCCESS!=lRet)
|
|
continue;
|
|
|
|
}
|
|
else
|
|
{
|
|
// We did not see an "Insertable" under ProgId, can
|
|
// this be an OLE 1.0 time server entry?
|
|
|
|
// Check for a \protocol\StdFileEditing\server entry.
|
|
lstrcpy(pszClass+cch, TEXT("\\protocol\\StdFileEditing\\server"));
|
|
DWORD dwTemp = OLEUI_CCHKEYMAX_SIZE;
|
|
lRet = RegQueryValue(hKey, pszClass, pszKey, (LONG*)&dwTemp);
|
|
if ((LONG)ERROR_SUCCESS == lRet)
|
|
{
|
|
// This is not a control
|
|
// skip it if excluding non-controls
|
|
if (fExcludeObjects)
|
|
continue;
|
|
|
|
// Check if the EXE actually exists.
|
|
// (By default we don't do this for speed.
|
|
// If an application wants to, it must provide
|
|
// IOF_VERIFYSERVERSEXIST flag in the request)
|
|
|
|
if (fVerify && !DoesFileExist(pszKey, OLEUI_CCHKEYMAX))
|
|
continue;
|
|
|
|
// get readable class name
|
|
dwTemp = OLEUI_CCHKEYMAX_SIZE;
|
|
*(pszClass+cch) = 0; // set back to rootkey
|
|
lRet=RegQueryValue(hKey, pszClass, pszKey, (LONG*)&dwTemp);
|
|
|
|
// attempt to get clsid directly from registry
|
|
lstrcpy(pszClass+cch, TEXT("\\CLSID"));
|
|
dwTemp = OLEUI_CCHKEYMAX_SIZE;
|
|
lRet = RegQueryValue(hKey, pszClass, pszID, (LONG*)&dwTemp);
|
|
if ((LONG)ERROR_SUCCESS == lRet)
|
|
bHaveCLSID = TRUE;
|
|
*(pszClass+cch) = 0; // set back to rootkey
|
|
}
|
|
else
|
|
{
|
|
// This is not OLE 1.0 either!
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// At this point we have an insertable candidate.
|
|
// or OLE 1.0 time.
|
|
|
|
// get CLSID to add to listbox.
|
|
CLSID clsid;
|
|
if (!bHaveCLSID)
|
|
{
|
|
if (FAILED(CLSIDFromProgID(pszClass, &clsid)))
|
|
continue;
|
|
if (FAILED(StringFromCLSID(clsid, &pszID)))
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
if (FAILED(CLSIDFromString(pszID, &clsid)))
|
|
continue;
|
|
}
|
|
|
|
// ##### WARNING #####: using 'continue' after this point
|
|
// would leak memory so don't use it!
|
|
|
|
// check if this CLSID is in the exclusion list.
|
|
BOOL fExclude = FALSE;
|
|
for (UINT i=0; i < cIDEx; i++)
|
|
{
|
|
if (IsEqualCLSID(clsid, lpIDEx[i]))
|
|
{
|
|
fExclude=TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// don't add objects without names
|
|
if (lstrlen(pszKey) > 0 && !fExclude)
|
|
{
|
|
// We got through all the conditions, add the string.
|
|
if (LB_ERR == SendMessage(hList, LB_FINDSTRING, 0, (LPARAM)pszKey))
|
|
{
|
|
pszKey[cch = lstrlen(pszKey)] = '\t';
|
|
lstrcpy(pszKey+cch+1, pszID);
|
|
SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)pszKey);
|
|
#if USE_STRING_CACHE==1
|
|
if (gInsObjStringCache.OKToUse())
|
|
{
|
|
if (!gInsObjStringCache.AddString(pszKey))
|
|
{
|
|
// Adding the string failed due to some reason
|
|
OleDbgAssert(!"Failure adding string");
|
|
|
|
// A failed Add() should mark the
|
|
// Cache not OK to use any more.
|
|
OleDbgAssert(!gInsObjStringCache.OKToUse())
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if (!bHaveCLSID)
|
|
OleStdFree((LPVOID)pszID);
|
|
} // While (TRUE)
|
|
RegCloseKey(hKey);
|
|
OleStdFree((LPVOID)pszExec);
|
|
|
|
#if USE_STRING_CACHE
|
|
}
|
|
#endif
|
|
|
|
// Select the first item by default
|
|
SendMessage(hList, LB_SETCURSEL, 0, 0L);
|
|
|
|
return cStrings;
|
|
}
|
|
|
|
/*
|
|
* FToggleObjectSource
|
|
*
|
|
* Purpose:
|
|
* Handles enabling, disabling, showing, and flag manipulation when the
|
|
* user changes between Create New, Insert File, and Link File in the
|
|
* Insert Object dialog.
|
|
*
|
|
* Parameters:
|
|
* hDlg HWND of the dialog
|
|
* lpIO LPINSERTOBJECT pointing to the dialog structure
|
|
* dwOption DWORD flag indicating the option just selected:
|
|
* IOF_SELECTCREATENEW or IOF_SELECTCREATEFROMFILE
|
|
*
|
|
* Return Value:
|
|
* BOOL TRUE if the option was already selected, FALSE otherwise.
|
|
*/
|
|
|
|
BOOL FToggleObjectSource(HWND hDlg, LPINSERTOBJECT lpIO, DWORD dwOption)
|
|
{
|
|
// Skip all of this if we're already selected.
|
|
if (lpIO->dwFlags & dwOption)
|
|
return TRUE;
|
|
|
|
#ifdef USE_STRING_CACHE
|
|
// if we're using string cache, we need to flush the cache if
|
|
// the list previously displayed was of different type
|
|
|
|
if(IOF_SELECTCREATECONTROL == dwOption)
|
|
{
|
|
if(g_dwOldListType == IOF_SELECTCREATENEW)
|
|
gInsObjStringCache.FlushCache();
|
|
g_dwOldListType = IOF_SELECTCREATECONTROL;
|
|
}
|
|
else if(IOF_SELECTCREATENEW == dwOption)
|
|
{
|
|
if(g_dwOldListType == IOF_SELECTCREATECONTROL)
|
|
gInsObjStringCache.FlushCache();
|
|
g_dwOldListType = IOF_SELECTCREATENEW;
|
|
}
|
|
#endif
|
|
|
|
|
|
// if we're switching from "from file" to "create new" and we've got
|
|
// an icon for "from file", then we need to save it so that we can
|
|
// show it if the user reselects "from file".
|
|
|
|
if ((IOF_SELECTCREATENEW == dwOption) &&
|
|
(lpIO->dwFlags & IOF_CHECKDISPLAYASICON))
|
|
{
|
|
lpIO->hMetaPictFile = (HGLOBAL)SendDlgItemMessage(hDlg,
|
|
IDC_IO_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L);
|
|
}
|
|
|
|
/*
|
|
* 1. Change the Display As Icon checked state to reflect the
|
|
* selection for this option, stored in the fAsIcon* flags.
|
|
*/
|
|
BOOL fTemp;
|
|
if (IOF_SELECTCREATENEW == dwOption)
|
|
fTemp = lpIO->fAsIconNew;
|
|
else if (IOF_SELECTCREATEFROMFILE == dwOption)
|
|
fTemp = lpIO->fAsIconFile;
|
|
else
|
|
fTemp = FALSE;
|
|
|
|
if (fTemp)
|
|
lpIO->dwFlags |= IOF_CHECKDISPLAYASICON;
|
|
else
|
|
lpIO->dwFlags &= ~IOF_CHECKDISPLAYASICON;
|
|
|
|
CheckDlgButton(hDlg, IDC_IO_DISPLAYASICON,
|
|
(BOOL)(0L!=(lpIO->dwFlags & IOF_CHECKDISPLAYASICON)));
|
|
|
|
EnableChangeIconButton(hDlg, fTemp);
|
|
|
|
/*
|
|
* Display Icon: Enabled on Create New or on Create from File if
|
|
* there is a selected file.
|
|
*/
|
|
if (IOF_SELECTCREATENEW == dwOption)
|
|
fTemp = TRUE;
|
|
else if (IOF_SELECTCREATEFROMFILE == dwOption)
|
|
fTemp = lpIO->fFileSelected;
|
|
else
|
|
fTemp = FALSE;
|
|
|
|
if (IOF_SELECTCREATECONTROL == dwOption)
|
|
StandardShowDlgItem(hDlg, IDC_IO_DISPLAYASICON, SW_HIDE);
|
|
else if (!(lpIO->dwFlags & IOF_DISABLEDISPLAYASICON))
|
|
StandardShowDlgItem(hDlg, IDC_IO_DISPLAYASICON, SW_SHOW);
|
|
|
|
StandardEnableDlgItem(hDlg, IDC_IO_DISPLAYASICON, fTemp);
|
|
|
|
// OK and Link follow the same enabling as Display As Icon.
|
|
StandardEnableDlgItem(hDlg, IDOK,
|
|
fTemp || IOF_SELECTCREATECONTROL == dwOption);
|
|
StandardEnableDlgItem(hDlg, IDC_IO_LINKFILE, fTemp);
|
|
|
|
// Enable Browse... when Create from File is selected.
|
|
fTemp = (IOF_SELECTCREATEFROMFILE != dwOption);
|
|
StandardEnableDlgItem(hDlg, IDC_IO_FILE, !fTemp);
|
|
StandardEnableDlgItem(hDlg, IDC_IO_FILEDISPLAY, !fTemp);
|
|
|
|
// Switch Object Type & Control Type listboxes if necessary
|
|
HWND hWnd1 = NULL, hWnd2 = NULL;
|
|
if (lpIO->bControlListActive && IOF_SELECTCREATENEW == dwOption)
|
|
{
|
|
hWnd1 = GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST);
|
|
hWnd2 = GetDlgItem(hDlg, IDC_IO_CONTROLTYPELIST);
|
|
SetWindowLong(hWnd1, GWL_ID, IDC_IO_CONTROLTYPELIST);
|
|
SetWindowLong(hWnd2, GWL_ID, IDC_IO_OBJECTTYPELIST);
|
|
lpIO->bControlListActive = FALSE;
|
|
}
|
|
else if (!lpIO->bControlListActive && IOF_SELECTCREATECONTROL == dwOption)
|
|
{
|
|
hWnd1 = GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST);
|
|
hWnd2 = GetDlgItem(hDlg, IDC_IO_CONTROLTYPELIST);
|
|
SetWindowLong(hWnd1, GWL_ID, IDC_IO_CONTROLTYPELIST);
|
|
SetWindowLong(hWnd2, GWL_ID, IDC_IO_OBJECTTYPELIST);
|
|
lpIO->bControlListActive = TRUE;
|
|
}
|
|
|
|
// Clear out any existing selection flags and set the new one
|
|
DWORD dwTemp = IOF_SELECTCREATENEW | IOF_SELECTCREATEFROMFILE |
|
|
IOF_SELECTCREATECONTROL;
|
|
lpIO->dwFlags = (lpIO->dwFlags & ~dwTemp) | dwOption;
|
|
|
|
if (dwOption & (IOF_SELECTCREATENEW|IOF_SELECTCREATECONTROL))
|
|
{
|
|
// refill class list box if necessary
|
|
if ((lpIO->bControlListActive && !lpIO->bControlListFilled) ||
|
|
(!lpIO->bControlListActive && !lpIO->bObjectListFilled))
|
|
{
|
|
URefillClassList(hDlg, lpIO);
|
|
}
|
|
}
|
|
|
|
if (hWnd1 != NULL && hWnd2 != NULL)
|
|
{
|
|
ShowWindow(hWnd1, SW_HIDE);
|
|
ShowWindow(hWnd2, SW_SHOW);
|
|
}
|
|
|
|
/*
|
|
* Switch between Object Type listbox on Create New and
|
|
* file buttons on others.
|
|
*/
|
|
UINT uTemp = (fTemp) ? SW_SHOWNORMAL : SW_HIDE;
|
|
StandardShowDlgItem(hDlg, IDC_IO_OBJECTTYPELIST, uTemp);
|
|
StandardShowDlgItem(hDlg, IDC_IO_OBJECTTYPETEXT, uTemp);
|
|
|
|
uTemp = (fTemp) ? SW_HIDE : SW_SHOWNORMAL;
|
|
StandardShowDlgItem(hDlg, IDC_IO_FILETEXT, uTemp);
|
|
StandardShowDlgItem(hDlg, IDC_IO_FILETYPE, uTemp);
|
|
StandardShowDlgItem(hDlg, IDC_IO_FILEDISPLAY, uTemp);
|
|
StandardShowDlgItem(hDlg, IDC_IO_FILE, uTemp);
|
|
|
|
// Link is always hidden if IOF_DISABLELINK is set.
|
|
if (IOF_DISABLELINK & lpIO->dwFlags)
|
|
uTemp = SW_HIDE;
|
|
|
|
StandardShowDlgItem(hDlg, IDC_IO_LINKFILE, uTemp); //last use of uTemp
|
|
|
|
// Remove add button when not in Insert control mode
|
|
uTemp = (IOF_SELECTCREATECONTROL == dwOption) ? SW_SHOW : SW_HIDE;
|
|
StandardShowDlgItem(hDlg, IDC_IO_ADDCONTROL, uTemp);
|
|
|
|
/*
|
|
* Show or hide controls as appropriate. Do the icon
|
|
* display last because it will take some time to repaint.
|
|
* If we do it first then the dialog looks too sluggish.
|
|
*/
|
|
|
|
int i = (lpIO->dwFlags & IOF_CHECKDISPLAYASICON) ? SW_SHOWNORMAL : SW_HIDE;
|
|
StandardShowDlgItem(hDlg, IDC_IO_CHANGEICON, i);
|
|
StandardShowDlgItem(hDlg, IDC_IO_ICONDISPLAY, i);
|
|
EnableChangeIconButton(hDlg, SW_SHOWNORMAL == i);
|
|
|
|
// Change result display
|
|
SetInsertObjectResults(hDlg, lpIO);
|
|
|
|
/*
|
|
* For Create New, twiddle the listbox to think we selected it
|
|
* so it updates the icon from the object type. set the focus
|
|
* to the list box.
|
|
*
|
|
* For Insert or Link file, set the focus to the filename button
|
|
* and update the icon if necessary.
|
|
*/
|
|
if (fTemp)
|
|
{
|
|
UpdateClassIcon(hDlg, lpIO, GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST));
|
|
SetFocus(GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST));
|
|
}
|
|
else
|
|
{
|
|
if (lpIO->fAsIconFile && (NULL != lpIO->hMetaPictFile) )
|
|
{
|
|
SendDlgItemMessage(hDlg, IDC_IO_ICONDISPLAY, IBXM_IMAGESET, 0,
|
|
(LPARAM)lpIO->hMetaPictFile);
|
|
lpIO->hMetaPictFile = 0;
|
|
}
|
|
else
|
|
{
|
|
UpdateClassIcon(hDlg, lpIO, NULL);
|
|
}
|
|
SetFocus(GetDlgItem(hDlg, IDC_IO_FILE));
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
* UpdateClassType
|
|
*
|
|
* Purpose:
|
|
* Updates static text control to reflect current file type. Assumes
|
|
* a valid filename.
|
|
*
|
|
* Parameters
|
|
* hDlg HWND of the dialog box.
|
|
* lpIO LPINSERTOBJECT pointing to the dialog structure
|
|
* fSet TRUE to set the text, FALSE to explicitly clear it
|
|
*
|
|
* Return Value:
|
|
* None
|
|
*/
|
|
|
|
void UpdateClassType(HWND hDlg, LPINSERTOBJECT lpIO, BOOL fSet)
|
|
{
|
|
LPTSTR lpszFileType = NULL;
|
|
if (fSet)
|
|
{
|
|
TCHAR szFileName[MAX_PATH];
|
|
GetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, szFileName, MAX_PATH);
|
|
|
|
CLSID clsid;
|
|
if (S_OK == GetClassFile(szFileName, &clsid))
|
|
OleRegGetUserType(clsid, USERCLASSTYPE_FULL, &lpszFileType);
|
|
}
|
|
|
|
if (lpszFileType != NULL)
|
|
{
|
|
SetDlgItemText(hDlg, IDC_IO_FILETYPE, lpszFileType);
|
|
OleStdFree(lpszFileType);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* UpdateClassIcon
|
|
*
|
|
* Purpose:
|
|
* Handles LBN_SELCHANGE for the Object Type listbox. On a selection
|
|
* change, we extract an icon from the server handling the currently
|
|
* selected object type using the utility function HIconFromClass.
|
|
* Note that we depend on the behavior of FillClassList to stuff the
|
|
* object class after a tab in the listbox string that we hide from
|
|
* view (see WM_INITDIALOG).
|
|
*
|
|
* Parameters
|
|
* hDlg HWND of the dialog box.
|
|
* lpIO LPINSERTOBJECT pointing to the dialog structure
|
|
* hList HWND of the Object Type listbox.
|
|
*
|
|
* Return Value:
|
|
* None
|
|
*/
|
|
|
|
static void UpdateClassIcon(HWND hDlg, LPINSERTOBJECT lpIO, HWND hList)
|
|
{
|
|
// If Display as Icon is not selected, exit
|
|
if (!(lpIO->dwFlags & IOF_CHECKDISPLAYASICON))
|
|
return;
|
|
|
|
/*
|
|
* When we change object type selection, get the new icon for that
|
|
* type into our structure and update it in the display. We use the
|
|
* class in the listbox when Create New is selected or the association
|
|
* with the extension in Create From File.
|
|
*/
|
|
|
|
DWORD cb = MAX_PATH;
|
|
UINT iSel;
|
|
if (lpIO->dwFlags & IOF_SELECTCREATENEW)
|
|
{
|
|
iSel = (UINT)SendMessage(hList, LB_GETCURSEL, 0, 0L);
|
|
|
|
if (LB_ERR==(int)iSel)
|
|
return;
|
|
|
|
// Check to see if we've already got the hMetaPict for this item
|
|
LRESULT dwRet = SendMessage(hList, LB_GETITEMDATA, (WPARAM)iSel, 0L);
|
|
|
|
HGLOBAL hMetaPict=(HGLOBAL)dwRet;
|
|
if (hMetaPict)
|
|
{
|
|
// Yep, we've already got it, so just display it and return.
|
|
SendDlgItemMessage(hDlg, IDC_IO_ICONDISPLAY, IBXM_IMAGESET,
|
|
0, (LPARAM)hMetaPict);
|
|
return;
|
|
}
|
|
iSel = (UINT)SendMessage(hList, LB_GETCURSEL, 0, 0L);
|
|
if (LB_ERR==(int)iSel)
|
|
return;
|
|
|
|
// Allocate a string to hold the entire listbox string
|
|
cb = (DWORD)SendMessage(hList, LB_GETTEXTLEN, iSel, 0L);
|
|
}
|
|
|
|
LPTSTR pszName = (LPTSTR)OleStdMalloc((cb+1)*sizeof(TCHAR));
|
|
if (NULL == pszName)
|
|
return;
|
|
*pszName = 0;
|
|
|
|
// Get the clsid we want.
|
|
HGLOBAL hMetaPict;
|
|
if (lpIO->dwFlags & IOF_SELECTCREATENEW)
|
|
{
|
|
// Grab the classname string from the list
|
|
SendMessage(hList, LB_GETTEXT, iSel, (LPARAM)pszName);
|
|
|
|
// Set pointer to CLSID (string)
|
|
LPTSTR pszCLSID = PointerToNthField(pszName, 2, '\t');
|
|
|
|
// Get CLSID from the string and then accociated icon
|
|
HRESULT hr = CLSIDFromString(pszCLSID, &lpIO->clsid);
|
|
if (FAILED(hr))
|
|
lpIO->clsid = GUID_NULL;
|
|
hMetaPict = OleGetIconOfClass(lpIO->clsid, NULL, TRUE);
|
|
}
|
|
|
|
else
|
|
{
|
|
// Get the class from the filename
|
|
GetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, pszName, MAX_PATH);
|
|
hMetaPict = OleGetIconOfFile(pszName,
|
|
lpIO->dwFlags & IOF_CHECKLINK ? TRUE : FALSE);
|
|
}
|
|
|
|
// Replace the current display with this new one.
|
|
SendDlgItemMessage(hDlg, IDC_IO_ICONDISPLAY, IBXM_IMAGESET,
|
|
0, (LPARAM)hMetaPict);
|
|
|
|
// Enable or disable "Change Icon" button depending on whether
|
|
// we've got a valid filename or not.
|
|
EnableChangeIconButton(hDlg, hMetaPict ? TRUE : FALSE);
|
|
|
|
// Save the hMetaPict so that we won't have to re-create
|
|
if (lpIO->dwFlags & IOF_SELECTCREATENEW)
|
|
SendMessage(hList, LB_SETITEMDATA, (WPARAM)iSel, (LPARAM)hMetaPict);
|
|
|
|
OleStdFree(pszName);
|
|
}
|
|
|
|
|
|
/*
|
|
* SetInsertObjectResults
|
|
*
|
|
* Purpose:
|
|
* Centralizes setting of the Result and icon displays in the Insert Object
|
|
* dialog. Handles loading the appropriate string from the module's
|
|
* resources and setting the text, displaying the proper result picture,
|
|
* and showing the proper icon.
|
|
*
|
|
* Parameters:
|
|
* hDlg HWND of the dialog box so we can access controls.
|
|
* lpIO LPINSERTOBJECT in which we assume that the
|
|
* current radiobutton and Display as Icon selections
|
|
* are set. We use the state of those variables to
|
|
* determine which string we use.
|
|
*
|
|
* Return Value:
|
|
* None
|
|
*/
|
|
|
|
void SetInsertObjectResults(HWND hDlg, LPINSERTOBJECT lpIO)
|
|
{
|
|
/*
|
|
* We need scratch memory for loading the stringtable string, loading
|
|
* the object type from the listbox, and constructing the final string.
|
|
* We therefore allocate three buffers as large as the maximum message
|
|
* length (512) plus the object type, guaranteeing that we have enough
|
|
* in all cases.
|
|
*/
|
|
UINT i = (UINT)SendDlgItemMessage(hDlg, IDC_IO_OBJECTTYPELIST, LB_GETCURSEL, 0, 0L);
|
|
|
|
UINT cch = 512;
|
|
|
|
if (i != LB_ERR)
|
|
{
|
|
cch += (UINT)SendDlgItemMessage(hDlg, IDC_IO_OBJECTTYPELIST, LB_GETTEXTLEN, i, 0L);
|
|
}
|
|
|
|
LPTSTR pszTemp= (LPTSTR)OleStdMalloc((DWORD)(4*cch)*sizeof(TCHAR));
|
|
if (NULL == pszTemp)
|
|
return;
|
|
|
|
LPTSTR psz1 = pszTemp;
|
|
LPTSTR psz2 = psz1+cch;
|
|
LPTSTR psz3 = psz2+cch;
|
|
LPTSTR psz4 = psz3+cch;
|
|
|
|
BOOL fAsIcon = (0L != (lpIO->dwFlags & IOF_CHECKDISPLAYASICON));
|
|
UINT iImage=0, iString1=0, iString2=0;
|
|
|
|
if (lpIO->dwFlags & (IOF_SELECTCREATENEW|IOF_SELECTCREATECONTROL))
|
|
{
|
|
iString1 = fAsIcon ? IDS_IORESULTNEWICON : IDS_IORESULTNEW;
|
|
iString2 = 0;
|
|
iImage = fAsIcon ? RESULTIMAGE_EMBEDICON : RESULTIMAGE_EMBED;
|
|
}
|
|
|
|
if (lpIO->dwFlags & IOF_SELECTCREATEFROMFILE)
|
|
{
|
|
// Pay attention to Link checkbox
|
|
if (lpIO->dwFlags & IOF_CHECKLINK)
|
|
{
|
|
iString1 = fAsIcon ? IDS_IORESULTLINKFILEICON1 : IDS_IORESULTLINKFILE1;
|
|
iString2 = fAsIcon ? IDS_IORESULTLINKFILEICON2 : IDS_IORESULTLINKFILE2;
|
|
iImage =fAsIcon ? RESULTIMAGE_LINKICON : RESULTIMAGE_LINK;
|
|
}
|
|
else
|
|
{
|
|
iString1 = IDS_IORESULTFROMFILE1;
|
|
iString2 = fAsIcon ? IDS_IORESULTFROMFILEICON2 : IDS_IORESULTFROMFILE2;
|
|
iImage =fAsIcon ? RESULTIMAGE_EMBEDICON : RESULTIMAGE_EMBED;
|
|
}
|
|
}
|
|
|
|
// Default is an empty string.
|
|
*psz1=0;
|
|
|
|
if (0 != LoadString(_g_hOleStdResInst, iString1, psz1, cch))
|
|
{
|
|
// Load second string, if necessary
|
|
if (0 != iString2 &&
|
|
0 != LoadString(_g_hOleStdResInst, iString2, psz4, cch))
|
|
{
|
|
lstrcat(psz1, psz4); // concatenate strings together.
|
|
}
|
|
|
|
// In Create New, do the extra step of inserting the object type string
|
|
if (lpIO->dwFlags & (IOF_SELECTCREATENEW|IOF_SELECTCREATECONTROL))
|
|
{
|
|
if (i == LB_ERR)
|
|
{
|
|
SetDlgItemText(hDlg, IDC_IO_RESULTTEXT, NULL);
|
|
|
|
// Change the image.
|
|
SendDlgItemMessage(hDlg, IDC_IO_RESULTIMAGE, RIM_IMAGESET, RESULTIMAGE_NONE, 0L);
|
|
|
|
OleStdFree((LPVOID)pszTemp);
|
|
return;
|
|
}
|
|
|
|
*psz2=NULL;
|
|
SendDlgItemMessage(hDlg, IDC_IO_OBJECTTYPELIST, LB_GETTEXT, i, (LPARAM)psz2);
|
|
|
|
// Null terminate at any tab (before the classname)
|
|
LPTSTR pszT = psz2;
|
|
while (_T('\t') != *pszT && 0 != *pszT)
|
|
pszT++;
|
|
OleDbgAssert(pszT < psz3);
|
|
*pszT=0;
|
|
|
|
// Build the string and point psz1 to it.
|
|
wsprintf(psz3, psz1, psz2);
|
|
psz1 = psz3;
|
|
}
|
|
}
|
|
|
|
// If LoadString failed, we simply clear out the results (*psz1=0 above)
|
|
SetDlgItemText(hDlg, IDC_IO_RESULTTEXT, psz1);
|
|
|
|
// Go change the image and Presto! There you have it.
|
|
SendDlgItemMessage(hDlg, IDC_IO_RESULTIMAGE, RIM_IMAGESET, iImage, 0L);
|
|
|
|
OleStdFree((LPVOID)pszTemp);
|
|
}
|
|
|
|
/*
|
|
* FValidateInsertFile
|
|
*
|
|
* Purpose:
|
|
* Given a possibly partial pathname from the file edit control,
|
|
* attempt to locate the file and if found, store the full path
|
|
* in the edit control IDC_IO_FILEDISPLAY.
|
|
*
|
|
* Parameters:
|
|
* hDlg HWND of the dialog box.
|
|
* fTellUser BOOL TRUE if function should tell user, FALSE if
|
|
* function should validate silently.
|
|
*
|
|
* Return Value:
|
|
* BOOL TRUE if the file is acceptable, FALSE otherwise.
|
|
*/
|
|
|
|
BOOL FValidateInsertFile(HWND hDlg, BOOL fTellUser, UINT FAR* lpnErrCode)
|
|
{
|
|
*lpnErrCode = 0;
|
|
|
|
/*
|
|
* To validate we attempt OpenFile on the string. If OpenFile
|
|
* fails then we display an error. If not, OpenFile will store
|
|
* the complete path to that file in the OFSTRUCT which we can
|
|
* then stuff in the edit control.
|
|
*/
|
|
TCHAR szFile[MAX_PATH];
|
|
if (0 == GetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, szFile, MAX_PATH))
|
|
return FALSE; // #4569 : return FALSE when there is no text in ctl
|
|
|
|
// if file is currently open (ie. sharing violation) OleCreateFromFile
|
|
// and OleCreateLinkToFile can still succeed; do not consider it an
|
|
// error.
|
|
if (!DoesFileExist(szFile, MAX_PATH))
|
|
{
|
|
*lpnErrCode = ERROR_FILE_NOT_FOUND;
|
|
if (fTellUser)
|
|
OpenFileError(hDlg, ERROR_FILE_NOT_FOUND, szFile);
|
|
return FALSE;
|
|
}
|
|
|
|
// get full pathname, since the file exists
|
|
TCHAR szPath[MAX_PATH];
|
|
LPTSTR lpszDummy;
|
|
GetFullPathName(szFile, sizeof(szPath)/sizeof(TCHAR), szPath, &lpszDummy);
|
|
SetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, szPath);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
* InsertObjectCleanup
|
|
*
|
|
* Purpose:
|
|
* Clears cached icon metafiles from those stored in the listbox.
|
|
*
|
|
* Parameters:
|
|
* hDlg HWND of the dialog.
|
|
*
|
|
* Return Value:
|
|
* None
|
|
*/
|
|
|
|
void InsertObjectCleanup(HWND hDlg)
|
|
{
|
|
HWND hList = GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST);
|
|
UINT iItems= (UINT)SendMessage(hList, LB_GETCOUNT, 0, 0L);
|
|
for (UINT i = 0; i < iItems; i++)
|
|
{
|
|
LRESULT dwRet = SendMessage(hList, LB_GETITEMDATA, (WPARAM)i, 0L);
|
|
HGLOBAL hMetaPict=(HGLOBAL)dwRet;
|
|
if (hMetaPict)
|
|
OleUIMetafilePictIconFree(hMetaPict);
|
|
}
|
|
}
|
|
|
|
void EnableChangeIconButton(HWND hDlg, BOOL fEnable)
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if(fEnable){
|
|
|
|
HWND hList = GetDlgItem(hDlg, IDC_IO_OBJECTTYPELIST);
|
|
int iCurSel = (int)SendMessage(hList, LB_GETCURSEL, 0, 0L);
|
|
|
|
CLSID clsid = {0};
|
|
|
|
if (1 == IsDlgButtonChecked(hDlg, IDC_IO_CREATENEW))
|
|
{
|
|
LPTSTR pszString = (LPTSTR)OleStdMalloc(
|
|
OLEUI_CCHKEYMAX_SIZE + OLEUI_CCHCLSIDSTRING_SIZE);
|
|
|
|
if(NULL == pszString)
|
|
{
|
|
fEnable = FALSE;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
SendMessage(hList, LB_GETTEXT, iCurSel, (LPARAM)pszString);
|
|
|
|
if(0 == *pszString)
|
|
{
|
|
fEnable = FALSE;
|
|
OleStdFree((LPVOID)pszString);
|
|
goto CLEANUP;
|
|
}
|
|
|
|
|
|
LPTSTR pszCLSID = PointerToNthField(pszString, 2, '\t');
|
|
|
|
if(NULL == pszCLSID || 0 == *pszCLSID)
|
|
{
|
|
fEnable = FALSE;
|
|
OleStdFree((LPVOID)pszString);
|
|
goto CLEANUP;
|
|
}
|
|
|
|
|
|
hr = CLSIDFromString(pszCLSID, &clsid);
|
|
OleStdFree((LPVOID)pszString);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
fEnable = FALSE;
|
|
}
|
|
}
|
|
else // IOF_SELECTCREATEFROMFILE
|
|
{
|
|
TCHAR szFileName[MAX_PATH] = {0};
|
|
GetDlgItemText(hDlg, IDC_IO_FILEDISPLAY, szFileName, MAX_PATH);
|
|
|
|
if (S_OK != GetClassFile(szFileName, &clsid))
|
|
{
|
|
int istrlen = lstrlen(szFileName);
|
|
LPTSTR lpszExtension = szFileName + istrlen -1;
|
|
|
|
while (lpszExtension > szFileName &&
|
|
*lpszExtension != '.')
|
|
{
|
|
lpszExtension = CharPrev(szFileName, lpszExtension);
|
|
}
|
|
|
|
*szFileName = 0;
|
|
|
|
GetAssociatedExecutable(lpszExtension, szFileName, sizeof(szFileName)/sizeof(szFileName[0]));
|
|
|
|
if(0 == *szFileName){
|
|
fEnable = FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CLEANUP:
|
|
|
|
StandardEnableDlgItem(hDlg, IDC_IO_CHANGEICON, fEnable);
|
|
|
|
}
|
|
|