home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c083 / 21.ddi / TRUETYPE.PAK / TRUETYPE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-02  |  24.7 KB  |  724 lines

  1.  // Borland C++ - (C) Copyright 1991, 1992 by Borland International
  2.  
  3. /*******************************************************************
  4.  
  5.     program - TrueType.c
  6.     purpose - a Windows program to demo True Type fonts.
  7.  
  8.  
  9.     This program shows off two features of Windows 3.1: True Type
  10. fonts, and common dialogs.
  11.  
  12.     True Type fonts are scalable fonts supplied by the system.  This
  13. program demonstrates resizing and rotation of True Type characters
  14. within a window, and allows the user to select the True Type font to
  15. be used.
  16.  
  17.     The dialog used in selecting the font is a Windows 3.1 "common
  18. dialog."  By including commdlg.h, a series of common dialogs becomes
  19. available to the program.  To invoke the font dialog, a CHOOSEFONTS
  20. structure is filled out, and ChooseFont() is called.  This system
  21. routine handles all the dialog processing needed to select a font via
  22. a dialog box.
  23.  
  24.     In contrast, the About Box dialog herein is programmed in the
  25. normal manner.  A dialog process is provided, and a thunk for it is
  26. created explicitly; Windows provides no automated handling for this
  27. program-specific dialog.
  28.  
  29.     Change font attributes through the menu selections.  Resize the
  30. window to see the text resized; the text "fan" will always reach the
  31. bottom and the right side of the window.
  32.  
  33. *******************************************************************/
  34.  
  35. #define STRICT
  36.  
  37. #include <windows.h>
  38. #pragma hdrstop
  39. #include <string.h>
  40. #include <stdlib.h>
  41. #include <math.h>
  42. #include <commdlg.h>
  43. #include <windowsx.h>
  44.  
  45. #include "TrueType.h"
  46.  
  47.  
  48. // data initialized by first instance
  49. typedef struct tagSETUPDATA
  50.     {
  51.         char   szAppName[10]; // name of application
  52.     } SETUPDATA;
  53.  
  54. SETUPDATA SetUpData;
  55.  
  56.  
  57. // Data that can be referenced throughout the
  58. // program but not passed to other instances
  59.  
  60. HINSTANCE hInst;                        // hInstance of application
  61. HWND      hwnd;                         // hWnd of main window
  62.  
  63. HANDLE    hdlg;                         // handle of dialog resource
  64.  
  65. DLGPROC   lpDlgProc;                    // ptr to proc for dialog box
  66. HWND      hDlgBox;                      // handle of dialog box
  67.  
  68. LOGFONT   MainFontRec;                  // logical font records,...
  69. LOGFONT   CornerFontRec;                // ...which store font data...
  70. LOGFONT   BorlandFontRec;               // ...for different fonts.
  71.  
  72. COLORREF  FanColor[10];                 // color array for "fan" of text
  73.  
  74. BOOL      ShadowAll;                    // TRUE iff fan text gets shadows
  75. BOOL      ShowAlignmentMarks;           // TRUE iff we show baselines of fan
  76.  
  77. #define ROUND(x)  (floor(x + .5))
  78. #define SQR(x)    (pow(x,2))
  79.  
  80. #define TITLE_LENGTH 30
  81.  
  82. LPCSTR ArcText = "TrueType";            // text seen along arc of fan
  83. const char* FanText = "Borland C++ for Windows";    // text for leaves of fan
  84. const char* BorlandText = "Borland";    // text for lower right window corner
  85. const int   Radius = 100;               // radius of fan "hub"
  86. const float Deg2Rad = M_PI / 18;        // conversion factor, degrees->radians
  87.  
  88. // function prototypes
  89.  
  90. int PASCAL      WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  91.                         LPSTR lpszCmdLine, int cmdShow);
  92.  
  93. void            Init(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  94.                         LPSTR lpszCmdLine, int cmdShow);
  95. void            InitFirst(HINSTANCE hInstance);
  96. void            InitEvery(HINSTANCE hInstance, int cmdShow);
  97.  
  98. LRESULT CALLBACK _export WndProc(HWND hWnd, UINT message,
  99.                          WPARAM wParam, LPARAM lParam);
  100.  
  101. BOOL CALLBACK  _export DlgBoxProc(HWND hDlg, UINT message,
  102.                            WPARAM wParam, LPARAM lParam);
  103.  
  104. void wmCreate(void);
  105. void cmAbout(void);
  106. void cmAlignmentMarks(void);
  107. void cmFonts(HWND);
  108. void cmShadows(void);
  109. void DoPaint(void);
  110. void cm(void);
  111.  
  112.  
  113. //*******************************************************************
  114. // WinMain - TrueType main
  115. //
  116. // parameters:
  117. //             hInstance     - The instance of this instance of this
  118. //                             application.
  119. //             hPrevInstance - The instance of the previous instance
  120. //                             of this application. This will be 0
  121. //                             if this is the first instance.
  122. //             lpszCmdLine   - A long pointer to the command line that
  123. //                             started this application.
  124. //             cmdShow       - Indicates how the window is to be shown
  125. //                             initially. ie. SW_SHOWNORMAL, SW_HIDE,
  126. //                             SW_MIMIMIZE.
  127. //
  128. // returns:
  129. //             wParam from last message.
  130. //
  131. //*******************************************************************
  132. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  133.                    LPSTR lpszCmdLine, int cmdShow)
  134. {
  135.     MSG msg;
  136.  
  137.     // Go init this application.
  138.     Init(hInstance, hPrevInstance, lpszCmdLine, cmdShow);
  139.  
  140.     // Get and dispatch messages for this applicaton.
  141.     while (GetMessage(&msg, NULL, 0, 0))
  142.     {
  143.         TranslateMessage(&msg);
  144.         DispatchMessage(&msg);
  145.     }  // while
  146.  
  147.     return(msg.wParam);
  148. }  // end of WinMain()
  149.  
  150. #if !defined(__WIN32__)
  151. //*******************************************************************
  152. // InitAdded - done only for added instances of TrueType demo
  153. //
  154. // parameters:
  155. //             hPrevInstance - The instance of the previous instance
  156. //                             of this application.
  157. //
  158. //*******************************************************************
  159. #pragma argsused
  160. void InitAdded(HINSTANCE hPrevInstance)
  161. {
  162.     // get the results of the initialization of first instance
  163.     GetInstanceData(hPrevInstance, (BYTE*) &SetUpData, sizeof(SETUPDATA));
  164. }  // end of InitAdded()
  165. #endif
  166.  
  167. //*******************************************************************
  168. // Init - init the TrueType demo application
  169. //
  170. // parameters:
  171. //             hInstance     - The instance of this instance of this
  172. //                             application.
  173. //             hPrevInstance - The instance of the previous instance
  174. //                             of this application. This will be 0
  175. //                             if this is the first instance.
  176. //             lpszCmdLine   - A long pointer to the command line that
  177. //                             started this application.
  178. //             cmdShow       - Indicates how the window is to be shown
  179. //                             initially. ie. SW_SHOWNORMAL, SW_HIDE,
  180. //                             SW_MIMIMIZE.
  181. //
  182. //*******************************************************************
  183. #pragma argsused
  184. void Init(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  185.              LPSTR lpszCmdLine, int cmdShow)
  186. {
  187.  
  188.   #if defined(__WIN32__)
  189.     InitFirst(hInstance);
  190.  
  191.   #else
  192.     if (!hPrevInstance)         // if no prev instance, this is first
  193.         InitFirst(hInstance);
  194.     else                        // this is not first instance
  195.         InitAdded(hPrevInstance);
  196.   #endif
  197.  
  198.     InitEvery(hInstance, cmdShow);       // init for all instances
  199. }  // end of Init()
  200.  
  201.  
  202. //*******************************************************************
  203. // InitFirst - done only for first instance of TrueType demo
  204. //
  205. // parameters:
  206. //             hInstance     - The instance of this instance of this
  207. //                             application.
  208. //
  209. //*******************************************************************
  210. void InitFirst(HINSTANCE hInstance)
  211. {
  212.     WNDCLASS wcTTFClass;
  213.  
  214.     // Get string from resource with application name.
  215.     LoadString(hInstance, IDS_NAME, (LPSTR) SetUpData.szAppName, 10);
  216.  
  217.     // Define the window class for this application.
  218.     wcTTFClass.style         = CS_HREDRAW | CS_VREDRAW;
  219.     wcTTFClass.lpfnWndProc   = WndProc;
  220.     wcTTFClass.cbClsExtra    = 0;
  221.     wcTTFClass.cbWndExtra    = 0;
  222.     wcTTFClass.hInstance     = hInstance;
  223.     wcTTFClass.hIcon         = LoadIcon(hInstance, SetUpData.szAppName);
  224.     wcTTFClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
  225.     wcTTFClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  226.     wcTTFClass.lpszClassName = SetUpData.szAppName;
  227.     wcTTFClass.lpszMenuName  = SetUpData.szAppName;
  228.  
  229.     // Register the class
  230.     RegisterClass(&wcTTFClass);
  231. }  // end of InitFirst()
  232.  
  233.  
  234. //*******************************************************************
  235. // InitEvery - done for every instance of TrueType demo program
  236. //
  237. // parameters:
  238. //             hInstance     - The instance of this instance of this
  239. //                             application.
  240. //             cmdShow       - Indicates how the window is to be shown
  241. //                             initially. ie. SW_SHOWNORMAL, SW_HIDE,
  242. //                             SW_MIMIMIZE.
  243. //
  244. //*******************************************************************
  245. #pragma argsused
  246. void InitEvery(HINSTANCE hInstance, int cmdShow)
  247. {
  248.     char title[TITLE_LENGTH+1];
  249.  
  250.     hInst = hInstance;       // save for use by window procs
  251.  
  252.     // fetch in the window title from the stringtable resource
  253.     LoadString(hInstance, IDS_TITLE, (LPSTR)title, TITLE_LENGTH);
  254.  
  255.     // Create applications main window.
  256.     hwnd = CreateWindow(SetUpData.szAppName,    // window class name
  257.                         (LPSTR)title,           // window title
  258.                         WS_OVERLAPPEDWINDOW,    // window style
  259.                         CW_USEDEFAULT,          // x etc.: use defaults
  260.                         CW_USEDEFAULT,          // y
  261.                         CW_USEDEFAULT,          // cx
  262.                         CW_USEDEFAULT,          // cy
  263.                         NULL,                   // no parent for this window
  264.                         NULL,                   // use the class menu
  265.                         hInstance,              // who created this window
  266.                         NULL                    // no parms to pass on
  267.                         );
  268.     ShowWindow(hwnd, cmdShow);
  269.     UpdateWindow(hwnd);
  270. } // end of InitEvery()
  271.  
  272.  
  273. //*******************************************************************
  274. // WndProc - handles messages for this application
  275. //
  276. // parameters:
  277. //             hWnd          - The window handle for this message
  278. //             message       - The message number
  279. //             wParam        - The WPARAM parameter for this message
  280. //             lParam        - The LPARAM parameter for this message
  281. //
  282. // returns:
  283. //             depends on message.
  284. //
  285. //*******************************************************************
  286. LRESULT CALLBACK _export WndProc(HWND hWnd, UINT message,
  287.                          WPARAM wParam, LPARAM lParam)
  288. {
  289.     switch (message)
  290.     {
  291.   case WM_CREATE:
  292.             wmCreate();
  293.             break;
  294.  
  295.   case WM_COMMAND:
  296.       switch (GET_WM_COMMAND_ID(wParam, lParam))
  297.       {
  298.     case CM_ABOUT:
  299.         cmAbout();
  300.         break;
  301.  
  302.     case CM_EXIT:
  303.         // Tell windows to destroy our window.
  304.         DestroyWindow(hWnd);
  305.         break;
  306.  
  307.     case CM_ALIGNMENTMARKS:
  308.         cmAlignmentMarks();
  309.         break;
  310.  
  311.     case CM_FONTS:
  312.         cmFonts(hWnd);
  313.         break;
  314.  
  315.     case CM_SHADOWS:
  316.         cmShadows();
  317.         break;
  318.  
  319.     default:
  320.         break;
  321.  
  322.       } // switch wParam
  323.       break;
  324.  
  325.   case WM_PAINT:
  326.       DoPaint();
  327.       break;
  328.  
  329.   case WM_GETMINMAXINFO:
  330.       // Limit the minimum size of the window to 300x300,
  331.       // so the fonts don't get too small
  332.       ((POINT far *)lParam)[3].x = 300;
  333.       ((POINT far *)lParam)[3].y = 300;
  334.       break;
  335.  
  336.   case WM_DESTROY:
  337.       // This is the end if we were closed by a DestroyWindow call.
  338.       PostQuitMessage(0);
  339.       break;
  340.  
  341.   default:
  342.       return(DefWindowProc(hWnd, message, wParam, lParam));
  343.     }  // switch message
  344.  
  345.     return(0L);
  346. }  // end of WndProc()
  347.  
  348.  
  349. //*******************************************************************
  350. // DlgBoxProc - handle dialog messages
  351. //
  352. // parameters:
  353. //             hDlg          - The window handle for this message
  354. //             message       - The message number
  355. //             wParam        - The WPARAM parameter for this message
  356. //             lParam        - The LPARAM parameter for this message
  357. //
  358. //*******************************************************************
  359. #pragma argsused
  360. BOOL CALLBACK _export DlgBoxProc(HWND hDlg, UINT message,
  361.          WPARAM wParam, LPARAM lParam)
  362. {
  363.  
  364.     switch (message)
  365.     {
  366.   case WM_SYSCOMMAND:
  367.       // Pass WM_SYSCOMMAND messages on to main window so both
  368.       // main window and dialog box get iconized, minimized etc.
  369.       // in parallel.
  370.       SendMessage(hwnd, message, wParam, lParam);
  371.       break;
  372.  
  373.   case WM_COMMAND:
  374.       // regardless of the command (only ID_OK should arrive)
  375.       // we want to exit the dialog
  376.       EndDialog(hDlg, TRUE);
  377.       break;
  378.  
  379.   default:
  380.       return FALSE;
  381.     }  // switch
  382.  
  383.     return(TRUE);
  384. }  // end of DlgBoxProc()
  385.  
  386.  
  387. static void
  388. MeasureText (HDC hDC, const char *str, SIZE *size)
  389. {
  390.   #if defined(__WIN32__)
  391.     GetTextExtentPoint(hDC, str, strlen(str), size);
  392.   #else
  393.     DWORD  d = GetTextExtent(hDC, str, strlen(str));
  394.  
  395.     size->cx = LOWORD(d);
  396.     size->cy = HIWORD(d);
  397.   #endif
  398. }
  399.  
  400. //*************************************************************************
  401. // DoPaint -- this is the WM_PAINT action routine for the main window.
  402. // It places the TrueType logo in the upper left corner of the window, draws
  403. // a "fan hub" around it, and draws "fan leaves" of text out from the hub.
  404. // These leaves are scaled to reach the bottom and the right edge of the
  405. // window, by defining an ellipse centered on the TrueType logo which just
  406. // touches those two edges.  The text strings span the distance from the
  407. // hub to the ellipse along radial lines, and are both scaled and rotated.
  408. //     Depending on user-set state variables, the ellipse and baselines
  409. // for the text fan may be shown (ShowAlignmentMarks), and/or the text may
  410. // be shadowed (ShadowAll).  Other attributes, such as bolding or
  411. // italicization, may be selected from the font dialog box.
  412. //*************************************************************************
  413. void DoPaint()
  414. {
  415.     PAINTSTRUCT       PaintInfo;
  416.     HDC               hDC;
  417.     LOGFONT           FontRec;
  418.     UINT              FmSize;
  419.     OUTLINETEXTMETRIC *FontMetric = 0;
  420.     int               FontHeight, x, y, j, k;
  421.     UINT              BaseWidth, DesiredExtent;
  422.     float             Theta;
  423.     LPCSTR            P;
  424.     RECT              R;
  425.     int               d;
  426.     SIZE              size;
  427.   #if defined(__WIN32__)
  428.     POINT             point;
  429.   #endif
  430.     UINT              FanTextLen = strlen(FanText);
  431.  
  432.     BeginPaint(hwnd, &PaintInfo);
  433.  
  434.     hDC = PaintInfo.hdc;
  435.     P = ArcText;
  436.  
  437.     // save device context; easiest way to preserve current state
  438.     SaveDC(hDC);
  439.  
  440.     // set initial font data (for TrueType logo)
  441.     FontRec = CornerFontRec;
  442.     SetBkMode(hDC, TRANSPARENT);
  443.     SetTextColor(hDC, RGB(128,128,128));
  444.     FontRec.lfHeight = FontRec.lfHeight * 2;
  445.     FontRec.lfWidth = floor(FontRec.lfWidth * 2.1);
  446.  
  447.     // create the TrueType logo
  448.     SelectObject(hDC, CreateFontIndirect(&FontRec));
  449.     TextOut(hDC, 18, 5, "T", 1);
  450.     SetTextColor(hDC, RGB(0,0,0));
  451.     TextOut(hDC, 32, 13,"T", 1);
  452.  
  453.     // determine window dimensions & set up fan text parameters
  454.     GetClientRect(hwnd, &R);
  455.     FontRec = MainFontRec;
  456.     DeleteObject(SelectObject(hDC, CreateFontIndirect(&FontRec)));
  457.  
  458.     FmSize = GetOutlineTextMetrics(hDC, 0, 0);
  459.     FontMetric = (OUTLINETEXTMETRIC*)malloc(FmSize);
  460.     FontMetric->otmpFamilyName = 0;
  461.     FontMetric->otmpFaceName = 0;
  462.     FontMetric->otmpStyleName = 0;
  463.     FontMetric->otmpFullName = 0;
  464.  
  465.     GetOutlineTextMetrics(hDC, FmSize, FontMetric);
  466.     FontHeight = FontMetric->otmTextMetrics.tmHeight;
  467.   #if defined(__WIN32__)
  468.     SetViewportOrgEx(hDC, FontHeight+2, 0, &point);
  469.   #else
  470.     SetViewportOrg(hDC, FontHeight+2, 0);
  471.   #endif
  472.     MeasureText(hDC, FanText, &size);
  473.     BaseWidth = size.cx;
  474.     R.right -= FontHeight+2;
  475.  
  476.     // get a "black brush" for drawing operations
  477.     SelectObject(hDC, GetStockObject(NULL_BRUSH));
  478.  
  479.     // if we want to show the alignment marks, draw the bounding ellipse
  480.     if (ShowAlignmentMarks)
  481.     {
  482.         Ellipse(hDC, -R.right, -R.bottom, R.right, R.bottom);
  483.     }
  484.  
  485.     // draw the "hub" of the fan
  486.     Ellipse(hDC, -(Radius-5), -(Radius-5), (Radius-5), Radius-5);
  487.     Ellipse(hDC, -(Radius-10), -(Radius-10), (Radius-10), Radius-10);
  488.  
  489.     SetTextColor(hDC, FanColor[0]);
  490.  
  491.     // loop over the "fan leaves"
  492.     for ( d = 27; d <= 36; d++)
  493.     {
  494.         x = ROUND(Radius * cos(d * Deg2Rad));
  495.         y = ROUND(Radius * sin(-d * Deg2Rad)); // -d because y axis is inverted
  496.  
  497.         Theta = -d * Deg2Rad;
  498.         if (x)
  499.         {
  500.             Theta = atan((R.right / (R.bottom * 1.0)) * (y / (x * 1.0)));
  501.         }
  502.  
  503.         j = ROUND(R.right * cos(Theta));
  504.         k = ROUND(R.bottom * sin(Theta));
  505.  
  506.         if (ShowAlignmentMarks)
  507.         {
  508.           #if defined(__WIN32__)
  509.             MoveToEx(hDC, x,y, &point);
  510.           #else
  511.             MoveTo(hDC, x, y);
  512.           #endif
  513.             LineTo(hDC, j,k);
  514.         }
  515.  
  516.         DesiredExtent = ROUND(sqrt(SQR(x*1.0 - j) + SQR(y*1.0 - k))) - 5;
  517.         FontRec = MainFontRec;
  518.         FontRec.lfEscapement = d * 100;
  519.         FontRec.lfWidth = floor((FontMetric->otmTextMetrics.tmAveCharWidth) *
  520.                                 (DesiredExtent / (BaseWidth * 1.0)));
  521.         DeleteObject(SelectObject(hDC, CreateFontIndirect(&FontRec)));
  522.         MeasureText(hDC, FanText, &size);
  523.  
  524.         for ( ;(size.cx > DesiredExtent) && (FontRec.lfWidth);
  525.              FontRec.lfWidth-- )
  526.         {
  527.             // Shave off some character width until the string fits
  528.             DeleteObject(SelectObject(hDC, CreateFontIndirect(&FontRec)));
  529.             MeasureText(hDC, FanText, &size);
  530.         }
  531.  
  532.         // Expand the string if necessary to make it fit the desired extent
  533.         if (size.cx < DesiredExtent)
  534.           { SetTextJustification(hDC,DesiredExtent - size.cx, 3); }
  535.         if (ShadowAll)
  536.         {
  537.             SetTextColor(hDC, RGB(0,0,0));
  538.             TextOut(hDC, x+2, y+1, FanText, FanTextLen);
  539.         }
  540.         SetTextColor(hDC, FanColor[d - 27]);
  541.         TextOut(hDC, x, y, FanText, FanTextLen);
  542.         // clear justifier's internal error accumulator
  543.         SetTextJustification(hDC,0,0);
  544.  
  545.         if (P[0])
  546.         {
  547.             FontRec = CornerFontRec;
  548.             FontRec.lfEscapement = (d+10) * 100;
  549.             FontRec.lfWidth = 0;
  550.             DeleteObject(SelectObject(hDC, CreateFontIndirect(&FontRec)));
  551.             SetTextColor(hDC, 0);
  552.             x = floor((Radius - FontHeight - 5) * cos(d * Deg2Rad));
  553.             y = floor((Radius - FontHeight - 5) * sin(-d * Deg2Rad));
  554.             TextOut(hDC, x, y, P, 1);
  555.             P++;
  556.         } // if
  557.     } // for d
  558.  
  559.     free(FontMetric);
  560.     FontMetric = 0;
  561.  
  562.     // lose the fan font, selecting in the Borland text font
  563.     DeleteObject(SelectObject(hDC, CreateFontIndirect(&BorlandFontRec)));
  564.     MeasureText(hDC, BorlandText, &size);
  565.     SetTextColor(hDC, RGB(0,0,0));
  566.     // write the Borland text in the lower right corner, with a shadow effect
  567.     TextOut(hDC, R.right - size.cx, R.bottom - size.cy, BorlandText,
  568.             strlen(BorlandText));
  569.     SetTextColor(hDC, RGB(255,0,0));
  570.     TextOut(hDC, R.right - size.cx - 5, R.bottom - size.cy, BorlandText,
  571.             strlen(BorlandText));
  572.  
  573.     DeleteObject(SelectObject(hDC, GetStockObject(SYSTEM_FONT)));
  574.     // restore the saved DC; easiest way to reset to entry state
  575.     RestoreDC(hDC, -1);
  576.     EndPaint(hwnd, &PaintInfo);
  577. } // end of DoPaint()
  578.  
  579.  
  580. //*************************************************************************
  581. // wmCreate -- action routine for the WM_CREATE message.  This routine
  582. // sets up font record data and colors for use in the painting routines,
  583. // and creates a thunk for the dialog process
  584. //*************************************************************************
  585. void wmCreate(void)
  586. {
  587.     // create the font data for the main font
  588.     MainFontRec.lfHeight = 26;
  589.     MainFontRec.lfWidth = 10;
  590.     MainFontRec.lfEscapement = 0;
  591.     MainFontRec.lfOrientation = 0;
  592.     MainFontRec.lfWeight = FW_BOLD;
  593.     MainFontRec.lfItalic = 0;
  594.     MainFontRec.lfUnderline = 0;
  595.     MainFontRec.lfStrikeOut = 0;
  596.     MainFontRec.lfCharSet = ANSI_CHARSET;
  597.     MainFontRec.lfOutPrecision = OUT_DEFAULT_PRECIS;
  598.     MainFontRec.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  599.     MainFontRec.lfQuality = PROOF_QUALITY;
  600.     MainFontRec.lfPitchAndFamily = VARIABLE_PITCH | FF_ROMAN;
  601.     strcpy(MainFontRec.lfFaceName,"Times New Roman");
  602.  
  603.     // structure copy (!) into corner font
  604.     CornerFontRec = MainFontRec;
  605.  
  606.     // copy again inot Borland font, but switch to Arial typeface, new size
  607.     BorlandFontRec  = MainFontRec;
  608.     BorlandFontRec.lfHeight = 60;
  609.     BorlandFontRec.lfWidth = 0;   // choose best width for this height
  610.     BorlandFontRec.lfWeight = 900;
  611.     strcpy(BorlandFontRec.lfFaceName, "Arial");
  612.  
  613.     // Array of colors used to color the fan text
  614.     FanColor[0] = RGB(255,0,0);
  615.     FanColor[1] = RGB(128,0,0);
  616.     FanColor[2] = RGB(255,128,0);
  617.     FanColor[3] = RGB(80,80,0);
  618.     FanColor[4] = RGB(80,255,0);
  619.     FanColor[5] = RGB(0,128,0);
  620.     FanColor[6] = RGB(0,128,255);
  621.     FanColor[7] = RGB(0,0,255);
  622.     FanColor[8] = RGB(128,128,128);
  623.     FanColor[9] = RGB(255,0,0);
  624.  
  625.     ShadowAll = 0;
  626.     ShowAlignmentMarks = 0;
  627. } // end of wmCreate()
  628.  
  629.  
  630. /*********************************************************************
  631.  cmXxxx routines -- these are action routines for menu commands
  632. *********************************************************************/
  633.  
  634.  
  635. //*************************************************************************
  636. // cmShadows -- toggle the ShadowsAll flag, and set the menu checkmark
  637. // as appropriate
  638. //*************************************************************************
  639. void cmShadows(void)
  640. {
  641.     ShadowAll = !ShadowAll;
  642.     if (ShadowAll)
  643.     {
  644.         CheckMenuItem(GetMenu(hwnd), CM_SHADOWS, MF_BYCOMMAND | MF_CHECKED);
  645.     }
  646.     else
  647.     {
  648.         CheckMenuItem(GetMenu(hwnd), CM_SHADOWS,
  649.                       MF_BYCOMMAND | MF_UNCHECKED);
  650.     }
  651.  
  652.     // Erase if going Shadow -> no Shadow
  653.     InvalidateRect(hwnd, NULL, !ShadowAll);
  654. }  // end of cmShadows()
  655.  
  656.  
  657. //*************************************************************************
  658. // cmAlignmentMarks -- toggle the state of ShowAlignmentMarks, and toggle
  659. // the checkmark in the menu to match
  660. //*************************************************************************
  661. void cmAlignmentMarks(void)
  662. {
  663.     ShowAlignmentMarks = !ShowAlignmentMarks;
  664.     if (ShowAlignmentMarks)
  665.     {
  666.         CheckMenuItem(GetMenu(hwnd), CM_ALIGNMENTMARKS,
  667.                       MF_BYCOMMAND | MF_CHECKED);
  668.     }
  669.     else
  670.     {
  671.         CheckMenuItem(GetMenu(hwnd), CM_ALIGNMENTMARKS,
  672.                       MF_BYCOMMAND | MF_UNCHECKED);
  673.     }
  674.  
  675.     // Erase if going Marks -> no Marks
  676.     InvalidateRect(hwnd, NULL, !ShowAlignmentMarks);
  677. }  // end of cmAlignmentMarks()
  678.  
  679.  
  680. //*************************************************************************
  681. // cmAbout -- invoke the "About" dialog.  Its return code is ignored, since
  682. // the About dialog doesn't return anything to the program.
  683. //*************************************************************************
  684. void cmAbout(void)
  685. {
  686.     lpDlgProc = (DLGPROC) MakeProcInstance( (FARPROC) DlgBoxProc, hInst);
  687.     DialogBox(hInst, "About", hwnd, lpDlgProc);
  688.     FreeProcInstance ( (FARPROC) lpDlgProc );
  689. }  // end of cmAbout()
  690.  
  691.  
  692. //*************************************************************************
  693. // cmFonts -- use the Choose Fonts common dialog to get a new font spec
  694. // from the user.  To do this, we fill out a CHOOSEFONTS structure and
  695. // pass it to the ChooseFonts routine.  Windows 3.1 takes care of the rest!
  696. //*************************************************************************
  697. void cmFonts(HWND hWnd)
  698. {
  699.     CHOOSEFONT CF;
  700.     LOGFONT FontRec = MainFontRec;
  701.  
  702.     CF.lStructSize    = sizeof(CF);
  703.     CF.hwndOwner      = hWnd;
  704.     CF.Flags          = CF_ANSIONLY | CF_TTONLY | CF_SCREENFONTS |
  705.       CF_INITTOLOGFONTSTRUCT | CF_ENABLETEMPLATE;
  706.     CF.nFontType      = SCREEN_FONTTYPE;
  707.     CF.lpLogFont      = &FontRec;
  708.     CF.nSizeMin       = 20;
  709.     CF.nSizeMax       = 20;
  710.     CF.lpTemplateName = "FontDlg";
  711.     CF.hInstance      = hInst;
  712.  
  713.     if (ChooseFont(&CF))
  714.     {
  715.         // Only get the font name, weight, and italics;
  716.   // we don't care about size
  717.         strcpy(MainFontRec.lfFaceName, FontRec.lfFaceName);
  718.         MainFontRec.lfWeight = FontRec.lfWeight;
  719.         MainFontRec.lfItalic = FontRec.lfItalic;
  720.         InvalidateRect(hwnd, NULL, TRUE);
  721.     }
  722. }  // end of cmFonts()
  723.  
  724.