home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / progwin / chap14 / fontlist.c next >
Encoding:
C/C++ Source or Header  |  1990-11-12  |  15.9 KB  |  433 lines

  1. /*-----------------------------------------
  2.    FONTLIST.C -- Font Enumeration Program
  3.                  (c) Charles Petzold, 1990
  4.   -----------------------------------------*/
  5.  
  6. #include <windows.h>
  7. #include <string.h>
  8. #include "fontlist.h"
  9.  
  10. typedef struct
  11.      {
  12.      GLOBALHANDLE hGMem ;
  13.      short        nCount ;
  14.      }
  15.      ENUMER ;
  16.  
  17. typedef struct
  18.      {
  19.      short        nFontType ;
  20.      LOGFONT      lf ;
  21.      TEXTMETRIC   tm ;
  22.      }
  23.      FONT ;
  24.  
  25. long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;
  26. int  FAR PASCAL EnumAllFaces (LPLOGFONT, LPTEXTMETRIC, short, ENUMER FAR *) ;
  27. int  FAR PASCAL EnumAllFonts (LPLOGFONT, LPTEXTMETRIC, short, ENUMER FAR *) ;
  28.  
  29. char szAppName[] = "FontList" ;
  30.  
  31. int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
  32.                     LPSTR lpszCmdLine, int nCmdShow)
  33.      {
  34.      HWND     hwnd ;
  35.      MSG      msg ;
  36.      WNDCLASS wndclass ;
  37.  
  38.      if (!hPrevInstance) 
  39.           {
  40.           wndclass.style         = CS_HREDRAW | CS_VREDRAW;
  41.           wndclass.lpfnWndProc   = WndProc ;
  42.           wndclass.cbClsExtra    = 0 ;
  43.           wndclass.cbWndExtra    = 0 ;
  44.           wndclass.hInstance     = hInstance ;
  45.           wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
  46.           wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
  47.           wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
  48.           wndclass.lpszMenuName  = szAppName ;
  49.           wndclass.lpszClassName = szAppName ;
  50.  
  51.           RegisterClass (&wndclass) ;
  52.           }
  53.      hwnd = CreateWindow (szAppName, "Font Enumeration",
  54.                           WS_OVERLAPPEDWINDOW | WS_VSCROLL,
  55.                           CW_USEDEFAULT, CW_USEDEFAULT,
  56.                           CW_USEDEFAULT, CW_USEDEFAULT,
  57.                           NULL, NULL, hInstance, NULL) ;
  58.  
  59.      ShowWindow (hwnd, nCmdShow) ;
  60.      UpdateWindow (hwnd) ;
  61.  
  62.      while (GetMessage (&msg, NULL, 0, 0))
  63.           {
  64.           TranslateMessage (&msg) ;
  65.           DispatchMessage (&msg) ;
  66.           }
  67.      return msg.wParam ;
  68.      }
  69.  
  70. int FAR PASCAL EnumAllFaces (LPLOGFONT lf, LPTEXTMETRIC tm,
  71.                              short nFontType, ENUMER FAR *enumer)
  72.      {
  73.      LPSTR lpFaces ;
  74.  
  75.      if (NULL == GlobalReAlloc (enumer->hGMem,
  76.                          (DWORD) LF_FACESIZE * (1 + enumer->nCount),
  77.                          GMEM_MOVEABLE))
  78.           return 0 ;
  79.  
  80.      lpFaces = GlobalLock (enumer->hGMem) ;
  81.      lstrcpy (lpFaces + enumer->nCount * LF_FACESIZE, lf->lfFaceName) ;
  82.      GlobalUnlock (enumer->hGMem) ;
  83.      enumer->nCount ++ ;
  84.      return 1 ;
  85.      }
  86.  
  87. int FAR PASCAL EnumAllFonts (LPLOGFONT lf, LPTEXTMETRIC tm,
  88.                              short nFontType, ENUMER FAR *enumer)
  89.      {
  90.      FONT FAR *font ;
  91.  
  92.      if (NULL == GlobalReAlloc (enumer->hGMem,
  93.                          (DWORD) sizeof (FONT) * (1 + enumer->nCount),
  94.                          GMEM_MOVEABLE))
  95.           return 0 ;
  96.  
  97.      font = (FONT FAR *) GlobalLock (enumer->hGMem) + enumer->nCount ;
  98.      font->nFontType = nFontType ;
  99.      font->lf = *lf ;
  100.      font->tm = *tm ;
  101.  
  102.      GlobalUnlock (enumer->hGMem) ;
  103.      enumer->nCount ++ ;
  104.      return 1 ;
  105.      }
  106.  
  107. void Display (HDC hdc, short cxChar, short cyChar, FONT FAR *font)
  108.      {
  109.      static FONT f ;
  110.  
  111.      static char *szYN [] = { "No",         "Yes" } ;
  112.      static char *szCS [] = { "ANSI",       "?????",   "Kanji",    "OEM" } ;
  113.      static char *szOP [] = { "Default",    "String",  "Char",    "Stroke" } ;
  114.      static char *szCP [] = { "Default",    "Char",    "Stroke",   "?????" } ;
  115.      static char *szQU [] = { "Draft",      "Default", "Proof",    "?????" } ;
  116.      static char *szP1 [] = { "Default",    "Fixed",   "Variable", "?????" } ;
  117.      static char *szP2 [] = { "Fixed",      "Variable" } ;
  118.      static char *szFA [] = { "Don't Care", "Roman",      "Swiss", "Modern",
  119.                               "Script",     "Decorative", "?????", "?????" } ;
  120.      static char *szVR [] = { "Stroke",     "Raster" } ;
  121.      static char *szGD [] = { "GDI",        "Device" } ;
  122.  
  123.      static struct 
  124.           {
  125.           short x ;
  126.           short y ;
  127.           char  *szFmt ;
  128.           short *pData ;
  129.           }
  130.           shorts [] = 
  131.           {
  132.            1,  1, "LOGFONT",            NULL, 
  133.            1,  2, "-------",            NULL,
  134.            1,  3, "Height:      %10d",  &f.lf.lfHeight,
  135.            1,  4, "Width:       %10d",  &f.lf.lfWidth,
  136.            1,  5, "Escapement:  %10d",  &f.lf.lfEscapement,
  137.            1,  6, "Orientation: %10d",  &f.lf.lfOrientation,
  138.            1,  7, "Weight:      %10d",  &f.lf.lfWeight,
  139.           28,  1, "TEXTMETRIC",         NULL,
  140.           28,  2, "----------",         NULL,
  141.           28,  3, "Height:       %5d",  &f.tm.tmHeight,
  142.           28,  4, "Ascent:       %5d",  &f.tm.tmAscent,
  143.           28,  5, "Descent:      %5d",  &f.tm.tmDescent,
  144.           28,  6, "Int. Leading: %5d",  &f.tm.tmInternalLeading,
  145.           28,  7, "Ext. Leading: %5d",  &f.tm.tmExternalLeading,
  146.           28,  8, "Ave. Width:   %5d",  &f.tm.tmAveCharWidth,
  147.           28,  9, "Max. Width:   %5d",  &f.tm.tmMaxCharWidth,
  148.           28, 10, "Weight:       %5d",  &f.tm.tmWeight,
  149.           51, 10, "Overhang:     %10d", &f.tm.tmOverhang,
  150.           51, 11, "Digitized X:  %10d", &f.tm.tmDigitizedAspectX,
  151.           51, 12, "Digitized Y:  %10d", &f.tm.tmDigitizedAspectY
  152.           } ;
  153.  
  154.      static struct 
  155.           {
  156.           short x ;
  157.           short y ;
  158.           char  *szFmt ;
  159.           BYTE  *pData ;
  160.           }
  161.           bytes [] = 
  162.           {
  163.           51,  3, "First Char:   %10d", &f.tm.tmFirstChar,
  164.           51,  4, "Last Char:    %10d", &f.tm.tmLastChar,
  165.           51,  5, "Default Char: %10d", &f.tm.tmDefaultChar,
  166.           51,  6, "Break Char:   %10d", &f.tm.tmBreakChar
  167.           } ;
  168.  
  169.      static struct 
  170.           {
  171.           short x ;
  172.           short y ;
  173.           char  *szFmt ;
  174.           BYTE  *pData ;
  175.           char  **szArray ;
  176.           short sAnd ;
  177.           short sShift ;
  178.           }
  179.           strings [] = 
  180.           {
  181.            1,  8, "Italic:      %10s",  &f.lf.lfItalic,         szYN, 1,    0,
  182.            1,  9, "Underline:   %10s",  &f.lf.lfUnderline,      szYN, 1,    0,
  183.            1, 10, "Strike-Out:  %10s",  &f.lf.lfStrikeOut,      szYN, 1,    0,
  184.            1, 11, "Char Set:    %10s",  &f.lf.lfCharSet,        szCS, 0xC0, 6,
  185.            1, 12, "Out  Prec:   %10s",  &f.lf.lfOutPrecision,   szOP, 3,    0,
  186.            1, 13, "Clip Prec:   %10s",  &f.lf.lfClipPrecision,  szCP, 3,    0, 
  187.            1, 14, "Quality:     %10s",  &f.lf.lfQuality,        szQU, 3,    0,
  188.            1, 15, "Pitch:       %10s",  &f.lf.lfPitchAndFamily, szP1, 3,    0,
  189.            1, 16, "Family:      %10s",  &f.lf.lfPitchAndFamily, szFA, 0x70, 4,
  190.           28, 11, "Italic:       %5s",  &f.tm.tmItalic,         szYN, 1,    0,
  191.           28, 12, "Underline:    %5s",  &f.tm.tmUnderlined,     szYN, 1,    0,
  192.           28, 13, "Strike-Out:   %5s",  &f.tm.tmStruckOut,      szYN, 1,    0,
  193.           51,  7, "Pitch:        %10s", &f.tm.tmPitchAndFamily, szP2, 1,    0,
  194.           51,  8, "Family:       %10s", &f.tm.tmPitchAndFamily, szFA, 0x70, 4,
  195.           51,  9, "Char Set:     %10s", &f.tm.tmCharSet,        szCS, 0xC0, 6,
  196.           36, 15, "Font Type:  %6s",    (BYTE *) &f.nFontType,  szVR, 1,    0,
  197.           55, 15, "%s",                 (BYTE *) &f.nFontType,  szGD, 2,    1
  198.           } ;
  199.     
  200.      char szBuffer [80] ;
  201.      int  i ;
  202.  
  203.      f = *font ;
  204.  
  205.      for (i = 0 ; i < sizeof shorts / sizeof shorts [0] ; i++)
  206.           TextOut (hdc, cxChar * shorts[i].x, cyChar * shorts[i].y, szBuffer,
  207.                    wsprintf (szBuffer, shorts[i].szFmt,
  208.                              *shorts[i].pData)) ;
  209.  
  210.      for (i = 0 ; i < sizeof bytes / sizeof bytes [0] ; i++)
  211.           TextOut (hdc, cxChar * bytes[i].x, cyChar * bytes[i].y, szBuffer,
  212.                    wsprintf (szBuffer, bytes[i].szFmt,
  213.                              *bytes[i].pData)) ;
  214.  
  215.      for (i = 0 ; i < sizeof strings / sizeof strings [0] ; i++)
  216.           TextOut (hdc, cxChar * strings[i].x, cyChar * strings[i].y, szBuffer,
  217.                    wsprintf (szBuffer, strings[i].szFmt,
  218.                              (LPSTR) ((strings[i].szArray)
  219.                                   [(*strings[i].pData & strings[i].sAnd) >>
  220.                                         strings[i].sShift]))) ;
  221.  
  222.      TextOut (hdc, cxChar, cyChar * 17, szBuffer,
  223.               wsprintf (szBuffer, "Face Name:   %10s",
  224.                         (LPSTR) f.lf.lfFaceName)) ;
  225.      }
  226.  
  227. HDC GetPrinterIC ()
  228.      {
  229.      char szPrinter [64] ;
  230.      char *szDevice, *szDriver, *szOutput ;
  231.  
  232.      GetProfileString ("windows", "device", "", szPrinter, 64) ;
  233.  
  234.      if ((szDevice = strtok (szPrinter, "," )) &&
  235.          (szDriver = strtok (NULL,      ", ")) && 
  236.          (szOutput = strtok (NULL,      ", ")))
  237.           
  238.                return CreateIC (szDriver, szDevice, szOutput, NULL) ;
  239.  
  240.      return NULL ;
  241.      }
  242.  
  243. long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  244.      {
  245.      static BOOL    bHaveInfo = FALSE ;
  246.      static ENUMER  enumer1, enumer2 ;
  247.      static FARPROC lpfnEnumAllFaces, lpfnEnumAllFonts ;
  248.      static short   cxChar, cyChar, nCurrent ;
  249.      static WORD    wCurrentDC = IDM_SCREEN ;
  250.      HANDLE         hInstance ;
  251.      HDC            hdc ;
  252.      HFONT          hFont ;
  253.      HMENU          hMenu ;
  254.      FONT FAR       *font ;
  255.      LPSTR          lpFaces ;
  256.      PAINTSTRUCT    ps ;
  257.      short          i ;
  258.      TEXTMETRIC     tm ;
  259.  
  260.      switch (message)
  261.           {
  262.           case WM_CREATE:
  263.                hInstance = ((LPCREATESTRUCT) lParam)-> hInstance ;
  264.                lpfnEnumAllFaces = MakeProcInstance (EnumAllFaces, hInstance) ;
  265.                lpfnEnumAllFonts = MakeProcInstance (EnumAllFonts, hInstance) ;
  266.  
  267.                hdc = GetDC (hwnd) ;
  268.                SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
  269.  
  270.                GetTextMetrics (hdc, (LPTEXTMETRIC) &tm) ;
  271.                cxChar = tm.tmAveCharWidth ;
  272.                cyChar = tm.tmHeight + tm.tmExternalLeading ;
  273.  
  274.                ReleaseDC (hwnd, hdc) ;
  275.                return 0 ;
  276.                               
  277.           case WM_COMMAND:
  278.                if (wParam == IDM_EXIT)
  279.                     {
  280.                     SendMessage (hwnd, WM_CLOSE, 0, 0L) ;
  281.                     return 0 ;
  282.                     }
  283.                else if (wParam == wCurrentDC)
  284.                     return 0 ;
  285.  
  286.                hMenu = GetMenu (hwnd) ;
  287.                CheckMenuItem (hMenu, wCurrentDC, MF_UNCHECKED) ;
  288.                CheckMenuItem (hMenu, wCurrentDC = wParam, MF_CHECKED) ;
  289.  
  290.                                         // fall through
  291.  
  292.           case WM_DEVMODECHANGE:
  293.           case WM_FONTCHANGE:
  294.                bHaveInfo = FALSE ;               
  295.                InvalidateRect (hwnd, NULL, TRUE) ;
  296.                return 0 ;
  297.  
  298.           case WM_PAINT:
  299.                if (!bHaveInfo)
  300.                     {
  301.                     if (enumer2.hGMem)
  302.                          GlobalFree (enumer2.hGMem) ;
  303.  
  304.                     enumer1.hGMem  = GlobalAlloc (GHND, 1L) ;
  305.                     enumer1.nCount = 0 ;
  306.  
  307.                     enumer2.hGMem  = GlobalAlloc (GHND, 1L) ;
  308.                     enumer2.nCount = 0 ;
  309.  
  310.                     if (NULL == enumer1.hGMem || NULL == enumer2.hGMem)
  311.                          goto MEMORY_ERROR ;
  312.  
  313.                     if (wCurrentDC == IDM_SCREEN)
  314.                          hdc = CreateIC ("DISPLAY", NULL, NULL, NULL) ;
  315.                     else
  316.                          hdc = GetPrinterIC () ;
  317.  
  318.                     if (hdc)
  319.                          {
  320.                          if (0 == EnumFonts (hdc, NULL, lpfnEnumAllFaces,
  321.                                                   (LPSTR) &enumer1))
  322.                               goto MEMORY_ERROR ;
  323.  
  324.                          lpFaces = GlobalLock (enumer1.hGMem) ;
  325.  
  326.                          for (i = 0 ; i < enumer1.nCount ; i++)
  327.                               if (0 == EnumFonts (hdc,
  328.                                              lpFaces + i * LF_FACESIZE,
  329.                                              lpfnEnumAllFonts,
  330.                                              (LPSTR) &enumer2))
  331.                                    goto MEMORY_ERROR ;
  332.  
  333.                          GlobalUnlock (enumer1.hGMem) ;
  334.                          enumer2.nCount-- ;
  335.      
  336.                          DeleteDC (hdc) ;
  337.                          bHaveInfo = TRUE ;
  338.                          }
  339.                     GlobalFree (enumer1.hGMem) ;
  340.                     SetScrollRange (hwnd, SB_VERT, 0, enumer2.nCount, FALSE) ;
  341.                     SetScrollPos   (hwnd, SB_VERT, nCurrent = 0, TRUE) ;
  342.                     }
  343.  
  344.                hdc = BeginPaint (hwnd, &ps) ;
  345.  
  346.                if (bHaveInfo)
  347.                     {
  348.                     SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
  349.  
  350.                     font = (FONT FAR *) GlobalLock (enumer2.hGMem) + nCurrent ;
  351.                     Display (hdc, cxChar, cyChar, font) ;
  352.  
  353.                     hFont = SelectObject (hdc, CreateFontIndirect (&font->lf));
  354.  
  355.                     TextOut (hdc, 1 * cxChar, 19 * cyChar,
  356.                         "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz",
  357.                          52) ;
  358.  
  359.                     GlobalUnlock (enumer2.hGMem) ;
  360.                     DeleteObject (SelectObject (hdc, hFont)) ;
  361.                     }
  362.  
  363.                EndPaint (hwnd, &ps) ;
  364.                return 0 ;
  365.  
  366.           case WM_KEYDOWN:
  367.                switch (wParam)
  368.                     {
  369.                     case VK_HOME:
  370.                          SendMessage (hwnd, WM_VSCROLL, SB_TOP, 0L) ;
  371.                          break ;
  372.                     case VK_END:
  373.                          SendMessage (hwnd, WM_VSCROLL, SB_BOTTOM, 0L) ;
  374.                          break ;
  375.                     case VK_LEFT:
  376.                     case VK_UP:
  377.                     case VK_PRIOR:
  378.                          SendMessage (hwnd, WM_VSCROLL, SB_LINEUP, 0L) ;
  379.                          break ;
  380.                     case VK_RIGHT:
  381.                     case VK_DOWN:
  382.                     case VK_NEXT:
  383.                          SendMessage (hwnd, WM_VSCROLL, SB_LINEDOWN, 0L) ;
  384.                          break ;
  385.                     default:
  386.                          return 0 ;
  387.                     }
  388.                return 0 ;
  389.  
  390.           case WM_VSCROLL:
  391.                switch (wParam)
  392.                     {
  393.                     case SB_TOP:
  394.                          nCurrent = 0 ;
  395.                          break ;
  396.                     case SB_BOTTOM:
  397.                          nCurrent = enumer2.nCount ;
  398.                          break ;
  399.                     case SB_LINEUP:
  400.                     case SB_PAGEUP:
  401.                          nCurrent -- ;
  402.                          break ;
  403.                     case SB_LINEDOWN:
  404.                     case SB_PAGEDOWN:
  405.                          nCurrent ++ ;
  406.                          break ;
  407.                     case SB_THUMBPOSITION:
  408.                          nCurrent = LOWORD (lParam) ;
  409.                          break ;
  410.                     default:
  411.                          return 0 ;
  412.                     }
  413.                nCurrent = min (max (0, nCurrent), enumer2.nCount) ;
  414.                SetScrollPos (hwnd, SB_VERT, nCurrent, TRUE) ;
  415.                InvalidateRect (hwnd, NULL, TRUE) ;
  416.                return 0 ;
  417.  
  418.           MEMORY_ERROR:
  419.                MessageBox (hwnd, "Cannot allocate memory, must end.",
  420.                     szAppName, MB_OK | MB_ICONSTOP | MB_SYSTEMMODAL) ;
  421.  
  422.                                              // fall through
  423.           case WM_CLOSE:
  424.                DestroyWindow (hwnd) ;
  425.                return 0 ;
  426.  
  427.           case WM_DESTROY:
  428.                PostQuitMessage (0) ;
  429.                return 0 ;
  430.           }
  431.      return DefWindowProc (hwnd, message, wParam, lParam) ;
  432.      }
  433.