TFontNameComboBox及TFontSizeComboBox的实现

    技术2022-05-11  170

    在用C++ Builder进行程序设计时,很多时候需要在运行状态下更改控件的字体名称或大小,虽然VCL类库中提供了TFontDialog对话框组件,但有时候并不是很方便。而C++ Builder本身又没有提供类似Word工具栏中的字体名称及大小的选择下拉列表,为方便使用,作者特编写两个字体组件 TFontNameComboBoxTFontSizeComboBox,下简单介绍一下实现的方法及原理。

      要想取得系统所支持的字体及字体的大小,需要用到Windows SDK中的EnumFontFamiliesEx或EnumFontFamilies函数。这两个函数的函数原型如下:

     

    int EnumFontFamiliesEx(

        HDC hdc, // handle to device context

        LPLOGFONT lpLogfont,// pointer to logical font information

        FONTENUMPROC lpEnumFontFamExProc, // pointer to callback function

        LPARAM lParam, // application-supplied data

        DWORD dwFlags // reserved; must be zero

        );

     

    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 

       ); 

     

    这两个函数的功能基本相同,但相对而言EnumFontFamiliesEx函数提供了更多的字体信息。在这两个函数中,都用到一个类型为FONTENUMPROC的回调函数,该函数的原型如下:

    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 

       );

    这两个函数更详细的说明请参考MSDN

    下面是组件的简单实现代码:

    /*===========================================================================  TFontNameComboBoxTFontNameSizeComboBox组件头文件  文件名称:FontComboBox.H  程序设计:梁生红  创建日期:2003-03-20===========================================================================*/#ifndef FontComboBoxH#define FontComboBoxH//---------------------------------------------------------------------------#include <SysUtils.hpp>#include <Controls.hpp>#include <Classes.hpp>#include <Forms.hpp>#include <StdCtrls.hpp>#include <printers.hpp>#include <Math.h>//---------------------------------------------------------------------------int static PixelsPerInch;//下列两个回调函数一定不能为类成员函数bool __stdcall EnumFontNameProc(ENUMLOGFONT FAR *lpelf,NEWTEXTMETRICEX FAR *lpntme,                                int FontType, LPARAM lParam);bool __stdcall EnumFontSizeProc(ENUMLOGFONT FAR *lpelf,NEWTEXTMETRIC FAR *lpntm,                                int FontType, LPARAM lParam);//---------------------------------------------------------------------------/* TODO : TFontNameComboBox的声明 */class PACKAGE TFontNameComboBox : public TCustomComboBox{private:protected:        void __fastcall Build();public:        __fastcall TFontNameComboBox(TComponent* Owner);__published:    __property Style;    __property Anchors;    __property BiDiMode;    __property Color;    __property Constraints;    __property Ctl3D;    __property DragCursor;    __property DragKind;    __property DragMode;    __property DropDownCount;    __property Enabled;    __property Font;    __property ItemHeight;    __property MaxLength;    __property ParentBiDiMode;    __property ParentColor;    __property ParentCtl3D;    __property ParentFont;    __property ParentShowHint;    __property PopupMenu;    __property ShowHint;    __property TabOrder;    __property TabStop;    __property Visible;    __property OnChange;    __property OnClick;    __property OnContextPopup;    __property OnDblClick;    __property OnDragDrop;    __property OnDragOver;    __property OnDrawItem;    __property OnDropDown;    __property OnEndDock;    __property OnEndDrag;    __property OnEnter;    __property OnExit;    __property OnKeyDown;    __property OnKeyPress;    __property OnKeyUp;    __property OnMeasureItem;    __property OnStartDock;    __property OnStartDrag;};//---------------------------------------------------------------------------/* TODO : TFontSizeComboBox的声明 */class PACKAGE TFontSizeComboBox : public TCustomComboBox{private:   AnsiString FFontName;   void __fastcall SetFontName(AnsiString AFontName);protected:   void __fastcall Build();public:        __fastcall TFontSizeComboBox(TComponent* Owner);__published:__published:    __property AnsiString FontName = {read = FFontName, write = SetFontName};    __property Style;    __property Anchors;    __property BiDiMode;    __property Color;    __property Constraints;    __property Ctl3D;    __property DragCursor;    __property DragKind;    __property DragMode;    __property DropDownCount;    __property Enabled;    __property Font;    __property ItemHeight;    __property MaxLength;    __property ParentBiDiMode;    __property ParentColor;    __property ParentCtl3D;    __property ParentFont;    __property ParentShowHint;    __property PopupMenu;    __property ShowHint;    __property TabOrder;    __property TabStop;    __property Visible;    __property OnChange;    __property OnClick;    __property OnContextPopup;    __property OnDblClick;    __property OnDragDrop;    __property OnDragOver;    __property OnDrawItem;    __property OnDropDown;    __property OnEndDock;    __property OnEndDrag;    __property OnEnter;    __property OnExit;    __property OnKeyDown;    __property OnKeyPress;    __property OnKeyUp;    __property OnMeasureItem;    __property OnStartDock;    __property OnStartDrag;};//---------------------------------------------------------------------------#endif实现文件/*===========================================================================  TFontNameComboBoxTFontNameSizeComboBox组件实现文件  文件名称:FontComboBox.CPP  程序设计:梁生红  创建日期:2003-03-20===========================================================================*/#include <vcl.h>#pragma hdrstop#include "FontComboBox.h"#pragma package(smart_init)//---------------------------------------------------------------------------static inline void ValidCtrCheck(TFontNameComboBox *){        new TFontNameComboBox(NULL);}//---------------------------------------------------------------------------static inline void ValidCtrCheck(TFontSizeComboBox *){        new TFontSizeComboBox(NULL);}//---------------------------------------------------------------------------/* TODO : 回调函数实现代码 */bool __stdcall EnumFontNameProc(ENUMLOGFONT FAR *lpelf,NEWTEXTMETRICEX FAR *lpntme,                                int FontType, LPARAM lParam){  char FontFullName[64];  strcpy(FontFullName,lpelf->elfFullName);  if(((TStrings*)(lParam))->IndexOf(FontFullName)==-1)    ((TStrings*)(lParam))->Add(FontFullName);  return true;}//----------------------------------------------------------------------------bool __stdcall EnumFontSizeProc(ENUMLOGFONT FAR *lpelf,NEWTEXTMETRIC FAR *lpntm,                                int FontType, LPARAM lParam){  if(FontType&TRUETYPE_FONTTYPE)    {        ((TStrings*)(lParam))->Add("8");        ((TStrings*)(lParam))->Add("9");        ((TStrings*)(lParam))->Add("10");        ((TStrings*)(lParam))->Add("11");        ((TStrings*)(lParam))->Add("12");        ((TStrings*)(lParam))->Add("14");        ((TStrings*)(lParam))->Add("16");        ((TStrings*)(lParam))->Add("18");        ((TStrings*)(lParam))->Add("20");        ((TStrings*)(lParam))->Add("22");        ((TStrings*)(lParam))->Add("24");        ((TStrings*)(lParam))->Add("26");        ((TStrings*)(lParam))->Add("28");        ((TStrings*)(lParam))->Add("36");        ((TStrings*)(lParam))->Add("48");        ((TStrings*)(lParam))->Add("72");        return false;    }  else    {          AnsiString s;          int i,v,v2;          v = floor((lpelf->elfLogFont.lfHeight-lpntm->tmInternalLeading)*72/PixelsPerInch);          s = IntToStr(v);          for(i = 0;i<((TStrings*)(lParam))->Count-1;i++)             {                v2 = StrToInt(((TStrings*)(lParam))->Strings[i]);                if(v2==v)                  return true;                if(v2>v)                 {                   ((TStrings*)(lParam))->Insert(i,s);                   return true;                 }            }          ((TStrings*)(lParam))->Add(s);        return true;    }}//---------------------------------------------------------------------------/* TODO : TFontNameComboBox实现部分 */__fastcall TFontNameComboBox::TFontNameComboBox(TComponent* Owner)        : TCustomComboBox(Owner){  Sorted = true;  if(!ComponentState.Contains(csDesigning))     Build();}//---------------------------------------------------------------------------void __fastcall TFontNameComboBox::Build(){  HDC DC = NULL;  LOGFONT LogFont;  TNotifyEvent OnChangeEvent;  OnChangeEvent = OnChange;  OnChange      = NULL;  Items->Clear();  LogFont.lfCharSet        = DEFAULT_CHARSET;  strcpy(LogFont.lfFaceName,"");  LogFont.lfPitchAndFamily = 0;  DC = GetDC(GetDesktopWindow());  try    {      EnumFontFamiliesEx(DC,&LogFont,(FONTENUMPROC)(EnumFontNameProc),LPARAM(Items),0);    }  __finally    {      ReleaseDC(GetDesktopWindow(),DC);    } OnChange = OnChangeEvent; if(Items->Count)   ItemIndex = 0;}//---------------------------------------------------------------------------/* TODO : TFontSizeComboBox实现部分 */__fastcall TFontSizeComboBox::TFontSizeComboBox(TComponent* Owner)        : TCustomComboBox(Owner){  Sorted = false;}//---------------------------------------------------------------------------void __fastcall TFontSizeComboBox::SetFontName(AnsiString AFontName){  FFontName = AFontName;  if(!ComponentState.Contains(csDesigning))    {      Items->Clear();      Build();    }  }//---------------------------------------------------------------------------void __fastcall TFontSizeComboBox::Build(){  TNotifyEvent OnChangeEvent = OnChange;  OnChange = NULL;  HDC DC = GetDC(GetDesktopWindow());  PixelsPerInch = GetDeviceCaps(DC, LOGPIXELSY);  try    {      EnumFontFamilies(DC, FFontName.c_str(), (FONTENUMPROC)(EnumFontSizeProc),LPARAM(Items));    }  __finally    {      ReleaseDC(GetDesktopWindow(),DC);    }  OnChange = OnChangeEvent;  if(Items->Count)    ItemIndex = 0;}//---------------------------------------------------------------------------namespace Fontcombobox{        void __fastcall PACKAGE Register()        {                 TComponentClass classes[2] = {__classid(TFontNameComboBox),                                               __classid(TFontSizeComboBox)};                 RegisterComponents("Samples", classes, 1);        }}//---------------------------------------------------------------------------


    最新回复(0)