PAINT.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:18k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /******************************************************************************
  2. *       This is a part of the Microsoft Source Code Samples. 
  3. *       Copyright (C) 1993-1997 Microsoft Corporation.
  4. *       All rights reserved. 
  5. *       This source code is only intended as a supplement to 
  6. *       Microsoft Development Tools and/or WinHelp documentation.
  7. *       See these sources for detailed information regarding the 
  8. *       Microsoft samples programs.
  9. ******************************************************************************/
  10. /******************************************************************************
  11. *
  12. *  MODULE:      PAINT.C
  13. *
  14. *  PURPOSE:     Given an HDC and a pointer to a bounding rectangle
  15. *               draw all graphics/fonts based on the flags set in
  16. *               the dwGraphicsOptions global variable.
  17. *
  18. *  FUNTIONS:    Paint              - main painting routine
  19. *               GetFirstGraphicSlot- computes bounding rect of 1st
  20. *                                      graphic
  21. *               GetNextGraphicSlot - computes bounding rect of next
  22. *                                      graphic
  23. *               DrawFonts          - draws enumerated fonts
  24. *               BuildFontList      - builds a list of fonts of fonts
  25. *                                      supported by a given DC
  26. *               MyEnumFaces        - enumerates the font facenames
  27. *                                      supported by a given DC
  28. *               MyEnumCopy         - copies LOGFONT & TEXTMETRIC info
  29. *                                      to a global variable
  30. *               MyEnumCount        - counts total number of fonts
  31. *                                      supported by a given DC
  32. *               FreeFontList       - frees a (BuildFontList-) font list
  33. *
  34. *  COMMENTS:    Most of the font-enumeration code "lifted" from NTF.EXE
  35. *               sample. For more complete documentation have a look a
  36. *               that.
  37. *
  38. ******************************************************************************/
  39. #include <windows.h>
  40. #include <string.h>
  41. #include "common.h"
  42. #include "paint.h"
  43. /******************************************************************************
  44. *
  45. *  FUNCTION:    Paint
  46. *
  47. *  INPUTS:      hdc    - device context to paint
  48. *               lpRect - bounding rectangle of device to paint
  49. *
  50. *  RETURNS:     TRUE if painting went ok, or
  51. *               FALSE if error while painting
  52. *
  53. ******************************************************************************/
  54. BOOL Paint (HDC hdc, LPRECT lpRect)
  55. {
  56.   RECT  rect;
  57.   HPEN  hpenSave;
  58.   RECTI ri;
  59.   if (gdwGraphicsOptions & DRAWAXIS)
  60.   {
  61.     //
  62.     // draw axis
  63.     //
  64.     rect = *lpRect;
  65.     hpenSave = SelectObject (hdc, GetStockObject (BLACK_PEN));
  66.     //
  67.     // if giMapMode == MM_TEXT, MM_ANISOTROPIC then (0,0) is upper left corner
  68.     //
  69.     if (giMapMode == MM_TEXT || giMapMode == MM_ANISOTROPIC)
  70.     {
  71.       MoveToEx (hdc, rect.left - glcyMenu/2, rect.bottom, NULL);
  72.       LineTo   (hdc, rect.left,  rect.bottom + glcyMenu/2);
  73.       LineTo   (hdc, rect.left + glcyMenu/2,  rect.bottom);
  74.       MoveToEx (hdc, rect.left,  rect.bottom + glcyMenu/2, NULL);
  75.       LineTo   (hdc, rect.left,  rect.top);
  76.       LineTo   (hdc, rect.right + glcyMenu/2, rect.top);
  77.       MoveToEx (hdc, rect.right, rect.top - glcyMenu/2, NULL);
  78.       LineTo   (hdc, rect.right + glcyMenu/2,  rect.top);
  79.       LineTo   (hdc, rect.right,  rect.top + glcyMenu/2);
  80.     }
  81.     //
  82.     // else (0,0) is lower left corner
  83.     //
  84.     else
  85.     {
  86.       MoveToEx (hdc, rect.left - glcyMenu/2, rect.bottom, NULL);
  87.       LineTo   (hdc, rect.left,  rect.bottom + glcyMenu/2);
  88.       LineTo   (hdc, rect.left + glcyMenu/2,  rect.bottom);
  89.       MoveToEx (hdc, rect.left,  rect.bottom + glcyMenu/2, NULL);
  90.       LineTo   (hdc, rect.left,  rect.top);
  91.       LineTo   (hdc, rect.right + glcyMenu/2, rect.top);
  92.       MoveToEx (hdc, rect.right, rect.top + glcyMenu/2, NULL);
  93.       LineTo   (hdc, rect.right + glcyMenu/2, rect.top);
  94.       LineTo   (hdc, rect.right, rect.top - glcyMenu/2);
  95.     }
  96.   }
  97.   SelectObject (hdc, hpenSave);
  98.   //
  99.   // look at bits in gdwGraphicsOptions & determine which graphics to draw
  100.   //
  101.   if (gdwGraphicsOptions & ENUMFONTS)
  102.   {
  103.     DrawFonts (hdc, lpRect);
  104.     return TRUE;
  105.   }
  106.   giDeltaX = (int) ((lpRect->right - BORDER) / NUM_GRAPHICS_XSLOTS);
  107.   giDeltaY = (int) ((lpRect->bottom - lpRect->top - BORDER)
  108.                                              / NUM_GRAPHICS_YSLOTS);
  109.   GetFirstGraphicSlot (lpRect, &ri);
  110.   if (gdwGraphicsOptions & ARC)
  111.   {
  112.     Arc (hdc, ri.left, ri.top, ri.right, ri.bottom,
  113.               ri.left, ri.top, ri.right-10, ri.bottom-10);
  114.     GetNextGraphicSlot (&ri);
  115.   }
  116.   if (gdwGraphicsOptions & ELLIPSE)
  117.   {
  118.     Ellipse (hdc, ri.left, ri.top, ri.right, ri.bottom);
  119.     GetNextGraphicSlot (&ri);
  120.   }
  121.   if (gdwGraphicsOptions & LINETO)
  122.   {
  123.     int i;
  124.     for (i = PS_SOLID; i <= PS_DASHDOTDOT; i++)
  125.     {
  126.       MoveToEx (hdc, ri.left, ri.top + (i+1)*giDeltaY/7, NULL);
  127.       LineTo   (hdc, ri.right, ri.top + (i+1)*giDeltaY/7);
  128.     }
  129.     GetNextGraphicSlot (&ri);
  130.   }
  131.   if (gdwGraphicsOptions & PIE)
  132.   {
  133.     Pie (hdc, ri.left, ri.top, ri.right, ri.bottom,
  134.               ri.left, ri.top, ri.right-10, ri.bottom-10);
  135.     GetNextGraphicSlot (&ri);
  136.   }
  137.   if (gdwGraphicsOptions & PLG_BLT)
  138.   {
  139.     HBITMAP hbm;
  140.     BITMAP  bm;
  141.     HDC     hdcMem;
  142.     POINT   ap[3];
  143.     hbm = LoadBitmap (ghInst, "printer");
  144.     hdcMem = CreateCompatibleDC (hdc);
  145.     SelectObject (hdcMem, hbm);
  146.     GetObject (hbm, sizeof(BITMAP), (LPSTR)&bm);
  147.     //
  148.     // special case here because PlgBlt requires coordinates
  149.     //   of upper left, upper right, & lower left
  150.     //
  151.     ap[0].x = (LONG) (ri.left + (ri.right - ri.left)/4);
  152.     ap[0].y = (LONG) (ri.top + (ri.bottom - ri.top)/4);
  153.     ap[1].x = (LONG) ri.right;
  154.     ap[1].y = (LONG) ri.top;
  155.     ap[2].x = (LONG) ri.left;
  156.     ap[2].y = (LONG) ri.bottom;
  157.     PlgBlt (hdc, ap, hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, NULL, 0, 0);
  158.     DeleteDC(hdcMem);
  159.     GetNextGraphicSlot (&ri);
  160.   }
  161.   if (gdwGraphicsOptions & POLYBEZIER)
  162.   {
  163.     POINT ap[4];
  164.     ap[0].x  = (LONG) ri.left;    ap[0].y = (LONG) ri.top;
  165.     ap[1].x  = (LONG) ri.left;    ap[1].y = (LONG) ri.bottom;
  166.     ap[2].x  = (LONG) ri.right;   ap[2].y = (LONG) ri.top;
  167.     ap[3].x  = (LONG) ri.right;   ap[3].y = (LONG) ri.bottom;
  168.     PolyBezier (hdc, ap, 4);
  169.     GetNextGraphicSlot (&ri);
  170.   }
  171.   if (gdwGraphicsOptions & POLYGON)
  172.   {
  173.     POINT ap[5];
  174.     ap[0].x  = (LONG) ri.left;    ap[0].y = (LONG) ri.top;
  175.     ap[1].x  = (LONG) ri.right;   ap[1].y = (LONG) ri.bottom;
  176.     ap[2].x  = (LONG) ri.right;   ap[2].y = (LONG) ri.top;
  177.     ap[3].x  = (LONG) ri.left;    ap[3].y = (LONG) ri.bottom;
  178.     ap[4].x  = (LONG) ri.left;    ap[4].y = (LONG) ri.top;
  179.     Polygon (hdc, ap, 4);
  180.     GetNextGraphicSlot (&ri);
  181.   }
  182.   if (gdwGraphicsOptions & POLYLINE)
  183.   {
  184.     POINT ap[4];
  185.     ap[0].x  = (LONG) ri.left;    ap[0].y = (LONG) ri.top;
  186.     ap[1].x  = (LONG) ri.left;    ap[1].y = (LONG) ri.bottom;
  187.     ap[2].x  = (LONG) ri.right;   ap[2].y = (LONG) ri.top;
  188.     ap[3].x  = (LONG) ri.right;   ap[3].y = (LONG) ri.bottom;
  189.     Polyline (hdc, ap, 4);
  190.     GetNextGraphicSlot (&ri);
  191.   }
  192.   if (gdwGraphicsOptions & POLYPOLYGON)
  193.   {
  194.     POINT ap[8];
  195.     int ai[2] = { 4, 4 };
  196.     ap[0].x = (LONG)  ri.left;
  197.     ap[0].y = (LONG)  ri.top;
  198.     ap[1].x = (LONG) (ri.left + giDeltaX/4);
  199.     ap[1].y = (LONG)  ri.top;
  200.     ap[2].x = (LONG) (ri.left + giDeltaX/4);
  201.     ap[2].y = (LONG) (ri.top  + giDeltaY/4);
  202.     ap[3].x = (LONG)  ri.left;
  203.     ap[3].y = (LONG) (ri.top  + giDeltaY/4);
  204.     ap[4].x = (LONG) (ri.right  - 2*giDeltaX/3);
  205.     ap[4].y = (LONG) (ri.bottom - 2*giDeltaY/3);
  206.     ap[5].x = (LONG)  ri.right;
  207.     ap[5].y = (LONG) (ri.bottom - 2*giDeltaY/3);
  208.     ap[6].x = (LONG)  ri.right;
  209.     ap[6].y = (LONG)  ri.bottom;
  210.     ap[7].x = (LONG) (ri.right  - 2*giDeltaX/3);
  211.     ap[7].y = (LONG)  ri.bottom;
  212.     PolyPolygon (hdc, ap, ai, 2);
  213.     GetNextGraphicSlot (&ri);
  214.   }
  215.   if (gdwGraphicsOptions & RECTANGLE)
  216.   {
  217.     Rectangle (hdc, ri.left, ri.top, ri.right, ri.bottom);
  218.     GetNextGraphicSlot (&ri);
  219.   }
  220.   if (gdwGraphicsOptions & ROUNDRECT)
  221.   {
  222.     RoundRect (hdc, ri.left, ri.top, ri.right, ri.bottom, 15, 25);
  223.     GetNextGraphicSlot (&ri);
  224.   }
  225.   if (gdwGraphicsOptions & STRETCH_BLT)
  226.   {
  227.     HBITMAP hbm;
  228.     BITMAP  bm;
  229.     HDC     hdcMem;
  230.     hbm = LoadBitmap (ghInst, "printer");
  231.     hdcMem = CreateCompatibleDC (hdc);
  232.     SelectObject (hdcMem, hbm);
  233.     GetObject (hbm, sizeof(BITMAP), (LPSTR)&bm);
  234.     StretchBlt (hdc, ri.left, ri.top, ri.right-ri.left,
  235.                 ri.bottom - ri.top, hdcMem, 0, 0,
  236.                 bm.bmWidth, bm.bmHeight, SRCCOPY);
  237.     DeleteDC(hdcMem);
  238.     GetNextGraphicSlot (&ri);
  239.   }
  240.   return TRUE;
  241. }
  242. /******************************************************************************
  243. *
  244. *  FUNCTION:    GetFirstGraphicSlot
  245. *
  246. *  INPUTS:      pri - pointer to a RECTI
  247. *
  248. ******************************************************************************/
  249. void GetFirstGraphicSlot (LPRECT lpRect, PRECTI pri)
  250. {
  251.   pri->left   = BORDER;
  252.   pri->top    = lpRect->top + BORDER;
  253.   pri->right  = giDeltaX;
  254.   pri->bottom = giDeltaY;
  255.   giColumn = 1;
  256. }
  257. /******************************************************************************
  258. *
  259. *  FUNCTION:    GetNextGraphicSlot
  260. *
  261. *  INPUTS:      pri - pointer to a RECTI
  262. *
  263. ******************************************************************************/
  264. void GetNextGraphicSlot (PRECTI pri)
  265. {
  266.   if (++giColumn <= NUM_GRAPHICS_XSLOTS)
  267.   {
  268.     pri->left  += giDeltaX;
  269.     pri->right += giDeltaX;
  270.   }
  271.   else
  272.   {
  273.     giColumn = 1;
  274.     pri->left   =  BORDER;
  275.     pri->top    += giDeltaY;
  276.     pri->right  =  giDeltaX;
  277.     pri->bottom += giDeltaY;
  278.   }
  279. }
  280. /******************************************************************************
  281. *
  282. *  FUNCTION:    DrawFonts
  283. *
  284. *  INPUTS:      hdc   - device context to enumerate from & draw on
  285. *               pRect - pointer to bounding rect to draw fonts in
  286. *
  287. *  LOCAL VARS:  i, j       - loop variables
  288. *               xText      - starting x position to draw text
  289. *               yText      - starting y position to draw text
  290. *               iMaxStrLen - length in pels of string to draw
  291. *
  292. ******************************************************************************/
  293. void DrawFonts (HDC hdc, LPRECT lpRect)
  294. {
  295.   int      i, j, xText, yText, iMaxStrLen = 0;
  296.   PARFONTS paf;
  297.   paf = BuildFontList (hdc);
  298.   xText = yText = 2;
  299.   //
  300.   // set the appropriate text align mode depending on
  301.   //   whether we're drawing from top down or bottom up
  302.   //
  303.   if (giMapMode == MM_TEXT | giMapMode == MM_ANISOTROPIC)
  304.     SetTextAlign (hdc, TA_TOP);
  305.   else
  306.     SetTextAlign (hdc, TA_BOTTOM);
  307.   for (i = 0; i < nFaces; i++)
  308.   {
  309.     for (j = 0; j < (paf + i)->nFonts; j++)
  310.     {
  311.       HFONT      hFont, hSaveFont;
  312.       SIZE       size;
  313.       POINT      LogPtExtent;
  314.       LogPtExtent.x = lpRect->right;
  315.       LogPtExtent.y = lpRect->bottom;
  316.       hFont = CreateFontIndirect ((paf + i)->lf + j);
  317.       hSaveFont = SelectObject (hdc, hFont);
  318.       TextOut (hdc, xText, yText, ((paf + i)->lf + j)->lfFaceName,
  319.                strlen(((paf + i)->lf + j)->lfFaceName));
  320.       GetTextExtentPoint (hdc, ((paf + i)->lf + j)->lfFaceName,
  321.                           strlen(((paf+i)->lf+j)->lfFaceName),
  322.                           &size);
  323.       size.cx += 2;
  324.       iMaxStrLen = iMaxStrLen > (int)size.cx ? iMaxStrLen: (int) size.cx;
  325.       if (!(i == (nFaces - 1) && j == ((paf + i)->nFonts - 1)))
  326.       {
  327.         TEXTMETRIC *pNextTM;
  328.         pNextTM = j < ((paf+i)->nFonts-1) ?
  329.                           (paf+i)->tm+j+1 : (paf+i+1)->tm;
  330.         //
  331.         // add in the height of the face name we just drew
  332.         //
  333.         yText += (int) ((paf + i)->tm + j)->tmHeight;
  334.         //
  335.         // if the next facename will be drawn outside the bounding rect then
  336.         //   start at first line of next column
  337.         //
  338.         if (yText + (int) pNextTM->tmHeight > (int) LogPtExtent.y)
  339.         {
  340.           yText = 2;
  341.           xText += iMaxStrLen + 2;
  342.           iMaxStrLen = 0;
  343.         }
  344.       }
  345.       SelectObject (hdc, hSaveFont);
  346.       DeleteObject (hFont);
  347.       if (xText > (int) LogPtExtent.x)
  348.       {
  349.         if (GetDeviceCaps (hdc, TECHNOLOGY) & DT_RASDISPLAY)
  350.         {
  351.           //
  352.           // If we're drawing to the screen & have run out of
  353.           //   room then tell user how many fonts there are left
  354.           //   (that we haven't displayed)
  355.           //
  356.           int   k;
  357.           int   iFontsLeft = (paf + i)->nFonts - j - 1;
  358.           char  buf[40];
  359.           SIZE  size;
  360.           for (k = i + 1; k < nFaces; k++)
  361.             iFontsLeft += (paf + k)->nFonts;
  362.           wsprintf (buf, GetStringRes(IDS_FMT_MOREDSPFNTNL),
  363.                     iFontsLeft);
  364.           GetTextExtentPoint (hdc, buf, strlen(buf), &size);
  365.           if ((xText = lpRect->right - size.cx) < glcyMenu + 1)
  366.             xText = glcyMenu/2 + 1;
  367.           TextOut (hdc, xText, lpRect->bottom, buf, strlen(buf));
  368.           goto done_enumfonts;
  369.         }
  370.         else
  371.         {
  372.           //
  373.           // Else we're drawing to a printer & have filled up
  374.           //   the first page. If there's any fonts left to draw
  375.           //   then start a new page.
  376.           //
  377.           if (!(i == nFaces - 1 && j == (paf + i)->nFonts - 1))
  378.           {
  379.             EndPage   (hdc);
  380.             xText = yText = 2;
  381.             StartPage (hdc);
  382.           }
  383.         }
  384.       }
  385.     }
  386.   }
  387. done_enumfonts:
  388.   FreeFontList (paf);
  389. }
  390. /*  In the callback functions for the enumerations, there is a limited
  391.  *  ability to pass in parameters.  For that reason, declare the following
  392.  *  global variables to be used by any of the call back functions.
  393.  *
  394.  *        HDC      hdcGlobal;
  395.  *        PARFONTS parFontsGlobal;
  396.  *        int      iFace,jFont;
  397.  *        int      nFaces;
  398.  *
  399.  *
  400.  * General call structure:
  401.  *
  402.  *        BuildFontList
  403.  *            EnumFonts
  404.  *                MyEnumCount
  405.  *            LocalAlloc
  406.  *            EnumFonts
  407.  *                MyEnumFaces
  408.  *                    EnumFonts
  409.  *                        MyEnumCount
  410.  *                    LocalAlloc
  411.  *                    LocalAlloc
  412.  *                    LocalAlloc
  413.  *                    EnumFonts
  414.  *                        MyEnumCopy
  415.  */
  416. /******************************************************************************
  417. *
  418. *  FUNCTION:    BuildFontList
  419. *
  420. *  GLOBAL VARS: (see above)
  421. *
  422. ******************************************************************************/
  423. PARFONTS BuildFontList (HDC hdcIn)
  424. {
  425.   nFaces = 0;
  426.   hdcGlobal = hdcIn;
  427.   //
  428.   // count the total number of face names.
  429.   //
  430.   EnumFonts (hdcGlobal, NULL, (FONTENUMPROC)MyEnumCount, (LPARAM)&nFaces);
  431.   //
  432.   // allocate the pointer to the array of PArFont structures.
  433.   //
  434.   parFontsGlobal = (PARFONTS) LocalAlloc (LPTR, sizeof(ARFONTS) * (nFaces+1));
  435.   //
  436.   // step through all fonts again.  For each one fill a LOGFONT and
  437.   //   a TEXTMETRIC stucture.
  438.   //
  439.   iFace = 0;
  440.   EnumFonts (hdcGlobal, NULL, (FONTENUMPROC)MyEnumFaces, 0);
  441.   return parFontsGlobal;
  442. }
  443. /******************************************************************************
  444. *
  445. *  FUNCTION:    MyEnumFaces
  446. *
  447. *  GLOBAL VARS: (see above)
  448. *
  449. ******************************************************************************/
  450. int CALLBACK MyEnumFaces (LPLOGFONT lpLogFont, LPTEXTMETRIC lpTEXTMETRICs,
  451.                           DWORD fFontType, LPVOID  lpData)
  452. {
  453.   int nFonts;
  454.   nFonts = 0;
  455.   EnumFonts (hdcGlobal, lpLogFont->lfFaceName, (FONTENUMPROC)MyEnumCount,
  456.              (LPARAM)&nFonts);
  457.   parFontsGlobal[iFace].lf   = (LOGFONT *)    LocalAlloc (LPTR,
  458.                                                           sizeof(LOGFONT) *
  459.                                                             nFonts);
  460.   parFontsGlobal[iFace].tm   = (TEXTMETRIC *) LocalAlloc (LPTR,
  461.                                                           sizeof(TEXTMETRIC) *
  462.                                                             nFonts);
  463.   parFontsGlobal[iFace].Type = (int *)        LocalAlloc (LPTR,
  464.                                                           sizeof(int) *
  465.                                                             nFonts);
  466.   if ((parFontsGlobal[iFace].lf   == NULL) ||
  467.       (parFontsGlobal[iFace].tm   == NULL) ||
  468.       (parFontsGlobal[iFace].Type == NULL))
  469.   {
  470.     ErrMsgBox (GetStringRes(IDS_LALLOCFAIL), ERR_MOD_NAME);
  471.     return FALSE;
  472.   }
  473.   parFontsGlobal[iFace].nFonts = nFonts;
  474.   jFont = 0;
  475.   EnumFonts (hdcGlobal, lpLogFont->lfFaceName, (FONTENUMPROC)MyEnumCopy, 0);
  476.   iFace++;
  477.   return TRUE;
  478. }
  479. /******************************************************************************
  480. *
  481. *  FUNCTION:    MyEnumCopy
  482. *
  483. *  GLOBAL VARS: (see above)
  484. *
  485. ******************************************************************************/
  486. int CALLBACK MyEnumCopy (LPLOGFONT lpLogFont, LPTEXTMETRIC lpTEXTMETRICs,
  487.                          DWORD fFontType, LPVOID  lpData)
  488. {
  489.   LOGFONT    *lplf;
  490.   TEXTMETRIC *lptm;
  491.   int        *pType;
  492.   lplf  = parFontsGlobal[iFace].lf;
  493.   lptm  = parFontsGlobal[iFace].tm;
  494.   pType = parFontsGlobal[iFace].Type;
  495.   lplf[jFont]  = *lpLogFont;
  496.   lptm[jFont]  = *lpTEXTMETRICs;
  497.   pType[jFont] = fFontType;
  498.   jFont++;
  499.   return TRUE;
  500. }
  501. /******************************************************************************
  502. *
  503. *  FUNCTION:    MyEnumCount
  504. *
  505. *  GLOBAL VARS: (see above)
  506. *
  507. ******************************************************************************/
  508. int CALLBACK MyEnumCount (LPLOGFONT lpLogFont, LPTEXTMETRIC lpTEXTMETRICs,
  509.                           DWORD fFontType, LPVOID lpData)
  510. {
  511.   (*(LPINT)lpData)++;
  512.   return TRUE;
  513. }
  514. /******************************************************************************
  515. *
  516. *  FUNCTION:    FreeFontList
  517. *
  518. *  INPUTS:      paf - pointer to ARFONTS struct to free
  519. *
  520. ******************************************************************************/
  521. void FreeFontList (PARFONTS paf)
  522. {
  523.   int i;
  524.   for (i = 0; i < nFaces; i++)
  525.   {
  526.     LocalFree (LocalHandle ((LPSTR) ((paf + i)->lf  )));
  527.     LocalFree (LocalHandle ((LPSTR) ((paf + i)->tm  )));
  528.     LocalFree (LocalHandle ((LPSTR) ((paf + i)->Type)));
  529.   }
  530.   LocalFree (LocalHandle ((LPSTR) paf));
  531. }