home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winui / comctl / reitp / drawicon.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-12  |  19.6 KB  |  710 lines

  1. /*
  2.  * DRAWICON.C
  3.  *
  4.  * Functions to handle creation of metafiles with icons and labels
  5.  * as well as functions to draw such metafiles with or without the label.
  6.  *
  7.  * The metafile is created with a comment that marks the records containing
  8.  * the label code.  Drawing the metafile enumerates the records, draws
  9.  * all records up to that point, then decides to either skip the label
  10.  * or draw it.
  11.  *
  12.  * Copyright (c)1992-1996 Microsoft Corporation, All Right Reserved
  13.  */
  14.  
  15. #define STRICT  1
  16. #include "olestd.h"
  17. #include "common.h"
  18. #include "utility.h"
  19.  
  20. /*
  21.  * Strings for metafile comments.  KEEP THESE IN SYNC WITH THE
  22.  * STRINGS IN GETICON.C.
  23.  */
  24.  
  25. static char szIconOnly[]="IconOnly";        //Where to stop to exclude label.
  26.  
  27.  
  28.  
  29.  
  30. /*
  31.  * OleUIMetafilePictIconFree
  32.  *
  33.  * Purpose:
  34.  *  Deletes the metafile contained in a METAFILEPICT structure and
  35.  *  frees the memory for the structure itself.
  36.  *
  37.  * Parameters:
  38.  *  hMetaPict       HGLOBAL metafilepict structure created in
  39.  *                  OleUIMetafilePictFromIconAndLabel
  40.  *
  41.  * Return Value:
  42.  *  None
  43.  */
  44.  
  45. STDAPI_(void) OleUIMetafilePictIconFree(HGLOBAL hMetaPict)
  46.    {
  47.    LPMETAFILEPICT      pMF;
  48.  
  49.    if (NULL==hMetaPict)
  50.       return;
  51.  
  52.    pMF=(LPMETAFILEPICT)GlobalLock(hMetaPict);
  53.  
  54.    if (NULL!=pMF)
  55.       {
  56.       if (NULL!=pMF->hMF)
  57.          DeleteMetaFile(pMF->hMF);
  58.       }
  59.  
  60.    GlobalUnlock(hMetaPict);
  61.    GlobalFree(hMetaPict);
  62.    return;
  63.    }
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72. /*
  73.  * OleUIMetafilePictIconDraw
  74.  *
  75.  * Purpose:
  76.  *  Draws the metafile from OleUIMetafilePictFromIconAndLabel, either with
  77.  *  the label or without.
  78.  *
  79.  * Parameters:
  80.  *  hDC             HDC on which to draw.
  81.  *  pRect           LPRECT in which to draw the metafile.
  82.  *  hMetaPict       HGLOBAL to the METAFILEPICT from
  83.  *                  OleUIMetafilePictFromIconAndLabel
  84.  *  fIconOnly       BOOL specifying to draw the label or not.
  85.  *
  86.  * Return Value:
  87.  *  BOOL            TRUE if the function is successful, FALSE if the
  88.  *                  given metafilepict is invalid.
  89.  */
  90.  
  91. STDAPI_(BOOL) OleUIMetafilePictIconDraw(HDC hDC, LPRECT pRect, HGLOBAL hMetaPict
  92.                              , BOOL fIconOnly)
  93.    {
  94.    LPMETAFILEPICT  pMF;
  95.    DRAWINFO        di;
  96.    int             cx, cy;
  97.    SIZE            size;
  98.    POINT           point;
  99.  
  100.    if (NULL==hMetaPict)
  101.       return FALSE;
  102.  
  103.    pMF=GlobalLock(hMetaPict);
  104.  
  105.    if (NULL==pMF)
  106.       return FALSE;
  107.  
  108.    di.Rect = *pRect;
  109.    di.fIconOnly = fIconOnly;
  110.  
  111.    //Transform to back to pixels
  112.    cx=XformWidthInHimetricToPixels(hDC, pMF->xExt);
  113.    cy=XformHeightInHimetricToPixels(hDC, pMF->yExt);
  114.  
  115.    SaveDC(hDC);
  116.  
  117.    SetMapMode(hDC, pMF->mm);
  118.    SetViewportOrgEx(hDC, (pRect->right - cx) / 2, 0, &point);
  119.  
  120.    SetViewportExtEx(hDC, min ((pRect->right - cx) / 2 + cx, cx), cy, &size);
  121.  
  122.    if (fIconOnly)
  123.       {
  124.       // Since we've used the __export keyword on the
  125.       // EnumMetafileIconDraw proc, we do not need to use
  126.       // MakeProcInstance
  127.       EnumMetaFile(hDC, pMF->hMF, (MFENUMPROC)EnumMetafileIconDraw
  128.          , (LPARAM)(LPDRAWINFO)&di);
  129.       }
  130.    else
  131.       PlayMetaFile(hDC, pMF->hMF);
  132.  
  133.    RestoreDC(hDC, -1);
  134.  
  135.    GlobalUnlock(hMetaPict);
  136.    return TRUE;
  137.    }
  138.  
  139.  
  140.  
  141.  
  142. /*
  143.  * EnumMetafileIconDraw
  144.  *
  145.  * Purpose:
  146.  *  EnumMetaFile callback function that draws either the icon only or
  147.  *  the icon and label depending on given flags.
  148.  *
  149.  * Parameters:
  150.  *  hDC             HDC into which the metafile should be played.
  151.  *  phTable         HANDLETABLE FAR * providing handles selected into the DC.
  152.  *  pMFR            METARECORD FAR * giving the enumerated record.
  153.  *  lParam          LPARAM flags passed in EnumMetaFile.
  154.  *
  155.  * Return Value:
  156.  *  int             0 to stop enumeration, 1 to continue.
  157.  */
  158.  
  159. int CALLBACK EXPORT EnumMetafileIconDraw(HDC hDC, HANDLETABLE FAR *phTable
  160.    , METARECORD FAR *pMFR, int cObj, LPARAM lParam)
  161.    {
  162.    LPDRAWINFO lpdi = (LPDRAWINFO)lParam;
  163.  
  164.    /*
  165.     * We play everything blindly except for DIBBITBLT (or DIBSTRETCHBLT)
  166.     * and ESCAPE with MFCOMMENT.  For the BitBlts we change the x,y to
  167.     * draw at (0,0) instead of wherever it was written to draw.  The
  168.     * comment tells us there to stop if we don't want to draw the label.
  169.     */
  170.  
  171.    //If we're playing icon only, stop enumeration at the comment.
  172.    if (lpdi->fIconOnly)
  173.       {
  174.       if (META_ESCAPE==pMFR->rdFunction && MFCOMMENT==pMFR->rdParm[0])
  175.          {
  176.          if (0==lstrcmpi(szIconOnly, (LPSTR)&pMFR->rdParm[2]))
  177.             return 0;
  178.          }
  179.  
  180.       /*
  181.        * Check for the records in which we want to munge the coordinates.
  182.        * destX is offset 6 for BitBlt, offset 9 for StretchBlt, either of
  183.        * which may appear in the metafile.
  184.        */
  185.       if (META_DIBBITBLT==pMFR->rdFunction)
  186.          pMFR->rdParm[6]=0;
  187.  
  188.       if (META_DIBSTRETCHBLT==pMFR->rdFunction)
  189.            pMFR->rdParm[9] = 0;
  190.  
  191.       }
  192.  
  193.  
  194.    PlayMetaFileRecord(hDC, phTable, pMFR, cObj);
  195.    return 1;
  196.    }
  197.  
  198.  
  199.  
  200.  
  201.  
  202. /*
  203.  * OleUIMetafilePictExtractLabel
  204.  *
  205.  * Purpose:
  206.  *  Retrieves the label string from metafile representation of an icon.
  207.  *
  208.  * Parameters:
  209.  *  hMetaPict       HGLOBAL to the METAFILEPICT containing the metafile.
  210.  *  lpszLabel       LPSTR in which to store the label.
  211.  *  cchLabel        UINT length of lpszLabel.
  212.  *  lpWrapIndex     DWORD index of first character in last line. Can be NULL
  213.  *                  if calling function doesn't care about word wrap.
  214.  *
  215.  * Return Value:
  216.  *  UINT            Number of characters copied.
  217.  */
  218. STDAPI_(UINT) OleUIMetafilePictExtractLabel(HGLOBAL hMetaPict, LPOLESTR lpszLabel
  219.                                 , UINT cchLabel, LPDWORD lpWrapIndex)
  220.    {
  221.    LPMETAFILEPICT  pMF;
  222.    LABELEXTRACT    le;
  223.    HDC             hDC;
  224.  
  225.    /*
  226.     * We extract the label by getting a screen DC and walking the metafile
  227.     * records until we see the ExtTextOut record we put there.  That
  228.     * record will have the string embedded in it which we then copy out.
  229.     */
  230.  
  231.    if (NULL==hMetaPict || NULL==lpszLabel || 0==cchLabel)
  232.       return FALSE;
  233.  
  234.    pMF=GlobalLock(hMetaPict);
  235.  
  236.    if (NULL==pMF)
  237.       return FALSE;
  238.  
  239.    le.lpsz=lpszLabel;
  240.    le.u.cch=cchLabel;
  241.    le.Index=0;
  242.    le.fFoundIconOnly=FALSE;
  243.    le.fFoundSource=FALSE;  //Unused for this function.
  244.    le.fFoundIndex=FALSE;   //Unused for this function.
  245.    le.PrevIndex = 0;
  246.  
  247.    //Use a screen DC so we have something valid to pass in.
  248.    hDC=GetDC(NULL);
  249.  
  250.    // Since we've used the EXPORT keyword on the
  251.    // EnumMetafileExtractLabel proc, we do not need to use
  252.    // MakeProcInstance
  253.  
  254.    EnumMetaFile(hDC, pMF->hMF, (MFENUMPROC)EnumMetafileExtractLabel, (LONG)(LPLABELEXTRACT)&le);
  255.  
  256.    ReleaseDC(NULL, hDC);
  257.  
  258.    GlobalUnlock(hMetaPict);
  259.  
  260.    //Tell where we wrapped (if calling function cares)
  261.    if (NULL != lpWrapIndex)
  262.       *lpWrapIndex = le.PrevIndex;
  263.  
  264.    //Return amount of text copied
  265.    return le.u.cch;
  266.    }
  267.  
  268.  
  269.  
  270.  
  271.  
  272. /*
  273.  * EnumMetafileExtractLabel
  274.  *
  275.  * Purpose:
  276.  *  EnumMetaFile callback function that walks a metafile looking for
  277.  *  ExtTextOut, then concatenates the text from each one into a buffer
  278.  *  in lParam.
  279.  *
  280.  * Parameters:
  281.  *  hDC             HDC into which the metafile should be played.
  282.  *  phTable         HANDLETABLE FAR * providing handles selected into the DC.
  283.  *  pMFR            METARECORD FAR * giving the enumerated record.
  284.  *  pLE             LPLABELEXTRACT providing the destination buffer and length.
  285.  *
  286.  * Return Value:
  287.  *  int             0 to stop enumeration, 1 to continue.
  288.  */
  289.  
  290. int CALLBACK EXPORT EnumMetafileExtractLabel(HDC hDC, HANDLETABLE FAR *phTable
  291.    , METARECORD FAR *pMFR, int cObj, LPLABELEXTRACT pLE)
  292.    {
  293.  
  294.    /*
  295.     * We don't allow anything to happen until we see "IconOnly"
  296.     * in an MFCOMMENT that is used to enable everything else.
  297.     */
  298.    if (!pLE->fFoundIconOnly)
  299.       {
  300.       if (META_ESCAPE==pMFR->rdFunction && MFCOMMENT==pMFR->rdParm[0])
  301.          {
  302.          if (0==lstrcmpi(szIconOnly, (LPSTR)&pMFR->rdParm[2]))
  303.             pLE->fFoundIconOnly=TRUE;
  304.          }
  305.  
  306.       return 1;
  307.       }
  308.  
  309.    //Enumerate all records looking for META_EXTTEXTOUT - there can be more
  310.    //than one.
  311.    if (META_EXTTEXTOUT==pMFR->rdFunction)
  312.       {
  313.       UINT        cchMax;
  314.       LPOLESTR    lpszTemp;
  315.  
  316.        /*
  317.        * If ExtTextOut has NULL fuOptions, then the rectangle is omitted
  318.        * from the record, and the string starts at rdParm[4].  If
  319.        * fuOptions is non-NULL, then the string starts at rdParm[8]
  320.        * (since the rectange takes up four WORDs in the array).  In
  321.        * both cases, the string continues for (rdParm[2]+1) >> 1
  322.        * words.  We just cast a pointer to rdParm[8] to an LPSTR and
  323.        * lstrcpyn into the buffer we were given.
  324.        *
  325.        * Note that we use element 8 in rdParm instead of 4 because we
  326.        * passed ETO_CLIPPED in for the options on ExtTextOut--docs say
  327.        * [4] which is rect doesn't exist if we passed zero there.
  328.        *
  329.        */
  330.  
  331.       cchMax=min(pLE->u.cch - pLE->Index, (UINT)pMFR->rdParm[2]);
  332.       lpszTemp = /*(LPOLESTR)*/((/*(LPSTR)*/pLE->lpsz) + pLE->Index);
  333.  
  334.       A2W ((LPSTR)&(pMFR->rdParm[8]), lpszTemp, cchMax);
  335.       lpszTemp[cchMax]='\0';
  336.  
  337.       pLE->u.cch = OLESTRLEN (pLE->lpsz);
  338.       pLE->PrevIndex = pLE->Index;
  339.       pLE->Index += cchMax;
  340.       }
  341.  
  342.    return 1;
  343.    }
  344.  
  345.  
  346.  
  347.  
  348.  
  349. /*
  350.  * OleUIMetafilePictExtractIcon
  351.  *
  352.  * Purpose:
  353.  *  Retrieves the icon from metafile into which DrawIcon was done before.
  354.  *
  355.  * Parameters:
  356.  *  hMetaPict       HGLOBAL to the METAFILEPICT containing the metafile.
  357.  *
  358.  * Return Value:
  359.  *  HICON           Icon recreated from the data in the metafile.
  360.  */
  361. STDAPI_(HICON) OleUIMetafilePictExtractIcon(HGLOBAL hMetaPict)
  362.    {
  363.    LPMETAFILEPICT  pMF;
  364.    HDC             hDC;
  365.    ICONEXTRACT     ie;
  366.  
  367.    /*
  368.     * We extract the label by getting a screen DC and walking the metafile
  369.     * records until we see the ExtTextOut record we put there.  That
  370.     * record will have the string embedded in it which we then copy out.
  371.     */
  372.  
  373.    if (NULL==hMetaPict)
  374.       return NULL;
  375.  
  376.    pMF=GlobalLock(hMetaPict);
  377.  
  378.    if (NULL==pMF)
  379.       return FALSE;
  380.  
  381.    //Use a screen DC so we have something valid to pass in.
  382.    hDC=GetDC(NULL);
  383.    ie.fAND=TRUE;
  384.  
  385.    // We get information back in the ICONEXTRACT structure.
  386.    // (Since we've used the EXPORT keyword on the
  387.    // EnumMetafileExtractLabel proc, we do not need to use
  388.    // MakeProcInstance)
  389.    EnumMetaFile(hDC, pMF->hMF, (MFENUMPROC)EnumMetafileExtractIcon, (LONG)(LPICONEXTRACT)&ie);
  390.  
  391.    ReleaseDC(NULL, hDC);
  392.    GlobalUnlock(hMetaPict);
  393.  
  394.    return ie.hIcon;
  395.    }
  396.  
  397.  
  398.  
  399.  
  400.  
  401. /*
  402.  * EnumMetafileExtractIcon
  403.  *
  404.  * Purpose:
  405.  *  EnumMetaFile callback function that walks a metafile looking for
  406.  *  StretchBlt (3.1) and BitBlt (3.0) records.  We expect to see two
  407.  *  of them, the first being the AND mask and the second being the XOR
  408.  *  data.  We
  409.  *  ExtTextOut, then copies the text into a buffer in lParam.
  410.  *
  411.  * Parameters:
  412.  *  hDC             HDC into which the metafile should be played.
  413.  *  phTable         HANDLETABLE FAR * providing handles selected into the DC.
  414.  *  pMFR            METARECORD FAR * giving the enumerated record.
  415.  *  pIE             LPICONEXTRACT providing the destination buffer and length.
  416.  *
  417.  * Return Value:
  418.  *  int             0 to stop enumeration, 1 to continue.
  419.  */
  420.  
  421. int CALLBACK EXPORT EnumMetafileExtractIcon(HDC hDC, HANDLETABLE FAR *phTable
  422.    , METARECORD FAR *pMFR, int cObj, LPICONEXTRACT pIE)
  423.    {
  424.    LPBITMAPINFO        lpBI;
  425.    LPBITMAPINFOHEADER  lpBH;
  426.    LPBYTE              lpbSrc;
  427.    LPBYTE              lpbDst;
  428.    UINT                uWidth, uHeight;
  429.    DWORD               cb;
  430.    HGLOBAL             hMem;
  431.    BITMAP              bm;
  432.    HBITMAP             hBmp;
  433.    int                 cxIcon, cyIcon;
  434.  
  435.  
  436.    //Continue enumeration if we don't see the records we want.
  437.    if (META_DIBBITBLT!=pMFR->rdFunction && META_DIBSTRETCHBLT!=pMFR->rdFunction)
  438.       return 1;
  439.  
  440.    /*
  441.     * Windows 3.0 DrawIcon uses META_DIBBITBLT in whereas 3.1 uses
  442.     * META_DIBSTRETCHBLT so we have to handle each case separately.
  443.     */
  444.  
  445.    if (META_DIBBITBLT==pMFR->rdFunction)       //Win3.0
  446.       {
  447.       //Get dimensions and the BITMAPINFO struct.
  448.       uHeight=pMFR->rdParm[1];
  449.       uWidth =pMFR->rdParm[2];
  450.       lpBI=(LPBITMAPINFO)&(pMFR->rdParm[8]);
  451.       }
  452.  
  453.    if (META_DIBSTRETCHBLT==pMFR->rdFunction)   //Win3.1
  454.       {
  455.       //Get dimensions and the BITMAPINFO struct.
  456.       uHeight=pMFR->rdParm[2];
  457.       uWidth =pMFR->rdParm[3];
  458.       lpBI=(LPBITMAPINFO)&(pMFR->rdParm[10]);
  459.       }
  460.  
  461.    lpBH=(LPBITMAPINFOHEADER)&(lpBI->bmiHeader);
  462.  
  463.    //Pointer to the bits which follows the BITMAPINFO structure.
  464.    lpbSrc=(LPBYTE)lpBI+lpBH->biSize;
  465.  
  466.    //Add the length of the color table.
  467.    if (0!=lpBH->biClrUsed)
  468.       lpbSrc+=(DWORD)(lpBH->biClrUsed*sizeof(RGBQUAD));
  469.    else
  470.       {
  471.       /*
  472.        * 1 << bc gives 2, 16, 256 for 1, 4, or 8 bits.  24-bit
  473.        * bitmaps have no color table, so there's no need to
  474.        * change lpbSrc.
  475.        */
  476.       if (lpBH->biBitCount <= 8)
  477.           lpbSrc+=(DWORD)((1 << (lpBH->biBitCount))*sizeof(RGBQUAD));
  478.       }
  479.  
  480.  
  481.    /*
  482.     * All the bits we have in lpbSrc are device-independent, so we
  483.     * need to change them over to be device-dependent using SetDIBits.
  484.     * Once we have a bitmap with the device-dependent bits, we can
  485.     * GetBitmapBits to have buffers with the real data.
  486.     *
  487.     * For each pass we have to allocate memory for the bits.  We save
  488.     * the memory for the mask between passes.
  489.     */
  490.  
  491.    //Use CreateBitmap for ANY monochrome bitmaps
  492.    if (pIE->fAND || 1==lpBH->biBitCount || lpBH->biBitCount > 8)
  493.       hBmp=CreateBitmap((UINT)lpBH->biWidth, (UINT)lpBH->biHeight, 1, 1, NULL);
  494.    else if (lpBH->biBitCount <= 8)
  495.       hBmp=CreateCompatibleBitmap(hDC, (UINT)lpBH->biWidth, (UINT)lpBH->biHeight);
  496.  
  497.    if (!hBmp || !SetDIBits(hDC, hBmp, 0, (UINT)lpBH->biHeight, (LPVOID)lpbSrc, lpBI, DIB_RGB_COLORS))
  498.       {
  499.       if (!pIE->fAND)
  500.          GlobalFree(pIE->hMemAND);
  501.  
  502.       DeleteObject(hBmp);
  503.       return 0;
  504.       }
  505.  
  506.    //Allocate memory and get the DDBits into it.
  507.    GetObject(hBmp, sizeof(bm), &bm);
  508.  
  509.    cb=bm.bmHeight*bm.bmWidthBytes * bm.bmPlanes;
  510.  
  511. //    if (cb % 4 != 0)        // dword align
  512. //      cb += 4 - (cb % 4);
  513.  
  514.    hMem=GlobalAlloc(GHND, cb);
  515.  
  516.    if (NULL==hMem)
  517.       {
  518.       if (NULL!=pIE->hMemAND)
  519.          GlobalFree(pIE->hMemAND);
  520.  
  521.       DeleteObject(hBmp);
  522.       return 0;
  523.       }
  524.  
  525.    lpbDst=(LPBYTE)GlobalLock(hMem);
  526.    GetBitmapBits(hBmp, cb, (LPVOID)lpbDst);
  527.  
  528.    DeleteObject(hBmp);
  529.    GlobalUnlock(hMem);
  530.  
  531.  
  532.    /*
  533.     * If this is the first pass (pIE->fAND==TRUE) then save the memory
  534.     * of the AND bits for the next pass.
  535.     */
  536.    if (pIE->fAND)
  537.       {
  538.       pIE->fAND=FALSE;
  539.       pIE->hMemAND=hMem;
  540.  
  541.       //Continue enumeration looking for the next blt record.
  542.       return 1;
  543.       }
  544.    else
  545.       {
  546.       //Get the AND pointer again.
  547.       lpbSrc=(LPBYTE)GlobalLock(pIE->hMemAND);
  548.  
  549.       /*
  550.        * Create the icon now that we have all the data.  lpbDst already
  551.        * points to the XOR bits.
  552.        */
  553.       cxIcon = GetSystemMetrics(SM_CXICON);
  554.       cyIcon = GetSystemMetrics(SM_CYICON);
  555.  
  556.       pIE->hIcon=CreateIcon(ghInst,
  557.                        uWidth,
  558.                        uHeight,
  559.                        (BYTE)bm.bmPlanes,
  560.                        (BYTE)bm.bmBitsPixel,
  561.                        (LPVOID)lpbSrc,
  562.                        (LPVOID)lpbDst);
  563.  
  564.       GlobalUnlock(pIE->hMemAND);
  565.       GlobalFree(pIE->hMemAND);
  566.       GlobalFree(hMem);
  567.  
  568.       //We're done so we can stop.
  569.       return 0;
  570.       }
  571.    }
  572.  
  573.  
  574.  
  575.  
  576.  
  577. /*
  578.  * OleUIMetafilePictExtractIconSource
  579.  *
  580.  * Purpose:
  581.  *  Retrieves the filename and index of the icon source from a metafile
  582.  *  created with OleUIMetafilePictFromIconAndLabel.
  583.  *
  584.  * Parameters:
  585.  *  hMetaPict       HGLOBAL to the METAFILEPICT containing the metafile.
  586.  *  lpszSource      LPSTR in which to store the source filename.  This
  587.  *                  buffer should be OLEUI_CCHPATHMAX characters.
  588.  *  piIcon          UINT FAR * in which to store the icon's index
  589.  *                  within lpszSource
  590.  *
  591.  * Return Value:
  592.  *  BOOL            TRUE if the records were found, FALSE otherwise.
  593.  */
  594. STDAPI_(BOOL) OleUIMetafilePictExtractIconSource(HGLOBAL hMetaPict
  595.    , LPOLESTR lpszSource, UINT FAR *piIcon)
  596.    {
  597.    LPMETAFILEPICT  pMF;
  598.    LABELEXTRACT    le;
  599.    HDC             hDC;
  600.  
  601.    /*
  602.     * We will walk the metafile looking for the two comment records
  603.     * following the IconOnly comment.  The flags fFoundIconOnly and
  604.     * fFoundSource indicate if we have found IconOnly and if we have
  605.     * found the source comment already.
  606.     */
  607.  
  608.    if (NULL==hMetaPict || NULL==lpszSource || NULL==piIcon)
  609.       return FALSE;
  610.  
  611.    pMF=GlobalLock(hMetaPict);
  612.  
  613.    if (NULL==pMF)
  614.       return FALSE;
  615.  
  616.    le.lpsz=lpszSource;
  617.    le.fFoundIconOnly=FALSE;
  618.    le.fFoundSource=FALSE;
  619.    le.fFoundIndex=FALSE;
  620.  
  621.    //Use a screen DC so we have something valid to pass in.
  622.    hDC=GetDC(NULL);
  623.  
  624.    EnumMetaFile(hDC, pMF->hMF, (MFENUMPROC)EnumMetafileExtractIconSource, (LONG)(LPLABELEXTRACT)&le);
  625.  
  626.    ReleaseDC(NULL, hDC);
  627.    GlobalUnlock(hMetaPict);
  628.  
  629.    //Copy the icon index to the caller's variable.
  630.    *piIcon=le.u.iIcon;
  631.  
  632.    //Check that we found everything.
  633.    return (le.fFoundIconOnly && le.fFoundSource && le.fFoundIndex);
  634.    }
  635.  
  636.  
  637. /*
  638.  * EnumMetafileExtractIconSource
  639.  *
  640.  * Purpose:
  641.  *  EnumMetaFile callback function that walks a metafile skipping the first
  642.  *  comment record, extracting the source filename from the second, and
  643.  *  the index of the icon in the third.
  644.  *
  645.  * Parameters:
  646.  *  hDC             HDC into which the metafile should be played.
  647.  *  phTable         HANDLETABLE FAR * providing handles selected into the DC.
  648.  *  pMFR            METARECORD FAR * giving the enumerated record.
  649.  *  pLE             LPLABELEXTRACT providing the destination buffer and
  650.  *                  area to store the icon index.
  651.  *
  652.  * Return Value:
  653.  *  int             0 to stop enumeration, 1 to continue.
  654.  */
  655. int CALLBACK EXPORT EnumMetafileExtractIconSource(HDC hDC, HANDLETABLE FAR *phTable
  656.    , METARECORD FAR *pMFR, int cObj, LPLABELEXTRACT pLE)
  657.    {
  658.    LPSTR       psz;
  659.  
  660.    /*
  661.     * We don't allow anything to happen until we see "IconOnly"
  662.     * in an MFCOMMENT that is used to enable everything else.
  663.     */
  664.    if (!pLE->fFoundIconOnly)
  665.       {
  666.       if (META_ESCAPE==pMFR->rdFunction && MFCOMMENT==pMFR->rdParm[0])
  667.          {
  668.          if (0==lstrcmpi(szIconOnly, (LPSTR)&pMFR->rdParm[2]))
  669.             pLE->fFoundIconOnly=TRUE;
  670.          }
  671.  
  672.       return 1;
  673.       }
  674.  
  675.    //Now see if we find the source string.
  676.    if (!pLE->fFoundSource)
  677.       {
  678.       if (META_ESCAPE==pMFR->rdFunction && MFCOMMENT==pMFR->rdParm[0])
  679.          {
  680.          A2W  ((LPSTR)&pMFR->rdParm[2], pLE->lpsz, OLEUI_CCHPATHMAX);
  681.          pLE->lpsz[OLEUI_CCHPATHMAX-1] = '\0';
  682.          pLE->fFoundSource=TRUE;
  683.          }
  684.  
  685.       return 1;
  686.       }
  687.  
  688.    //Next comment will be the icon index.
  689.    if (META_ESCAPE==pMFR->rdFunction && MFCOMMENT==pMFR->rdParm[0])
  690.       {
  691.       /*
  692.        * This string contains the icon index in string form,
  693.        * so we need to convert back to a UINT.  After we see this
  694.        * we can stop the enumeration.  The comment will have
  695.        * a null terminator because we made sure to save it.
  696.        */
  697.       psz=(LPSTR)&pMFR->rdParm[2];
  698.       pLE->u.iIcon=0;
  699.  
  700.       //Do Ye Olde atoi
  701.       while (*psz)
  702.          pLE->u.iIcon=(10*pLE->u.iIcon)+((*psz++)-'0');
  703.  
  704.       pLE->fFoundIndex=TRUE;
  705.       return 0;
  706.       }
  707.  
  708.    return 1;
  709.    }
  710.