天天看點

EnumFontFamilies

  PC的文字遊戲一般在設定界面中有選擇字型的地方,一般來說是從系統字型中篩選出合适的字型,很少會給玩家字型對話框來選擇的。這個篩選是靠EnumFontFamilies。

  int EnumFontFamilies(

    HDC hdc,                        // handle to device control

    LPCTSTR lpszFamily,             // pointer to family-name string

    FONTENUMPROC lpEnumFontFamProc, // pointer to callback function

    LPARAM lParam                   // address of application-supplied data 

   );

 裡面主要的參數是FONTENUMPROC lpEnumFontFamProc,定義如下:

  int CALLBACK EnumFontFamProc(

    ENUMLOGFONT FAR *lpelf,   // pointer to logical-font data

    NEWTEXTMETRIC FAR *lpntm, // pointer to physical-font data

    int FontType,             // type of font

    LPARAM lParam             // address of application-defined data 

   );

  第一個參數指向ENUMLOGFONT資料,

typedef struct tagENUMLOGFONT { // elf 

    LOGFONT elfLogFont;

    BCHAR    elfFullName[LF_FULLFACESIZE];

    BCHAR    elfStyle[LF_FACESIZE];

} ENUMLOGFONT;

  其實也就是一個LOGFONT + 字型名,是以調試的時候可以在記憶體跟随這個結構來看字型名。

 LOGFONT應該很熟了,如下:

typedef struct tagLOGFONT { // lf 

   LONG lfHeight;

   LONG lfWidth;

   LONG lfEscapement;

   LONG lfOrientation;

   LONG lfWeight;                   // 10

   BYTE lfItalic;                   // 14

   BYTE lfUnderline;

   BYTE lfStrikeOut;

   BYTE lfCharSet;                  // 17 一般判斷這裡

   BYTE lfOutPrecision;             // 18

   BYTE lfClipPrecision;

   BYTE lfQuality;

   BYTE lfPitchAndFamily;

   TCHAR lfFaceName[LF_FACESIZE];   // 1c

} LOGFONT;

  第二個指向 NEWTEXTMETRIC,結構如下:

typedef struct tagNEWTEXTMETRIC { // ntm 

    LONG   tmHeight;

    LONG   tmAscent;

    LONG   tmDescent;

    LONG   tmInternalLeading;

    LONG   tmExternalLeading;

    LONG   tmAveCharWidth;

    LONG   tmMaxCharWidth;

    LONG   tmWeight;

    LONG   tmOverhang;

    LONG   tmDigitizedAspectX;

    LONG   tmDigitizedAspectY;

    BCHAR  tmFirstChar;

    BCHAR  tmLastChar;

    BCHAR  tmDefaultChar;

    BCHAR  tmBreakChar;

    BYTE   tmItalic;

    BYTE   tmUnderlined;

    BYTE   tmStruckOut;

    BYTE   tmPitchAndFamily;

    BYTE   tmCharSet;

    DWORD  ntmFlags;

    UINT   ntmSizeEM;

    UINT   ntmCellHeight;

    UINT   ntmAvgWidth;

} NEWTEXTMETRIC;

  字段很多,不一一介紹了。

  第三個參數FontType隻有3個值:

    DEVICE_FONTTYPE   1

    RASTER_FONTTYPE   2

    TRUETYPE_FONTTYPE 4  一般選這個

  最後一個參數LPARAM lParam其實就是EnumFontFamilies中第4個參數,可以傳點使用者自定義資料。

  下面是一個執行個體。

00450700  /.  55            push    ebp                              ;  EnumFontFamilies_Callback

00450701  |.  8BEC          mov     ebp, esp

00450703  |.  F645 10 04    test    byte ptr [ebp+10], 4    // 這裡看FontType是不是TRUETYPE_FONTTYPE 

00450707  |.  8B45 08       mov     eax, dword ptr [ebp+8]  // eax = lpelf

0045070A  |.  75 07         jnz     short 00450713

0045070C  |.  B8 01000000   mov     eax, 1

00450711  |.  EB 4A         jmp     short 0045075D

00450713  |>  8A50 17       mov     dl, byte ptr [eax+17]   // [eax + 17] is lpelf->lfCharSet

00450716  |.  80FA 80       cmp     dl, 80                  // Charset -> 86 80是SJIS,改成86簡體,88繁體

00450719  |.  74 07         je      short 00450722

0045071B  |.  B8 01000000   mov     eax, 1

00450720  |.  EB 3B         jmp     short 0045075D

00450722  |>  33D2          xor     edx, edx

00450724  |.  8A50 1B       mov     dl, byte ptr [eax+1B]

00450727  |.  83E2 03       and     edx, 3

0045072A  |.  4A            dec     edx

0045072B  |.  74 07         je      short 00450734

0045072D  |.  B8 01000000   mov     eax, 1

00450732  |.  EB 29         jmp     short 0045075D

00450734  |>  0FBE50 1C     movsx   edx, byte ptr [eax+1C]

00450738  |.  83FA 40       cmp     edx, 40

0045073B  |.  75 07         jnz     short 00450744

0045073D  |.  B8 01000000   mov     eax, 1

00450742  |.  EB 19         jmp     short 0045075D

00450744  |>  83C0 1C       add     eax, 1C

00450747  |.  50            push    eax                              ; /lParam

00450748  |.  6A 00         push    0                                ; |wParam = 0

0045074A  |.  68 43010000   push    143                              ; |Message = CB_ADDSTRING

0045074F  |.  8B55 14       mov     edx, dword ptr [ebp+14]          ; |

00450752  |.  52            push    edx                              ; |hWnd

00450753  |.  E8 C8741900   call    <jmp.&USER32.SendMessageA>       ; /SendMessageA

00450758  |.  B8 01000000   mov     eax, 1                           // 這裡向ComboBox添加項目

0045075D  |>  5D            pop     ebp

0045075E  /.  C2 1000       retn    10