home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / gdi / fonts / fontview / fontview.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  53KB  |  1,310 lines

  1.  
  2. /******************************************************************************\
  3. *       This is a part of the Microsoft Source Code Samples. 
  4. *       Copyright (C) 1993-1997 Microsoft Corporation.
  5. *       All rights reserved. 
  6. *       This source code is only intended as a supplement to 
  7. *       Microsoft Development Tools and/or WinHelp documentation.
  8. *       See these sources for detailed information regarding the 
  9. *       Microsoft samples programs.
  10. \******************************************************************************/
  11.  
  12. #define NOMINMAX
  13. #include <windows.h>
  14.  
  15. #include "FontView.H"
  16.  
  17. #include <math.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <time.h>
  21.  
  22. #if !defined (WIN32)
  23. #define APIENTRY FAR PASCAL
  24. typedef unsigned int UINT;
  25. #define WNDPROC FARPROC
  26. #define DLGPROC FARPROC
  27. #endif
  28.  
  29.  
  30. char szAppName[] = "FontView";
  31. char szAppTitle[] = "FontView - A Font Examination Utility";
  32.  
  33. BOOL bZoomed = FALSE;
  34.  
  35. HWND    hwndMain, hwndClient;
  36. HWND    hwndMenuField, hwndTimeField;
  37. HWND    hwndLabel1, hwndCreateParam, hwndCreateValue, hwndZoom;
  38.  
  39. LOGFONT lf = {0,0,0,0,0,0,0,0,0,0,0,0,0,""};
  40.  
  41. HMENU   hSysMenuMain = (HMENU)NULL;
  42. HMENU   hFileMenu    = (HMENU)NULL;
  43. HMENU   hEditMenu    = (HMENU)NULL;
  44. HMENU   hViewMenu    = (HMENU)NULL;
  45. HMENU   hMetricsMenu = (HMENU)NULL;
  46. HMENU   hHelpMenu    = (HMENU)NULL;
  47. HMENU   hSysMenuAdv  = (HMENU)NULL;
  48. HMENU   hMenu        = (HMENU)NULL;
  49.  
  50. LONG APIENTRY WndProc         (HWND, UINT, UINT, LONG);
  51. LONG APIENTRY ClientProc      (HWND, UINT, UINT, LONG);
  52. LONG APIENTRY ClientCharSetProc      (HWND, UINT, UINT, LONG);
  53. LONG APIENTRY ClientGlyphProc      (HWND, UINT, UINT, LONG);
  54.  
  55. BOOL FillInParam (HWND, int);
  56. BOOL FillInValue (HWND, int);
  57. int FAR PASCAL EnumFontNames (LPLOGFONT, LPTEXTMETRIC, short, LPINT);
  58.  
  59. WNDPROC fpCharSetProc = 0;
  60. WNDPROC fpGlyphProc = 0;
  61.  
  62. /* Dialogs.C Prototypes */
  63. BOOL APIENTRY SimpleDlgProc   (HWND, UINT, UINT, LONG);
  64. BOOL APIENTRY CreateDlgProc   (HWND, UINT, UINT, LONG);
  65. BOOL APIENTRY MetricsDlgProc   (HWND, UINT, UINT, LONG);
  66. BOOL APIENTRY EnumDlgProc   (HWND, UINT, UINT, LONG);
  67.  
  68. /* Display.C Prototypes */
  69. void DrawAscii (HDC hdc, RECT *pRect, WORD direction);
  70. BYTE FindChar (HDC hdc, RECT *pRect, int x, int y);
  71. void DrawGlyph (HDC hdc, RECT *pRect, BYTE glyph, HFONT hfont);
  72.  
  73. /* ToolBar.C Prototypes */
  74. BOOL InitToolBar (HANDLE);
  75. BOOL CreateToolBar (HWND, HANDLE, int);
  76. BOOL AdjustToolBar (HWND);
  77. HWND AddToolLabel (HANDLE , int, LPSTR, int, DWORD);
  78. HWND AddToolCombo (HANDLE, int, int, DWORD);
  79. HWND AddToolButton (HANDLE, int, LPSTR, int, int, DWORD);
  80. BOOL AddToolSpace (int, int);
  81. int ToolBarHeight (HWND);
  82.  
  83. /* StatusBar.C Prototypes */
  84. BOOL InitStatusBar (HANDLE);
  85. BOOL CreateStatusBar (HWND, HANDLE, int);
  86. BOOL AdjustStatusBar (HWND);
  87. HWND AddStatusField (HANDLE, int, int, int, BOOL);
  88. int StatusBarHeight (HWND);
  89.  
  90.  
  91. int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
  92. {
  93.  
  94.     MSG         msg;
  95.     WNDCLASS    wndclass;
  96.     HANDLE      hAccelTable;
  97.  
  98.     if (!hPrevInst) {
  99.         wndclass.style         = CS_HREDRAW | CS_VREDRAW;
  100. #if defined(WIN32)
  101.         wndclass.lpfnWndProc   = (WNDPROC)WndProc;
  102. #else
  103.         wndclass.lpfnWndProc   = WndProc;
  104. #endif
  105.         wndclass.cbClsExtra    = 0;
  106.         wndclass.cbWndExtra    = 0;
  107.         wndclass.hInstance     = hInst;
  108.         wndclass.hIcon         = LoadIcon (hInst, szAppName);
  109.         wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW);
  110.         wndclass.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE+1);
  111.         wndclass.lpszMenuName  = szAppName;
  112.         wndclass.lpszClassName = szAppName;
  113.  
  114.         if (!RegisterClass (&wndclass)) {
  115.             return FALSE;
  116.         }
  117.  
  118.         wndclass.style         = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
  119. #if defined(WIN32)
  120.         wndclass.lpfnWndProc   = (WNDPROC)ClientProc;
  121. #else
  122.         wndclass.lpfnWndProc   = ClientProc;
  123. #endif
  124.         wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  125.         wndclass.lpszMenuName  = NULL;
  126.         wndclass.lpszClassName = "FontClient";
  127.  
  128.         if (!RegisterClass (&wndclass)) {
  129.             return FALSE;
  130.         }
  131.  
  132.         fpCharSetProc = MakeProcInstance ((WNDPROC)ClientCharSetProc, hInst);
  133.         fpGlyphProc   = MakeProcInstance ((WNDPROC)ClientGlyphProc, hInst);
  134.  
  135.         if (!InitToolBar (hInst)) {
  136.             return FALSE;
  137.         }
  138.  
  139.         if (!InitStatusBar (hInst)) {
  140.             return FALSE;
  141.         }
  142.     }
  143.  
  144.  
  145.     hwndMain = CreateWindow (szAppName, szAppName,
  146.         WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
  147.         CW_USEDEFAULT, 0,
  148.         CW_USEDEFAULT, 0,
  149.         NULL, NULL, hInst, NULL);
  150.  
  151.     if (!hwndMain) {
  152.         return FALSE;
  153.     }
  154.     /* Get handles to the various menus. Some of these we will use later */
  155.     /* to display menu descriptions in the status bar */
  156.         hSysMenuMain = GetSystemMenu(hwndMain,FALSE);
  157.     hMenu = GetMenu(hwndMain);
  158.     if (hMenu) {
  159.         hFileMenu = GetSubMenu(hMenu,0);
  160.         hEditMenu = GetSubMenu(hMenu,1);
  161.         hViewMenu = GetSubMenu(hMenu, 2);
  162.         hMetricsMenu = GetSubMenu(hMenu,3);
  163.         hHelpMenu = GetSubMenu(hMenu,4);
  164.     }
  165.  
  166.     if (CreateToolBar (hwndMain, hInst, ID_TOOLBAR)) {
  167.         hwndLabel1 = AddToolLabel (hInst, 0, "CreateFont:", 0, SS_RIGHT);
  168.         AddToolSpace (6, 0);
  169.         hwndCreateParam = AddToolCombo (hInst, ID_CREATEPARAM, -25, CBS_DROPDOWN | WS_VSCROLL);
  170.         FillInParam (hwndCreateParam, 0);
  171.  
  172.         AddToolSpace (10, 0);
  173.         hwndCreateValue = AddToolCombo (hInst, ID_CREATEVALUE, -30, CBS_DROPDOWN | WS_VSCROLL);
  174.         FillInValue (hwndCreateValue, CFP_BASE+0);
  175.  
  176.         AddToolSpace (10, 0);
  177.         hwndZoom = AddToolButton (hInst, ID_ZOOM, "ZOOM", 24, 0, BS_OWNERDRAW);
  178.  
  179.     } else {
  180.         return FALSE;
  181.     }
  182.  
  183.  
  184.     if (CreateStatusBar (hwndMain, hInst, ID_STATUSBAR)) {
  185.         hwndMenuField = AddStatusField (hInst, ID_MENUFIELD, 100, 0, FALSE);
  186.         hwndTimeField = AddStatusField (hInst, ID_TIMEFIELD, -13, -13, TRUE);
  187.         if (hwndTimeField) {
  188.             SetTimer (hwndMain, 1, 1000, NULL);
  189.         }
  190.     } else {
  191.         return FALSE;
  192.     }
  193.  
  194.     hwndClient = CreateWindow ("FontClient", "FontClient",
  195.         WS_CHILD | WS_CLIPSIBLINGS | WS_BORDER | WS_VISIBLE,
  196.         0, 0, 0, 0,
  197.         hwndMain,(HMENU)666, hInst, NULL);
  198.  
  199.     SetWindowLong (hwndClient, GWL_WNDPROC, (DWORD)fpCharSetProc);
  200.     bZoomed = FALSE;
  201.  
  202.     if (!hwndMain) {
  203.         return FALSE;
  204.     }
  205.  
  206.     ShowWindow (hwndMain, nCmdShow);
  207.     InvalidateRect (hwndZoom, NULL, TRUE);
  208.  
  209.     hAccelTable = LoadAccelerators (hInst, szAppName);
  210.  
  211.     while (GetMessage (&msg, NULL, 0, 0)) {
  212.         if (!TranslateAccelerator (hwndMain, hAccelTable, &msg)) {
  213.             TranslateMessage (&msg);
  214.             DispatchMessage (&msg);
  215.         }
  216.     }
  217.  
  218.  
  219.     return msg.wParam;
  220.  
  221.     lpCmdLine; // Just to resolve reference
  222. }
  223.  
  224.  
  225. /* ================================================================================================ *\
  226.     Fill in the first combo box with all the different 'CreateFont' parameters that we can change
  227. \* ================================================================================================ */
  228. BOOL FillInParam (HWND hwnd, int focus)
  229. {
  230.     int index;
  231.  
  232.     index = 0;
  233.     SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"nHeight");
  234.     SendMessage (hwnd, CB_SETITEMDATA, index++, CFP_HEIGHT);
  235.     SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"nWidth");
  236.     SendMessage (hwnd, CB_SETITEMDATA, index++, CFP_WIDTH);
  237.     SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"nEscapement");
  238.     SendMessage (hwnd, CB_SETITEMDATA, index++, CFP_ESCAPEMENT);
  239.     SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"nOrientation");
  240.     SendMessage (hwnd, CB_SETITEMDATA, index++, CFP_ORIENTATION);
  241.     SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"nWeight");
  242.     SendMessage (hwnd, CB_SETITEMDATA, index++, CFP_WEIGHT);
  243.     SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"cItalic");
  244.     SendMessage (hwnd, CB_SETITEMDATA, index++, CFP_ITALIC);
  245.     SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"cUnderline");
  246.     SendMessage (hwnd, CB_SETITEMDATA, index++, CFP_UNDERLINE);
  247.     SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"cStrikeOut");
  248.     SendMessage (hwnd, CB_SETITEMDATA, index++, CFP_STRIKEOUT);
  249.     SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"cCharSet");
  250.     SendMessage (hwnd, CB_SETITEMDATA, index++, CFP_CHARSET);
  251.     SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"cOutputPrecision");
  252.     SendMessage (hwnd, CB_SETITEMDATA, index++, CFP_OUTPUTPRECISION);
  253.     SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"cClipPrecision");
  254.     SendMessage (hwnd, CB_SETITEMDATA, index++, CFP_CLIPPRECISION);
  255.     SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"cQuality");
  256.     SendMessage (hwnd, CB_SETITEMDATA, index++, CFP_QUALITY);
  257.     SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"cPitch...");
  258.     SendMessage (hwnd, CB_SETITEMDATA, index++, CFP_PITCH);
  259.     SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"c...Family");
  260.     SendMessage (hwnd, CB_SETITEMDATA, index++, CFP_FAMILY);
  261.     SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"lpFacename");
  262.     SendMessage (hwnd, CB_SETITEMDATA, index++, CFP_FACENAME);
  263.     SendMessage (hwnd, CB_SETCURSEL, focus, 0);
  264.     return TRUE;
  265. }
  266.  
  267. /* ================================================================================================ *\
  268.     Fill in the second combo box with valid values, based on the current setting in the first combo
  269. \* ================================================================================================ */
  270. BOOL FillInValue (HWND hwnd, int param)
  271. {
  272.     int i, index, focus;
  273.     long data;
  274.     char szTmp[80];
  275.     ATOM atom;
  276.     HDC  hdc;
  277.     FARPROC lpEnumFonts;
  278.     HINSTANCE hInst;
  279.  
  280.     SendMessage (hwnd, CB_RESETCONTENT, 0, 0);
  281.     focus = -1;
  282.     index = 0;
  283.  
  284.     // Each of the following cases will contain two different 'loops', the first one will fill the
  285.     // combo box with values, the second will locate the current setting in the combobox and set
  286.     // the focus to it. If the value is not currently in the combobox, then it will be inserted at
  287.     // the proper location.
  288.  
  289.     switch (param) {
  290.         case CFP_HEIGHT:
  291.             // Lets just toss in a range of heights, from -72 to 72, by twos
  292.             // If the user wants to enter in a custom value, they need to use
  293.             // the 'CreateFont' dialog for now.
  294.             for (i=-72; i<72; i+=2) {
  295.                 if (i < 0) {
  296.                     wsprintf (szTmp, "%d = cell height = %u", i, abs(i));
  297.                 } else if (i == 0) {
  298.                     wsprintf (szTmp, "%u = default", i);
  299.                 } else {
  300.                     wsprintf (szTmp, "%u = character height", i);
  301.                 }
  302.                 SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)szTmp);
  303.                 SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)i);
  304.             }
  305.  
  306.             for (i=0; i<index; i++) {
  307.                 data = (long)SendMessage (hwnd, CB_GETITEMDATA, i, 0);
  308.                 if (data == lf.lfHeight) {
  309.                     focus = i;
  310.                     break;
  311.                 } else if (data > lf.lfHeight) {
  312.                     wsprintf (szTmp, "%u", lf.lfHeight);
  313.                     SendMessage (hwnd, CB_INSERTSTRING, i, (DWORD)(LPSTR)szTmp);
  314.                     SendMessage (hwnd, CB_SETITEMDATA, i, (DWORD)lf.lfHeight);
  315.                     focus = i;
  316.                     break;
  317.                 }
  318.             }
  319.             if (focus == -1) {
  320.                 wsprintf (szTmp, "%u", lf.lfHeight);
  321.                 focus = (int)SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)szTmp);
  322.                 SendMessage (hwnd, CB_SETITEMDATA, focus, (DWORD)lf.lfHeight);
  323.             }
  324.  
  325.             break;
  326.  
  327.         case CFP_WIDTH:
  328.             // Lets just toss in a range of widths, from 0 to 72, by twos
  329.             // If the user wants to enter in a custom value, they need to use
  330.             // the 'CreateFont' dialog for now.
  331.             for (i=0; i<72; i+=2) {
  332.                 if (i==0) {
  333.                     wsprintf (szTmp, "%u = default aspect", i);
  334.                 } else {
  335.                     wsprintf (szTmp, "%u", i);
  336.                 }
  337.                 SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)szTmp);
  338.                 SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)i);
  339.             }
  340.             for (i=0; i<index; i++) {
  341.                 data = SendMessage (hwnd, CB_GETITEMDATA, i, 0);
  342.                 if (data == lf.lfWidth) {
  343.                     focus = i;
  344.                     break;
  345.                 } else if (data > lf.lfWidth) {
  346.                     wsprintf (szTmp, "%u", lf.lfWidth);
  347.                     SendMessage (hwnd, CB_INSERTSTRING, i, (DWORD)(LPSTR)szTmp);
  348.                     SendMessage (hwnd, CB_SETITEMDATA, i, (DWORD)lf.lfWidth);
  349.                     focus = i;
  350.                     break;
  351.                 }
  352.             }
  353.             break;
  354.  
  355.         case CFP_ESCAPEMENT:
  356.             for (i=0; i<4500; i+=10) {
  357.                 wsprintf (szTmp, "%u = (%u/10 degrees)", i, i);
  358.                 SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)szTmp);
  359.                 SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)i);
  360.             }
  361.             for (i=0; i<index; i++) {
  362.                 data = SendMessage (hwnd, CB_GETITEMDATA, i, 0);
  363.                 if (data == lf.lfEscapement) {
  364.                     focus = i;
  365.                     break;
  366.                 } else if (data > lf.lfEscapement) {
  367.                     wsprintf (szTmp, "%u = (%u/10 degrees)", lf.lfWidth);
  368.                     SendMessage (hwnd, CB_INSERTSTRING, i, (DWORD)(LPSTR)szTmp);
  369.                     SendMessage (hwnd, CB_SETITEMDATA, i, (DWORD)lf.lfEscapement);
  370.                     focus = i;
  371.                     break;
  372.                 }
  373.             }
  374.             break;
  375.  
  376.         case CFP_ORIENTATION:
  377.             for (i=0; i<4500; i+=10) {
  378.                 wsprintf (szTmp, "%u = (%u/10 degrees)", i, i);
  379.                 SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)szTmp);
  380.                 SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)i);
  381.             }
  382.             for (i=0; i<index; i++) {
  383.                 data = SendMessage (hwnd, CB_GETITEMDATA, i, 0);
  384.                 if (data == lf.lfOrientation) {
  385.                     focus = i;
  386.                     break;
  387.                 } else if (data > lf.lfOrientation) {
  388.                     wsprintf (szTmp, "%u = (%u/10 degrees)", lf.lfWidth);
  389.                     SendMessage (hwnd, CB_INSERTSTRING, i, (DWORD)(LPSTR)szTmp);
  390.                     SendMessage (hwnd, CB_SETITEMDATA, i, (DWORD)lf.lfOrientation);
  391.                     focus = i;
  392.                     break;
  393.                 }
  394.             }
  395.             break;
  396.  
  397.         case CFP_WEIGHT:
  398.             index = 0;
  399.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"0 = FW_DONTCARE");
  400.             SendMessage (hwnd, CB_SETITEMDATA, index++, 0);
  401.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"100 = FW_THIN");
  402.             SendMessage (hwnd, CB_SETITEMDATA, index++, 100);
  403.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"200 = FW_EXTRALIGHT");
  404.             SendMessage (hwnd, CB_SETITEMDATA, index++, 200);
  405.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"300 = FW_LIGHT");
  406.             SendMessage (hwnd, CB_SETITEMDATA, index++, 300);
  407.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"400 = FW_NORMAL");
  408.             SendMessage (hwnd, CB_SETITEMDATA, index++, 400);
  409.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"500 = FW_MEDIUM");
  410.             SendMessage (hwnd, CB_SETITEMDATA, index++, 500);
  411.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"600 = FW_SEMIBOLD");
  412.             SendMessage (hwnd, CB_SETITEMDATA, index++, 600);
  413.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"700 = FW_BOLD");
  414.             SendMessage (hwnd, CB_SETITEMDATA, index++, 700);
  415.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"800 = FW_EXTRABOLD");
  416.             SendMessage (hwnd, CB_SETITEMDATA, index++, 800);
  417.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"900 = FW_HEAVY");
  418.             SendMessage (hwnd, CB_SETITEMDATA, index++, 900);
  419.  
  420.             for (i=0; i<index; i++) {
  421.                 data = SendMessage (hwnd, CB_GETITEMDATA, i, 0);
  422.                 if (data == lf.lfWeight) {
  423.                     focus = i;
  424.                     break;
  425.                 } else if (data > lf.lfWeight) {
  426.                     wsprintf (szTmp, "%u", lf.lfWeight);
  427.                     SendMessage (hwnd, CB_INSERTSTRING, i, (DWORD)(LPSTR)szTmp);
  428.                     focus = i;
  429.                     break;
  430.                 }
  431.             }
  432.             break;
  433.  
  434.         case CFP_ITALIC:
  435.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"FALSE");
  436.             SendMessage (hwnd, CB_SETITEMDATA, 0, (DWORD)FALSE);
  437.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"TRUE");
  438.             SendMessage (hwnd, CB_SETITEMDATA, 1, (DWORD)TRUE);
  439.             focus = (lf.lfItalic?1:0);
  440.             break;
  441.  
  442.         case CFP_UNDERLINE:
  443.             index=0;
  444.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"FALSE");
  445.             SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)FALSE);
  446.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"TRUE");
  447.             SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)TRUE);
  448.             focus = (lf.lfUnderline?1:0);
  449.             break;
  450.  
  451.         case CFP_STRIKEOUT:
  452.             index=0;
  453.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"FALSE");
  454.             SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)FALSE);
  455.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"TRUE");
  456.             SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)TRUE);  \
  457.             focus = (lf.lfStrikeOut?1:0);
  458.             break;
  459.  
  460.         case CFP_CHARSET:
  461.             index = 0;
  462.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"0 = ANSI_CHARSET");
  463.             SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)ANSI_CHARSET);
  464.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"SYMBOL_CHARSET");
  465.             SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)SYMBOL_CHARSET);
  466.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"SHIFTJIS_CHARSET");
  467.             SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)SHIFTJIS_CHARSET);
  468.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"OEM_CHARSET");
  469.             SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)OEM_CHARSET);
  470.             for (i=0; i<index; i++) {
  471.                 data = SendMessage (hwnd, CB_GETITEMDATA, i, 0);
  472.                 if (data == (long)lf.lfCharSet) {
  473.                     focus = i;
  474.                     break;
  475.                 }
  476.             }
  477.             break;
  478.  
  479.             break;
  480.  
  481.         case CFP_OUTPUTPRECISION:
  482.             index=0;
  483.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"0 = OUT_DEFAULT_PRECIS");
  484.             SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)OUT_DEFAULT_PRECIS);
  485.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"OUT_STRING_PRECIS");
  486.             SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)OUT_STRING_PRECIS);
  487.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"OUT_CHARACTER_PRECIS");
  488.             SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)OUT_CHARACTER_PRECIS);
  489.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"OUT_STROKE_PRECIS");
  490.             SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)OUT_STROKE_PRECIS);
  491.             for (i=0; i<index; i++) {
  492.                 data = SendMessage (hwnd, CB_GETITEMDATA, i, 0);
  493.                 if (data == (long)lf.lfOutPrecision) {
  494.                     focus = i;
  495.                     break;
  496.                 }
  497.             }
  498.             break;
  499.  
  500.         case CFP_CLIPPRECISION:
  501.             index=0;
  502.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"0 = CLIP_DEFAULT_PRECIS");
  503.             SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)CLIP_DEFAULT_PRECIS);
  504.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"CLIP_CHARACTER_PRECIS");
  505.             SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)CLIP_CHARACTER_PRECIS);
  506.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"CLIP_STROKE_PRECIS");
  507.             SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)CLIP_STROKE_PRECIS);
  508.             for (i=0; i<index; i++) {
  509.                 data = SendMessage (hwnd, CB_GETITEMDATA, i, 0);
  510.                 if (data == (long)lf.lfClipPrecision) {
  511.                     focus = i;
  512.                     break;
  513.                 }
  514.             }
  515.             break;
  516.  
  517.         case CFP_QUALITY:
  518.             index=0;
  519.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"0 = DEFAULT_QUALITY");
  520.             SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)DEFAULT_QUALITY);
  521.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"DRAFT_QUALITY");
  522.             SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)DRAFT_QUALITY);
  523.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"PROOF_QUALITY");
  524.             SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)PROOF_QUALITY);
  525.             for (i=0; i<index; i++) {
  526.                 data = SendMessage (hwnd, CB_GETITEMDATA, i, 0);
  527.                 if (data == (long)lf.lfQuality) {
  528.                     focus = i;
  529.                     break;
  530.                 }
  531.             }
  532.             break;
  533.  
  534.         case CFP_PITCH:
  535.             index=0;
  536.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"0 = DEFAULT_PITCH");
  537.             SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)DEFAULT_PITCH);
  538.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"FIXED_PITCH");
  539.             SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)FIXED_PITCH);
  540.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"VARIABLE_PITCH");
  541.             SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)VARIABLE_PITCH);
  542.             for (i=0; i<index; i++) {
  543.                 data = SendMessage (hwnd, CB_GETITEMDATA, i, 0);
  544.                 if (data == (long)(0x03&lf.lfPitchAndFamily)) {
  545.                     focus = i;
  546.                     break;
  547.                 }
  548.             }
  549.             break;
  550.  
  551.         case CFP_FAMILY:
  552.             index=0;
  553.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"0 = FF_DONTCARE");
  554.             SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)FF_DONTCARE);
  555.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"FF_ROMAN");
  556.             SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)FF_ROMAN);
  557.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"FF_SWISS");
  558.             SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)FF_SWISS);
  559.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"FF_MODERN");
  560.             SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)FF_MODERN);
  561.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"FF_SCRIPT");
  562.             SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)FF_SCRIPT);
  563.             SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"FF_DECORATIVE");
  564.             SendMessage (hwnd, CB_SETITEMDATA, index++, (DWORD)FF_DECORATIVE);
  565.             for (i=0; i<index; i++) {
  566.                 data = SendMessage (hwnd, CB_GETITEMDATA, i, 0);
  567.                 if (data == (long)(0xFC&lf.lfPitchAndFamily)) {
  568.                     focus = i;
  569.                     break;
  570.                 }
  571.             }
  572.             break;
  573.  
  574.         case CFP_FACENAME:
  575.             index = (int)SendMessage (hwnd, CB_ADDSTRING, 0, (DWORD)(LPSTR)"(none)");
  576.             SendMessage (hwnd, CB_SETITEMDATA, index, 0);
  577.             if (lstrcmp(lf.lfFaceName, "(none)") == 0) {
  578.                 lf.lfFaceName[0] = 0;
  579.             }
  580.             hdc = GetDC (hwnd);
  581.  
  582. #if defined (WIN32)
  583.             hInst = (HINSTANCE)GetWindowLong (hwnd, GWL_HINSTANCE);
  584. #else
  585.             hInst = (HINSTANCE)GetWindowWord (hwnd, GWW_HINSTANCE);
  586. #endif
  587.             lpEnumFonts = MakeProcInstance ((FARPROC)EnumFontNames, hInst);
  588.             EnumFonts (hdc, NULL, (FONTENUMPROC)lpEnumFonts, (LPARAM)&hwnd);
  589.             FreeProcInstance (lpEnumFonts);
  590.             ReleaseDC (hwnd, hdc);
  591.             atom = GlobalFindAtom ((LPSTR)lf.lfFaceName);
  592.             if (atom == (ATOM)0 && (lstrlen (lf.lfFaceName)>0)) {
  593.                 index = (int)SendMessage (hwnd, CB_ADDSTRING, 0, (LONG)(LPSTR)lf.lfFaceName);
  594.                 focus = index;
  595.             } else if (lstrlen(lf.lfFaceName)==0) {
  596.                 index = (int)SendMessage (hwnd, CB_FINDSTRING, (UINT)-1, (LONG)(LPSTR)"(none)");
  597.                 focus = index;
  598.             } else {
  599.                 index = (int)SendMessage (hwnd, CB_GETCOUNT, 0, 0);
  600.                 for (i=0; i<index; i++) {
  601.                     data = SendMessage (hwnd, CB_GETITEMDATA, i, 0);
  602.                     if ((DWORD)data == (DWORD)atom) {
  603.                         focus = i;
  604.                         break;
  605.                     }
  606.                 }
  607.             }
  608.             break;
  609.     }
  610.     if (focus >= 0) {
  611.         SendMessage (hwnd, CB_SETCURSEL, focus, 0);
  612.     } else {
  613.         SendMessage (hwnd, CB_SETCURSEL, 0, 0);
  614.     }
  615.     return TRUE;
  616. }
  617.  
  618.  
  619. // Font enumeration callback. This adds the font name to the atom list.
  620. int FAR PASCAL EnumFontNames (LPLOGFONT lpLogFont, LPTEXTMETRIC lpTextMetric, short nFontType, LPINT lpData)
  621. {
  622.     HWND hwnd;
  623.     FARPROC lpFontEnumProc;
  624.     HDC  hdc;
  625.     ATOM atom;
  626.     HWND hwndCombo;
  627.     int  index;
  628.  
  629.     hwnd = GetFocus();
  630.     hdc  = GetDC(hwnd);
  631.     hwndCombo = (HWND)*lpData;
  632.  
  633.     atom = GlobalFindAtom ((LPSTR)lpLogFont->lfFaceName);
  634.     if (atom == (ATOM)0) {
  635.         atom = GlobalAddAtom (lpLogFont->lfFaceName);
  636.     }
  637.     if (index = SendMessage(hwndCombo, CB_FINDSTRING, (UINT)-1, (LONG)(LPSTR)lpLogFont->lfFaceName) == CB_ERR) {
  638.         index = (int)SendMessage (hwndCombo, CB_ADDSTRING, 0, (LONG)(LPSTR)lpLogFont->lfFaceName);
  639.         SendMessage (hwndCombo, CB_SETITEMDATA, index, atom);
  640.     }
  641.  
  642.     ReleaseDC(hwnd, hdc);
  643.  
  644.     return TRUE;
  645.  
  646.     lpTextMetric;   // unreferenced formal paramater
  647.     nFontType;      // unreferenced formal parameter
  648.     lpFontEnumProc; // unreferenced formal parameter
  649. }
  650.  
  651.  
  652. // A quick little routine that will center one window over another, handy for dialog boxes.
  653. BOOL CenterWindow (HWND hwndChild, HWND hwndParent)
  654. {
  655.     RECT    rChild, rParent;
  656.     int     wChild, hChild, wParent, hParent;
  657.     int     wScreen, hScreen, xNew, yNew;
  658.     HDC     hdc;
  659.  
  660.     GetWindowRect (hwndChild, &rChild);
  661.     wChild = rChild.right - rChild.left;
  662.     hChild = rChild.bottom - rChild.top;
  663.  
  664.     GetWindowRect (hwndParent, &rParent);
  665.     wParent = rParent.right - rParent.left;
  666.     hParent = rParent.bottom - rParent.top;
  667.  
  668.     hdc = GetDC (hwndChild);
  669.     wScreen = GetDeviceCaps (hdc, HORZRES);
  670.     hScreen = GetDeviceCaps (hdc, VERTRES);
  671.     ReleaseDC (hwndChild, hdc);
  672.  
  673.     xNew = rParent.left + ((wParent - wChild) /2);
  674.     if (xNew < 0) {
  675.         xNew = 0;
  676.     } else if ((xNew+wChild) > wScreen) {
  677.         xNew = wScreen - wChild;
  678.     }
  679.  
  680.     yNew = rParent.top  + ((hParent - hChild) /2);
  681.     if (yNew < 0) {
  682.         yNew = 0;
  683.     } else if ((yNew+hChild) > hScreen) {
  684.         yNew = hScreen - hChild;
  685.     }
  686.  
  687.     return SetWindowPos (hwndChild, NULL, xNew, yNew, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
  688. }
  689.  
  690.  
  691. LONG APIENTRY WndProc (HWND hwnd, UINT msg, UINT wParam, LONG lParam)
  692. {
  693.     HINSTANCE hInst;
  694.     HDC hdc;
  695.     PAINTSTRUCT ps;
  696.     FARPROC lpDlgFunc;
  697.     char    szMsg [80];
  698.     time_t  lTime;
  699.     struct tm *datetime;
  700.  
  701. #define HOUR (datetime->tm_hour)
  702. #define MIN (datetime->tm_min)
  703. #define SEC (datetime->tm_sec)
  704.  
  705.     char    szTime [20];
  706.     int     index;
  707.     RECT rect;
  708.  
  709. static int  idMenuSelect;
  710.     int     tmp, wmEvent, wmId;
  711.     HWND    wmhWnd;
  712.     POINT   point;
  713.     BOOL bRedraw;
  714.     int wmMenuCmd, wmFlags;
  715.     HMENU wmhMenu;
  716.  
  717.         if (hwnd) {
  718. #if defined (WIN32)
  719.         hInst = (HINSTANCE)GetWindowLong (hwnd, GWL_HINSTANCE);
  720. #else
  721.         hInst = (HINSTANCE)GetWindowWord (hwnd, GWW_HINSTANCE);
  722. #endif
  723.         }
  724.  
  725.     switch (msg) {
  726.     case WM_CREATE:
  727.             return DefWindowProc (hwnd, msg, wParam, lParam);
  728.             break;
  729.  
  730.         case WM_TIMER:
  731.             time (&lTime);
  732.             datetime = localtime (&lTime);
  733.             wsprintf (szTime, "%02d:%02d:%02d %s",
  734.             (HOUR%12?HOUR%12:12), MIN, SEC, (LPSTR)(HOUR/12?"PM":"AM"));
  735.             SetWindowText (hwndTimeField, szTime);
  736.             break;
  737.  
  738.         case WM_SIZE:
  739.             AdjustToolBar (hwnd);
  740.             AdjustStatusBar (hwnd);
  741.             GetClientRect (hwnd, &rect);
  742.             rect.top += ToolBarHeight (hwnd);
  743.             rect.bottom -= StatusBarHeight (hwnd);
  744.             SetWindowPos (hwndClient, NULL, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, SWP_NOZORDER);
  745.             break;
  746.  
  747.         case WM_CHAR:
  748.             switch (wParam) {
  749.                 case VK_F10:
  750.                     wParam = VK_MENU;
  751.                     return DefWindowProc (hwnd, msg, wParam, lParam);
  752.                     break;
  753.             }
  754.             break;
  755.  
  756.         case WM_PARENTNOTIFY:
  757. #if defined (WIN32)
  758.             wmEvent = wParam; // Same as Win16, but only on (x,y) msgs
  759. #else
  760.             wmEvent = wParam;
  761. #endif
  762.             point.x = (int)LOWORD(lParam);
  763.             point.y = (int)HIWORD(lParam);
  764.  
  765.             ClientToScreen (hwnd, &point);
  766.             wmhWnd  = WindowFromPoint(point);
  767.             if (wmhWnd) {
  768. #if defined (WIN32)
  769.                 wmId = GetWindowLong (wmhWnd, GWL_ID);
  770. #else
  771.                 wmId = GetWindowWord (wmhWnd, GWW_ID);
  772. #endif
  773.                         } else {
  774.                                 break;
  775.                         }
  776.             switch (wmEvent) {
  777.                 case WM_LBUTTONDOWN:
  778.                 case WM_MBUTTONDOWN:
  779.                 case WM_RBUTTONDOWN:
  780.                     if (!LoadString (hInst, (UINT)wmId, szMsg, sizeof(szMsg))) {
  781.                         wsprintf ((LPSTR)szMsg, "Unable to load ParentNotify string #%u", wmId);
  782.                     }
  783.                     SetWindowText (hwndMenuField, szMsg);
  784.                     break;
  785.             }
  786.             break;
  787.  
  788.         case WM_COMMAND:
  789. #if defined (WIN32)
  790.             wmId = LOWORD(wParam);
  791.             wmEvent = HIWORD(wParam);
  792. #else
  793.             wmId = wParam;
  794.             wmEvent = HIWORD(lParam);
  795. #endif
  796.  
  797.             switch (wmId) {
  798.                 case ID_CREATEPARAM:
  799.  
  800.                     switch (wmEvent) {
  801.                         case CBN_SETFOCUS: //Indicates that the combo box has received input focus.
  802.                         case CBN_DROPDOWN: //Informs the owner of the combo box that its list box is about to be dropped down.
  803.                             if (!LoadString (hInst, wmId, szMsg, sizeof(szMsg))) {
  804.                                 wsprintf ((LPSTR)szMsg, "Unable to load FontName string #%u", wmId);
  805.                             }
  806.                             SetWindowText (hwndMenuField, szMsg);
  807.                             break;
  808.  
  809.                         case CBN_SELCHANGE: //Sent when the selection has been changed.
  810.                             index = (int)SendMessage (hwndCreateParam, CB_GETCURSEL, 0, 0);
  811.                             if (index != CB_ERR) {
  812.                                 SendMessage (hwndCreateParam, CB_GETLBTEXT, index, (LONG)(LPSTR)szMsg);
  813.                                 FillInValue (hwndCreateValue, CFP_BASE+index);
  814.                             } else {
  815.                                 wsprintf (szMsg, "FontName: CB_ERR while retrieving text");
  816.                             }
  817.                             SetWindowText (hwndMenuField, szMsg);
  818.                             break;
  819.                     }
  820.                     break;
  821.  
  822.                 case ID_CREATEVALUE:
  823.                     switch (wmEvent){
  824.                         int iCreateParam;
  825.                         int iParamValue;
  826.  
  827.                         case CBN_SETFOCUS: //Indicates that the combo box has received input focus.
  828.                         case CBN_DROPDOWN: //Informs the owner of the combo box that its list box is about to be dropped down.
  829.                             if (!LoadString (hInst, wmId, szMsg, sizeof(szMsg))) {
  830.                                 wsprintf (szMsg, "Unable to load FontSize string #%u", wmId);
  831.                             }
  832.                             break;
  833.  
  834.                         case CBN_SELCHANGE: //Sent when the selection has been changed.
  835.                             index = (int)SendMessage (hwndCreateValue, CB_GETCURSEL, 0, 0);
  836.                             bRedraw = FALSE;
  837.                             if (index != CB_ERR) {
  838.                                 SendMessage (hwndCreateValue, CB_GETLBTEXT, index, (LONG)(LPSTR)szMsg);
  839.                                 iCreateParam =
  840.                                     (int)SendMessage (hwndCreateParam, CB_GETITEMDATA,
  841.                                         (WORD)SendMessage (hwndCreateParam, CB_GETCURSEL, 0, (DWORD)0),
  842.                                     (DWORD)0);
  843.                                 iParamValue = (int)SendMessage (hwndCreateValue, CB_GETITEMDATA, index, 0);
  844.  
  845.                                 switch (iCreateParam) {
  846.                                     BYTE tmpByte;
  847.  
  848.                                     case CFP_HEIGHT:
  849.                                         if (lf.lfHeight != iParamValue) {
  850.                                             lf.lfHeight = iParamValue;
  851.                                             bRedraw = TRUE;
  852.                                         }
  853.                                         break;
  854.  
  855.                                     case CFP_WIDTH:
  856.                                         if (lf.lfWidth != iParamValue) {
  857.                                             lf.lfWidth = iParamValue;
  858.                                             bRedraw = TRUE;
  859.                                         }
  860.                                         break;
  861.  
  862.                                     case CFP_ESCAPEMENT:
  863.                                         if (lf.lfEscapement != iParamValue) {
  864.                                             lf.lfEscapement= iParamValue;
  865.                                             bRedraw = TRUE;
  866.                                         }
  867.                                         break;
  868.  
  869.                                     case CFP_ORIENTATION:
  870.                                         if (lf.lfOrientation!= iParamValue) {
  871.                                             lf.lfOrientation= iParamValue;
  872.                                             bRedraw = TRUE;
  873.                                         }
  874.                                         break;
  875.  
  876.                                     case CFP_WEIGHT:
  877.                                         if (lf.lfWeight != iParamValue) {
  878.                                             lf.lfWeight= iParamValue;
  879.                                             bRedraw = TRUE;
  880.                                         }
  881.                                         break;
  882.  
  883.                                     case CFP_ITALIC:
  884.                                         if ((int)lf.lfItalic != iParamValue) {
  885.                                             lf.lfItalic = (BYTE)iParamValue;
  886.                                             bRedraw = TRUE;
  887.                                         }
  888.                                         break;
  889.  
  890.                                     case CFP_UNDERLINE:
  891.                                         if (lf.lfUnderline != (BYTE)iParamValue) {
  892.                                             lf.lfUnderline= (BYTE)iParamValue;
  893.                                             bRedraw = TRUE;
  894.                                         }
  895.                                         break;
  896.  
  897.                                     case CFP_STRIKEOUT:
  898.                                         if (lf.lfStrikeOut != (BYTE)iParamValue) {
  899.                                             lf.lfStrikeOut= (BYTE)iParamValue;
  900.                                             bRedraw = TRUE;
  901.                                         }
  902.                                         break;
  903.  
  904.                                     case CFP_CHARSET:
  905.                                         if (lf.lfCharSet != (BYTE)iParamValue) {
  906.                                             lf.lfCharSet= (BYTE)iParamValue;
  907.                                             bRedraw = TRUE;
  908.                                         }
  909.                                         break;
  910.  
  911.                                     case CFP_OUTPUTPRECISION:
  912.                                         if (lf.lfOutPrecision != (BYTE)iParamValue) {
  913.                                             lf.lfOutPrecision = (BYTE)iParamValue;
  914.                                             bRedraw = TRUE;
  915.                                         }
  916.                                         break;
  917.  
  918.                                     case CFP_CLIPPRECISION:
  919.                                         if (lf.lfClipPrecision != (BYTE)iParamValue) {
  920.                                             lf.lfClipPrecision = (BYTE)iParamValue;
  921.                                             bRedraw = TRUE;
  922.                                         }
  923.                                         break;
  924.  
  925.                                     case CFP_QUALITY:
  926.                                         if (lf.lfQuality != (BYTE)iParamValue) {
  927.                                             lf.lfQuality = (BYTE)iParamValue;
  928.                                             bRedraw = TRUE;
  929.                                         }
  930.                                         break;
  931.  
  932.                                     case CFP_PITCH:
  933.                                         tmpByte = lf.lfPitchAndFamily;
  934.                                         tmpByte &= 0xFC;
  935.                                         tmpByte |= iParamValue;
  936.                                         if (tmpByte != lf.lfPitchAndFamily) {
  937.                                             lf.lfPitchAndFamily = tmpByte;
  938.                                             bRedraw = TRUE;
  939.                                         }
  940.                                         break;
  941.  
  942.                                     case CFP_FAMILY:
  943.                                         tmpByte = lf.lfPitchAndFamily;
  944.                                         tmpByte &= 0x03;
  945.                                         tmpByte |= iParamValue;
  946.                                         if (tmpByte != lf.lfPitchAndFamily) {
  947.                                             lf.lfPitchAndFamily = tmpByte;
  948.                                             bRedraw = TRUE;
  949.                                         }
  950.                                         break;
  951.  
  952.                                     case CFP_FACENAME:
  953.                                         if (lstrcmp (lf.lfFaceName, szMsg)!=0) {
  954.                                             if (lstrcmp(lf.lfFaceName, "(none)") == 0) {
  955.                                                 lf.lfFaceName[0] = 0;
  956.                                             } else {
  957.                                                 wsprintf (lf.lfFaceName, "%s",(LPSTR)szMsg);
  958.                                                 bRedraw = TRUE;
  959.                                             }
  960.                                         }
  961.                                         break;
  962.                                 }
  963.                             } else {
  964.                                 wsprintf (szMsg, "CreateValue: CB_ERR while retrieving text");
  965.                             }
  966.                             if (bRedraw) {
  967.                                 InvalidateRect (hwndClient, NULL, TRUE);
  968.                             }
  969.                             SetWindowText (hwndMenuField, szMsg);
  970.                             break;
  971.                     }
  972.                     break;
  973.  
  974.                 // The Menu Selections
  975.                 case IDM_NEW:
  976.                 case IDM_OPEN:
  977.                 case IDM_CLOSE:
  978.                 case IDM_SAVE:
  979.                 case IDM_SAVEAS:
  980.                 case IDM_PRINT:
  981.                 case IDM_PRINTSET:
  982.                     SetWindowText (hwndMenuField, "This command is not yet implemented.");
  983.                     break;
  984.  
  985.                 case IDM_EXIT:
  986.                     DestroyWindow(hwnd);
  987.                     break;
  988.  
  989.                 case IDM_UNDO:
  990.                 case IDM_CUT:
  991.                 case IDM_COPY:
  992.                 case IDM_PASTE:
  993.                 case IDM_DELETE:
  994.                 case IDM_FIND:
  995.                 case IDM_REPLACE:
  996.                     SetWindowText (hwndMenuField, "This command is not yet implemented.");
  997.                     break;
  998.  
  999.  
  1000.                                 case ID_ZOOM:
  1001.                                         if (bZoomed) {
  1002.                         SetWindowLong (hwndClient, GWL_WNDPROC, (LONG)fpCharSetProc);
  1003.                         bZoomed = FALSE;
  1004.                     } else {
  1005.                         SetWindowLong (hwndClient, GWL_WNDPROC, (LONG)fpGlyphProc);
  1006.                         bZoomed = TRUE;
  1007.                     }
  1008.                     InvalidateRect (hwndClient, NULL, TRUE);
  1009.                     break;
  1010.  
  1011.                 case IDM_CHARSET: // Display the full characater set
  1012.                     SetWindowLong (hwndClient, GWL_WNDPROC, (LONG)fpCharSetProc);
  1013.                     InvalidateRect (hwndClient, NULL, TRUE);
  1014.                     bZoomed = FALSE;
  1015.                     break;
  1016.  
  1017.                 case IDM_GLYPH: // Display a single glyph from the font
  1018.                     SetWindowLong (hwndClient, GWL_WNDPROC, (LONG)fpGlyphProc);
  1019.                     InvalidateRect (hwndClient, NULL, TRUE);
  1020.                     bZoomed = TRUE;
  1021.                     break;
  1022.  
  1023.                     break;
  1024.  
  1025.                 case IDM_TOOLBAR: // This would hide the tool bar
  1026.                     SetWindowText (hwndMenuField, "This command is not yet implemented.");
  1027.                     break;
  1028.  
  1029.                 case IDM_STATUSBAR: // This would hide the status bar
  1030.                     SetWindowText (hwndMenuField, "This command is not yet implemented.");
  1031.                     break;
  1032.  
  1033.                 case IDM_CREATEFONT:
  1034.                     lpDlgFunc = MakeProcInstance((FARPROC) CreateDlgProc, hInst);
  1035.                     DialogBoxParam(hInst, "CreateFont", hwnd, (DLGPROC)lpDlgFunc, (DWORD)(LPLOGFONT)&lf);
  1036.                     FreeProcInstance(lpDlgFunc);
  1037.                     index = (int)SendMessage (hwndCreateParam, CB_GETCURSEL, 0, 0);
  1038.                     if (index != CB_ERR) {
  1039.                         FillInValue (hwndCreateValue, CFP_BASE+index);
  1040.                     } else {
  1041.                         wsprintf (szMsg, "CreateFont: CB_ERR while setting values");
  1042.                     }
  1043.                     InvalidateRect (hwndClient, NULL, TRUE);
  1044.  
  1045.                     break;
  1046.  
  1047.                 case IDM_TEXTMETRIC:
  1048.                     lpDlgFunc = MakeProcInstance((FARPROC) MetricsDlgProc, hInst);
  1049.                     DialogBoxParam(hInst, "TextMetric", hwnd, (DLGPROC)lpDlgFunc, (DWORD)(LPLOGFONT)&lf);
  1050.                     FreeProcInstance(lpDlgFunc);
  1051.                     index = (int)SendMessage (hwndCreateParam, CB_GETCURSEL, 0, 0);
  1052.                     if (index != CB_ERR) {
  1053.                         FillInValue (hwndCreateValue, CFP_BASE+index);
  1054.                     } else {
  1055.                         wsprintf (szMsg, "CreateFont: CB_ERR while setting values");
  1056.                     }
  1057.                     InvalidateRect (hwndClient, NULL, TRUE);
  1058.                     break;
  1059.  
  1060.                 case IDM_ENUMFONTS:
  1061.                     lpDlgFunc = MakeProcInstance((FARPROC) EnumDlgProc, hInst);
  1062.                     DialogBoxParam(hInst, "EnumFonts", hwnd, (DLGPROC)lpDlgFunc, (DWORD)(LPLOGFONT)&lf);
  1063.                     FreeProcInstance(lpDlgFunc);
  1064.                     index = (int)SendMessage (hwndCreateParam, CB_GETCURSEL, 0, 0);
  1065.                     if (index != CB_ERR) {
  1066.                         FillInValue (hwndCreateValue, CFP_BASE+index);
  1067.                     } else {
  1068.                         wsprintf (szMsg, "CreateFont: CB_ERR while setting values");
  1069.                     }
  1070.                     InvalidateRect (hwndClient, NULL, TRUE);
  1071.                     break;
  1072.  
  1073.                 case IDM_OUTLINEMETRICS:
  1074.                     SetWindowText (hwndMenuField, "This command is not yet implemented.");
  1075.                     break;
  1076.  
  1077.                 case IDM_HELP_CONTENTS:
  1078.                     WinHelp (hwnd, "FontView.HLP", HELP_KEY, (DWORD)(LPSTR)"CONTENTS");
  1079.                     break;
  1080.                 case IDM_HELP_INDEX:
  1081.                     WinHelp (hwnd, "FontView.HLP", HELP_KEY, (DWORD)(LPSTR)"INDEX");
  1082.                     break;
  1083.                 case IDM_HELP_OVERVIEW:
  1084.                     WinHelp (hwnd, "FontView.HLP", HELP_KEY, (DWORD)(LPSTR)"OVERVIEW");
  1085.                     break;
  1086.                 case IDM_HELP_GLOSSARY:
  1087.                     WinHelp (hwnd, "FontView.HLP", HELP_KEY, (DWORD)(LPSTR)"GLOSSARY");
  1088.                     break;
  1089.                 case IDM_HELP_TUTORIAL:
  1090.                     WinHelp (hwnd, "FontView.HLP", HELP_KEY, (DWORD)(LPSTR)"TUTORIAL");
  1091.                     break;
  1092.                 case IDM_HELP_DEMO:
  1093.                     WinHelp (hwnd, "FontView.HLP", HELP_KEY, (DWORD)(LPSTR)"DEMO");
  1094.                     break;
  1095.                 case IDM_HELP_HELP:
  1096.                     WinHelp (hwnd, "FontView.HLP", HELP_KEY, (DWORD)(LPSTR)"HELP");
  1097.                     break;
  1098.  
  1099.                 case IDM_ABOUT:
  1100.                     lpDlgFunc = MakeProcInstance((FARPROC) SimpleDlgProc, hInst);
  1101.                     DialogBox(hInst,
  1102.                         (wmId==IDM_ABOUT)?"FONTVIEW":"UsageBox",
  1103.                         hwnd,
  1104.                         (DLGPROC)lpDlgFunc);
  1105.                     FreeProcInstance(lpDlgFunc);
  1106.                     break;
  1107.  
  1108.  
  1109.  
  1110.             }
  1111.             break;
  1112.  
  1113.     case WM_PAINT:
  1114.         hdc = BeginPaint (hwnd, &ps);
  1115.         EndPaint (hwnd, &ps);
  1116.         break;
  1117.  
  1118.     case WM_MENUSELECT:
  1119.         /* A menu item is hilited, get description text for status bar */
  1120.         tmp = idMenuSelect;
  1121.  
  1122. #if defined (WIN32)
  1123.         wmMenuCmd = LOWORD(wParam);
  1124.         wmFlags = HIWORD(wParam);
  1125.         wmhMenu = (HMENU)lParam;
  1126. #else
  1127.         wmMenuCmd =  wParam;
  1128.         wmFlags = LOWORD(lParam);
  1129.         wmhMenu = (HMENU)HIWORD(lParam);
  1130. #endif
  1131.  
  1132.         if((wmhMenu == 0) && (wmFlags = -1)) {
  1133.                 tmp = idMenuSelect = 0;
  1134.                 SetWindowText(hwndMenuField, "Ready...");
  1135.         } else if(wmhMenu == 0) {
  1136.             /* don't do anything for this */
  1137.         } else if(wmFlags & MF_POPUP) {
  1138.             if((HMENU)wmMenuCmd == hSysMenuMain)
  1139.                     idMenuSelect = IDM_SYSMENU;
  1140.             else if((HMENU)wmMenuCmd == hFileMenu)
  1141.                     idMenuSelect = IDM_FILE;
  1142.             else if((HMENU)wmMenuCmd == hEditMenu)
  1143.                     idMenuSelect = IDM_EDIT;
  1144.             else if((HMENU)wmMenuCmd == hViewMenu)
  1145.                     idMenuSelect = IDM_VIEW;
  1146.             else if((HMENU)wmMenuCmd == hMetricsMenu)
  1147.                     idMenuSelect = IDM_DIALOG;
  1148.             else if((HMENU)wmMenuCmd == hHelpMenu)
  1149.                     idMenuSelect = IDM_HELP;
  1150.         } else {
  1151.             if(wmMenuCmd != 0) {            /* separators have wparam of 0 */
  1152.                 idMenuSelect = wmMenuCmd;
  1153.             }
  1154.         }
  1155.  
  1156.         if (idMenuSelect != tmp) {
  1157.             if (!LoadString ( hInst, (int)idMenuSelect, szMsg, sizeof(szMsg))) {
  1158.                 wsprintf ((LPSTR)szMsg, "Unable to load menu string #%u", idMenuSelect);
  1159.             }
  1160.             SetWindowText (hwndMenuField, szMsg);
  1161.         }
  1162.         break;
  1163.  
  1164.         case WM_QUERYENDSESSION:
  1165.             return (MessageBox (GetFocus(), "Exit Application?", szAppTitle,
  1166.                 MB_ICONQUESTION | MB_YESNO) == IDYES);
  1167.  
  1168.         case WM_DESTROY:
  1169.             if (hwnd == hwndMain) {
  1170.                 PostQuitMessage (0);
  1171.             }
  1172.             break;
  1173.  
  1174.         default:
  1175.             return DefWindowProc (hwnd, msg, wParam, lParam);
  1176.     }
  1177.     return 0L;
  1178. }
  1179.  
  1180. LONG APIENTRY ClientProc (HWND hwnd, UINT msg, UINT wParam, LONG lParam)
  1181. {
  1182.     switch (msg) {
  1183.         default:
  1184.             return DefWindowProc (hwnd, msg, wParam, lParam);
  1185.     }
  1186.     return 0L;
  1187. }
  1188.  
  1189.  
  1190. LONG APIENTRY ClientCharSetProc (HWND hwnd, UINT msg, UINT wParam, LONG lParam)
  1191. {
  1192.     HINSTANCE hInst;
  1193.     PAINTSTRUCT ps;
  1194.     HFONT hfont, hfontPrev;
  1195.     RECT rect;
  1196.     HDC hdc;
  1197.     int x, y;
  1198.     BYTE glyph;
  1199.  
  1200.         if (hwnd) {
  1201. #if defined (WIN32)
  1202.         hInst = (HINSTANCE)GetWindowLong (hwnd, GWL_HINSTANCE);
  1203. #else
  1204.         hInst = (HINSTANCE)GetWindowWord (hwnd, GWW_HINSTANCE);
  1205. #endif
  1206.         }
  1207.     switch (msg) {
  1208.         case WM_PAINT:
  1209.             hdc = BeginPaint (hwnd, &ps);
  1210.             hfont = CreateFontIndirect (&lf);
  1211.             hfontPrev = SelectObject (hdc, hfont);
  1212.             GetClientRect (hwnd, &rect);
  1213.             DrawAscii (hdc, &rect, 0);
  1214.             SelectObject (hdc, hfontPrev);
  1215.             DeleteObject (hfont);
  1216.             EndPaint (hwnd, &ps);
  1217.             break;
  1218.  
  1219.         case WM_LBUTTONDBLCLK:
  1220.             x = LOWORD(lParam);
  1221.             y = HIWORD(lParam);
  1222.             //OutputDebugString ("WM_LBUTTONDOWN\n\r");
  1223.             hdc = GetWindowDC (hwnd);
  1224.             hfont = CreateFontIndirect (&lf);
  1225.             hfontPrev = SelectObject (hdc, hfont);
  1226.             GetClientRect (hwnd, &rect);
  1227.  
  1228.             glyph = FindChar (hdc, &rect, x, y);
  1229.             if (glyph) {
  1230.                 SetWindowLong (hwndClient, GWL_WNDPROC, (LONG)fpGlyphProc);
  1231.                 bZoomed = TRUE;
  1232.                 SendMessage (hwndClient, WM_USER, (UINT)glyph, 0);
  1233.                 InvalidateRect (hwndClient, NULL, TRUE);
  1234.             }
  1235.  
  1236.             SelectObject (hdc, hfontPrev);
  1237.             DeleteObject (hfont);
  1238.             ReleaseDC (hwnd, hdc);
  1239.             break;
  1240.  
  1241.  
  1242.         default:
  1243.             return DefWindowProc (hwnd, msg, wParam, lParam);
  1244.     }
  1245.     return 0L;
  1246. }
  1247.  
  1248. LONG APIENTRY ClientGlyphProc (HWND hwnd, UINT msg, UINT wParam, LONG lParam)
  1249. {
  1250.     HINSTANCE hInst;
  1251.     PAINTSTRUCT ps;
  1252.     HFONT hfont, hfontPrev;
  1253.     RECT rect;
  1254.     HDC hdc;
  1255.     TEXTMETRIC tm;
  1256.     static BYTE glyph = 'A';
  1257.  
  1258.         if (hwnd) {
  1259. #if defined (WIN32)
  1260.         hInst = (HINSTANCE)GetWindowLong (hwnd, GWL_HINSTANCE);
  1261. #else
  1262.         hInst = (HINSTANCE)GetWindowWord (hwnd, GWW_HINSTANCE);
  1263. #endif
  1264.         }
  1265.  
  1266.     switch (msg) {
  1267.         case WM_LBUTTONDBLCLK:
  1268.         case WM_LBUTTONDOWN:
  1269.             glyph--;
  1270.             InvalidateRect (hwnd, NULL, TRUE);
  1271.             break;
  1272.  
  1273.         case WM_RBUTTONDBLCLK:
  1274.         case WM_RBUTTONDOWN:
  1275.             glyph++;
  1276.             InvalidateRect (hwnd, NULL, TRUE);
  1277.             break;
  1278.  
  1279.         case WM_USER:
  1280.             glyph = (BYTE)wParam;
  1281.             break;
  1282.  
  1283.         case WM_PAINT:
  1284.             hdc = BeginPaint (hwnd, &ps);
  1285.             hfont = CreateFontIndirect (&lf);
  1286.             hfontPrev = SelectObject (hdc, hfont);
  1287.             GetClientRect (hwnd, &rect);
  1288.  
  1289.             GetTextMetrics (hdc, &tm);
  1290.             if (glyph < tm.tmFirstChar) {
  1291.                 MessageBeep (0);
  1292.                 glyph = tm.tmFirstChar;
  1293.             }
  1294.             if (glyph > tm.tmLastChar) {
  1295.                 MessageBeep(0);
  1296.                 glyph = tm.tmLastChar;
  1297.             }
  1298.  
  1299.             DrawGlyph (hdc, &rect, glyph, hfont);
  1300.             SelectObject (hdc, hfontPrev);
  1301.             DeleteObject (hfont);
  1302.             EndPaint (hwnd, &ps);
  1303.             break;
  1304.  
  1305.         default:
  1306.             return DefWindowProc (hwnd, msg, wParam, lParam);
  1307.     }
  1308.     return 0L;
  1309. }
  1310.