第17章 文本和字体_17.3 逻辑字体

17.3 逻辑字体

17.3.1 逻辑字体的创建和选择

(1)创建逻辑字体 hFont= CreateFontIndirect(&lf); //其中LOGFONT为结构体

(2)SelectObject(hdc,hFont); //选入并匹配字体或使用从ChooseFont中选择的字体

(3)返回选入设备环境的字体信息:

①GetTextFace(hdc,sizeof(szFaceName)/sizeof(TCHAR),szFaceName);//返回字样名称

②GetTextMetrics(hdc,&tm); //注意:TEXTMETRIC结构体和LOGFONT的不同。

17.3.2 PICKFONT程序

/*-----------------------------------------
   PICKFONT.C -- Create Logical Font
                 (c) Charles Petzold, 1998
  -----------------------------------------*/

#include <windows.h>
#include "resource.h"

     // Structure shared between main window and dialog box

typedef struct
{
     int        iDevice, iMapMode ;
     BOOL       fMatchAspect ;
     BOOL       fAdvGraphics ;
     LOGFONT    lf ;
     TEXTMETRIC tm ;
     TCHAR      szFaceName [LF_FULLFACESIZE] ;
}
DLGPARAMS ;

     // Formatting for BCHAR fields of TEXTMETRIC structure

#ifdef UNICODE
#define BCHARFORM TEXT ("0x%04X")
#else
#define BCHARFORM TEXT ("0x%02X")
#endif

     // Global variables

HWND  hdlg ;
TCHAR szAppName[] = TEXT ("PickFont") ;

     // Forward declarations of functions

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
BOOL    CALLBACK DlgProc (HWND, UINT, WPARAM, LPARAM) ;
void SetLogFontFromFields    (HWND hdlg, DLGPARAMS * pdp) ;
void SetFieldsFromTextMetric (HWND hdlg, DLGPARAMS * pdp) ;
void MySetMapMode (HDC hdc, int iMapMode) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     HWND     hwnd ;
     MSG      msg ;
     WNDCLASS wndclass ;
     
     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     wndclass.lpszMenuName  = szAppName ; 
     wndclass.lpszClassName = szAppName ;
     
     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("This program requires Windows NT!"),
               szAppName, MB_ICONERROR) ;
          return 0 ;
     }
     
     hwnd = CreateWindow (szAppName, TEXT ("PickFont: Create Logical Font"),
                          WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          NULL, NULL, hInstance, NULL) ;
     
     ShowWindow (hwnd, iCmdShow) ;
     UpdateWindow (hwnd) ;
     
     while (GetMessage (&msg, NULL, 0, 0))
     {
          if (hdlg == 0 || !IsDialogMessage (hdlg, &msg))
          {
               TranslateMessage (&msg) ;
               DispatchMessage (&msg) ;
          }
     }
     return msg.wParam ;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     static DLGPARAMS dp ;
     static TCHAR     szText[] = TEXT ("x41x42x43x44x45 ")
                                 TEXT ("x61x62x63x64x65 ")

                                 TEXT ("xC0xC1xC2xC3xC4xC5 ")
                                 TEXT ("xE0xE1xE2xE3xE4xE5 ") 
#ifdef UNICODE
                                 TEXT ("x0390x0391x0392x0393x0394x0395 ")
                                 TEXT ("x03B0x03B1x03B2x03B3x03B4x03B5 ")

                                 TEXT ("x0410x0411x0412x0413x0414x0415 ")
                                 TEXT ("x0430x0431x0432x0433x0434x0435 ")

                                 TEXT ("x5000x5001x5002x5003x5004") 
#endif
                                 ;
     HDC              hdc ;
     PAINTSTRUCT      ps ;
     RECT             rect ;
     
     switch (message)
     {
     case WM_CREATE:
          dp.iDevice = IDM_DEVICE_SCREEN ;

          hdlg = CreateDialogParam (((LPCREATESTRUCT) lParam)->hInstance, 
                                    szAppName, hwnd, DlgProc, (LPARAM) &dp) ;
          return 0 ;

     case WM_SETFOCUS:
          SetFocus (hdlg) ;
          return 0 ;

     case WM_COMMAND:
          switch (LOWORD (wParam))
          {
          case IDM_DEVICE_SCREEN:
          case IDM_DEVICE_PRINTER:
               CheckMenuItem (GetMenu (hwnd), dp.iDevice, MF_UNCHECKED) ;
               dp.iDevice = LOWORD (wParam) ;
               CheckMenuItem (GetMenu (hwnd), dp.iDevice, MF_CHECKED) ;
               SendMessage (hwnd, WM_COMMAND, IDOK, 0) ;
               return 0 ;
          }
          break ;

     case WM_PAINT:
          hdc = BeginPaint (hwnd, &ps) ;

               // Set graphics mode so escapement works in Windows NT

          SetGraphicsMode (hdc, dp.fAdvGraphics ? GM_ADVANCED : GM_COMPATIBLE) ;

               // Set the mapping mode and the mapper flag

          MySetMapMode (hdc, dp.iMapMode) ;
          SetMapperFlags (hdc, dp.fMatchAspect) ;

               // Find the point to begin drawing text

          GetClientRect (hdlg, &rect) ;
          rect.bottom += 1 ;
          DPtoLP (hdc, (PPOINT) &rect, 2) ;

               // Create and select the font; display the text

          SelectObject (hdc, CreateFontIndirect (&dp.lf)) ;
          TextOut (hdc, rect.left, rect.bottom, szText, lstrlen (szText)) ;

          DeleteObject (SelectObject (hdc, GetStockObject (SYSTEM_FONT))) ;
          EndPaint (hwnd, &ps) ;
          return 0 ;
          
     case WM_DESTROY:
          PostQuitMessage (0) ;
          return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}

BOOL CALLBACK DlgProc (HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
{
     static DLGPARAMS * pdp ;
     static PRINTDLG    pd = { sizeof (PRINTDLG) } ;
     HDC                hdcDevice ;
     HFONT              hFont ;
     
     switch (message)
     {
     case WM_INITDIALOG:
               // Save pointer to dialog-parameters structure in WndProc

          pdp = (DLGPARAMS *) lParam ;

          SendDlgItemMessage (hdlg, IDC_LF_FACENAME, EM_LIMITTEXT, 
                                    LF_FACESIZE - 1, 0) ;

          CheckRadioButton (hdlg, IDC_OUT_DEFAULT, IDC_OUT_OUTLINE,
                                  IDC_OUT_DEFAULT) ;

          CheckRadioButton (hdlg, IDC_DEFAULT_QUALITY, IDC_PROOF_QUALITY,
                                  IDC_DEFAULT_QUALITY) ;

          CheckRadioButton (hdlg, IDC_DEFAULT_PITCH, IDC_VARIABLE_PITCH,
                                  IDC_DEFAULT_PITCH) ;

          CheckRadioButton (hdlg, IDC_FF_DONTCARE, IDC_FF_DECORATIVE,
                                  IDC_FF_DONTCARE) ;

          CheckRadioButton (hdlg, IDC_MM_TEXT, IDC_MM_LOGTWIPS,
                                  IDC_MM_TEXT) ;

          SendMessage (hdlg, WM_COMMAND, IDOK, 0) ;

                                   // fall through
     case WM_SETFOCUS:
          SetFocus (GetDlgItem (hdlg, IDC_LF_HEIGHT)) ;
          return FALSE ;

     case WM_COMMAND:
          switch (LOWORD (wParam))
          {
          case IDC_CHARSET_HELP:
               MessageBox (hdlg, 
                           TEXT ("0 = Ansi
")
                           TEXT ("1 = Default
")
                           TEXT ("2 = Symbol
")
                           TEXT ("128 = Shift JIS (Japanese)
")
                           TEXT ("129 = Hangul (Korean)
")
                           TEXT ("130 = Johab (Korean)
")
                           TEXT ("134 = GB 2312 (Simplified Chinese)
")
                           TEXT ("136 = Chinese Big 5 (Traditional Chinese)
")
                           TEXT ("177 = Hebrew
")
                           TEXT ("178 = Arabic
")
                           TEXT ("161 = Greek
")
                           TEXT ("162 = Turkish
")
                           TEXT ("163 = Vietnamese
")
                           TEXT ("204 = Russian
")
                           TEXT ("222 = Thai
")
                           TEXT ("238 = East European
")
                           TEXT ("255 = OEM"),
                           szAppName, MB_OK | MB_ICONINFORMATION) ;
               return TRUE ;

               // These radio buttons set the lfOutPrecision field

          case IDC_OUT_DEFAULT:   
               pdp->lf.lfOutPrecision = OUT_DEFAULT_PRECIS ;  
               return TRUE ;

          case IDC_OUT_STRING:
               pdp->lf.lfOutPrecision = OUT_STRING_PRECIS ;  
               return TRUE ;

          case IDC_OUT_CHARACTER:
               pdp->lf.lfOutPrecision = OUT_CHARACTER_PRECIS ;  
               return TRUE ;

          case IDC_OUT_STROKE:
               pdp->lf.lfOutPrecision = OUT_STROKE_PRECIS ;  
               return TRUE ;

          case IDC_OUT_TT:
               pdp->lf.lfOutPrecision = OUT_TT_PRECIS ;  
               return TRUE ;

          case IDC_OUT_DEVICE:
               pdp->lf.lfOutPrecision = OUT_DEVICE_PRECIS ;  
               return TRUE ;

          case IDC_OUT_RASTER:
               pdp->lf.lfOutPrecision = OUT_RASTER_PRECIS ;  
               return TRUE ;

          case IDC_OUT_TT_ONLY:
               pdp->lf.lfOutPrecision = OUT_TT_ONLY_PRECIS ;  
               return TRUE ;

          case IDC_OUT_OUTLINE:
               pdp->lf.lfOutPrecision = OUT_OUTLINE_PRECIS ;  
               return TRUE ;

               // These three radio buttons set the lfQuality field

          case IDC_DEFAULT_QUALITY:
               pdp->lf.lfQuality = DEFAULT_QUALITY ;   
               return TRUE ;

          case IDC_DRAFT_QUALITY:
               pdp->lf.lfQuality = DRAFT_QUALITY ;  
               return TRUE ;

          case IDC_PROOF_QUALITY:
               pdp->lf.lfQuality = PROOF_QUALITY ;  
               return TRUE ;

               // These three radio buttons set the lower nibble
               //   of the lfPitchAndFamily field

          case IDC_DEFAULT_PITCH:
               pdp->lf.lfPitchAndFamily = (BYTE)
                    ((0xF0 & pdp->lf.lfPitchAndFamily) | DEFAULT_PITCH) ; 
               return TRUE ;

          case IDC_FIXED_PITCH:
               pdp->lf.lfPitchAndFamily = (BYTE)
                    ((0xF0 & pdp->lf.lfPitchAndFamily) | FIXED_PITCH) ; 
               return TRUE ;

          case IDC_VARIABLE_PITCH:
               pdp->lf.lfPitchAndFamily = (BYTE)
                    ((0xF0 & pdp->lf.lfPitchAndFamily) | VARIABLE_PITCH) ;  
               return TRUE ;

               // These six radio buttons set the upper nibble
               //   of the lpPitchAndFamily field

          case IDC_FF_DONTCARE:
               pdp->lf.lfPitchAndFamily = (BYTE)
                    ((0x0F & pdp->lf.lfPitchAndFamily) | FF_DONTCARE) ;  
               return TRUE ;

          case IDC_FF_ROMAN:
               pdp->lf.lfPitchAndFamily = (BYTE)
                    ((0x0F & pdp->lf.lfPitchAndFamily) | FF_ROMAN) ;  
               return TRUE ;

          case IDC_FF_SWISS:
               pdp->lf.lfPitchAndFamily = (BYTE)
                    ((0x0F & pdp->lf.lfPitchAndFamily) | FF_SWISS) ;  
               return TRUE ;

          case IDC_FF_MODERN:
               pdp->lf.lfPitchAndFamily = (BYTE)
                    ((0x0F & pdp->lf.lfPitchAndFamily) | FF_MODERN) ;  
               return TRUE ;

          case IDC_FF_SCRIPT:
               pdp->lf.lfPitchAndFamily = (BYTE)
                    ((0x0F & pdp->lf.lfPitchAndFamily) | FF_SCRIPT) ;  
               return TRUE ;

          case IDC_FF_DECORATIVE:
               pdp->lf.lfPitchAndFamily = (BYTE)
                    ((0x0F & pdp->lf.lfPitchAndFamily) | FF_DECORATIVE) ;  
               return TRUE ;

               // Mapping mode:

          case IDC_MM_TEXT:
          case IDC_MM_LOMETRIC:
          case IDC_MM_HIMETRIC:
          case IDC_MM_LOENGLISH:
          case IDC_MM_HIENGLISH:
          case IDC_MM_TWIPS:
          case IDC_MM_LOGTWIPS:
               pdp->iMapMode = LOWORD (wParam) ;
               return TRUE ;

               // OK button pressed
               // -----------------

          case IDOK:
                    // Get LOGFONT structure

               SetLogFontFromFields (hdlg, pdp) ;

                    // Set Match-Aspect and Advanced Graphics flags

               pdp->fMatchAspect = IsDlgButtonChecked (hdlg, IDC_MATCH_ASPECT) ;
               pdp->fAdvGraphics = IsDlgButtonChecked (hdlg, IDC_ADV_GRAPHICS) ;

                    // Get Information Context

               if (pdp->iDevice == IDM_DEVICE_SCREEN)
               {
                    hdcDevice = CreateIC (TEXT ("DISPLAY"), NULL, NULL, NULL) ;
               }
               else
               {
                    pd.hwndOwner = hdlg ;
                    pd.Flags = PD_RETURNDEFAULT | PD_RETURNIC ;
                    pd.hDevNames = NULL ;
                    pd.hDevMode = NULL ;

                    PrintDlg (&pd) ;

                    hdcDevice = pd.hDC ;
               }
                    // Set the mapping mode and the mapper flag

               MySetMapMode (hdcDevice, pdp->iMapMode) ;
               SetMapperFlags (hdcDevice, pdp->fMatchAspect) ;

                    // Create font and select it into IC

               hFont = CreateFontIndirect (&pdp->lf) ;
               SelectObject (hdcDevice, hFont) ;

                    // Get the text metrics and face name

               GetTextMetrics (hdcDevice, &pdp->tm) ;
               GetTextFace (hdcDevice, LF_FULLFACESIZE, pdp->szFaceName) ;
               DeleteDC (hdcDevice) ;
               DeleteObject (hFont) ;

                    // Update dialog fields and invalidate main window

               SetFieldsFromTextMetric (hdlg, pdp) ;
               InvalidateRect (GetParent (hdlg), NULL, TRUE) ;
               return TRUE ;
          }
          break ;
     }
     return FALSE ;
}
void SetLogFontFromFields (HWND hdlg, DLGPARAMS * pdp)
{
     pdp->lf.lfHeight      = GetDlgItemInt (hdlg, IDC_LF_HEIGHT,  NULL, TRUE) ;
     pdp->lf.lfWidth       = GetDlgItemInt (hdlg, IDC_LF_WIDTH,   NULL, TRUE) ;
     pdp->lf.lfEscapement  = GetDlgItemInt (hdlg, IDC_LF_ESCAPE,  NULL, TRUE) ;
     pdp->lf.lfOrientation = GetDlgItemInt (hdlg, IDC_LF_ORIENT,  NULL, TRUE) ;
     pdp->lf.lfWeight      = GetDlgItemInt (hdlg, IDC_LF_WEIGHT,  NULL, TRUE) ;
     pdp->lf.lfCharSet     = GetDlgItemInt (hdlg, IDC_LF_CHARSET, NULL, FALSE) ;

     pdp->lf.lfItalic = 
                    IsDlgButtonChecked (hdlg, IDC_LF_ITALIC) == BST_CHECKED ;
     pdp->lf.lfUnderline = 
                    IsDlgButtonChecked (hdlg, IDC_LF_UNDER)  == BST_CHECKED ;
     pdp->lf.lfStrikeOut = 
                    IsDlgButtonChecked (hdlg, IDC_LF_STRIKE) == BST_CHECKED ;

     GetDlgItemText (hdlg, IDC_LF_FACENAME, pdp->lf.lfFaceName, LF_FACESIZE) ;
}

void SetFieldsFromTextMetric (HWND hdlg, DLGPARAMS * pdp) 
{
     TCHAR   szBuffer [10] ;
     TCHAR * szYes = TEXT ("Yes") ; 
     TCHAR * szNo  = TEXT ("No") ;
     TCHAR * szFamily [] = { TEXT ("Don't Know"), TEXT ("Roman"),
                             TEXT ("Swiss"),      TEXT ("Modern"),
                             TEXT ("Script"),     TEXT ("Decorative"), 
                             TEXT ("Undefined") } ;

     SetDlgItemInt (hdlg, IDC_TM_HEIGHT,   pdp->tm.tmHeight,           TRUE) ;
     SetDlgItemInt (hdlg, IDC_TM_ASCENT,   pdp->tm.tmAscent,           TRUE) ;
     SetDlgItemInt (hdlg, IDC_TM_DESCENT,  pdp->tm.tmDescent,          TRUE) ;
     SetDlgItemInt (hdlg, IDC_TM_INTLEAD,  pdp->tm.tmInternalLeading,  TRUE) ;
     SetDlgItemInt (hdlg, IDC_TM_EXTLEAD,  pdp->tm.tmExternalLeading,  TRUE) ;
     SetDlgItemInt (hdlg, IDC_TM_AVECHAR,  pdp->tm.tmAveCharWidth,     TRUE) ;
     SetDlgItemInt (hdlg, IDC_TM_MAXCHAR,  pdp->tm.tmMaxCharWidth,     TRUE) ;
     SetDlgItemInt (hdlg, IDC_TM_WEIGHT,   pdp->tm.tmWeight,           TRUE) ;
     SetDlgItemInt (hdlg, IDC_TM_OVERHANG, pdp->tm.tmOverhang,         TRUE) ;
     SetDlgItemInt (hdlg, IDC_TM_DIGASPX,  pdp->tm.tmDigitizedAspectX, TRUE) ;
     SetDlgItemInt (hdlg, IDC_TM_DIGASPY,  pdp->tm.tmDigitizedAspectY, TRUE) ;

     wsprintf (szBuffer, BCHARFORM, pdp->tm.tmFirstChar) ;
     SetDlgItemText (hdlg, IDC_TM_FIRSTCHAR, szBuffer) ;

     wsprintf (szBuffer, BCHARFORM, pdp->tm.tmLastChar) ;
     SetDlgItemText (hdlg, IDC_TM_LASTCHAR, szBuffer) ;

     wsprintf (szBuffer, BCHARFORM, pdp->tm.tmDefaultChar) ;
     SetDlgItemText (hdlg, IDC_TM_DEFCHAR, szBuffer) ;

     wsprintf (szBuffer, BCHARFORM, pdp->tm.tmBreakChar) ;
     SetDlgItemText (hdlg, IDC_TM_BREAKCHAR, szBuffer) ;

     SetDlgItemText (hdlg, IDC_TM_ITALIC, pdp->tm.tmItalic     ? szYes : szNo) ;
     SetDlgItemText (hdlg, IDC_TM_UNDER,  pdp->tm.tmUnderlined ? szYes : szNo) ;
     SetDlgItemText (hdlg, IDC_TM_STRUCK, pdp->tm.tmStruckOut  ? szYes : szNo) ;

     SetDlgItemText (hdlg, IDC_TM_VARIABLE, 
               TMPF_FIXED_PITCH & pdp->tm.tmPitchAndFamily ? szYes : szNo) ;

     SetDlgItemText (hdlg, IDC_TM_VECTOR, 
               TMPF_VECTOR & pdp->tm.tmPitchAndFamily ? szYes : szNo) ;

     SetDlgItemText (hdlg, IDC_TM_TRUETYPE, 
               TMPF_TRUETYPE & pdp->tm.tmPitchAndFamily ? szYes : szNo) ;

     SetDlgItemText (hdlg, IDC_TM_DEVICE, 
               TMPF_DEVICE & pdp->tm.tmPitchAndFamily ? szYes : szNo) ;

     SetDlgItemText (hdlg, IDC_TM_FAMILY, 
               szFamily [min (6, pdp->tm.tmPitchAndFamily >> 4)]) ;

     SetDlgItemInt  (hdlg, IDC_TM_CHARSET,   pdp->tm.tmCharSet, FALSE) ;
     SetDlgItemText (hdlg, IDC_TM_FACENAME, pdp->szFaceName) ;
}

void MySetMapMode (HDC hdc, int iMapMode)
{
     switch (iMapMode)
     {
     case IDC_MM_TEXT:       SetMapMode (hdc, MM_TEXT) ;       break ;
     case IDC_MM_LOMETRIC:   SetMapMode (hdc, MM_LOMETRIC) ;   break ;
     case IDC_MM_HIMETRIC:   SetMapMode (hdc, MM_HIMETRIC) ;   break ;
     case IDC_MM_LOENGLISH:  SetMapMode (hdc, MM_LOENGLISH) ;  break ;
     case IDC_MM_HIENGLISH:  SetMapMode (hdc, MM_HIENGLISH) ;  break ;
     case IDC_MM_TWIPS:      SetMapMode (hdc, MM_TWIPS) ;      break ;
     case IDC_MM_LOGTWIPS:
          SetMapMode (hdc, MM_ANISOTROPIC) ;
          SetWindowExtEx (hdc, 1440, 1440, NULL) ;
          SetViewportExtEx (hdc, GetDeviceCaps (hdc, LOGPIXELSX),
                                 GetDeviceCaps (hdc, LOGPIXELSY), NULL) ;
          break ;
     }
}

//resource.h

//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by PickFont.rc
//
#define IDC_LF_HEIGHT                   1000
#define IDC_LF_WIDTH                    1001
#define IDC_LF_ESCAPE                   1002
#define IDC_LF_ORIENT                   1003
#define IDC_LF_WEIGHT                   1004
#define IDC_MM_TEXT                     1005
#define IDC_MM_LOMETRIC                 1006
#define IDC_MM_HIMETRIC                 1007
#define IDC_MM_LOENGLISH                1008
#define IDC_MM_HIENGLISH                1009
#define IDC_MM_TWIPS                    1010
#define IDC_MM_LOGTWIPS                 1011
#define IDC_LF_ITALIC                   1012
#define IDC_LF_UNDER                    1013
#define IDC_LF_STRIKE                   1014
#define IDC_MATCH_ASPECT                1015
#define IDC_ADV_GRAPHICS                1016
#define IDC_LF_CHARSET                  1017
#define IDC_CHARSET_HELP                1018
#define IDC_DEFAULT_QUALITY             1019
#define IDC_DRAFT_QUALITY               1020
#define IDC_PROOF_QUALITY               1021
#define IDC_LF_FACENAME                 1022
#define IDC_OUT_DEFAULT                 1023
#define IDC_OUT_STRING                  1024
#define IDC_OUT_CHARACTER               1025
#define IDC_OUT_STROKE                  1026
#define IDC_OUT_TT                      1027
#define IDC_OUT_DEVICE                  1028
#define IDC_OUT_RASTER                  1029
#define IDC_OUT_TT_ONLY                 1030
#define IDC_OUT_OUTLINE                 1031
#define IDC_DEFAULT_PITCH               1032
#define IDC_FIXED_PITCH                 1033
#define IDC_VARIABLE_PITCH              1034
#define IDC_FF_DONTCARE                 1035
#define IDC_FF_ROMAN                    1036
#define IDC_FF_SWISS                    1037
#define IDC_FF_MODERN                   1038
#define IDC_FF_SCRIPT                   1039
#define IDC_FF_DECORATIVE               1040
#define IDC_TM_HEIGHT                   1041
#define IDC_TM_ASCENT                   1042
#define IDC_TM_DESCENT                  1043
#define IDC_TM_INTLEAD                  1044
#define IDC_TM_EXTLEAD                  1045
#define IDC_TM_AVECHAR                  1046
#define IDC_TM_MAXCHAR                  1047
#define IDC_TM_WEIGHT                   1048
#define IDC_TM_OVERHANG                 1049
#define IDC_TM_DIGASPX                  1050
#define IDC_TM_DIGASPY                  1051
#define IDC_TM_FIRSTCHAR                1052
#define IDC_TM_LASTCHAR                 1053
#define IDC_TM_DEFCHAR                  1054
#define IDC_TM_BREAKCHAR                1055
#define IDC_TM_ITALIC                   1056
#define IDC_TM_UNDER                    1057
#define IDC_TM_STRUCK                   1058
#define IDC_TM_VARIABLE                 1059
#define IDC_TM_VECTOR                   1060
#define IDC_TM_TRUETYPE                 1061
#define IDC_TM_DEVICE                   1062
#define IDC_TM_FAMILY                   1063
#define IDC_TM_CHARSET                  1064
#define IDC_TM_FACENAME                 1065
#define IDM_DEVICE_SCREEN               40001
#define IDM_DEVICE_PRINTER              40002

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        103
#define _APS_NEXT_COMMAND_VALUE         40003
#define _APS_NEXT_CONTROL_VALUE         1066
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

//PickFont.c

//Microsoft Developer Studio generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE DISCARDABLE 
BEGIN
    "resource.h"
END

2 TEXTINCLUDE DISCARDABLE 
BEGIN
    "#include ""afxres.h""
"
    ""
END

3 TEXTINCLUDE DISCARDABLE 
BEGIN
    "
"
    ""
END

#endif    // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

PICKFONT DIALOG DISCARDABLE  0, 0, 348, 308
STYLE WS_CHILD | WS_VISIBLE | WS_BORDER
FONT 8, "MS Sans Serif"
BEGIN
    LTEXT           "&Height:",IDC_STATIC,8,10,44,8
    EDITTEXT        IDC_LF_HEIGHT,64,8,24,12,ES_AUTOHSCROLL
    LTEXT           "&Width",IDC_STATIC,8,26,44,8
    EDITTEXT        IDC_LF_WIDTH,64,24,24,12,ES_AUTOHSCROLL
    LTEXT           "Escapement:",IDC_STATIC,8,42,44,8
    EDITTEXT        IDC_LF_ESCAPE,64,40,24,12,ES_AUTOHSCROLL
    LTEXT           "Orientation:",IDC_STATIC,8,58,44,8
    EDITTEXT        IDC_LF_ORIENT,64,56,24,12,ES_AUTOHSCROLL
    LTEXT           "Weight:",IDC_STATIC,8,74,44,8
    EDITTEXT        IDC_LF_WEIGHT,64,74,24,12,ES_AUTOHSCROLL
    GROUPBOX        "Mapping Mode",IDC_STATIC,97,3,96,90,WS_GROUP
    CONTROL         "Text",IDC_MM_TEXT,"Button",BS_AUTORADIOBUTTON,104,13,56,
                    8
    CONTROL         "Low Metric",IDC_MM_LOMETRIC,"Button",BS_AUTORADIOBUTTON,
                    104,24,56,8
    CONTROL         "High Metric",IDC_MM_HIMETRIC,"Button",
                    BS_AUTORADIOBUTTON,104,35,56,8
    CONTROL         "Low English",IDC_MM_LOENGLISH,"Button",
                    BS_AUTORADIOBUTTON,104,46,56,8
    CONTROL         "High English",IDC_MM_HIENGLISH,"Button",
                    BS_AUTORADIOBUTTON,104,57,56,8
    CONTROL         "Twips",IDC_MM_TWIPS,"Button",BS_AUTORADIOBUTTON,104,68,
                    56,8
    CONTROL         "Logical Twips",IDC_MM_LOGTWIPS,"Button",
                    BS_AUTORADIOBUTTON,104,79,64,8
    CONTROL         "Italic",IDC_LF_ITALIC,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,8,90,48,12
    CONTROL         "Underline",IDC_LF_UNDER,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,8,104,48,12
    CONTROL         "Strike Out",IDC_LF_STRIKE,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,8,118,48,12
    CONTROL         "Match Aspect",IDC_MATCH_ASPECT,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,60,104,62,8
    CONTROL         "Adv Grfx Mode",IDC_ADV_GRAPHICS,"Button",
                    BS_AUTOCHECKBOX | WS_TABSTOP,60,118,62,8
    LTEXT           "Character Set:",IDC_STATIC,8,137,46,8
    EDITTEXT        IDC_LF_CHARSET,58,135,24,12,ES_AUTOHSCROLL
    PUSHBUTTON      "?",IDC_CHARSET_HELP,90,135,14,14
    GROUPBOX        "Quality",IDC_STATIC,132,98,62,48,WS_GROUP
    CONTROL         "Default",IDC_DEFAULT_QUALITY,"Button",
                    BS_AUTORADIOBUTTON,136,110,40,8
    CONTROL         "Draft",IDC_DRAFT_QUALITY,"Button",BS_AUTORADIOBUTTON,
                    136,122,40,8
    CONTROL         "Proof",IDC_PROOF_QUALITY,"Button",BS_AUTORADIOBUTTON,
                    136,134,40,8
    LTEXT           "Face Name:",IDC_STATIC,8,154,44,8
    EDITTEXT        IDC_LF_FACENAME,58,152,136,12,ES_AUTOHSCROLL
    GROUPBOX        "Output Precision",IDC_STATIC,8,166,118,133,WS_GROUP
    CONTROL         "OUT_DEFAULT_PRECIS",IDC_OUT_DEFAULT,"Button",
                    BS_AUTORADIOBUTTON,12,178,112,8
    CONTROL         "OUT_STRING_PRECIS",IDC_OUT_STRING,"Button",
                    BS_AUTORADIOBUTTON,12,191,112,8
    CONTROL         "OUT_CHARACTER_PRECIS",IDC_OUT_CHARACTER,"Button",
                    BS_AUTORADIOBUTTON,12,204,112,8
    CONTROL         "OUT_STROKE_PRECIS",IDC_OUT_STROKE,"Button",
                    BS_AUTORADIOBUTTON,12,217,112,8
    CONTROL         "OUT_TT_PRECIS",IDC_OUT_TT,"Button",BS_AUTORADIOBUTTON,
                    12,230,112,8
    CONTROL         "OUT_DEVICE_PRECIS",IDC_OUT_DEVICE,"Button",
                    BS_AUTORADIOBUTTON,12,243,112,8
    CONTROL         "OUT_RASTER_PRECIS",IDC_OUT_RASTER,"Button",
                    BS_AUTORADIOBUTTON,12,256,112,8
    CONTROL         "OUT_TT_ONLY_PRECIS",IDC_OUT_TT_ONLY,"Button",
                    BS_AUTORADIOBUTTON,12,269,112,8
    CONTROL         "OUT_OUTLINE_PRECIS",IDC_OUT_OUTLINE,"Button",
                    BS_AUTORADIOBUTTON,12,282,112,8
    GROUPBOX        "Pitch",IDC_STATIC,132,166,62,50,WS_GROUP
    CONTROL         "Default",IDC_DEFAULT_PITCH,"Button",BS_AUTORADIOBUTTON,
                    137,176,52,8
    CONTROL         "Fixed",IDC_FIXED_PITCH,"Button",BS_AUTORADIOBUTTON,137,
                    189,52,8
    CONTROL         "Variable",IDC_VARIABLE_PITCH,"Button",
                    BS_AUTORADIOBUTTON,137,203,52,8
    GROUPBOX        "Family",IDC_STATIC,132,218,62,82,WS_GROUP
    CONTROL         "Don't Care",IDC_FF_DONTCARE,"Button",BS_AUTORADIOBUTTON,
                    137,229,52,8
    CONTROL         "Roman",IDC_FF_ROMAN,"Button",BS_AUTORADIOBUTTON,137,241,
                    52,8
    CONTROL         "Swiss",IDC_FF_SWISS,"Button",BS_AUTORADIOBUTTON,137,253,
                    52,8
    CONTROL         "Modern",IDC_FF_MODERN,"Button",BS_AUTORADIOBUTTON,137,
                    265,52,8
    CONTROL         "Script",IDC_FF_SCRIPT,"Button",BS_AUTORADIOBUTTON,137,
                    277,52,8
    CONTROL         "Decorative",IDC_FF_DECORATIVE,"Button",
                    BS_AUTORADIOBUTTON,137,289,52,8
    DEFPUSHBUTTON   "OK",IDOK,247,286,50,14
    GROUPBOX        "Text Metrics",IDC_STATIC,201,2,140,272,WS_GROUP
    LTEXT           "Height:",IDC_STATIC,207,12,64,8
    LTEXT           "0",IDC_TM_HEIGHT,281,12,44,8
    LTEXT           "Ascent:",IDC_STATIC,207,22,64,8
    LTEXT           "0",IDC_TM_ASCENT,281,22,44,8
    LTEXT           "Descent:",IDC_STATIC,207,32,64,8
    LTEXT           "0",IDC_TM_DESCENT,281,32,44,8
    LTEXT           "Internal Leading:",IDC_STATIC,207,42,64,8
    LTEXT           "0",IDC_TM_INTLEAD,281,42,44,8
    LTEXT           "External Leading:",IDC_STATIC,207,52,64,8
    LTEXT           "0",IDC_TM_EXTLEAD,281,52,44,8
    LTEXT           "Ave Char Width:",IDC_STATIC,207,62,64,8
    LTEXT           "0",IDC_TM_AVECHAR,281,62,44,8
    LTEXT           "Max Char Width:",IDC_STATIC,207,72,64,8
    LTEXT           "0",IDC_TM_MAXCHAR,281,72,44,8
    LTEXT           "Weight:",IDC_STATIC,207,82,64,8
    LTEXT           "0",IDC_TM_WEIGHT,281,82,44,8
    LTEXT           "Overhang:",IDC_STATIC,207,92,64,8
    LTEXT           "0",IDC_TM_OVERHANG,281,92,44,8
    LTEXT           "Digitized Aspect X:",IDC_STATIC,207,102,64,8
    LTEXT           "0",IDC_TM_DIGASPX,281,102,44,8
    LTEXT           "Digitized Aspect Y:",IDC_STATIC,207,112,64,8
    LTEXT           "0",IDC_TM_DIGASPY,281,112,44,8
    LTEXT           "First Char:",IDC_STATIC,207,122,64,8
    LTEXT           "0",IDC_TM_FIRSTCHAR,281,122,44,8
    LTEXT           "Last Char:",IDC_STATIC,207,132,64,8
    LTEXT           "0",IDC_TM_LASTCHAR,281,132,44,8
    LTEXT           "Default Char:",IDC_STATIC,207,142,64,8
    LTEXT           "0",IDC_TM_DEFCHAR,281,142,44,8
    LTEXT           "Break Char:",IDC_STATIC,207,152,64,8
    LTEXT           "0",IDC_TM_BREAKCHAR,281,152,44,8
    LTEXT           "Italic?",IDC_STATIC,207,162,64,8
    LTEXT           "0",IDC_TM_ITALIC,281,162,44,8
    LTEXT           "Underlined?",IDC_STATIC,207,172,64,8
    LTEXT           "0",IDC_TM_UNDER,281,172,44,8
    LTEXT           "Struck Out?",IDC_STATIC,207,182,64,8
    LTEXT           "0",IDC_TM_STRUCK,281,182,44,8
    LTEXT           "Variable Pitch?",IDC_STATIC,207,192,64,8
    LTEXT           "0",IDC_TM_VARIABLE,281,192,44,8
    LTEXT           "Vector Font?",IDC_STATIC,207,202,64,8
    LTEXT           "0",IDC_TM_VECTOR,281,202,44,8
    LTEXT           "TrueType Font?",IDC_STATIC,207,212,64,8
    LTEXT           "0",IDC_TM_TRUETYPE,281,212,44,8
    LTEXT           "Device Font?",IDC_STATIC,207,222,64,8
    LTEXT           "0",IDC_TM_DEVICE,281,222,44,8
    LTEXT           "Family:",IDC_STATIC,207,232,64,8
    LTEXT           "0",IDC_TM_FAMILY,281,232,44,8
    LTEXT           "Character Set:",IDC_STATIC,207,242,64,8
    LTEXT           "0",IDC_TM_CHARSET,281,242,44,8
    LTEXT           "0",IDC_TM_FACENAME,207,262,128,8
END


/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//

#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE 
BEGIN
    "PICKFONT", DIALOG
    BEGIN
        LEFTMARGIN, 8
        RIGHTMARGIN, 341
        BOTTOMMARGIN, 300
    END
END
#endif    // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Menu
//

PICKFONT MENU DISCARDABLE 
BEGIN
    POPUP "&Device"
    BEGIN
        MENUITEM "&Screen",                     IDM_DEVICE_SCREEN, CHECKED
        MENUITEM "&Printer",                    IDM_DEVICE_PRINTER
    END
END

#endif    // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED

17.3.3 逻辑字体结构

(1)LOGFONT结构

字段

含义

lfHeight

(逻辑单位)

①lfHeight=0表示默认的字符高度;

②lfHeight>0,会匹配tmHeight大小的字体(注意含tmInternalLeading)。
③lfHeight<0时,会匹配tmHeight-tmInternalLeading大小的字体,即平时所说的字号大小。Windows根据lfHeight反向去查找字号的大小。
(注意:字号与字体高度的关系lfHeight =-(磅值*GetDeviceCaps(hdc,LOGPIXELSY)*72);

lfWidth

(逻辑单位)

①lfWidth =0,表示由Windows根据字符高度来选择合适的字体。

②lfWidth ≠0时,对TrueType字体会返回比正常字符稍宽或稍窄的字体,对点阵字体不起作用。

③lfWidth = tmAveCharWidth;

④正确使用方法:将lfWidth先设为0,并创建逻辑字体,再选入设备环境,然后调用GetTextMetrics获得tmAveCharWidth。并按比例调节tmAveCharWidth值,然后根据调节过的该值作为lfWidth字段值创建一个新字体。

lfEscapement

①字符串的方向,整个字符串以水平方向逆时针旋转的角度(单位是1/10度)如0表示字符串从左向右;900垂直向上;1800从右向左;2700垂直向下。

②字符串的每个字符并未被旋转,其基线和X轴是平行的。也就是每个字符还是垂直的。(SetGraphicsModes为GM_ADVANCED下)

③将SetGraphicsModes设为GM_COMPATIBLE字符串的每个字符也一直被旋转,也就是每个字符还是垂直于字符串延伸方向

lfOrientation

①单个字符的倾斜方向,是从水平方向往逆时针旋转的角度,单位也是1/10度。如900逆时针旋转90度

②使用该字段时一定要设置SetGraphicsMode为GM_ADVANCED才有效。

lfWeight

①指定是否使用粗体字。

②在WINGID.H中定义,其可用值

A、FW_DONTCARE(0);B、FW_THIN(100);C、FW_EXTRALIGHT(200)

D、FW_LIGHT(300);E、FW_NORMAL(400);F、FW_SEMIBOLD(600)

H、FW_BOLD(700);I、FW_EXTRABOLD(800);J、FW_HEAVY(900);

lfItalic

①非0值表示使用斜体。

②对于点阵字体,Windows会通过合成斜效果;对于TrueType会使用单独的斜字体。或该字体的倾斜属性版本

lfUnderLine

非0值表示字符加下划线

lfStrikeOut

非0值表示删除线

lfCharSet

①字符集,默认为1,即DEFAULT_CHARSET

②lfCharSet==0时,表示ANSI_CHARSET。

lfOutPrecision

通过字体的大小特征来匹配真实的字体。该字段设定相当复杂。一般不使用。但如果使用OUT_TT_ONLY_PRECIS,可能确保返回一个TrueType字体。

lfQuality

①只影响点阵字体,对TrueType字体没影响。

②DRAFT_QUALITY表示缩放点阵字体到期望的大小。PROOF_QUALITY表示不缩放。DEFULT_QUALITY(值为0)表示不在乎真实字体的美观程度

lfPitchAndFamily

①该字段是一个字节大小,由两部分组成:最低两位表示是否等宽,高6位表示字体族

②最低2位:DEFAULT_PITCH(0);FIXED_PITCH(1);VARIABLE_PITCH(2)③高6位:FF_DONTCARE(0x00);FF_ROMAN(0x10);FF_SWISS(0x20);

          FF_MODERN(0x30);FF_SCRIPT(0x40);FF_DECORATIVE(0x50)

lfFacename

实际字体的字样名字

该字段的长度为LF_FACESIZE(32个字符)的字节数组

17.3.4 字体匹配算法

(1)lfCharSet字段:字符集,该字段是重要字段

(2)lfPitchAndFamily字段:如果包含FIXED_PITCH值时,该字段非常重要。

(3)lfFaceName:当指定字体的字样名称时,表明了用户的意图。如果为NULL,但lfPitchAndFamily指定了某一字体族(除FF_DONTCARE外),那么lfPitchAndFamily的重要性被提高。

(4)lfHeight:对于点阵字体,Windows会尝试匹配lfHeight。如果是TrueType或笔画字体,Windows会对字体进行简单的缩放来得到期望的字体高度。

(5)设定lfQuality为PROOF_QUALITY可防止Windows对点阵字体缩放,而且表示字体的美观更重要,字符的高度则是比较次要的。

(6)lfHeight和lfWeight的比值和显示器纵横从不符合时。可以调用SetMapperFlags(hdc,TRUE)来避免Windows去找一个为不同纵横比显示器而设计的特殊点阵列字体。(对于TrueType没必要这样做)。

17.3.5 获取字体信息(TEXTMETRIC结构,除纵横比外,其余字段以逻辑单位表示)

字段

含义

tmHeight

字符高度。

tmAscent

基线之上的垂直高度

tmDescent

基线之下的垂直高度

tmInternalLeading

内部间隔,一般用来标重音符号

tmExternalLeading

外部间隔值。tmHeight不包含该部分的尺寸

tmAveCharWidth

小写字母的平均宽度

tmMaxCharWidth

该字体中最宽的字符宽度。等宽字体其值等于tmAverCharWidth

tmWeigth

字符的粗细程序,取值从0到999。400为正常字符,700为粗字体

tmOverhang

字符加粗时,该字符会变略宽。此字段代表额外的宽度。对于粗字体其宽度为tmAverCharWidth+tmOverHang,对于非粗字体的其宽度为tmAverChaWidth值

tmDigitizedAspectX

tmDigitizedAspectY

字体的纵横比,等于调用GetDeviceCaps时的

LOGPIXELSX/LOGPIXELSY.

tmFirstChar

该字体中第一个字符的编码

tmLastChar

该字体中最后一个字符的编码

tmDefaultChar

当希望显示一个字符在该字体中并不存在时,用该字段定义的字符来代替。

tmBreakChar

Windows认为在该字符处是可以断行的,一般该字段的值为32.也就是空格字符。

tmItalic

是否是斜体字

tmUnderlined

是否带下划线

tmStruckOut

是否带删除线

tmPitchAndFamily

低四位表示字体特性(如等宽或变宽)

高四位表示字符族(与LONGFONT中的含义一样)

tmCharSet

字符集

#define ANSI_CHARSET            0

#define DEFAULT_CHARSET         1

#define SYMBOL_CHARSET          2

#define MAC_CHARSET             77

#define SHIFTJIS_CHARSET        128

#define HANGEUL_CHARSET         129

#define HANGUL_CHARSET          129

#define JOHAB_CHARSET           130

#define GB2312_CHARSET          134

#define CHINESEBIG5_CHARSET     136

#define GREEK_CHARSET           161

#define TURKISH_CHARSET         162

#define VIETNAMESE_CHARSET      163

#define HEBREW_CHARSET          177

#define ARABIC_CHARSET          178

#define BALTIC_CHARSET          186

#define RUSSIAN_CHARSET         204

#define THAI_CHARSET            222

#define EASTEUROPE_CHARSET      238

#define OEM_CHARSET             255

  

17.3.6 EZFONT系统

(1)SetGraphicsMode(hdc,iMode):设置设备环境的图形模式

iMode

含义

GM_COMPATIBLE

缺省的模式。应用程序只能通过设置窗口或视口原点来改变逻辑坐标系到设备坐标系的转换。(如调用SetWindowsExtEx或SetViewportExtEx)。但是如果调用SetWorldTransform或ModifyWorldTransform来转换将失败

GM_ADVANCED

从逻辑坐标系统到设备坐标系统,使用的是高级模式转换,即通过SetWorldTransform或ModifyWorldTransform,进行矩阵变换来达到目的。(注意:当使用这种模式时,可以用映射模式来改变对字体进行缩放,代码如下)

  GetClientRect (hwnd, &rect) ;

SetGraphicsMode(hdc, GM_ADVANCED);

SetMapMode(hdc, MM_ISOTROPIC);

SetTextAlign(hdc, TA_CENTER);

SetWindowExtEx(hdc, 200, -200, NULL);

SetViewportExtEx(hdc, rect.right, rect.bottom, NULL);

SetViewportOrgEx(hdc, rect.right / 2, rect.bottom / 2, NULL);

TextOut(hdc, 0, 0, szStr, lstrlen(szStr));//文字放大且上下翻转

(2)SetWorldTransform(hDc,&xform);——旋转逻辑坐标系

  x' = x * eM11 + y * eM21 + eDx; (x', y')为新坐标,(x,y)为原坐标

  y' = x * eM12 + y * eM22 + eDy;

对于旋转来讲

  x' = cos(q)*x – sin(q)*y + x0;  (x0,y0)为坐标原点; q为顺时针旋转的角度

  y' = sin(q)*x  + cos(q)*y + y0;

(3)通过改变字体大小按比例缩放方法(不是通过映射模式的)

  ①先通过指定LOGFONT的lfHeight字段大小获得相应的字体。(注意lfWidth先设为0)
  ②通用GetTextMetrics获取新创建出来字体tmWidth大小。
  ③设置新的lfWidth = tmAverCharWidth* 指定的宽度/指定的高度,根据新的lfHeight和新的lfWidth创建一个新字体,并选入设备环境。这样一个按指定比例的字体创建出来。

 【RotateFont】

 

/*------------------------------------------------------------
FONTROTATE.C -- Font Rotate Demo
(c) Charles Petzold, 1998
------------------------------------------------------------*/
#include <windows.h>
#include <math.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
TCHAR szAppName[] = TEXT("FontRotate");
TCHAR szTitle[] = TEXT("FontRotate:Rotate Font Demo");
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   PSTR szCmdLine, int iCmdShow)
{
    HWND         hwnd;
    MSG          msg;
    WNDCLASSEX     wndclass;
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.cbSize = sizeof(WNDCLASSEX);
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(hInstance, szAppName);
    wndclass.hIconSm = LoadIcon(hInstance, szAppName);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szAppName;
    if (!RegisterClassEx(&wndclass))
    {
        MessageBox(NULL, TEXT("This program requires Windows NT!"),
                   szAppName, MB_ICONERROR);
        return 0;
    }

    hwnd = CreateWindow(szAppName,                  // window class name
                        szTitle, // window caption
                        WS_OVERLAPPEDWINDOW,        // window style
                        CW_USEDEFAULT,              // initial x position
                        CW_USEDEFAULT,              // initial y position
                        CW_USEDEFAULT,              // initial x size
                        CW_USEDEFAULT,              // initial y size
                        NULL,                       // parent window handle
                        NULL,                       // window menu handle
                        hInstance,                  // program instance handle
                        NULL);                     // creation parameters

    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    TCHAR* szStr45 = TEXT("顺时针旋转45度");
    TCHAR* szStrDownUp = TEXT("字体缩放,并上下翻转");

    HDC         hdc;
    PAINTSTRUCT ps;
    RECT        rect;
    static XFORM   xfm;
    float theta = (float)(45 * 3.14 / 180.0f);

    switch (message)
    {
    case WM_CREATE:
        //构造旋转矩阵
        xfm.eM11 = (FLOAT)cos(theta);
        xfm.eM12 = (FLOAT)sin(theta);
        xfm.eM21 = -(FLOAT)sin(theta);
        xfm.eM22 = (FLOAT)cos(theta);
        xfm.eDx = 0;
        xfm.eDy = 0;
        return 0;

    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);

        GetClientRect(hwnd, &rect);

        SetGraphicsMode(hdc, GM_ADVANCED);  //这句很关键,是在映射模式中缩放字体的关键!
        SetWorldTransform(hdc, &xfm); //顺时针转theta度
        SetMapMode(hdc, MM_ISOTROPIC);
        SetTextAlign(hdc, TA_CENTER);
        SetWindowExtEx(hdc, 50, 200, NULL); //字体缩放,并旋转45度
        SetViewportExtEx(hdc, rect.right, rect.bottom, NULL);
        SetViewportOrgEx(hdc, rect.right / 2, rect.bottom / 2, NULL);
        TextOut(hdc, 0, 0, szStr45, lstrlen(szStr45));

        ModifyWorldTransform(hdc, NULL, MWT_IDENTITY);//恢复旋转矩阵为默认值
        SetWindowExtEx(hdc, 50, -200, NULL); //字体缩放,并上下翻转(因为负范围)
        SetViewportExtEx(hdc, rect.right, rect.bottom, NULL);
        SetViewportOrgEx(hdc, rect.right / 2, 100, NULL);
        TextOut(hdc, 0, 0, szStrDownUp, lstrlen(szStrDownUp));//字体缩放并上下翻转(因为负范围)

        EndPaint(hwnd, &ps);
        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

EZTest程序】测试指定不同磅值下,匹配到的字体情况。

 

(注意观察:lfHeight值和tmHeight值,一般多个lfHeight对应一个tmHeight。)

/*------------------------------------------------------------
EZTEST.C -- Test of EZFONT(Easy Font)
(c) Charles Petzold, 1998
------------------------------------------------------------*/
#include <windows.h>
#include "EzFont.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
TCHAR szAppName[] = TEXT("EZTest");
TCHAR szTitle[] = TEXT("EZTest:Test of EZFONT");
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   PSTR szCmdLine, int iCmdShow)
{
    HWND         hwnd;
    MSG          msg;
    WNDCLASSEX     wndclass;
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.cbSize = sizeof(WNDCLASSEX);
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(hInstance, szAppName);
    wndclass.hIconSm = LoadIcon(hInstance, szAppName);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szAppName;
    if (!RegisterClassEx(&wndclass))
    {
        MessageBox(NULL, TEXT("This program requires Windows NT!"),
                   szAppName, MB_ICONERROR);
        return 0;
    }

    hwnd = CreateWindow(szAppName,                  // window class name
                        szTitle, // window caption
                        WS_OVERLAPPEDWINDOW,        // window style
                        CW_USEDEFAULT,              // initial x position
                        CW_USEDEFAULT,              // initial y position
                        CW_USEDEFAULT,              // initial x size
                        CW_USEDEFAULT,              // initial y size
                        NULL,                       // parent window handle
                        NULL,                       // window menu handle
                        hInstance,                  // program instance handle
                        NULL);                     // creation parameters

    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
void PaintRoutine(HWND hwnd, HDC hdc, int cxArea, int cyArea)
{
    HFONT  hFont;
    LOGFONT lf;
    int y, iPointSize;
    TCHAR szBuffer[100];
    TEXTMETRIC tm;
    //设备为Logic Twips 映射模式
    SetMapMode(hdc, MM_ANISOTROPIC);
    SetWindowExtEx(hdc, 1440, 1440, NULL);
    SetViewportExtEx(hdc, GetDeviceCaps(hdc, LOGPIXELSX),
                     GetDeviceCaps(hdc, LOGPIXELSY), NULL);
    //测试一些字体
    y = 0;
    /*
    字体大小从8磅到12磅,但并不是每个大小都有一个完全匹配的字体,通过
    tmHeight的值和lfHeight不同就可以观察出来。如好一个lfHeight对应一个
    tmHeight.
    */
    for (iPointSize = 80; iPointSize <= 120; iPointSize++)
    {
        hFont = EzCreateFont(hdc, TEXT("Times New Roman"), iPointSize, 0, 0, TRUE);
        GetObject(hFont, sizeof(LOGFONT), &lf);
        SelectObject(hdc, hFont);
        GetTextMetrics(hdc, &tm);
        TextOut(hdc, 0, y, szBuffer,
                wsprintf(szBuffer,
                TEXT("Times New Roman font of %i.%i points  ")
                TEXT("lf.lfHeight= %i,tm.tmHeight=%i"),
                iPointSize / 10, iPointSize & 10,
                lf.lfHeight, tm.tmHeight));
        DeleteObject(SelectObject(hdc, GetStockObject(SYSTEM_FONT)));
        y += tm.tmHeight;
    }
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC         hdc;
    PAINTSTRUCT ps;
    static int cxClient, cyClient;

    switch (message)
    {
    case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        return 0;
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);

        PaintRoutine(hwnd, hdc, cxClient, cyClient);
        EndPaint(hwnd, &ps);
        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

//EzFont.h

/*----------------------------------------------------------
EZFONT.H  header file
------------------------------------------------------------*/
#pragma  once 
#include <windows.h>
//iDeciPtHeight:字体高度:(单位1/10磅)如,12磅字体时,iDeciPtHeight=120
//iDecPtWidth:字体宽度(与上面单位一样)
//iAttributes:字体属性,如粗、斜、下划线、删除线等
//fLogRes:是否使用逻辑分辨率
HFONT EzCreateFont(HDC hdc, TCHAR* szFaceName, int iDeciPtHeight,
                   int iDeciPtWidth, int iAttributes, BOOL fLogRes);
#define EZ_ATTR_BOLD        1
#define EZ_ATTR_ITATIC      2
#define EZ_ATTR_UNDERLINE   4
#define Ez_ATTR_STRIKEOUT   8

//EzFont.c

/*-------------------------------------------------------------
EZFONT.C -- Easy Font Creation
(c) Charles Petzold, 1998
-------------------------------------------------------------*/
#include <windows.h>
#include <math.h>
#include "EzFont.h"
HFONT EzCreateFont(HDC hdc, TCHAR* szFaceName, int iDeciPtHeight,
                   int iDeciPtWidth, int iAttributes, BOOL fLogRes)
{
    HFONT hFont;
    LOGFONT lf;
    TEXTMETRIC tm;
    FLOAT  cxDpi, cyDpi;
    POINT pt;
    SaveDC(hdc);
    //设置高级图形模式,此模式下可以通过矩阵实现逻辑坐标到设备坐标的转换。
    SetGraphicsMode(hdc, GM_ADVANCED);
    ModifyWorldTransform(hdc, NULL, MWT_IDENTITY); //恢复变换到初始状态
    SetViewportOrgEx(hdc, 0, 0, NULL);
    SetWindowOrgEx(hdc, 0, 0, NULL);
    if (fLogRes)
    {
        //使用逻辑分辨率(单位:像素/英寸)
        cxDpi = (FLOAT)GetDeviceCaps(hdc, LOGPIXELSX);
        cyDpi = (FLOAT)GetDeviceCaps(hdc, LOGPIXELSY);
    } else
    {
        //实际的分辨率(单位:像素/英寸)
        cxDpi = (FLOAT)(25.4 * GetDeviceCaps(hdc, HORZRES) /
                        GetDeviceCaps(hdc, HORZSIZE));
        cyDpi = (FLOAT)(25.4 * GetDeviceCaps(hdc, VERTRES) /
                        GetDeviceCaps(hdc, VERTSIZE));  //vertsize单位为mm
    }
    //求出指定磅值的字体,需要多少像素点
    pt.x = (int)(iDeciPtWidth* cxDpi / 72);  //像素大小(设备单位)
    pt.y = (int)(iDeciPtHeight* cyDpi / 72); //像素大小(设备单位)
    DPtoLP(hdc, &pt, 1); //将像素大小由设备单位转为逻辑单位,也就是字体在逻辑坐标系中的大小
    lf.lfHeight = -(int)(fabs(pt.y) / 10.0 + 0.5); //加0.5是为了向上取整
    lf.lfWidth = 0; //注意这里要先设0,因为系统根据lfHeight匹配字体,会得到其固有的width
    //而iDeciPtWidth会因高级图形模式允许对字体进行拉伸和缩放。
    lf.lfEscapement = 0;
    lf.lfOrientation = 0;
    lf.lfWeight = iAttributes & EZ_ATTR_BOLD ? 700 : 0;
    lf.lfItalic = iAttributes & EZ_ATTR_ITATIC ? 1 : 0;
    lf.lfUnderline = iAttributes& EZ_ATTR_UNDERLINE ? 1 : 0;
    lf.lfStrikeOut = iAttributes& Ez_ATTR_STRIKEOUT ? 1 : 0;
    lf.lfCharSet = DEFAULT_CHARSET; //默认字符集
    lf.lfOutPrecision = 0;
    lf.lfClipPrecision = 0;
    lf.lfQuality = 0;
    lf.lfPitchAndFamily = 0;

    lstrcpy(lf.lfFaceName, szFaceName);
    hFont = CreateFontIndirect(&lf);
    if (iDeciPtWidth != 0)
    {
        hFont = (HFONT)SelectObject(hdc, hFont); //选入,并返回旧字体
        GetTextMetrics(hdc, &tm); //获取新字体信息
        DeleteObject(SelectObject(hdc, hFont));//将旧的选入,交并删除新的字体
        //字体的被左右拉伸,能这样实现的前提是设为高级图形模式,即SetGraphicsMode(hdc, GM_ADVANCED);
        lf.lfWidth = (int)(tm.tmAveCharWidth*fabs(pt.x) / fabs(pt.y) + 0.5);
        hFont = CreateFontIndirect(&lf);
    }
    RestoreDC(hdc, -1);
    return hFont;
}

17.3.7 字体旋转

(1)在SetGraphicsMode(hdc,GM_ADVANCED)高级图形模式下,做字体的旋转

(2)lfEscapement每次增加30度,字体大小设为54磅

【FontRot程序】
/*------------------------------------------------------------
FONTDEMO.C -- Font Demonstration Shel Program
(c) Charles Petzold, 1998
------------------------------------------------------------*/
#include <windows.h>
#include "resource.h"
#include "..\EzTest\EzFont.h"
extern void PaintRoutine(HWND, HDC, int, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE hInst;
extern TCHAR szAppName[];
extern TCHAR szTitle[];
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT("About2");
    HWND         hwnd;
    MSG          msg;
    WNDCLASSEX     wndclass;
    hInst = hInstance;
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.cbSize = sizeof(WNDCLASSEX);
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(hInstance, szAppName);
    wndclass.hIconSm = LoadIcon(hInstance, szAppName);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = szAppName;
    wndclass.lpszClassName = szAppName;
    if (!RegisterClassEx(&wndclass))
    {
        MessageBox(NULL, TEXT("This program requires Windows NT!"),
                   szAppName, MB_ICONERROR);
        return 0;
    }

    hwnd = CreateWindow(szAppName,                  // window class name
                        szTitle, // window caption
                        WS_OVERLAPPEDWINDOW,        // window style
                        CW_USEDEFAULT,              // initial x position
                        CW_USEDEFAULT,              // initial y position
                        CW_USEDEFAULT,              // initial x size
                        CW_USEDEFAULT,              // initial y size
                        NULL,                       // parent window handle
                        NULL,                       // window menu handle
                        hInstance,                  // program instance handle
                        NULL);                     // creation parameters

    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static int cxClient, cyClient;
    static DOCINFO di = { sizeof(DOCINFO), TEXT("Font Demo:Printing") };
    static PRINTDLG pd = { sizeof(PRINTDLG) };
    int cxPage, cyPage;
    HDC         hdc, hdcPrn;
    PAINTSTRUCT ps;
    BOOL fSuccess;
    switch (message)
    {
    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case IDM_PRINT:
            //获得打印机DC
            pd.hwndOwner = hwnd;
            pd.Flags = PD_RETURNDC | PD_NOPAGENUMS | PD_NOSELECTION;
            if (!PrintDlg(&pd))
                return 0;
            if (NULL == (hdcPrn = pd.hDC))
            {
                MessageBox(hwnd, TEXT("Cannot obtain PrinterDC"),
                           szAppName, MB_ICONEXCLAMATION | MB_OK);
                return 0;
            }

            //获得可打印区域的大小
            cxPage = GetDeviceCaps(hdcPrn, HORZRES);
            cyPage = GetDeviceCaps(hdcPrn, VERTRES);
            fSuccess = FALSE;
            //打印页面
            SetCursor(LoadCursor(NULL, IDC_WAIT));
            ShowCursor(TRUE);
            if ((StartDoc(hdcPrn, &di) >0) && (StartPage(hdcPrn)>0))
            {
                PaintRoutine(hwnd, hdcPrn, cxPage, cyPage);
                if (EndPage(hdcPrn)>0)
                {
                    fSuccess = TRUE;
                    EndDoc(hdcPrn);
                }
            }
            DeleteDC(hdcPrn);
            ShowCursor(FALSE);
            SetCursor(LoadCursor(NULL, IDC_ARROW));
            if (!fSuccess)
                MessageBox(hwnd, TEXT("Error encountered during printing"),
                szAppName, MB_ICONEXCLAMATION | MB_OK);
            return 0;

        case IDM_ABOUT:
            MessageBox(hwnd, TEXT("Font Demonstration Program
")
                       TEXT(" (c) Charles Petzold,1998"),
                       szAppName, MB_ICONINFORMATION | MB_OK);
            return 0;
        }

        break;
    case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        return 0;
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);

        PaintRoutine(hwnd, hdc, cxClient, cyClient);
        EndPaint(hwnd, &ps);
        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

//FontRot.c

/*--------------------------------------------------------
FONTROT.C —— Rotate Fonts
(c)Charles Petzold,1998
---------------------------------------------------------*/
#include <windows.h>
#include "..\EzTest\EzFont.h"

TCHAR szAppName[] = TEXT("FontRot");
TCHAR szTitle[] = TEXT("FontRot:Rotated Fonts");
void PaintRoutine(HWND hwnd, HDC hdc, int cxArea, int cyArea)
{
    static TCHAR szString[] = TEXT("Rotation");
    HFONT hFont;
    int i;
    LOGFONT lf;
    //创建一个54磅大小的字体
    hFont = EzCreateFont(hdc, TEXT("Times New Roman"), 540, 0, 0, TRUE);
    GetObject(hFont, sizeof(LOGFONT), &lf);
    DeleteObject(hFont);
    //以这个字体为模版大小,通过指定lfEscapement来创建不同字体
    SetBkMode(hdc, TRANSPARENT);
    SetTextAlign(hdc, TA_BASELINE);
    SetViewportOrgEx(hdc, cxArea / 2, cyArea / 2, NULL);
    for (i = 0; i < 12; i++)
    {
        lf.lfEscapement = lf.lfOrientation = i * 300; //每次30度
        SelectObject(hdc, CreateFontIndirect(&lf));
        TextOut(hdc, 0, 0, szString, lstrlen(szString));
        DeleteObject(SelectObject(hdc, GetStockObject(SYSTEM_FONT)));
    }
}

//resource.h

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 FontDemo.rc 使用
//
#define IDR_MENU1                       101
#define IDM_PRINT                       40001
#define IDM_ABOUT                       40002
// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        102
#define _APS_NEXT_COMMAND_VALUE         40003
#define _APS_NEXT_CONTROL_VALUE         1001
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

//FontDemo.rc

// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// 中文(简体,中国) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""
"
""
END
3 TEXTINCLUDE
BEGIN
"
"
""
END
#endif    // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
FONTDEMO MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&Print...", 40001
END
POPUP "&Help"
BEGIN
MENUITEM "&About...", 40002
END
END
#endif    // 中文(简体,中国) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED

 //EzFont.h和EzFont.c文件与上一个程序相同。

原文地址:https://www.cnblogs.com/5iedu/p/4701215.html