在用C++ Builder进行程序设计时,很多时候需要在运行状态下更改控件的字体名称或大小,虽然VCL类库中提供了TFontDialog对话框组件,但有时候并不是很方便。而C++ Builder本身又没有提供类似Word工具栏中的字体名称及大小的选择下拉列表,为方便使用,作者特编写两个字体组件 TFontNameComboBox和TFontSizeComboBox,下简单介绍一下实现的方法及原理。
要想取得系统所支持的字体及字体的大小,需要用到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。 下面是组件的简单实现代码:
/*=========================================================================== TFontNameComboBox及TFontNameSizeComboBox组件头文件 文件名称: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
实现文件 /*=========================================================================== TFontNameComboBox及TFontNameSizeComboBox组件实现文件 文件名称: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); } } //---------------------------------------------------------------------------

|