TFontNameComboBox及TFontSizeComboBox的实现

类别:Delphi 点击:0 评论:0 推荐:

在用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);
        }
}
//---------------------------------------------------------------------------

本文地址:http://com.8s8s.com/it/it5422.htm