home *** CD-ROM | disk | FTP | other *** search
/ Windows Graphics Programming / Feng_Yuan_Win32_GDI_DirectX.iso / Samples / Chapt_15 / Text / ChooseFont.cpp next >
Encoding:
C/C++ Source or Header  |  2000-05-12  |  13.4 KB  |  498 lines

  1. //-----------------------------------------------------------------------------------//
  2. //              Windows Graphics Programming: Win32 GDI and DirectDraw               //
  3. //                             ISBN  0-13-086985-6                                   //
  4. //                                                                                   //
  5. //  Written            by  Yuan, Feng                             www.fengyuan.com   //
  6. //  Copyright (c) 2000 by  Hewlett-Packard Company                www.hp.com         //
  7. //  Published          by  Prentice Hall PTR, Prentice-Hall, Inc. www.phptr.com      //
  8. //                                                                                   //
  9. //  FileName   : choosefont.cpp                                                         //
  10. //  Description: Customized font selection dialog box                                //
  11. //  Version    : 1.00.000, May 31, 2000                                              //
  12. //-----------------------------------------------------------------------------------//
  13.  
  14. // ChooseFont.cpp Customized Font Selection Dialog Box
  15. #define STRICT
  16. #define NOCRYPT
  17.  
  18. #pragma pack(push, 4)
  19. #include <windows.h>
  20. #pragma pack(pop)
  21.  
  22. #include <assert.h>
  23. #include <tchar.h>
  24. #include <math.h>
  25. #include <commctrl.h>
  26. #include <stdio.h>
  27.  
  28. #include "..\..\include\fonttext.h"
  29. #include "..\..\include\treeview.h"
  30. #include "..\..\include\OutlineMetric.h"
  31.  
  32. #include "ChooseFont.h"
  33.  
  34. // add a single string to a tree view
  35.  
  36. // { <tag> <format> }
  37. // <tag>::= g |   // dword, dword, dword, dword
  38. //          8 |   // dword, dword
  39. //          4 |   // dword
  40. //          2 |   // unsigned short
  41. //          1 |   // unsigned char
  42. //          &     // address of input data
  43.  
  44. const TCHAR Format_LOGFONT [] =
  45.     "4lfHeight: %d\0"
  46.     "4lfWidth:  %d\0"
  47.     "4lfEscapement: %d\0"
  48.     "4lfOrientation: %d\0"
  49.     "4lfWeight: %d\0"
  50.     "1lfItalic: %d\0"
  51.     "1lfUnderline: %d\0"
  52.     "1lfStrikeOut: %d\0"
  53.     "1lfCharSet: %d\0"
  54.     "1lfOutPrecision: %d\0"
  55.     "1lfClipPrecision: %d\0"
  56.     "1lfQuality: %d\0"
  57.     "1lfPitchAndFamily: 0x%x\0"
  58.     "&lfFaceName: %s\0";
  59.  
  60.  
  61. const TCHAR Format_TEXTMETRIC [] =
  62.     "4tmHeight: %d\0"
  63.     "4tmAscent: %d\0"
  64.     "4tmDescent: %d\0"
  65.     "4tmInternalLeading: %d\0"
  66.     "4tmExternalLeading: %d\0"
  67.     "4tmAveCharWidth: %d\0"
  68.     "4tmMaxCharWidth: %d\0"
  69.     "4tmWeight: %d\0"
  70.     "4tmOverhang: %d\0"
  71.     "4tmDigitizedAspectX: %d\0"
  72.     "4tmDigitizedAspectY: %d\0"
  73.     "1tmFirstChar: %d\0"
  74.     "1tmLastChar: %d\0"
  75.     "1tmDefaultChar: %d\0"
  76.     "1tmBreakChar: %d\0"
  77.     "1tmItalic: %d\0"
  78.     "1tmUnderlined: %d\0"
  79.     "1tmStruckOut: %d\0"
  80.     "1tmPitchAndFamily: 0x%x\0"
  81.     "1tmCharSet: %d\0";
  82.  
  83. const TCHAR Format_PANOSE [] = 
  84.     "1bFamilyType: %d\0"
  85.     "1bSerifStyle: %d\0"
  86.     "1bWeight: %d\0"
  87.     "1bProportion: %d\0"
  88.     "1bContrast: %d\0"
  89.     "1bStrokeVariation: %d\0"
  90.     "1bArmStyle: %d\0"
  91.     "1bLetterform: %d\0"
  92.     "1bMidline: %d\0"
  93.     "1bXHeight: %d\0";
  94.  
  95. // partial
  96. const TCHAR Format_OUTLINETEXTMETRIC1 [] =
  97.     "4otmSize: %d\n";
  98.  
  99. const TCHAR Format_OUTLINETEXTMETRIC4 [] =
  100.     "4otmfsSelection: 0x%x\0"
  101.     "4otmfsType: %d\0"
  102.     "4otmsCharSlopeRise: %d\0"
  103.     "4otmsCharSlopeRun: %d\0"
  104.     "4otmItalicAngle: %d\0"
  105.     "4otmEMSquare: %d\0"
  106.     "4otmAscent: %d\0"
  107.     "4otmDescent: %d\0"
  108.     "4otmLineGap: %d\0"
  109.     "4otmsCapEmHeight: %d\0"
  110.     "4otmsXHeight: %d\0"
  111.     "gotmrcFontBox: {%d,%d,%d,%d}\0"
  112.     "4otmMacAscent: %d\0"
  113.     "4otmMacDescent: %d\0"
  114.     "4otmMacLineGap: %d\0"
  115.     "4otmusMinimumPPEM: %d\0"
  116.     "8otmptSubscriptSize: {%d,%d}\0"
  117.     "8otmptSubscriptOffset: {%d,%d}\0"
  118.     "8otmptSuperscriptSize: (%d,%d}\0"
  119.     "8otmptSuperscriptOffset: (%d,%d}\0"
  120.     "4otmsStrikeoutSize: %d\0"
  121.     "4otmsStrikeoutPosition: %d\0"
  122.     "4otmsUnderscoreSize: %d\0"
  123.     "4otmsUnderscorePosition: %d\0";
  124.  
  125. const TCHAR Format_FONTSIGNATURE [] =
  126.     "4fsUsb[0]: 0x%08X\0"
  127.     "4fsUsb[1]: 0x%08X\0"
  128.     "4fsUsb[2]: 0x%08X\0"
  129.     "4fsUsb[3]: 0x%08X\0"
  130.     "4fsCsb[0]: 0x%08X\0"
  131.     "4fsCsb[1]: 0x%08X\0";
  132.  
  133.  
  134. HTREEITEM AddCharWidth(KTreeView & Tree, HDC hDC, const TCHAR * name, HTREEITEM hLast, int typ)
  135. {
  136.     hLast = Tree.InsertItem(hLast, TVI_ROOT, name);
  137.  
  138.     INT       intWidth[256];
  139.     FLOAT     fltWidth[256];
  140.     ABC       abcWidth[256];
  141.     ABCFLOAT abcfWidth[256];
  142.  
  143.     UINT uFirst = ' ';
  144.     UINT uLast  = 0x80;
  145.  
  146.     switch ( typ )
  147.     {
  148.         case 0:         GetCharWidth32(hDC, uFirst, uLast, intWidth);  break;
  149.         case 1:      GetCharWidthFloat(hDC, uFirst, uLast, fltWidth);  break;
  150.         case 2:       GetCharABCWidths(hDC, uFirst, uLast, abcWidth);  break;
  151.         case 3:  GetCharABCWidthsFloat(hDC, uFirst, uLast, abcfWidth); break;
  152.     }
  153.  
  154.     for (UINT ch=uFirst; ch<=uLast; ch++)
  155.     {
  156.         TCHAR mess[MAX_PATH];
  157.  
  158.         sprintf(mess, "%d '%c': ", ch, ch);
  159.  
  160.         TCHAR * num = mess + _tcslen(mess);
  161.  
  162.         switch ( typ )
  163.         {
  164.             case 0: sprintf(num, "%d",    intWidth[ch-uFirst]); break;
  165.             case 1: sprintf(num, "%7.3f", fltWidth[ch-uFirst]); break;
  166.             case 2: sprintf(num, "%d %d %d", abcWidth[ch-uFirst].abcA, abcWidth[ch-uFirst].abcB, abcWidth[ch-uFirst].abcC); break;
  167.             case 3: sprintf(num, "%7.3f %7.3f %7.3f", abcfWidth[ch-uFirst].abcfA, abcfWidth[ch-uFirst].abcfB, abcfWidth[ch-uFirst].abcfC); break;
  168.         }
  169.  
  170.         Tree.InsertItem(TVI_LAST, hLast, mess);
  171.     }
  172.  
  173.     return hLast;
  174. }
  175.  
  176.  
  177. const term Dic_GCP [] =
  178. {
  179.     {    GCP_DBCS,        "GCP_DBCS"            },
  180.     {    GCP_REORDER,    "GCP_REORDER"        },
  181.     {    GCP_USEKERNING, "GCP_USEKERNING"    },
  182.     {    GCP_GLYPHSHAPE, "GCP_GLYPHSHARE"    },
  183.     {    GCP_LIGATE,        "GCP_LIGATE"        },
  184.     {    GCP_DIACRITIC,    "GCP_DIACRITIC"        },
  185.     {    GCP_KASHIDA,    "GCP_KASHIDA"        },
  186.     {    GCP_ERROR,        "GCP_ERROR"            },
  187.     {    GCP_JUSTIFY,    "GCP_JUSTIFY"        },
  188.     {    FLI_GLYPHS,        "FLI_GLYPHS"        },
  189.     {    0,                NULL                }
  190. };
  191.  
  192.  
  193. // Base on LOGFONT, create font, select font, decode font information in a TreeView
  194. void DecodeFont(KTreeView & Tree, LOGFONT * pLf, int dpi)
  195. {
  196.     TCHAR t1[MAX_PATH], t2[MAX_PATH];
  197.  
  198.     HDC hDC     = GetDC(NULL);
  199.  
  200.     HFONT hFont = CreateFontIndirect(pLf);
  201.  
  202.     HTREEITEM hLast, h1;
  203.  
  204.     // LOGFONT
  205.     hLast = Tree.InsertTree(TVI_LAST, TVI_ROOT, "LOGFONT", Format_LOGFONT, pLf);
  206.  
  207.     SelectObject(hDC, hFont);
  208.  
  209.     GetTextFace(hDC, MAX_PATH, t1);
  210.     wsprintf(t2, "GetTextFace: %s", t1);
  211.  
  212.     // GetTextFace
  213.     hLast = Tree.InsertItem(hLast,    TVI_ROOT, t2);
  214.  
  215.     // GetFontLangageInfo
  216.     DWORD langinfo = GetFontLanguageInfo(hDC);
  217.  
  218.     wsprintf(t1, "GetFontLanguageInfo: 0x%x", langinfo);
  219.     hLast = Tree.InsertItem(hLast, TVI_ROOT, t1);
  220.     Tree.AddFlags(hLast, langinfo, Dic_GCP);
  221.  
  222.     // GetTextCharset
  223.     wsprintf(t1, "GetTextCharset: 0x%x", GetTextCharset(hDC));
  224.     hLast = Tree.InsertItem(hLast, TVI_ROOT, t1);
  225.  
  226.     {
  227.         FONTSIGNATURE fs;
  228.         GetTextCharsetInfo(hDC, & fs, 0);
  229.  
  230.         hLast = Tree.InsertTree(hLast, TVI_ROOT, "FONTSIGNATURE", Format_FONTSIGNATURE, & fs);
  231.     }
  232.     
  233.     // TEXTMETRIC
  234.     {
  235.         TEXTMETRIC tm;
  236.         GetTextMetrics(hDC, & tm);
  237.         hLast = Tree.InsertTree(hLast, TVI_ROOT, "TEXTMETRIC", Format_TEXTMETRIC, & tm);
  238.     }
  239.  
  240.     // OUTLINETEXTMETIRC
  241.     {
  242.         KOutlineTextMetric otm(hDC);
  243.  
  244.         if ( otm.m_pOtm )
  245.         {
  246.             // first field of OUTLINTTEXTMETRIC
  247.             hLast = Tree.InsertTree(hLast, TVI_ROOT, "OUTLINETEXTMETRIC", Format_OUTLINETEXTMETRIC1, otm.m_pOtm);
  248.     
  249.             // otmTextMetrics
  250.             h1    =    Tree.InsertTree(TVI_LAST, hLast, "otmTextMetrics: TEXTMETRIC", Format_TEXTMETRIC, & otm.m_pOtm->otmTextMetrics);
  251.  
  252.             // otmPanseNumber
  253.             h1    =    Tree.InsertTree(h1,       hLast, "otmPanoseNumber: PANOSE",    Format_PANOSE,     & otm.m_pOtm->otmPanoseNumber);
  254.  
  255.             // main fields after PANOSE
  256.             h1    = Tree.InsertTree(h1,       hLast, NULL,                         Format_OUTLINETEXTMETRIC4, & otm.m_pOtm->otmfsSelection);
  257.     
  258.             wsprintf(t1, "otmpFamilyName: %s", otm.GetName(otm.m_pOtm->otmpFamilyName));
  259.             h1 = Tree.InsertItem(h1, hLast, t1);
  260.  
  261.             wsprintf(t1, "otmpFaceName: %s", otm.GetName(otm.m_pOtm->otmpFaceName));
  262.             h1 = Tree.InsertItem(h1, hLast, t1);
  263.  
  264.             wsprintf(t1, "otmpStyleName: %s", otm.GetName(otm.m_pOtm->otmpStyleName));
  265.             h1 = Tree.InsertItem(h1, hLast, t1);
  266.  
  267.             wsprintf(t1, "otmpFullName: %s", otm.GetName(otm.m_pOtm->otmpFullName));
  268.             h1 = Tree.InsertItem(h1, hLast, t1);
  269.         }
  270.     }
  271.  
  272.     hLast = AddCharWidth(Tree, hDC, "GetCharWidth32",        hLast, 0);
  273.     hLast = AddCharWidth(Tree, hDC, "GetCharWidthFloat",     hLast, 1);
  274.     hLast = AddCharWidth(Tree, hDC, "GetCharABCWidths",      hLast, 2);
  275.     hLast = AddCharWidth(Tree, hDC, "GetCharABCWidthsFloat", hLast, 3);
  276.  
  277.     // Kerning pairs
  278.     {
  279.         KKerningPair kerning(hDC);
  280.  
  281.         wsprintf(t1, "GetKerningPairs: %d pairs", kerning.m_nPairs);
  282.  
  283.         hLast = Tree.InsertItem(hLast, TVI_ROOT, t1);
  284.  
  285.         for (int i=0; i<kerning.m_nPairs; i++)
  286.         {
  287.             wsprintf(t1, "'%c' (%02x) '%c' (%02x) -> %d", 
  288.                 kerning.m_pKerningPairs[i].wFirst,  kerning.m_pKerningPairs[i].wFirst, 
  289.                 kerning.m_pKerningPairs[i].wSecond, kerning.m_pKerningPairs[i].wSecond, 
  290.                 kerning.m_pKerningPairs[i].iKernAmount);
  291.  
  292.             Tree.InsertItem(TVI_LAST, hLast, t1);
  293.         }
  294.     }
  295.  
  296.     // Cleanup
  297.     SelectObject(hDC, GetStockObject(ANSI_FIXED_FONT));
  298.     DeleteObject(hDC);
  299.     DeleteObject(hFont);
  300. }
  301.  
  302.  
  303. void GenerateTree(HWND hDlg, KTreeView & Tree, int dpi)
  304. {
  305.     LOGFONT lf;
  306.  
  307.     SendMessage(hDlg, WM_CHOOSEFONT_GETLOGFONT, 0, (LPARAM) & lf);
  308.  
  309.     Tree.DeleteAllItems();
  310.     DecodeFont(Tree, & lf, dpi);
  311. }
  312.  
  313. /*
  314. // Resolution setup dialog box: not used
  315. class KSetup : public KDialog
  316. {
  317.     virtual BOOL OnInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam)
  318.     {
  319.         m_hWnd = hWnd;
  320.     
  321.         SendDlgItemMessage(hWnd, IDC_SCREEN, BM_SETCHECK, BST_CHECKED, 0);
  322.         return TRUE;
  323.     }
  324.     
  325.     virtual BOOL OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
  326.     {
  327.         switch ( LOWORD(wParam) )
  328.         {
  329.             case IDOK:
  330.                 {
  331.                     int rslt = 1;
  332.  
  333.                     if ( SendDlgItemMessage(hWnd, IDC_120, BM_GETCHECK, 0, 0)==BST_CHECKED )
  334.                         rslt = 120;
  335.                     else if ( SendDlgItemMessage(hWnd, IDC_180, BM_GETCHECK, 0, 0)==BST_CHECKED )
  336.                         rslt = 180;
  337.                     else if ( SendDlgItemMessage(hWnd, IDC_300, BM_GETCHECK, 0, 0)==BST_CHECKED )
  338.                         rslt = 300;
  339.                     else if ( SendDlgItemMessage(hWnd, IDC_1800, BM_GETCHECK, 0, 0)==BST_CHECKED )
  340.                         rslt = 1800;
  341.  
  342.                     EndDialog(hWnd, rslt);
  343.                     return TRUE;
  344.                 }
  345.             
  346.             case IDCANCEL:
  347.                 EndDialog(hWnd, 0);
  348.                 return TRUE;
  349.         }
  350.  
  351.         return FALSE;
  352.     }
  353.  
  354. };
  355. */
  356.  
  357. // Customized Font Selection Dialog Box
  358. class KChooseFont
  359. {
  360.     typedef enum { MAX_DPINO= 5 };
  361.  
  362.     KTreeView m_Tree;
  363.     HWND      m_hButton[MAX_DPINO];
  364.     int          m_nDPI   [MAX_DPINO];
  365.  
  366.     // member hook function
  367.     UINT HookProc(HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
  368.     {
  369.         switch ( uiMsg )
  370.         {
  371.             case WM_INITDIALOG:
  372.                 {
  373.                     RECT rect;
  374.                     GetWindowRect(hDlg, & rect);
  375.                     // enlarge the window by 260 pixels on the right
  376.                     MoveWindow(hDlg, rect.left, rect.top, rect.right - rect.left + 260, 
  377.                         rect.bottom - rect.top, TRUE);
  378.  
  379.                     // get new client area dimension
  380.                     GetClientRect(hDlg, & rect);
  381.  
  382.                     // add a treeview child window on the right
  383.                     m_Tree.Create(hDlg, 1, rect.right - 270, 2, 266, rect.bottom - 4,
  384.                                 (HINSTANCE) GetWindowLong(hDlg, GWL_HINSTANCE));
  385.  
  386.                     GetWindowRect(GetDlgItem(hDlg, 0x402), & rect);
  387.                     MapWindowPoints(NULL, hDlg, (POINT *) & rect, 2);
  388.                     
  389.                     HDC hDC = GetDC(NULL);
  390.                     m_nDPI[0] = GetDeviceCaps(hDC, LOGPIXELSX);
  391.                     DeleteObject(hDC);
  392.  
  393.                     m_nDPI[1] =  120;
  394.                     m_nDPI[2] =  180;
  395.                     m_nDPI[3] =  300;
  396.                     m_nDPI[4] = 1800;
  397.  
  398.                     ReleaseDC(NULL, hDC);
  399.  
  400. /*                    for (int i=0; i<MAX_DPINO; i++)
  401.                     {
  402.                         rect.top    += 30;
  403.                         rect.bottom += 30;
  404.                     
  405.                         TCHAR temp[32];
  406.                         wsprintf(temp, "%d dpi", m_nDPI[i]);
  407.                         
  408.                         m_hButton[i] = CreateWindow("BUTTON", temp,
  409.                             WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
  410.                             rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
  411.                             hDlg, (HMENU) (1234+i), (HINSTANCE) GetWindowLong(hDlg, GWL_HINSTANCE), NULL);
  412.  
  413.                         SendMessage(m_hButton[i], WM_SETFONT, SendDlgItemMessage(hDlg, 0x402, WM_GETFONT, 0, 0), TRUE);
  414.                     }
  415. */
  416.                 }
  417.                 return 1;
  418.  
  419.             case WM_COMMAND:
  420.                 if ( LOWORD(wParam)==0x402 ) // APPLY button
  421.                 {
  422.                     int dpi = m_nDPI[0];
  423.  
  424. /*                    for (int i=0; i<MAX_DPINO; i++)
  425.                         if ( SendMessage(m_hButton[i], BM_GETCHECK, 0, 0)==BST_CHECKED )
  426.                         {
  427.                             dpi = m_nDPI[i];
  428.                             break;
  429.                         }
  430. */
  431.                     GenerateTree(hDlg, m_Tree, dpi);
  432.                     return 1;
  433.                 }
  434.         }
  435.  
  436.         return 0;
  437.     }
  438.  
  439.     // static hook function
  440.     static UINT CALLBACK CFHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
  441.     {
  442.         if ( uiMsg == WM_INITDIALOG )
  443.         {
  444.             CHOOSEFONT * p = (CHOOSEFONT *) lParam;
  445.  
  446.             if ( IsBadWritePtr(p, sizeof(CHOOSEFONT)) )
  447.                 return 0;
  448.         
  449.             SetWindowLong(hdlg, GWL_USERDATA, p->lCustData);
  450.         }
  451.  
  452.         KChooseFont * p = (KChooseFont *) GetWindowLong(hdlg, GWL_USERDATA);
  453.  
  454.         if ( IsBadWritePtr(p, sizeof(KChooseFont)) )
  455.             return 0;
  456.         else
  457.             return p->HookProc(hdlg, uiMsg, wParam, lParam);
  458.     }
  459.  
  460. public:
  461.     CHOOSEFONT m_cf; 
  462.     LOGFONT       m_lf; 
  463.  
  464.     HFONT ChooseFont(HINSTANCE hInstance)
  465.     {
  466.         // Initialize members of the CHOOSEFONT structure. 
  467.         memset(& m_cf, 0, sizeof(m_cf));
  468.  
  469.         m_cf.lStructSize = sizeof(CHOOSEFONT); 
  470.         m_cf.lpLogFont   = & m_lf; 
  471.         m_cf.Flags         = CF_APPLY | CF_BOTH | CF_EFFECTS | CF_ENABLEHOOK; 
  472.         m_cf.lpfnHook    = CFHookProc;
  473.         m_cf.rgbColors   = RGB(0,0,0); 
  474.         m_cf.nFontType   = SCREEN_FONTTYPE; 
  475.         m_cf.lCustData   = (LPARAM) this; // pass to hook function
  476.  
  477. //        KSetup setup;
  478.  
  479. //        int rslt = setup.Dialogbox(hInstance, MAKEINTRESOURCE(IDD_SETUP));
  480.  
  481.         if ( ::ChooseFont(&m_cf) ) 
  482.             return CreateFontIndirect(& m_lf);
  483.         else
  484.             return NULL;
  485.     }
  486. };    
  487.  
  488.  
  489. void FontSelection(HINSTANCE hInst)
  490. {
  491.     KChooseFont cf;
  492.  
  493.     HFONT hFont = cf.ChooseFont(hInst);
  494.  
  495.     DeleteObject(hFont);
  496. }
  497.  
  498.