在用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
1<sysutils.hpp>
2#include <controls.hpp>
3#include <classes.hpp>
4#include <forms.hpp>
5#include <stdctrls.hpp>
6#include <printers.hpp>
7#include <math.h>
8_ //--------------------------------------------------------------------------- _
9int static PixelsPerInch;
10
11_ // _ _ 下列两个回调函数一定不能为类成员函数 _
12bool __stdcall EnumFontNameProc(ENUMLOGFONT FAR *lpelf,NEWTEXTMETRICEX FAR *lpntme,
13int FontType, LPARAM lParam);
14
15bool __stdcall EnumFontSizeProc(ENUMLOGFONT FAR *lpelf,NEWTEXTMETRIC FAR *lpntm,
16int FontType, LPARAM lParam);
17
18_ //--------------------------------------------------------------------------- _
19_ /* TODO : TFontNameComboBox _ 的声明 */
20class PACKAGE TFontNameComboBox : public TCustomComboBox
21{
22private :
23protected :
24void __fastcall Build();
25public :
26__fastcall TFontNameComboBox(TComponent* Owner);
27__published :
28__property Style;
29__property Anchors;
30__property BiDiMode;
31__property Color;
32__property Constraints;
33__property Ctl3D;
34__property DragCursor;
35__property DragKind;
36__property DragMode;
37__property DropDownCount;
38__property Enabled;
39__property Font;
40__property ItemHeight;
41__property MaxLength;
42__property ParentBiDiMode;
43__property ParentColor;
44__property ParentCtl3D;
45__property ParentFont;
46__property ParentShowHint;
47__property PopupMenu;
48__property ShowHint;
49__property TabOrder;
50__property TabStop;
51__property Visible;
52__property OnChange;
53__property OnClick;
54__property OnContextPopup;
55__property OnDblClick;
56__property OnDragDrop;
57__property OnDragOver;
58__property OnDrawItem;
59__property OnDropDown;
60__property OnEndDock;
61__property OnEndDrag;
62__property OnEnter;
63__property OnExit;
64__property OnKeyDown;
65__property OnKeyPress;
66__property OnKeyUp;
67__property OnMeasureItem;
68__property OnStartDock;
69__property OnStartDrag;
70};
71_ //--------------------------------------------------------------------------- _
72_ /* TODO : TFontSizeComboBox _ 的声明 */
73class PACKAGE TFontSizeComboBox : public TCustomComboBox
74{
75private :
76AnsiString FFontName;
77void __fastcall SetFontName(AnsiString AFontName);
78protected :
79void __fastcall Build();
80public :
81__fastcall TFontSizeComboBox(TComponent* Owner);
82__published :
83__published :
84__property AnsiString FontName = {read = FFontName, write = SetFontName};
85__property Style;
86__property Anchors;
87__property BiDiMode;
88__property Color;
89__property Constraints;
90__property Ctl3D;
91__property DragCursor;
92__property DragKind;
93__property DragMode;
94__property DropDownCount;
95__property Enabled;
96__property Font;
97__property ItemHeight;
98__property MaxLength;
99__property ParentBiDiMode;
100__property ParentColor;
101__property ParentCtl3D;
102__property ParentFont;
103__property ParentShowHint;
104__property PopupMenu;
105__property ShowHint;
106__property TabOrder;
107__property TabStop;
108__property Visible;
109__property OnChange;
110__property OnClick;
111__property OnContextPopup;
112__property OnDblClick;
113__property OnDragDrop;
114__property OnDragOver;
115__property OnDrawItem;
116__property OnDropDown;
117__property OnEndDock;
118__property OnEndDrag;
119__property OnEnter;
120__property OnExit;
121__property OnKeyDown;
122__property OnKeyPress;
123__property OnKeyUp;
124__property OnMeasureItem;
125__property OnStartDock;
126__property OnStartDrag;
127};
128_ //--------------------------------------------------------------------------- _
129#endif
130
131实现文件
132_ /*=========================================================================== _
133_ TFontNameComboBox _ _ 及 TFontNameSizeComboBox 组件实现文件 _
134_ 文件名称: FontComboBox.CPP _
135_ _ _ 程序设计:梁生红 _
136_ 创建日期: 2003-03-20 _
137_ ===========================================================================*/ _
138#include <vcl.h>
139#pragma hdrstop
140
141#include "FontComboBox.h"
142#pragma package(smart_init)
143_ //--------------------------------------------------------------------------- _
144static inline void ValidCtrCheck(TFontNameComboBox *)
145{
146new TFontNameComboBox(NULL);
147}
148_ //--------------------------------------------------------------------------- _
149static inline void ValidCtrCheck(TFontSizeComboBox *)
150{
151new TFontSizeComboBox(NULL);
152}
153_ //--------------------------------------------------------------------------- _
154_ /* TODO : _ 回调函数实现代码 */
155bool __stdcall EnumFontNameProc(ENUMLOGFONT FAR *lpelf,NEWTEXTMETRICEX FAR *lpntme,
156int FontType, LPARAM lParam)
157{
158char FontFullName[64];
159strcpy(FontFullName,lpelf->elfFullName);
160if (((TStrings*)(lParam))->IndexOf(FontFullName)==-1)
161((TStrings*)(lParam))->Add(FontFullName);
162return true ;
163}
164_ //---------------------------------------------------------------------------- _
165bool __stdcall EnumFontSizeProc(ENUMLOGFONT FAR *lpelf,NEWTEXTMETRIC FAR *lpntm,
166int FontType, LPARAM lParam)
167{
168if (FontType&TRUETYPE_FONTTYPE)
169{
170((TStrings*)(lParam))->Add("8");
171((TStrings*)(lParam))->Add("9");
172((TStrings*)(lParam))->Add("10");
173((TStrings*)(lParam))->Add("11");
174((TStrings*)(lParam))->Add("12");
175((TStrings*)(lParam))->Add("14");
176((TStrings*)(lParam))->Add("16");
177((TStrings*)(lParam))->Add("18");
178((TStrings*)(lParam))->Add("20");
179((TStrings*)(lParam))->Add("22");
180((TStrings*)(lParam))->Add("24");
181((TStrings*)(lParam))->Add("26");
182((TStrings*)(lParam))->Add("28");
183((TStrings*)(lParam))->Add("36");
184((TStrings*)(lParam))->Add("48");
185((TStrings*)(lParam))->Add("72");
186return false ;
187}
188else
189{
190AnsiString s;
191int i,v,v2;
192v = floor((lpelf->elfLogFont.lfHeight-lpntm->tmInternalLeading)*72/PixelsPerInch);
193s = IntToStr(v);
194for (i = 0;i<((TStrings*)(lParam))->Count-1;i++)
195{
196v2 = StrToInt(((TStrings*)(lParam))->Strings[i]);
197if (v2==v)
198return true ;
199if (v2>v)
200{
201((TStrings*)(lParam))->Insert(i,s);
202return true ;
203}
204}
205((TStrings*)(lParam))->Add(s);
206return true ;
207}
208}
209_ //---------------------------------------------------------------------------
210
211_
212_ /* TODO : TFontNameComboBox _ 实现部分 */
213__fastcall TFontNameComboBox::TFontNameComboBox(TComponent* Owner)
214: TCustomComboBox(Owner)
215{
216Sorted = true ;
217if (!ComponentState.Contains(csDesigning))
218Build();
219}
220_ //--------------------------------------------------------------------------- _
221void __fastcall TFontNameComboBox::Build()
222{
223
224HDC DC = NULL;
225LOGFONT LogFont;
226TNotifyEvent OnChangeEvent;
227
228OnChangeEvent = OnChange;
229OnChange = NULL;
230Items->Clear();
231LogFont.lfCharSet = DEFAULT_CHARSET;
232strcpy(LogFont.lfFaceName,"");
233LogFont.lfPitchAndFamily = 0;
234
235DC = GetDC(GetDesktopWindow());
236try
237{
238EnumFontFamiliesEx(DC,&LogFont,(FONTENUMPROC)(EnumFontNameProc),LPARAM(Items),0);
239}
240__finally
241{
242ReleaseDC(GetDesktopWindow(),DC);
243}
244OnChange = OnChangeEvent;
245if (Items->Count)
246ItemIndex = 0;
247
248}
249_ //--------------------------------------------------------------------------- _
250_ /* TODO : TFontSizeComboBox _ 实现部分 */
251__fastcall TFontSizeComboBox::TFontSizeComboBox(TComponent* Owner)
252: TCustomComboBox(Owner)
253{
254Sorted = false ;
255}
256_ //--------------------------------------------------------------------------- _
257void __fastcall TFontSizeComboBox::SetFontName(AnsiString AFontName)
258{
259FFontName = AFontName;
260if (!ComponentState.Contains(csDesigning))
261{
262Items->Clear();
263Build();
264}
265}
266_ //--------------------------------------------------------------------------- _
267void __fastcall TFontSizeComboBox::Build()
268{
269TNotifyEvent OnChangeEvent = OnChange;
270OnChange = NULL;
271HDC DC = GetDC(GetDesktopWindow());
272PixelsPerInch = GetDeviceCaps(DC, LOGPIXELSY);
273try
274{
275EnumFontFamilies(DC, FFontName.c_str(), (FONTENUMPROC)(EnumFontSizeProc),LPARAM(Items));
276}
277__finally
278{
279ReleaseDC(GetDesktopWindow(),DC);
280}
281OnChange = OnChangeEvent;
282if (Items->Count)
283ItemIndex = 0;
284}
285_ //--------------------------------------------------------------------------- _
286namespace Fontcombobox
287{
288void __fastcall PACKAGE Register()
289{
290TComponentClass classes[2] = { __classid (TFontNameComboBox),
291__classid (TFontSizeComboBox)};
292RegisterComponents("Samples", classes, 1);
293}
294}
295_ //---------------------------------------------------------------------------
296
297_</vcl.h></math.h></printers.hpp></stdctrls.hpp></forms.hpp></classes.hpp></controls.hpp></sysutils.hpp>