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

Windows编程

开发平台:

Visual C++

  1. /*****************************************************************************
  2. *       This is a part of the Microsoft Source Code Samples.
  3. *       Copyright (C) 1992-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.  * FX.C                               *
  13.  *  *
  14.  * PURPOSE:  Routines for rendering text with stange effects                *
  15.  *  *
  16.  *  *
  17.  * FillOut            - Converts an array of line segments into an array of *
  18.  *                       all the points in the segments      *
  19.  *  *
  20.  * RenderPathPoints   - Renders the outline of points returned from GetPath * 
  21.  *  *
  22.  * RenderAndFillPath  - Renders the points returned from GetPath as a       *
  23.  *                       filled polygon  *
  24.  *  *
  25.  * TextEffect         - Draws a string of text between two guide lines      *
  26.  *  *
  27.  *****************************************************************************/
  28.  
  29. #include <windows.h>
  30. #include "fx.h"
  31. // This structure is used by FillOut for passing data into LineDDA
  32. typedef struct tagSEG {
  33.   DWORD dwPos;
  34.   LPPOINT lpPoints; 
  35. } PTS;
  36. /**********************************************************************
  37.  *                                                                    *
  38.  * AddSegment - used with LineDDA to add points from a line segment   *
  39.  *    to an array containing all the points on a set of line segments *
  40.  *                                                                    *
  41.  *********************************************************************/
  42. VOID CALLBACK AddSegment(int x, int y, PTS *pts)
  43. {
  44.    pts->lpPoints[pts->dwPos].x = x;
  45.    pts->lpPoints[pts->dwPos].y = y;
  46.    pts->dwPos++;
  47. /**********************************************************************
  48.  *                                                                    *
  49.  * CountPoints - used with LineDDA to determine the number of points  *
  50.  *    needed to store all the points on a set of line segments        *
  51.  *                                                                    *
  52.  *********************************************************************/
  53. VOID CALLBACK CountPoints(int x, int y, LPDWORD lpdwNumPts)
  54. {
  55.    (*lpdwNumPts)++;
  56.    UNREFERENCED_PARAMETER(x);
  57.    UNREFERENCED_PARAMETER(y);
  58. /**********************************************************************
  59.  *                                                                    *
  60.  * FUNCTION:  FillOut(LPPOINT, LPDWORD)                               *
  61.  *   *
  62.  * PURPOSE:   Converts an array of line segments into an array of all *
  63.  *            of the points comprising the line segments.             *
  64.  *                                                                    *
  65.  *********************************************************************/
  66. BOOL FillOut(LPPOINT *lpPoints, LPDWORD lpdwNumPts)
  67. {
  68.    DWORD i;
  69.    LPPOINT lpPts = *lpPoints;
  70.    PTS pts;
  71.    DWORD dwNumPts = 0;
  72.    // Make sure we have at least two points
  73.    if (*lpdwNumPts < 2) {
  74.      MessageBox(NULL, "You need at least two points for a guide line.", "Not enough points!", MB_ICONSTOP);
  75.      *lpdwNumPts = 0;
  76.      return FALSE;
  77.    }
  78.    // Find out how namy points are on the segments
  79.    for (i=0; i<*lpdwNumPts - 1; i++) 
  80.      LineDDA(lpPts[i].x, lpPts[i].y, lpPts[i+1].x, lpPts[i+1].y, (LINEDDAPROC)CountPoints, (LPARAM)&dwNumPts);
  81.    
  82.    // If there are too many points, print an anoying message so the user doesnt do it again
  83.    if (dwNumPts > MAXFILLPOINTS) {
  84.      MessageBox(NULL, "Make your guide lines a bit shorter please!", "Too many points!", MB_ICONSTOP);
  85.      *lpdwNumPts = 0;
  86.      return FALSE;  // Bail
  87.    }
  88.    
  89.    // Allocate memory for the the points and initialize our "last point" index
  90.    pts.lpPoints = (LPPOINT)GlobalAlloc(GPTR, dwNumPts * sizeof(POINT));
  91.    pts.dwPos = 0;
  92.                                                                     
  93.    // Convert the segments to points
  94.    for (i=0; i<*lpdwNumPts - 1; i++) 
  95.      LineDDA(lpPts[i].x, lpPts[i].y, lpPts[i+1].x, lpPts[i+1].y, (LINEDDAPROC)AddSegment, (LPARAM)&pts);
  96.    
  97.    // Get rid of the original array of segments...
  98.    GlobalFree(lpPts);
  99.  
  100.    // ... and replace it with the new points
  101.    *lpPoints = pts.lpPoints;
  102.    *lpdwNumPts = pts.dwPos;
  103.    
  104.    // Check to see if anything hit the fan
  105.    if (!pts.dwPos)
  106.      return FALSE;
  107.    return TRUE;  
  108. }
  109. /**********************************************************************
  110.  *                                                                    *
  111.  * FUNCTION:  PolyDraw95(HDC, LPPOINT, LPBYTE, int)                   *
  112.  *   *
  113.  * PURPOSE:   Draws the points returned from a call to GetPath()      *
  114.  *            to an HDC                                               *
  115.  *                                                                    *
  116.  * NOTES:     This function is similar to the Windows NT function     *
  117.  *            PolyDraw which draws a set of line segments and B閦ier  *
  118.  *            curves.  Since PolyDraw is not supported on Windows 95  *
  119.  *            this PolyDraw95 is used instead.                        *  
  120.  *                                                                    *
  121.  *********************************************************************/
  122. BOOL PolyDraw95(HDC  hdc,              // handle of a device context 
  123.                 CONST LPPOINT lppt,    // address of array of points 
  124.                 CONST LPBYTE lpbTypes, // address of line and curve identifiers  
  125.                 int  cCount)         // count of points 
  126. {
  127.   int i;
  128.   
  129.   for (i=0; i<cCount; i++) 
  130.     switch (lpbTypes[i]) {
  131.       case PT_MOVETO : 
  132.          MoveToEx(hdc, lppt[i].x, lppt[i].y, NULL); 
  133.          break;
  134.       
  135.       case PT_LINETO | PT_CLOSEFIGURE:
  136.       case PT_LINETO : 
  137.          LineTo(hdc, lppt[i].x, lppt[i].y); 
  138.          break;
  139.       
  140.       case PT_BEZIERTO | PT_CLOSEFIGURE:
  141.       case PT_BEZIERTO :
  142.      PolyBezierTo(hdc, &lppt[i], 3);
  143.  i+=2;
  144.          break;
  145.    }
  146.    return TRUE;
  147. }  
  148. /**********************************************************************
  149.  *                                                                    *
  150.  * FUNCTION:  RenderPathPoints(HDC, LPPOINT, LPBYTE, int, BOOL)       *
  151.  *   *
  152.  * PURPOSE:   Renders the points returned from a call to GetPath()    *
  153.  *            by converting them back into a path and calling either  *
  154.  *            FillPath or StrokePath to display them.                 *
  155.  *                                                                    *
  156.  * NOTE:      The R2_MERGEPENNOT is used here so that things like the *
  157.  *            inside of and "a" or an "o" get painted correctly when  *
  158.  *            using FillPath.                                         *
  159.  *                                                                    *
  160.  *********************************************************************/
  161. BOOL RenderPathPoints(HDC hDC, LPPOINT lpPoints, LPBYTE lpTypes, int iNumPts, BOOL bOutline)
  162. {
  163.   BeginPath(hDC); // Draw into a path so that we can use FillPath()
  164.   PolyDraw95(hDC, lpPoints, lpTypes, iNumPts);
  165.   CloseFigure(hDC);
  166.   EndPath(hDC);   
  167.   // Draw the path
  168.   if (bOutline)  
  169.     StrokePath(hDC); // As an outline
  170.   else 
  171.       {              // As solid figures
  172.         int iROP2 = SetROP2(hDC, R2_MERGEPENNOT);
  173.         HPEN hPen = SelectObject(hDC, GetStockObject(NULL_PEN)); // Just say "no" to outlines
  174.         HBRUSH hBrush = SelectObject(hDC, GetStockObject(BLACK_BRUSH)); // Paint It Black
  175.         FillPath(hDC);  
  176.         // Restore the DC to its previous state
  177.         SetROP2(hDC, iROP2);        
  178.         SelectObject(hDC, hPen);
  179.         SelectObject(hDC, hBrush);
  180.       } 
  181.   
  182.   return TRUE;
  183. }
  184. /**********************************************************************
  185.  *                                                                    *
  186.  * FUNCTION:  GetRealTextExtent(LPPOINT, int, LPSIZE)                 *
  187.  *   *
  188.  * PURPOSE:   Makes sure that the extents in a SIZE are large enough  *
  189.  *            to bound the points in an array.                        *
  190.  *                                                                    *
  191.  * NOTES:     Why not just use GetTextExtentPoint32?  Well, the text  *
  192.  *            extents returned by GetTextExtentPoint32 dont include   *
  193.  *            the overhang of an italics character into the next      *
  194.  *            cell.  This function expands the extents to include     *
  195.  *            the greatest x, and y extents of the string data.       *
  196.  *                                                                    *
  197.  *********************************************************************/
  198. void GetRealTextExtent(LPPOINT lpPoints, int iNumPts, LPSIZE size)
  199. {
  200.   int i;
  201.   for (i=0; i<iNumPts; i++) {
  202.     if (lpPoints[i].x > size->cx) size->cx = lpPoints[i].x;
  203.     if (lpPoints[i].y > size->cy) size->cy = lpPoints[i].y;
  204.   }
  205. }
  206. /**********************************************************************
  207.  *                                                                    *
  208.  * FUNCTION:  TextEffect(HDC, LPPOINT, LPPOINT, DWORD, DWORD,         *
  209.  *                            LPSTR, BOOL)     *
  210.  *   *
  211.  * PURPOSE:   Draws a string of text in the currently selected font   *
  212.  *            using two arrays of points as guide lines for orienting *
  213.  *            the text.  The text can be displayed either as outlines *
  214.  *            or as filled characters.                                *
  215.  *                                                                    *
  216.  *********************************************************************/
  217. BOOL TextEffect(HDC hDC,            // DC to display into
  218.                 LPPOINT lpTop,   // Top guide line
  219.                 LPPOINT lpBot,  // Bottom guide line
  220.                 DWORD dwTopPts,  // Number of points in top guide
  221.                 DWORD dwBotPts,  // Number of points in bottom guide
  222.                 LPSTR szText,  // Text string to apply effects to
  223.                 BOOL bOutlineOnly)  // Print as outline or as solid text
  224. {
  225.    LPPOINT lpPoints;   // Path data points
  226.    LPBYTE lpTypes;   // Path data types
  227.    int i, iNumPts;
  228.    SIZE size;   // Text size info
  229.    float fXScale, fYScale;   // Scaling values
  230.    int iTopInd, iBotInd;   // Guide array indices
  231.    // Set to transparent so we dont get an outline around the text string
  232.    SetBkMode(hDC, TRANSPARENT);
  233.       
  234.    // Output the text into a path
  235.    BeginPath(hDC);
  236.    TextOut(hDC, 0, 0, szText, strlen(szText));
  237.    EndPath(hDC);    
  238.       
  239.    // How many points are in the path
  240.    iNumPts = GetPath(hDC, NULL, NULL, 0);
  241.    if (iNumPts == -1) return FALSE;
  242.    // Allocate room for the points
  243.    lpPoints = (LPPOINT)GlobalAlloc(GPTR, sizeof(POINT) * iNumPts);
  244.    if (!lpPoints) return FALSE;
  245.    // Allocate room for the point types
  246.    lpTypes = GlobalAlloc(GPTR, iNumPts);
  247.    if (!lpTypes) {
  248.      GlobalFree(lpPoints);
  249.     return FALSE;
  250.    }
  251.    
  252.    // Get the points and types from the current path
  253.    iNumPts = GetPath(hDC, lpPoints, lpTypes, iNumPts);
  254.    // Even more error checking
  255.    if (iNumPts == -1) {
  256.      GlobalFree(lpTypes);
  257.      GlobalFree(lpPoints);
  258.  return FALSE;
  259.    }
  260.    
  261.    //Get extents of the text string for scaling purposes  
  262.    GetTextExtentPoint32(hDC, szText, strlen(szText), &size);
  263.    // OK, but lets make sure our extents are big enough (handle italics fonts)
  264.    GetRealTextExtent(lpPoints, iNumPts, &size);
  265.    
  266.    // Relocate the points in the path based on the guide lines
  267.    for (i=0; i < iNumPts; i++) {
  268.      // How far along is this point on the x-axis
  269.      fXScale = (float)lpPoints[i].x / (float)size.cx;
  270.      // What point on the top guide does this coorespond to
  271.      iTopInd = (int)(fXScale * (dwTopPts-1));
  272.  // What point on the bottom guide does this coorespond to
  273.      iBotInd = (int)(fXScale * (dwBotPts-1));
  274.      // How far along is this point on the y-axis
  275.      fYScale = (float)lpPoints[i].y / (float)size.cy;
  276.      // Scale the points to their new locations
  277.      lpPoints[i].x = (int)((lpBot[iBotInd].x * fYScale) + (lpTop[iTopInd].x * (1.0f-fYScale)));
  278.      lpPoints[i].y = (int)((lpBot[iBotInd].y * fYScale) + (lpTop[iTopInd].y * (1.0f-fYScale)));
  279.    }
  280.    // Draw the new path 
  281.    RenderPathPoints(hDC, lpPoints, lpTypes, iNumPts, bOutlineOnly);
  282.    
  283.    GlobalFree(lpPoints);
  284.    GlobalFree(lpTypes);
  285.    return TRUE;
  286. }