|
|
/*************************************************************************
** ** The following API's are now OBSOLETE because equivalent API's have been ** added to the OLE2.DLL library ** GetIconOfFile superceeded by OleGetIconOfFile ** GetIconOfClass superceeded by OleGetIconOfClass ** OleUIMetafilePictFromIconAndLabel ** superceeded by OleMetafilePictFromIconAndLabel *************************************************************************/
/*
* GETICON.C * * Functions to create DVASPECT_ICON metafile from filename or classname. * * GetIconOfFile * GetIconOfClass * OleUIMetafilePictFromIconAndLabel * HIconAndSourceFromClass Extracts the first icon in a class's server path * and returns the path and icon index to caller. * FIconFileFromClass Retrieves the path to the exe/dll containing the * default icon, and the index of the icon. * OleStdIconLabelTextOut Draw icon label text (line break if necessary) * * (c) Copyright Microsoft Corp. 1992-1993 All Rights Reserved */
/*******
* * ICON (DVASPECT_ICON) METAFILE FORMAT: * * The metafile generated with OleUIMetafilePictFromIconAndLabel contains * the following records which are used by the functions in DRAWICON.C * to draw the icon with and without the label and to extract the icon, * label, and icon source/index. * * SetWindowOrg * SetWindowExt * DrawIcon: * Inserts records of DIBBITBLT or DIBSTRETCHBLT, once for the * AND mask, one for the image bits. * Escape with the comment "IconOnly" * This indicates where to stop record enumeration to draw only * the icon. * SetTextColor * SetTextAlign * SetBkColor * CreateFont * SelectObject on the font. * ExtTextOut * One or more ExtTextOuts occur if the label is wrapped. The * text in these records is used to extract the label. * SelectObject on the old font. * DeleteObject on the font. * Escape with a comment that contains the path to the icon source. * Escape with a comment that is the ASCII of the icon index. * *******/
#define STRICT 1
#include "ole2ui.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <commdlg.h>
#include <memory.h>
#include <cderr.h>
#include "common.h"
#include "utility.h"
static TCHAR szSeparators[] = TEXT(" \t\\/!:");
#define IS_SEPARATOR(c) ( (c) == TEXT(' ') || (c) == TEXT('\\') \
|| (c) == TEXT('/') || (c) == TEXT('\t') \ || (c) == TEXT('!') || (c) == TEXT(':') ) #define IS_FILENAME_DELIM(c) ( (c) == TEXT('\\') || (c) == TEXT('/') \
|| (c) == TEXT(':') )
#if defined( OBSOLETE )
static HINSTANCE s_hInst;
static TCHAR szMaxWidth[] =TEXT("WWWWWWWWWW");
//Strings for metafile comments.
static TCHAR szIconOnly[]=TEXT("IconOnly"); //Where to stop to exclude label.
#ifdef WIN32
static TCHAR szOLE2DLL[] = TEXT("ole2w32.dll"); // name of OLE 2.0 library
#else
static TCHAR szOLE2DLL[] = TEXT("ole2.dll"); // name of OLE 2.0 library
#endif
#define ICONINDEX 0
#define AUXUSERTYPE_SHORTNAME USERCLASSTYPE_SHORT // short name
#define HIMETRIC_PER_INCH 2540 // number HIMETRIC units per inch
#define PTS_PER_INCH 72 // number points (font size) per inch
#define MAP_PIX_TO_LOGHIM(x,ppli) MulDiv(HIMETRIC_PER_INCH, (x), (ppli))
#define MAP_LOGHIM_TO_PIX(x,ppli) MulDiv((ppli), (x), HIMETRIC_PER_INCH)
static TCHAR szVanillaDocIcon[] = TEXT("DefIcon");
static TCHAR szDocument[40] = TEXT("");
/*
* GetIconOfFile(HINSTANCE hInst, LPSTR lpszPath, BOOL fUseFileAsLabel) * * Purpose: * Returns a hMetaPict containing an icon and label (filename) for the * specified filename. * * Parameters: * hinst * lpszPath LPTSTR path including filename to use * fUseFileAsLabel BOOL TRUE if the icon's label is the filename, FALSE if * there should be no label. * * Return Value: * HGLOBAL hMetaPict containing the icon and label - if there's no * class in reg db for the file in lpszPath, then we use * Document. If lpszPath is NULL, then we return NULL. */
STDAPI_(HGLOBAL) GetIconOfFile(HINSTANCE hInst, LPTSTR lpszPath, BOOL fUseFileAsLabel) { TCHAR szIconFile[OLEUI_CCHPATHMAX]; TCHAR szLabel[OLEUI_CCHLABELMAX]; LPTSTR lpszClsid = NULL; CLSID clsid; HICON hDefIcon = NULL; UINT IconIndex = 0; HGLOBAL hMetaPict; HRESULT hResult;
if (NULL == lpszPath) // even if fUseFileAsLabel is FALSE, we still
return NULL; // need a valid filename to get the class.
s_hInst = hInst;
hResult = GetClassFileA(lpszPath, &clsid);
if (NOERROR == hResult) // use the clsid we got to get to the icon
{ hDefIcon = HIconAndSourceFromClass(&clsid, (LPTSTR)szIconFile, &IconIndex); }
if ( (NOERROR != hResult) || (NULL == hDefIcon) ) { // Here, either GetClassFile failed or HIconAndSourceFromClass failed.
LPTSTR lpszTemp;
lpszTemp = lpszPath;
while ((*lpszTemp != TEXT('.')) && (*lpszTemp != TEXT('\0'))) lpszTemp++;
if (TEXT('.') != *lpszTemp) goto UseVanillaDocument;
if (FALSE == GetAssociatedExecutable(lpszTemp, (LPTSTR)szIconFile)) goto UseVanillaDocument;
hDefIcon = ExtractIcon(s_hInst, szIconFile, IconIndex); }
if (hDefIcon <= (HICON)1) // ExtractIcon returns 1 if szExecutable is not exe,
{ // 0 if there are no icons.
UseVanillaDocument:
lstrcpy((LPTSTR)szIconFile, (LPTSTR)szOLE2DLL); IconIndex = ICONINDEX; hDefIcon = ExtractIcon(s_hInst, szIconFile, IconIndex);
}
// Now let's get the label we want to use.
if (fUseFileAsLabel) // strip off path, so we just have the filename.
{ int istrlen; LPTSTR lpszBeginFile;
istrlen = lstrlen(lpszPath);
// set pointer to END of path, so we can walk backwards through it.
lpszBeginFile = lpszPath + istrlen -1;
while ( (lpszBeginFile >= lpszPath) && (!IS_FILENAME_DELIM(*lpszBeginFile)) ) lpszBeginFile--;
lpszBeginFile++; // step back over the delimiter
LSTRCPYN(szLabel, lpszBeginFile, sizeof(szLabel)/sizeof(TCHAR)); }
else // use the short user type (AuxUserType2) for the label
{
if (0 == OleStdGetAuxUserType(&clsid, AUXUSERTYPE_SHORTNAME, (LPTSTR)szLabel, OLEUI_CCHLABELMAX_SIZE, NULL)) {
if ('\0'==szDocument[0]) { LoadString( s_hInst,IDS_DEFICONLABEL,szDocument,sizeof(szDocument)/sizeof(TCHAR)); } lstrcpy(szLabel, szDocument); } }
hMetaPict = OleUIMetafilePictFromIconAndLabel(hDefIcon, szLabel, (LPTSTR)szIconFile, IconIndex);
DestroyIcon(hDefIcon);
return hMetaPict;
}
/*
* GetIconOfClass(HINSTANCE hInst, REFCLSID rclsid, LPSTR lpszLabel, BOOL fUseTypeAsLabel) * * Purpose: * Returns a hMetaPict containing an icon and label (human-readable form * of class) for the specified clsid. * * Parameters: * hinst * rclsid REFCLSID pointing to clsid to use. * lpszLabel label to use for icon. * fUseTypeAsLabel Use the clsid's user type name as the icon's label. * * Return Value: * HGLOBAL hMetaPict containing the icon and label - if we * don't find the clsid in the reg db then we * return NULL. */
STDAPI_(HGLOBAL) GetIconOfClass(HINSTANCE hInst, REFCLSID rclsid, LPTSTR lpszLabel, BOOL fUseTypeAsLabel) {
TCHAR szLabel[OLEUI_CCHLABELMAX]; TCHAR szIconFile[OLEUI_CCHPATHMAX]; HICON hDefIcon; UINT IconIndex; HGLOBAL hMetaPict;
s_hInst = hInst;
if (!fUseTypeAsLabel) // Use string passed in as label
{ if (NULL != lpszLabel) LSTRCPYN(szLabel, lpszLabel, OLEUI_CCHLABELMAX_SIZE); else *szLabel = TEXT('\0'); } else // Use AuxUserType2 (short name) as label
{
if (0 == OleStdGetAuxUserType(rclsid, AUXUSERTYPE_SHORTNAME, (LPTSTR)szLabel, OLEUI_CCHLABELMAX_SIZE, NULL))
// If we can't get the AuxUserType2, then try the long name
if (0 == OleStdGetUserTypeOfClass(rclsid, szLabel, OLEUI_CCHKEYMAX_SIZE, NULL)) { if (TEXT('\0')==szDocument[0]) { LoadString( s_hInst,IDS_DEFICONLABEL,szDocument,sizeof(szDocument)/sizeof(TCHAR)); } lstrcpy(szLabel, szDocument); // last resort
} }
// Get the icon, icon index, and path to icon file
hDefIcon = HIconAndSourceFromClass(rclsid, (LPTSTR)szIconFile, &IconIndex);
if (NULL == hDefIcon) // Use Vanilla Document
{ lstrcpy((LPTSTR)szIconFile, (LPTSTR)szOLE2DLL); IconIndex = ICONINDEX; hDefIcon = ExtractIcon(s_hInst, szIconFile, IconIndex); }
// Create the metafile
hMetaPict = OleUIMetafilePictFromIconAndLabel(hDefIcon, szLabel, (LPTSTR)szIconFile, IconIndex);
DestroyIcon(hDefIcon);
return hMetaPict;
}
/*
* OleUIMetafilePictFromIconAndLabel * * Purpose: * Creates a METAFILEPICT structure that container a metafile in which * the icon and label are drawn. A comment record is inserted between * the icon and the label code so our special draw function can stop * playing before the label. * * Parameters: * hIcon HICON to draw into the metafile * pszLabel LPTSTR to the label string. * pszSourceFile LPTSTR containing the local pathname of the icon * as we either get from the user or from the reg DB. * iIcon UINT providing the index into pszSourceFile where * the icon came from. * * Return Value: * HGLOBAL Global memory handle containing a METAFILEPICT where * the metafile uses the MM_ANISOTROPIC mapping mode. The * extents reflect both icon and label. */
STDAPI_(HGLOBAL) OleUIMetafilePictFromIconAndLabel(HICON hIcon, LPTSTR pszLabel , LPTSTR pszSourceFile, UINT iIcon) { HDC hDC, hDCScreen; HMETAFILE hMF; HGLOBAL hMem; LPMETAFILEPICT pMF; UINT cxIcon, cyIcon; UINT cxText, cyText; UINT cx, cy; UINT cchLabel = 0; HFONT hFont, hFontT; int cyFont; TCHAR szIndex[10]; RECT TextRect; SIZE size; POINT point; UINT fuAlign;
if (NULL==hIcon) // null label is valid but NOT a null icon
return NULL;
//Create a memory metafile
hDC=(HDC)CreateMetaFile(NULL);
if (NULL==hDC) return NULL;
//Allocate the metafilepict
hMem=GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(METAFILEPICT));
if (NULL==hMem) { hMF=CloseMetaFile(hDC); DeleteMetaFile(hMF); return NULL; }
if (NULL!=pszLabel) { cchLabel=lstrlen(pszLabel);
if (cchLabel >= OLEUI_CCHLABELMAX) pszLabel[cchLabel] = TEXT('\0'); // truncate string
}
//Need to use the screen DC for these operations
hDCScreen=GetDC(NULL); cyFont=-(8*GetDeviceCaps(hDCScreen, LOGPIXELSY))/72;
//cyFont was calculated to give us 8 point.
hFont=CreateFont(cyFont, 5, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET , OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY , FF_SWISS, TEXT("MS Sans Serif"));
hFontT=SelectObject(hDCScreen, hFont);
GetTextExtentPoint(hDCScreen,szMaxWidth,lstrlen(szMaxWidth),&size); SelectObject(hDCScreen, hFontT);
cxText = size.cx; cyText = size.cy * 2;
cxIcon = GetSystemMetrics(SM_CXICON); cyIcon = GetSystemMetrics(SM_CYICON);
// If we have no label, then we want the metafile to be the width of
// the icon (plus margin), not the width of the fattest string.
if ( (NULL == pszLabel) || (TEXT('\0') == *pszLabel) ) cx = cxIcon + cxIcon / 4; else cx = max(cxText, cxIcon);
cy=cyIcon+cyText+4;
//Set the metafile size to fit the icon and label
SetWindowOrgEx(hDC, 0, 0, &point); SetWindowExtEx(hDC, cx, cy, &size);
//Set up rectangle to pass to OleStdIconLabelTextOut
SetRectEmpty(&TextRect);
TextRect.right = cx; TextRect.bottom = cy;
//Draw the icon and the text, centered with respect to each other.
DrawIcon(hDC, (cx-cxIcon)/2, 0, hIcon);
//String that indicates where to stop if we're only doing icons
Escape(hDC, MFCOMMENT, lstrlen(szIconOnly)+1, szIconOnly, NULL);
SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT)); SetBkMode(hDC, TRANSPARENT); fuAlign = SetTextAlign(hDC, TA_LEFT | TA_TOP | TA_NOUPDATECP);
OleStdIconLabelTextOut(hDC, hFont, 0, cy - cyText, ETO_CLIPPED, &TextRect, pszLabel, cchLabel, NULL);
//Write comments containing the icon source file and index.
if (NULL!=pszSourceFile) { //+1 on string lengths insures the null terminator is embedded.
Escape(hDC, MFCOMMENT, lstrlen(pszSourceFile)+1, pszSourceFile, NULL);
cchLabel=wsprintf(szIndex, TEXT("%u"), iIcon); Escape(hDC, MFCOMMENT, cchLabel+1, szIndex, NULL); }
SetTextAlign(hDC, fuAlign);
//All done with the metafile, now stuff it all into a METAFILEPICT.
hMF=CloseMetaFile(hDC);
if (NULL==hMF) { GlobalFree(hMem); ReleaseDC(NULL, hDCScreen); return NULL; }
//Fill out the structure
pMF=(LPMETAFILEPICT)GlobalLock(hMem);
//Transform to HIMETRICS
cx=XformWidthInPixelsToHimetric(hDCScreen, cx); cy=XformHeightInPixelsToHimetric(hDCScreen, cy); ReleaseDC(NULL, hDCScreen);
pMF->mm=MM_ANISOTROPIC; pMF->xExt=cx; pMF->yExt=cy; pMF->hMF=hMF;
GlobalUnlock(hMem);
DeleteObject(hFont);
return hMem; }
#endif // OBSOLETE
/*
* GetAssociatedExecutable * * Purpose: Finds the executable associated with the provided extension * * Parameters: * lpszExtension LPSTR points to the extension we're trying to find * an exe for. Does **NO** validation. * * lpszExecutable LPSTR points to where the exe name will be returned. * No validation here either - pass in 128 char buffer. * * Return: * BOOL TRUE if we found an exe, FALSE if we didn't. * */
BOOL FAR PASCAL GetAssociatedExecutable(LPTSTR lpszExtension, LPTSTR lpszExecutable)
{ HKEY hKey; LONG dw; LRESULT lRet; TCHAR szValue[OLEUI_CCHKEYMAX]; TCHAR szKey[OLEUI_CCHKEYMAX]; LPTSTR lpszTemp, lpszExe;
lRet = RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey);
if (ERROR_SUCCESS != lRet) return FALSE;
dw = OLEUI_CCHPATHMAX_SIZE; lRet = RegQueryValue(hKey, lpszExtension, (LPTSTR)szValue, &dw); //ProgId
if (ERROR_SUCCESS != lRet) { RegCloseKey(hKey); return FALSE; }
// szValue now has ProgID
lstrcpy(szKey, szValue); lstrcat(szKey, TEXT("\\Shell\\Open\\Command"));
dw = OLEUI_CCHPATHMAX_SIZE; lRet = RegQueryValue(hKey, (LPTSTR)szKey, (LPTSTR)szValue, &dw);
if (ERROR_SUCCESS != lRet) { RegCloseKey(hKey); return FALSE; }
// szValue now has an executable name in it. Let's null-terminate
// at the first post-executable space (so we don't have cmd line
// args.
lpszTemp = (LPTSTR)szValue;
while ((TEXT('\0') != *lpszTemp) && (iswspace(*lpszTemp))) lpszTemp++; // Strip off leading spaces
lpszExe = lpszTemp;
while ((TEXT('\0') != *lpszTemp) && (!iswspace(*lpszTemp))) lpszTemp++; // Step through exe name
*lpszTemp = TEXT('\0'); // null terminate at first space (or at end).
lstrcpy(lpszExecutable, lpszExe);
return TRUE;
}
/*
* HIconAndSourceFromClass * * Purpose: * Given an object class name, finds an associated executable in the * registration database and extracts the first icon from that * executable. If none is available or the class has no associated * executable, this function returns NULL. * * Parameters: * rclsid pointer to clsid to look up. * pszSource LPSTR in which to place the source of the icon. * This is assumed to be OLEUI_CCHPATHMAX * puIcon UINT FAR * in which to store the index of the * icon in pszSource. * * Return Value: * HICON Handle to the extracted icon if there is a module * associated to pszClass. NULL on failure to either * find the executable or extract and icon. */
HICON FAR PASCAL HIconAndSourceFromClass(REFCLSID rclsid, LPTSTR pszSource, UINT FAR *puIcon) { HICON hIcon; UINT IconIndex;
if (NULL==rclsid || NULL==pszSource || IsEqualCLSID(rclsid,&CLSID_NULL)) return NULL;
if (!FIconFileFromClass(rclsid, pszSource, OLEUI_CCHPATHMAX_SIZE, &IconIndex)) return NULL;
hIcon=ExtractIcon(ghInst, pszSource, IconIndex);
if ((HICON)32 > hIcon) hIcon=NULL; else *puIcon= IconIndex;
return hIcon; }
/*
* PointerToNthField * * Purpose: * Returns a pointer to the beginning of the nth field. * Assumes null-terminated string. * * Parameters: * lpszString string to parse * nField field to return starting index of. * chDelimiter char that delimits fields * * Return Value: * LPSTR pointer to beginning of nField field. * NOTE: If the null terminator is found * Before we find the Nth field, then * we return a pointer to the null terminator - * calling app should be sure to check for * this case. * */ LPTSTR FAR PASCAL PointerToNthField(LPTSTR lpszString, int nField, TCHAR chDelimiter) { LPTSTR lpField = lpszString; int cFieldFound = 1;
if (1 ==nField) return lpszString;
while (*lpField != TEXT('\0')) {
if (*lpField++ == chDelimiter) {
cFieldFound++;
if (nField == cFieldFound) return lpField; } }
return lpField;
}
/*
* FIconFileFromClass * * Purpose: * Looks up the path to executable that contains the class default icon. * * Parameters: * rclsid pointer to CLSID to look up. * pszEXE LPSTR at which to store the server name * cch UINT size of pszEXE * lpIndex LPUINT to index of icon within executable * * Return Value: * BOOL TRUE if one or more characters were loaded into pszEXE. * FALSE otherwise. */
BOOL FAR PASCAL FIconFileFromClass(REFCLSID rclsid, LPTSTR pszEXE, UINT cchBytes, UINT FAR *lpIndex) {
LONG dw; LONG lRet; HKEY hKey; LPMALLOC lpIMalloc; HRESULT hrErr; LPTSTR lpBuffer; LPTSTR lpIndexString; UINT cBufferSize = 136;// room for 128 char path and icon's index
TCHAR szKey[64]; LPSTR pszClass; UINT cch=cchBytes / sizeof(TCHAR); // number of characters
if (NULL==rclsid || NULL==pszEXE || 0==cch || IsEqualCLSID(rclsid,&CLSID_NULL)) return FALSE;
//Here, we use CoGetMalloc and alloc a buffer (maxpathlen + 8) to
//pass to RegQueryValue. Then, we copy the exe to pszEXE and the
//index to *lpIndex.
hrErr = CoGetMalloc(MEMCTX_TASK, &lpIMalloc);
if (NOERROR != hrErr) return FALSE;
lpBuffer = (LPTSTR)lpIMalloc->lpVtbl->Alloc(lpIMalloc, cBufferSize);
if (NULL == lpBuffer) { lpIMalloc->lpVtbl->Release(lpIMalloc); return FALSE; }
if (CoIsOle1Class(rclsid)) {
LPOLESTR lpszProgID;
// we've got an ole 1.0 class on our hands, so we look at
// progID\protocol\stdfileedting\server to get the
// name of the executable.
ProgIDFromCLSID(rclsid, &lpszProgID);
//Open up the class key
#ifdef UNICODE
lRet=RegOpenKey(HKEY_CLASSES_ROOT, lpszProgID, &hKey); #else
{ char szTemp[255];
wcstombs(szTemp, lpszProgID, 255); lRet=RegOpenKey(HKEY_CLASSES_ROOT, szTemp, &hKey); } #endif
if (ERROR_SUCCESS != lRet) { lpIMalloc->lpVtbl->Free(lpIMalloc, lpszProgID); lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer); lpIMalloc->lpVtbl->Release(lpIMalloc); return FALSE; }
dw=(LONG)cBufferSize; lRet = RegQueryValue(hKey, TEXT("Protocol\\StdFileEditing\\Server"), lpBuffer, &dw);
if (ERROR_SUCCESS != lRet) {
RegCloseKey(hKey); lpIMalloc->lpVtbl->Free(lpIMalloc, lpszProgID); lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer); lpIMalloc->lpVtbl->Release(lpIMalloc); return FALSE; }
// Use server and 0 as the icon index
LSTRCPYN(pszEXE, lpBuffer, cch);
*lpIndex = 0;
RegCloseKey(hKey); lpIMalloc->lpVtbl->Free(lpIMalloc, lpszProgID); lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer); lpIMalloc->lpVtbl->Release(lpIMalloc); return TRUE;
}
/*
* We have to go walking in the registration database under the * classname, so we first open the classname key and then check * under "\\DefaultIcon" to get the file that contains the icon. */
StringFromCLSIDA(rclsid, &pszClass);
lstrcpy(szKey, TEXT("CLSID\\"));
lstrcat(szKey, pszClass);
//Open up the class key
lRet=RegOpenKey(HKEY_CLASSES_ROOT, szKey, &hKey);
if (ERROR_SUCCESS != lRet) { lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer); lpIMalloc->lpVtbl->Free(lpIMalloc, pszClass); lpIMalloc->lpVtbl->Release(lpIMalloc); return FALSE; }
//Get the executable path and icon index.
dw=(LONG)cBufferSize; lRet=RegQueryValue(hKey, TEXT("DefaultIcon"), lpBuffer, &dw);
if (ERROR_SUCCESS != lRet) { // no DefaultIcon key...try LocalServer
dw=(LONG)cBufferSize; lRet=RegQueryValue(hKey, TEXT("LocalServer"), lpBuffer, &dw);
if (ERROR_SUCCESS != lRet) { // no LocalServer entry either...they're outta luck.
RegCloseKey(hKey); lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer); lpIMalloc->lpVtbl->Free(lpIMalloc, pszClass); lpIMalloc->lpVtbl->Release(lpIMalloc); return FALSE; }
// Use server from LocalServer or Server and 0 as the icon index
LSTRCPYN(pszEXE, lpBuffer, cch);
*lpIndex = 0;
RegCloseKey(hKey); lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer); lpIMalloc->lpVtbl->Free(lpIMalloc, pszClass); lpIMalloc->lpVtbl->Release(lpIMalloc); return TRUE; }
RegCloseKey(hKey);
// lpBuffer contains a string that looks like "<pathtoexe>,<iconindex>",
// so we need to separate the path and the icon index.
lpIndexString = PointerToNthField(lpBuffer, 2, TEXT(','));
if (TEXT('\0') == *lpIndexString) // no icon index specified - use 0 as default.
{ *lpIndex = 0;
} else { LPTSTR lpTemp; static TCHAR szTemp[16];
lstrcpy((LPTSTR)szTemp, lpIndexString);
// Put the icon index part into *pIconIndex
#ifdef UNICODE
{ char szTEMP1[16];
wcstombs(szTEMP1, szTemp, 16); *lpIndex = atoi((const char *)szTEMP1); } #else
*lpIndex = atoi((const char *)szTemp); #endif
// Null-terminate the exe part.
#ifdef WIN32
lpTemp = CharPrev(lpBuffer, lpIndexString); #else
lpTemp = AnsiPrev(lpBuffer, lpIndexString); #endif
*lpTemp = TEXT('\0'); }
if (!LSTRCPYN(pszEXE, lpBuffer, cch)) { lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer); lpIMalloc->lpVtbl->Free(lpIMalloc, pszClass); lpIMalloc->lpVtbl->Release(lpIMalloc); return FALSE; }
// Free the memory we alloc'd and leave.
lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer); lpIMalloc->lpVtbl->Free(lpIMalloc, pszClass); lpIMalloc->lpVtbl->Release(lpIMalloc); return TRUE; }
/*
* OleStdIconLabelTextOut * * Purpose: * Replacement for DrawText to be used in the "Display as Icon" metafile. * Uses ExtTextOut to output a string center on (at most) two lines. * Uses a very simple word wrap algorithm to split the lines. * * Parameters: (same as for ExtTextOut, except for hFont) * hDC device context to draw into; if this is NULL, then we don't * ETO the text, we just return the index of the beginning * of the second line * hFont font to use * nXStart x-coordinate of starting position * nYStart y-coordinate of starting position * fuOptions rectangle type * lpRect rect far * containing rectangle to draw text in. * lpszString string to draw * cchString length of string (truncated if over OLEUI_CCHLABELMAX) * lpDX spacing between character cells * * Return Value: * UINT Index of beginning of last line (0 if there's only one * line of text). * */
STDAPI_(UINT) OleStdIconLabelTextOut(HDC hDC, HFONT hFont, int nXStart, int nYStart, UINT fuOptions, RECT FAR * lpRect, LPTSTR lpszString, UINT cchString, int FAR * lpDX) {
HDC hDCScreen; static TCHAR szTempBuff[OLEUI_CCHLABELMAX]; int cxString, cyString, cxMaxString; int cxFirstLine, cyFirstLine, cxSecondLine; int index; int cch = cchString; TCHAR chKeep; LPTSTR lpszSecondLine; HFONT hFontT; BOOL fPrintText = TRUE; UINT iLastLineStart = 0; SIZE size;
// Initialization stuff...
if (NULL == hDC) // If we got NULL as the hDC, then we don't actually call ETO
fPrintText = FALSE;
// Make a copy of the string (NULL or non-NULL) that we're using
if (NULL == lpszString) *szTempBuff = TEXT('\0');
else LSTRCPYN(szTempBuff, lpszString, sizeof(szTempBuff)/sizeof(TCHAR));
// set maximum width
cxMaxString = lpRect->right - lpRect->left;
// get screen DC to do text size calculations
hDCScreen = GetDC(NULL);
hFontT=SelectObject(hDCScreen, hFont);
// get the extent of our label
#ifdef WIN32
// GetTextExtentPoint32 has fixed the off-by-one bug.
GetTextExtentPoint32(hDCScreen, szTempBuff, cch, &size); #else
GetTextExtentPoint(hDCScreen, szTempBuff, cch, &size); #endif
cxString = size.cx; cyString = size.cy;
// Select in the font we want to use
if (fPrintText) SelectObject(hDC, hFont);
// String is smaller than max string - just center, ETO, and return.
if (cxString <= cxMaxString) {
if (fPrintText) ExtTextOut(hDC, nXStart + (lpRect->right - cxString) / 2, nYStart, fuOptions, lpRect, szTempBuff, cch, NULL);
iLastLineStart = 0; // only 1 line of text
goto CleanupAndLeave; }
// String is too long...we've got to word-wrap it.
// Are there any spaces, slashes, tabs, or bangs in string?
if (lstrlen(szTempBuff) != (int) #ifdef UNICODE
wcscspn(szTempBuff, szSeparators) #else
strcspn(szTempBuff, szSeparators) #endif
) { // Yep, we've got spaces, so we'll try to find the largest
// space-terminated string that will fit on the first line.
index = cch;
while (index >= 0) {
TCHAR cchKeep;
// scan the string backwards for spaces, slashes, tabs, or bangs
while (!IS_SEPARATOR(szTempBuff[index]) ) index--;
if (index <= 0) break;
cchKeep = szTempBuff[index]; // remember what char was there
szTempBuff[index] = TEXT('\0'); // just for now
#ifdef WIN32
GetTextExtentPoint32( hDCScreen, (LPTSTR)szTempBuff,lstrlen((LPTSTR)szTempBuff),&size); #else
GetTextExtentPoint( hDCScreen, (LPTSTR)szTempBuff,lstrlen((LPTSTR)szTempBuff),&size); #endif
cxFirstLine = size.cx; cyFirstLine = size.cy;
szTempBuff[index] = cchKeep; // put the right char back
if (cxFirstLine <= cxMaxString) {
iLastLineStart = index + 1;
if (!fPrintText) goto CleanupAndLeave;
ExtTextOut(hDC, nXStart + (lpRect->right - cxFirstLine) / 2, nYStart, fuOptions, lpRect, (LPTSTR)szTempBuff, index + 1, lpDX);
lpszSecondLine = (LPTSTR)szTempBuff;
lpszSecondLine += (index + 1) ;
GetTextExtentPoint(hDCScreen, lpszSecondLine, lstrlen(lpszSecondLine), &size);
// If the second line is wider than the rectangle, we
// just want to clip the text.
cxSecondLine = min(size.cx, cxMaxString);
ExtTextOut(hDC, nXStart + (lpRect->right - cxSecondLine) / 2, nYStart + cyFirstLine, fuOptions, lpRect, lpszSecondLine, lstrlen(lpszSecondLine), lpDX);
goto CleanupAndLeave;
} // end if
index--;
} // end while
} // end if
// Here, there are either no spaces in the string (strchr(szTempBuff, ' ')
// returned NULL), or there spaces in the string, but they are
// positioned so that the first space terminated string is still
// longer than one line. So, we walk backwards from the end of the
// string until we find the largest string that will fit on the first
// line , and then we just clip the second line.
cch = lstrlen((LPTSTR)szTempBuff);
chKeep = szTempBuff[cch]; szTempBuff[cch] = TEXT('\0');
GetTextExtentPoint(hDCScreen, szTempBuff, lstrlen(szTempBuff),&size);
cxFirstLine = size.cx; cyFirstLine = size.cy;
while (cxFirstLine > cxMaxString) { // We allow 40 characters in the label, but the metafile is
// only as wide as 10 W's (for aesthetics - 20 W's wide looked
// dumb. This means that if we split a long string in half (in
// terms of characters), then we could still be wider than the
// metafile. So, if this is the case, we just step backwards
// from the halfway point until we get something that will fit.
// Since we just let ETO clip the second line
szTempBuff[cch--] = chKeep; if (0 == cch) goto CleanupAndLeave;
chKeep = szTempBuff[cch]; szTempBuff[cch] = TEXT('\0');
GetTextExtentPoint( hDCScreen, szTempBuff, lstrlen(szTempBuff), &size); cxFirstLine = size.cx; }
iLastLineStart = cch;
if (!fPrintText) goto CleanupAndLeave;
ExtTextOut(hDC, nXStart + (lpRect->right - cxFirstLine) / 2, nYStart, fuOptions, lpRect, (LPTSTR)szTempBuff, lstrlen((LPTSTR)szTempBuff), lpDX);
szTempBuff[cch] = chKeep; lpszSecondLine = szTempBuff; lpszSecondLine += cch ;
GetTextExtentPoint( hDCScreen, (LPTSTR)lpszSecondLine, lstrlen(lpszSecondLine), &size);
// If the second line is wider than the rectangle, we
// just want to clip the text.
cxSecondLine = min(size.cx, cxMaxString);
ExtTextOut(hDC, nXStart + (lpRect->right - cxSecondLine) / 2, nYStart + cyFirstLine, fuOptions, lpRect, lpszSecondLine, lstrlen(lpszSecondLine), lpDX);
CleanupAndLeave: SelectObject(hDCScreen, hFontT); ReleaseDC(NULL, hDCScreen); return iLastLineStart;
}
|