summaryrefslogtreecommitdiffstats
path: root/private/ole2ui32/drawicon.cpp
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ole2ui32/drawicon.cpp
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ole2ui32/drawicon.cpp')
-rw-r--r--private/ole2ui32/drawicon.cpp674
1 files changed, 674 insertions, 0 deletions
diff --git a/private/ole2ui32/drawicon.cpp b/private/ole2ui32/drawicon.cpp
new file mode 100644
index 000000000..1fd01514b
--- /dev/null
+++ b/private/ole2ui32/drawicon.cpp
@@ -0,0 +1,674 @@
+/*
+ * DRAWICON.CPP
+ *
+ * Functions to handle creation of metafiles with icons and labels
+ * as well as functions to draw such metafiles with or without the label.
+ *
+ * The metafile is created with a comment that marks the records containing
+ * the label code. Drawing the metafile enumerates the records, draws
+ * all records up to that point, then decides to either skip the label
+ * or draw it.
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+#include "precomp.h"
+#include "utility.h"
+#include "malloc.h"
+
+// Private implementation
+
+//Structure for label and source extraction from a metafile
+typedef struct tagLABELEXTRACT
+{
+ LPTSTR lpsz;
+ UINT Index; // index in lpsz (so we can retrieve 2+ lines)
+ DWORD PrevIndex; // index of last line (so we can mimic word wrap)
+
+ union
+ {
+ UINT cch; //Length of label for label extraction
+ UINT iIcon; //Index of icon in source extraction.
+ } u;
+
+ //For internal use in enum procs
+ BOOL fFoundIconOnly;
+ BOOL fFoundSource;
+ BOOL fFoundIndex;
+} LABELEXTRACT, FAR * LPLABELEXTRACT;
+
+
+//Structure for extracting icons from a metafile (CreateIcon parameters)
+typedef struct tagICONEXTRACT
+{
+ HICON hIcon; //Icon created in the enumeration proc.
+
+ /*
+ * Since we want to handle multitasking well we have the caller
+ * of the enumeration proc instantiate these variables instead of
+ * using statics in the enum proc (which would be bad).
+ */
+ BOOL fAND;
+ HGLOBAL hMemAND; //Enumeration proc allocates and copies
+} ICONEXTRACT, FAR * LPICONEXTRACT;
+
+
+//Structure to use to pass info to EnumMetafileDraw
+typedef struct tagDRAWINFO
+{
+ RECT Rect;
+ BOOL fIconOnly;
+} DRAWINFO, FAR * LPDRAWINFO;
+
+
+int CALLBACK EnumMetafileIconDraw(HDC, HANDLETABLE FAR *, METARECORD FAR *, int, LPARAM);
+int CALLBACK EnumMetafileExtractLabel(HDC, HANDLETABLE FAR *, METARECORD FAR *, int, LPLABELEXTRACT);
+int CALLBACK EnumMetafileExtractIcon(HDC, HANDLETABLE FAR *, METARECORD FAR *, int, LPICONEXTRACT);
+int CALLBACK EnumMetafileExtractIconSource(HDC, HANDLETABLE FAR *, METARECORD FAR *, int, LPLABELEXTRACT);
+
+/*
+ * Strings for metafile comments. KEEP THESE IN SYNC WITH THE
+ * STRINGS IN GETICON.CPP
+ */
+
+static const char szIconOnly[] = "IconOnly"; // Where to stop to exclude label.
+
+/*
+ * OleUIMetafilePictIconFree
+ *
+ * Purpose:
+ * Deletes the metafile contained in a METAFILEPICT structure and
+ * frees the memory for the structure itself.
+ *
+ * Parameters:
+ * hMetaPict HGLOBAL metafilepict structure created in
+ * OleMetafilePictFromIconAndLabel
+ *
+ * Return Value:
+ * None
+ */
+
+STDAPI_(void) OleUIMetafilePictIconFree(HGLOBAL hMetaPict)
+{
+ if (NULL != hMetaPict)
+ {
+ STGMEDIUM stgMedium;
+ stgMedium.tymed = TYMED_MFPICT;
+ stgMedium.hMetaFilePict = hMetaPict;
+ stgMedium.pUnkForRelease = NULL;
+ ReleaseStgMedium(&stgMedium);
+ }
+}
+
+/*
+ * OleUIMetafilePictIconDraw
+ *
+ * Purpose:
+ * Draws the metafile from OleMetafilePictFromIconAndLabel, either with
+ * the label or without.
+ *
+ * Parameters:
+ * hDC HDC on which to draw.
+ * pRect LPRECT in which to draw the metafile.
+ * hMetaPict HGLOBAL to the METAFILEPICT from
+ * OleMetafilePictFromIconAndLabel
+ * fIconOnly BOOL specifying to draw the label or not.
+ *
+ * Return Value:
+ * BOOL TRUE if the function is successful, FALSE if the
+ * given metafilepict is invalid.
+ */
+
+STDAPI_(BOOL) OleUIMetafilePictIconDraw(HDC hDC, LPCRECT pRect,
+ HGLOBAL hMetaPict, BOOL fIconOnly)
+{
+ if (NULL == hMetaPict)
+ return FALSE;
+
+ LPMETAFILEPICT pMF = (LPMETAFILEPICT)GlobalLock(hMetaPict);
+
+ if (NULL == pMF)
+ return FALSE;
+
+ DRAWINFO di;
+ di.Rect = *pRect;
+ di.fIconOnly = fIconOnly;
+
+ //Transform to back to pixels
+ int cx = XformWidthInHimetricToPixels(hDC, pMF->xExt);
+ int cy = XformHeightInHimetricToPixels(hDC, pMF->yExt);
+
+ SaveDC(hDC);
+
+ SetMapMode(hDC, pMF->mm);
+ SetViewportOrgEx(hDC, (pRect->right - cx) / 2, 0, NULL);
+ SetViewportExtEx(hDC, min ((pRect->right - cx) / 2 + cx, cx), cy, NULL);
+
+ if (fIconOnly)
+ EnumMetaFile(hDC, pMF->hMF, (MFENUMPROC)EnumMetafileIconDraw, (LPARAM)&di);
+ else
+ PlayMetaFile(hDC, pMF->hMF);
+
+ RestoreDC(hDC, -1);
+
+ GlobalUnlock(hMetaPict);
+ return TRUE;
+}
+
+/*
+ * EnumMetafileIconDraw
+ *
+ * Purpose:
+ * EnumMetaFile callback function that draws either the icon only or
+ * the icon and label depending on given flags.
+ *
+ * Parameters:
+ * hDC HDC into which the metafile should be played.
+ * phTable HANDLETABLE FAR * providing handles selected into the DC.
+ * pMFR METARECORD FAR * giving the enumerated record.
+ * lParam LPARAM flags passed in EnumMetaFile.
+ *
+ * Return Value:
+ * int 0 to stop enumeration, 1 to continue.
+ */
+int CALLBACK EnumMetafileIconDraw(HDC hDC, HANDLETABLE FAR *phTable,
+ METARECORD FAR *pMFR, int cObj, LPARAM lParam)
+{
+ LPDRAWINFO lpdi = (LPDRAWINFO)lParam;
+
+ /*
+ * We play everything blindly except for DIBBITBLT (or DIBSTRETCHBLT)
+ * and ESCAPE with MFCOMMENT. For the BitBlts we change the x,y to
+ * draw at (0,0) instead of wherever it was written to draw. The
+ * comment tells us there to stop if we don't want to draw the label.
+ */
+
+ //If we're playing icon only, stop enumeration at the comment.
+ if (lpdi->fIconOnly)
+ {
+ if (META_ESCAPE==pMFR->rdFunction && MFCOMMENT==pMFR->rdParm[0])
+ {
+ if (0 == lstrcmpiA(szIconOnly, (LPSTR)&pMFR->rdParm[2]))
+ return 0;
+ }
+
+ /*
+ * Check for the records in which we want to munge the coordinates.
+ * destX is offset 6 for BitBlt, offset 9 for StretchBlt, either of
+ * which may appear in the metafile.
+ */
+ if (META_DIBBITBLT == pMFR->rdFunction)
+ pMFR->rdParm[6]=0;
+
+ if (META_DIBSTRETCHBLT == pMFR->rdFunction)
+ pMFR->rdParm[9] = 0;
+ }
+
+ PlayMetaFileRecord(hDC, phTable, pMFR, cObj);
+ return 1;
+}
+
+
+/*
+ * OleUIMetafilePictExtractLabel
+ *
+ * Purpose:
+ * Retrieves the label string from metafile representation of an icon.
+ *
+ * Parameters:
+ * hMetaPict HGLOBAL to the METAFILEPICT containing the metafile.
+ * lpszLabel LPSTR in which to store the label.
+ * cchLabel UINT length of lpszLabel.
+ * lpWrapIndex DWORD index of first character in last line. Can be NULL
+ * if calling function doesn't care about word wrap.
+ *
+ * Return Value:
+ * UINT Number of characters copied.
+ */
+STDAPI_(UINT) OleUIMetafilePictExtractLabel(HGLOBAL hMetaPict, LPTSTR lpszLabel,
+ UINT cchLabel, LPDWORD lpWrapIndex)
+{
+ if (NULL == hMetaPict || NULL == lpszLabel || 0 == cchLabel)
+ return FALSE;
+
+ /*
+ * We extract the label by getting a screen DC and walking the metafile
+ * records until we see the ExtTextOut record we put there. That
+ * record will have the string embedded in it which we then copy out.
+ */
+ LPMETAFILEPICT pMF = (LPMETAFILEPICT)GlobalLock(hMetaPict);
+
+ if (NULL == pMF)
+ return FALSE;
+
+ LABELEXTRACT le;
+ le.lpsz=lpszLabel;
+ le.u.cch=cchLabel;
+ le.Index=0;
+ le.fFoundIconOnly=FALSE;
+ le.fFoundSource=FALSE; //Unused for this function.
+ le.fFoundIndex=FALSE; //Unused for this function.
+ le.PrevIndex = 0;
+
+ //Use a screen DC so we have something valid to pass in.
+ HDC hDC = GetDC(NULL);
+ EnumMetaFile(hDC, pMF->hMF, (MFENUMPROC)EnumMetafileExtractLabel, (LONG)(LPLABELEXTRACT)&le);
+ ReleaseDC(NULL, hDC);
+
+ GlobalUnlock(hMetaPict);
+
+ //Tell where we wrapped (if calling function cares)
+ if (NULL != lpWrapIndex)
+ *lpWrapIndex = le.PrevIndex;
+
+ //Return amount of text copied
+ return le.u.cch;
+}
+
+/*
+ * EnumMetafileExtractLabel
+ *
+ * Purpose:
+ * EnumMetaFile callback function that walks a metafile looking for
+ * ExtTextOut, then concatenates the text from each one into a buffer
+ * in lParam.
+ *
+ * Parameters:
+ * hDC HDC into which the metafile should be played.
+ * phTable HANDLETABLE FAR * providing handles selected into the DC.
+ * pMFR METARECORD FAR * giving the enumerated record.
+ * pLE LPLABELEXTRACT providing the destination buffer and length.
+ *
+ * Return Value:
+ * int 0 to stop enumeration, 1 to continue.
+ */
+
+int CALLBACK EnumMetafileExtractLabel(HDC hDC, HANDLETABLE FAR *phTable,
+ METARECORD FAR *pMFR, int cObj, LPLABELEXTRACT pLE)
+{
+ /*
+ * We don't allow anything to happen until we see "IconOnly"
+ * in an MFCOMMENT that is used to enable everything else.
+ */
+ if (!pLE->fFoundIconOnly)
+ {
+ if (META_ESCAPE == pMFR->rdFunction && MFCOMMENT == pMFR->rdParm[0])
+ {
+ if (0 == lstrcmpiA(szIconOnly, (LPSTR)&pMFR->rdParm[2]))
+ pLE->fFoundIconOnly=TRUE;
+ }
+ return 1;
+ }
+
+ //Enumerate all records looking for META_EXTTEXTOUT - there can be more
+ //than one.
+ if (META_EXTTEXTOUT == pMFR->rdFunction)
+ {
+ /*
+ * If ExtTextOut has NULL fuOptions, then the rectangle is omitted
+ * from the record, and the string starts at rdParm[4]. If
+ * fuOptions is non-NULL, then the string starts at rdParm[8]
+ * (since the rectange takes up four WORDs in the array). In
+ * both cases, the string continues for (rdParm[2]+1) >> 1
+ * words. We just cast a pointer to rdParm[8] to an LPSTR and
+ * lstrcpyn into the buffer we were given.
+ *
+ * Note that we use element 8 in rdParm instead of 4 because we
+ * passed ETO_CLIPPED in for the options on ExtTextOut--docs say
+ * [4] which is rect doesn't exist if we passed zero there.
+ *
+ */
+
+ UINT cchMax = min(pLE->u.cch - pLE->Index, (UINT)pMFR->rdParm[2]);
+ LPTSTR lpszTemp = pLE->lpsz + pLE->Index;
+#ifdef _UNICODE
+ MultiByteToWideChar(CP_ACP, 0, (LPSTR)&pMFR->rdParm[8], cchMax,
+ lpszTemp, cchMax+1);
+#else
+ lstrcpyn(lpszTemp, (LPSTR)&pMFR->rdParm[8], cchMax+1);
+#endif
+ lpszTemp[cchMax+1] = 0;
+
+ pLE->PrevIndex = pLE->Index;
+ pLE->Index += cchMax;
+ }
+ return 1;
+}
+
+/*
+ * OleUIMetafilePictExtractIcon
+ *
+ * Purpose:
+ * Retrieves the icon from metafile into which DrawIcon was done before.
+ *
+ * Parameters:
+ * hMetaPict HGLOBAL to the METAFILEPICT containing the metafile.
+ *
+ * Return Value:
+ * HICON Icon recreated from the data in the metafile.
+ */
+STDAPI_(HICON) OleUIMetafilePictExtractIcon(HGLOBAL hMetaPict)
+{
+ if (NULL == hMetaPict)
+ return NULL;
+
+ /*
+ * We extract the label by getting a screen DC and walking the metafile
+ * records until we see the ExtTextOut record we put there. That
+ * record will have the string embedded in it which we then copy out.
+ */
+ LPMETAFILEPICT pMF = (LPMETAFILEPICT)GlobalLock(hMetaPict);
+
+ if (NULL == pMF)
+ return FALSE;
+
+ ICONEXTRACT ie;
+ ie.fAND = TRUE;
+
+ //Use a screen DC so we have something valid to pass in.
+ HDC hDC=GetDC(NULL);
+ EnumMetaFile(hDC, pMF->hMF, (MFENUMPROC)EnumMetafileExtractIcon, (LONG)&ie);
+ ReleaseDC(NULL, hDC);
+
+ GlobalUnlock(hMetaPict);
+
+ return ie.hIcon;
+}
+
+/*
+ * EnumMetafileExtractIcon
+ *
+ * Purpose:
+ * EnumMetaFile callback function that walks a metafile looking for
+ * StretchBlt (3.1) and BitBlt (3.0) records. We expect to see two
+ * of them, the first being the AND mask and the second being the XOR
+ * data. We
+ * ExtTextOut, then copies the text into a buffer in lParam.
+ *
+ * Parameters:
+ * hDC HDC into which the metafile should be played.
+ * phTable HANDLETABLE FAR * providing handles selected into the DC.
+ * pMFR METARECORD FAR * giving the enumerated record.
+ * pIE LPICONEXTRACT providing the destination buffer and length.
+ *
+ * Return Value:
+ * int 0 to stop enumeration, 1 to continue.
+ */
+
+int CALLBACK EnumMetafileExtractIcon(HDC hDC, HANDLETABLE FAR *phTable,
+ METARECORD FAR *pMFR, int cObj, LPICONEXTRACT pIE)
+{
+ //Continue enumeration if we don't see the records we want.
+ if (META_DIBBITBLT != pMFR->rdFunction && META_DIBSTRETCHBLT != pMFR->rdFunction)
+ return 1;
+
+ UNALIGNED BITMAPINFO* lpBI;
+ UINT uWidth, uHeight;
+ /*
+ * Windows 3.0 DrawIcon uses META_DIBBITBLT in whereas 3.1 uses
+ * META_DIBSTRETCHBLT so we have to handle each case separately.
+ */
+ if (META_DIBBITBLT==pMFR->rdFunction) //Win3.0
+ {
+ //Get dimensions and the BITMAPINFO struct.
+ uHeight = pMFR->rdParm[1];
+ uWidth = pMFR->rdParm[2];
+ lpBI = (LPBITMAPINFO)&(pMFR->rdParm[8]);
+ }
+
+ if (META_DIBSTRETCHBLT == pMFR->rdFunction) //Win3.1
+ {
+ //Get dimensions and the BITMAPINFO struct.
+ uHeight = pMFR->rdParm[2];
+ uWidth = pMFR->rdParm[3];
+ lpBI = (LPBITMAPINFO)&(pMFR->rdParm[10]);
+ }
+
+ UNALIGNED BITMAPINFOHEADER* lpBH=(LPBITMAPINFOHEADER)&(lpBI->bmiHeader);
+
+ //Pointer to the bits which follows the BITMAPINFO structure.
+ LPBYTE lpbSrc=(LPBYTE)lpBI+sizeof(BITMAPINFOHEADER);
+
+ //Add the length of the color table (if one exists)
+ if (0 != lpBH->biClrUsed)
+ {
+ // If we have an explicit count of colors used, we
+ // can find the offset to the data directly
+ lpbSrc += (lpBH->biClrUsed*sizeof(RGBQUAD));
+ }
+ else if (lpBH->biCompression == BI_BITFIELDS)
+ {
+ // 16 or 32 bpp, indicated by BI_BITFIELDS in the compression
+ // field, have 3 DWORD masks for adjusting subsequent
+ // direct-color values, and no palette
+ lpbSrc += 3 * sizeof(DWORD);
+ }
+ else
+ {
+ // In other cases, there is an array of RGBQUAD entries
+ // equal to 2^(biBitCount) where biBitCount is the number
+ // of bits per pixel. The exception is 24 bpp bitmaps,
+ // which have no color table and just use direct RGB values.
+ lpbSrc += (lpBH->biBitCount == 24) ? 0 :
+ (1 << (lpBH->biBitCount)) * sizeof(RGBQUAD);
+ }
+
+ // copy into aligned stack space (since SetDIBits needs aligned data)
+ size_t nSize = lpbSrc - (LPBYTE)lpBI;
+ LPBITMAPINFO lpTemp = (LPBITMAPINFO)_alloca(nSize);
+ memcpy(lpTemp, lpBI, nSize);
+
+ /*
+ * All the bits we have in lpbSrc are device-independent, so we
+ * need to change them over to be device-dependent using SetDIBits.
+ * Once we have a bitmap with the device-dependent bits, we can
+ * GetBitmapBits to have buffers with the real data.
+ *
+ * For each pass we have to allocate memory for the bits. We save
+ * the memory for the mask between passes.
+ */
+
+ HBITMAP hBmp;
+
+ //Use CreateBitmap for ANY monochrome bitmaps
+ if (pIE->fAND || 1==lpBH->biBitCount)
+ hBmp=CreateBitmap((UINT)lpBH->biWidth, (UINT)lpBH->biHeight, 1, 1, NULL);
+ else
+ hBmp=CreateCompatibleBitmap(hDC, (UINT)lpBH->biWidth, (UINT)lpBH->biHeight);
+
+ if (!hBmp || !SetDIBits(hDC, hBmp, 0, (UINT)lpBH->biHeight, (LPVOID)lpbSrc, lpTemp, DIB_RGB_COLORS))
+ {
+ if (!pIE->fAND)
+ GlobalFree(pIE->hMemAND);
+
+ DeleteObject(hBmp);
+ return 0;
+ }
+
+ //Allocate memory and get the DDBits into it.
+ BITMAP bm;
+ GetObject(hBmp, sizeof(bm), &bm);
+
+ DWORD cb = bm.bmHeight*bm.bmWidthBytes * bm.bmPlanes;
+ HGLOBAL hMem = GlobalAlloc(GHND, cb);
+
+ if (NULL==hMem)
+ {
+ if (NULL != pIE->hMemAND)
+ GlobalFree(pIE->hMemAND);
+
+ DeleteObject(hBmp);
+ return 0;
+ }
+
+ LPBYTE lpbDst = (LPBYTE)GlobalLock(hMem);
+ GetBitmapBits(hBmp, cb, (LPVOID)lpbDst);
+ DeleteObject(hBmp);
+ GlobalUnlock(hMem);
+
+ /*
+ * If this is the first pass (pIE->fAND==TRUE) then save the memory
+ * of the AND bits for the next pass.
+ */
+ if (pIE->fAND)
+ {
+ pIE->fAND = FALSE;
+ pIE->hMemAND = hMem;
+
+ //Continue enumeration looking for the next blt record.
+ return 1;
+ }
+ else
+ {
+ //Get the AND pointer again.
+ lpbSrc=(LPBYTE)GlobalLock(pIE->hMemAND);
+
+ /*
+ * Create the icon now that we have all the data. lpbDst already
+ * points to the XOR bits.
+ */
+
+ int cxIcon = GetSystemMetrics(SM_CXICON);
+ int cyIcon = GetSystemMetrics(SM_CYICON);
+
+ pIE->hIcon = CreateIcon(_g_hOleStdInst, uWidth, uHeight,
+ (BYTE)bm.bmPlanes, (BYTE)bm.bmBitsPixel, lpbSrc, lpbDst);
+
+ GlobalUnlock(pIE->hMemAND);
+ GlobalFree(pIE->hMemAND);
+ GlobalFree(hMem);
+
+ return 0;
+ }
+}
+
+
+/*
+ * OleUIMetafilePictExtractIconSource
+ *
+ * Purpose:
+ * Retrieves the filename and index of the icon source from a metafile
+ * created with OleMetafilePictFromIconAndLabel.
+ *
+ * Parameters:
+ * hMetaPict HGLOBAL to the METAFILEPICT containing the metafile.
+ * lpszSource LPTSTR in which to store the source filename. This
+ * buffer should be MAX_PATH characters.
+ * piIcon UINT FAR * in which to store the icon's index
+ * within lpszSource
+ *
+ * Return Value:
+ * BOOL TRUE if the records were found, FALSE otherwise.
+ */
+STDAPI_(BOOL) OleUIMetafilePictExtractIconSource(HGLOBAL hMetaPict,
+ LPTSTR lpszSource, UINT FAR *piIcon)
+{
+ if (NULL == hMetaPict || NULL == lpszSource || NULL == piIcon)
+ return FALSE;
+
+ /*
+ * We will walk the metafile looking for the two comment records
+ * following the IconOnly comment. The flags fFoundIconOnly and
+ * fFoundSource indicate if we have found IconOnly and if we have
+ * found the source comment already.
+ */
+
+ LPMETAFILEPICT pMF = (LPMETAFILEPICT)GlobalLock(hMetaPict);
+ if (NULL == pMF)
+ return FALSE;
+
+ LABELEXTRACT le;
+ le.lpsz = lpszSource;
+ le.fFoundIconOnly = FALSE;
+ le.fFoundSource = FALSE;
+ le.fFoundIndex = FALSE;
+
+ //Use a screen DC so we have something valid to pass in.
+ HDC hDC = GetDC(NULL);
+ EnumMetaFile(hDC, pMF->hMF, (MFENUMPROC)EnumMetafileExtractIconSource,
+ (LONG)(LPLABELEXTRACT)&le);
+ ReleaseDC(NULL, hDC);
+ GlobalUnlock(hMetaPict);
+
+ //Copy the icon index to the caller's variable.
+ *piIcon=le.u.iIcon;
+
+ //Check that we found everything.
+ return (le.fFoundIconOnly && le.fFoundSource && le.fFoundIndex);
+}
+
+
+/*
+ * EnumMetafileExtractIconSource
+ *
+ * Purpose:
+ * EnumMetaFile callback function that walks a metafile skipping the first
+ * comment record, extracting the source filename from the second, and
+ * the index of the icon in the third.
+ *
+ * Parameters:
+ * hDC HDC into which the metafile should be played.
+ * phTable HANDLETABLE FAR * providing handles selected into the DC.
+ * pMFR METARECORD FAR * giving the enumerated record.
+ * pLE LPLABELEXTRACT providing the destination buffer and
+ * area to store the icon index.
+ *
+ * Return Value:
+ * int 0 to stop enumeration, 1 to continue.
+ */
+
+int CALLBACK EnumMetafileExtractIconSource(HDC hDC, HANDLETABLE FAR *phTable,
+ METARECORD FAR *pMFR, int cObj, LPLABELEXTRACT pLE)
+{
+ /*
+ * We don't allow anything to happen until we see "IconOnly"
+ * in an MFCOMMENT that is used to enable everything else.
+ */
+ if (!pLE->fFoundIconOnly)
+ {
+ if (META_ESCAPE == pMFR->rdFunction && MFCOMMENT == pMFR->rdParm[0])
+ {
+ if (0 == lstrcmpiA(szIconOnly, (LPSTR)&pMFR->rdParm[2]))
+ pLE->fFoundIconOnly=TRUE;
+ }
+ return 1;
+ }
+
+ //Now see if we find the source string.
+ if (!pLE->fFoundSource)
+ {
+ if (META_ESCAPE == pMFR->rdFunction && MFCOMMENT == pMFR->rdParm[0])
+ {
+#ifdef _UNICODE
+ MultiByteToWideChar(CP_ACP, 0, (LPSTR)&pMFR->rdParm[2], -1,
+ pLE->lpsz, MAX_PATH);
+#else
+ lstrcpyn(pLE->lpsz, (LPSTR)&pMFR->rdParm[2], MAX_PATH);
+#endif
+ pLE->lpsz[MAX_PATH-1] = '\0';
+ pLE->fFoundSource=TRUE;
+ }
+ return 1;
+ }
+
+ //Next comment will be the icon index.
+ if (META_ESCAPE == pMFR->rdFunction && MFCOMMENT == pMFR->rdParm[0])
+ {
+ /*
+ * This string contains the icon index in string form,
+ * so we need to convert back to a UINT. After we see this
+ * we can stop the enumeration. The comment will have
+ * a null terminator because we made sure to save it.
+ */
+ LPSTR psz = (LPSTR)&pMFR->rdParm[2];
+ pLE->u.iIcon = 0;
+
+ //Do Ye Olde atoi
+ while (*psz)
+ pLE->u.iIcon = (10*pLE->u.iIcon)+((*psz++)-'0');
+
+ pLE->fFoundIndex=TRUE;
+ return 0;
+ }
+ return 1;
+}