fcfontcombo.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:18k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. unit fcFontCombo;
  2. {
  3. //
  4. // Components : TfcFontCombo
  5. //
  6. // Copyright (c) 1999 by Woll2Woll Software
  7. // 6/6/99 - RSW - Destroy gets called when DLL is unloaded
  8. // 6/6/99 - Add screen fonts
  9. // 10/1/2001- Exposed OnMouseEnter and OnMouseLeave to be consistent with InfoPower.
  10. // 10/1/2001- Exposed PopupMenu property and OnContextPopup event.
  11. // 10/29/2001- Hide hints or flicker occurs when key is pressed and hint showing.
  12. }
  13. interface
  14. {$i fcIfDef.pas}
  15. uses Graphics, Windows, Messages, Classes, SysUtils, Controls, fcCombo, Dialogs,
  16.   fcTreeCombo, Forms, Printers, fcCommon, fcTreeView, fcToolTip
  17.   {$ifdef fcDelphi4Up}
  18.   ,ImgList
  19.   {$endif};
  20. type
  21.   TfcCustomFontCombo = class;
  22.   TfcComboFontType = (ftFontPrinter, ftFontTrueType, ftFontOther, ftFontRaster);
  23.   TfcAddFontEvent = procedure(FontCombo: TfcCustomFontCombo; FontName: string;
  24.     FontType: TfcComboFontType; EnumLogFont: TEnumLogFont; NewTextMetric: TNewTextMetric;
  25.     var Accept: Boolean) of object;
  26.   TfcFontHintEvent = procedure(FontCombo: TfcCustomFontCombo; FontName: string;
  27.     var Hint: string; const Font: TFont) of object;
  28.   TfcFontPopupNode = class(TfcTreeComboTreeNode)
  29.   private
  30.     FRecentFont: Boolean;
  31.   public
  32.     property RecentFont: Boolean read FRecentFont write FRecentFont;
  33.   end;
  34.   TfcFontPopupTreeView = class(TfcPopupTreeView)
  35.   protected
  36.     procedure EndItemPainting(Node: TfcTreeNode; ARect: TRect; AItemState: TfcItemStates); override;
  37.   public
  38.     constructor Create(Owner: TComponent); override;
  39.   end;
  40.   {
  41.   // TfcCustomFontCombo
  42.   //
  43.   // Properties:
  44.   // - MaxMRU: This property specifies the maximum number of items
  45.   //           that will be added to the most recently used section
  46.   //           of the drop down tree view.  If this property is -1
  47.   //           then MRU functionality is disabled.
  48.   //
  49.   // - PreLoad: When this property is set, the fonts are loaded into
  50.   //           the combo upon creation.  However, when this property
  51.   //           is false, the fonts are loaded in either when you
  52.   //           enter the control or drop it down depending on whether
  53.   //           ShowMatchText is true or false, respectively.
  54.   //
  55.   // - RecentFonts: A list of fonts that appear at the top of the
  56.   //           font combo.  This property is automatically managed
  57.   //           if the MaxMRU property contains a value other than
  58.   //           -1.
  59.   //
  60.   // - ShowFontHints: When true, holding the mouse over a font
  61.   //           selection in the drop-down list will pop-up a hint
  62.   //           displaying the font name in that font's face.
  63.   //
  64.   // Methods:
  65.   // - Reload: Causes the font combo to reload its fonts.  If
  66.   //           RecentFontsOnly is true, then only reloads the
  67.   //           items at the top corresponding to the values in
  68.   //           the RecentFonts property.
  69.   //
  70.   // Events:
  71.   // - OnAddFont: Occurs immediately before adding a font to the
  72.   //           font combo.  Accept is initially true -- setting it
  73.   //           to false will prevent the font from being added to
  74.   //           the font combo.
  75.   //
  76.   // - OnGenerateFontHint: Occurs immediately before displaying a
  77.   //           hint for a particular font.  Customization on the hint
  78.   //           text and font can occur here.  Only occurs when the
  79.   //           ShowFontHints property is true.
  80.   }
  81.   TfcFontType = (fcScreenFonts, fcPrinterFonts, fcRasterFonts);
  82.   TfcCustomFontCombo = class(TfcCustomTreeCombo)
  83.   private
  84.     FOldHintClass: THintWindowClass;
  85.     FOldSelectedText: string;
  86.     FCheckMRUChange: Boolean;
  87.     FImmediateHints: Boolean;
  88.     FMaxMRU: Integer;
  89.     FOldHintPause: Integer;
  90.     FPreLoad: Boolean;
  91.     FRecentFonts: TStringList;
  92.     FShowFontHint: Boolean;
  93.     FOnAddFont: TfcAddFontEvent;
  94.     FOnGenerateFontHint: TfcFontHintEvent;
  95.     {$ifdef fcDelphi4Up}
  96.     FFontSelections: TfcFontType;
  97.     {$endif}
  98.     // Property Access Methods
  99.     function GetSelectedFont: string;
  100.     procedure SetMaxMRU(Value: Integer);
  101.     procedure SetRecentFonts(Value: TStringList);
  102.     // Message Handlers
  103.     procedure CMEnter(var Message: TCMEnter); message CM_ENTER;
  104.     procedure ChangeHint(HintClass: THintWindowClass);
  105.   protected
  106.     // Virtual Methods
  107.     function FontCallBack(EnumLogFont: TEnumLogFont; NewTextMetric: TNewTextMetric;
  108.       FontType: Integer): Integer; virtual;
  109.     procedure GenerateFontHint(FontName: string; var AHint: string; AHintFont: TFont); virtual;
  110.     procedure MaintainMaxMRU; virtual;
  111.     procedure MRUChange(FontName: string); virtual;
  112.     procedure RecentFontsChanging(Sender: TObject); virtual;
  113.     procedure RecentFontsChange(Sender: TObject); virtual;
  114.     procedure TreeViewMouseMove(TreeView: TfcCustomTreeView; Node: TfcTreeNode; Shift: TShiftState; X, Y: Integer); virtual;
  115.     procedure TreeViewChange(Sender: TfcCustomTreeView; Node: TfcTreeNode); virtual;
  116.     // Overridden Methods
  117.     function CreatePopupTreeView: TfcPopupTreeView; override;
  118.     function GetStartingNode: TfcTreeNode; override;
  119.     procedure CreateWnd; override;
  120.     procedure KeyPress(var Key: Char); override;
  121.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  122.     procedure DoAddFont(
  123.                 AFontText: string; AFontType: TfcComboFontType;
  124.                 EnumLogFont: TEnumLogFont; NewTextMetric: TNewTextMetric;
  125.                 var Accept: boolean); virtual;
  126.   public
  127.     Patch: Variant;
  128.     constructor Create(AOwner: TComponent); override;
  129.     destructor Destroy; override;
  130.     procedure CloseUp(Accept: Boolean); override;
  131.     procedure DropDown; override;
  132.     procedure Reload(RecentFontsOnly: Boolean); virtual;
  133.     property ImmediateHints: Boolean read FImmediateHints write FImmediateHints;
  134.     property MaxMRU: Integer read FMaxMRU write SetMaxMRU;
  135.     property PreLoad: Boolean read FPreLoad write FPreLoad;
  136.     property RecentFonts: TStringList read FRecentFonts write SetRecentFonts;
  137.     property ShowFontHint: Boolean read FShowFontHint write FShowFontHint;
  138.     property SelectedFont: string read GetSelectedFont;
  139.     {$ifdef fcDelphi4Up}
  140.     property FontSelections: TfcFontType read FFontSelections write FFontSelections default fcScreenFonts;
  141.     {$endif}
  142.     property OnAddFont: TfcAddFontEvent read FOnAddFont write FOnAddFont;
  143.     property OnGenerateFontHint: TfcFontHintEvent read FOnGenerateFontHint write FOnGenerateFontHint;
  144.   end;
  145.   TfcFontCombo = class(TfcCustomFontCombo)
  146.   published
  147.     property Controller;
  148.     property DisableThemes;
  149.     
  150.     {$ifdef fcDelphi4Up}
  151.     property Anchors;
  152.     property BiDiMode;
  153.     property Constraints;
  154.     property ParentBiDiMode;    
  155.     {$endif}
  156.     property AllowClearKey;
  157.     property AutoSelect;
  158.     property AutoSize;
  159.     property BorderStyle;
  160.     property ButtonStyle;
  161.     property ButtonEffects;
  162.     property ButtonGlyph;
  163.     property ButtonWidth;
  164.     property CharCase;
  165.     property DropDownCount default 8;
  166.     property DropDownWidth;
  167.     property Enabled;
  168.     property Frame;
  169.     property Font;
  170.     property ImmediateHints;
  171.     property MaxMRU default 6;
  172.     property PreLoad default False;
  173.     property PopupMenu;
  174.     property ReadOnly;
  175.     property RecentFonts;
  176.     property ShowFontHint default True;
  177.     property ShowHint;
  178.     property ShowMatchText default True;
  179.     property Sorted default True;
  180.     property Style default csDropDownList;
  181.     property TabOrder;
  182.     property TreeOptions;
  183.     property Visible;
  184.     {$ifdef fcDelphi4Up}
  185.     property FontSelections;
  186.     {$endif}
  187.     property OnAddFont;
  188.     property OnCloseUp;
  189.     property OnChange;
  190.     {$ifdef fcDelphi5Up}
  191.     property OnContextPopup;
  192.     {$endif}
  193.     property OnDropDown;
  194.     property OnEnter;
  195.     property OnExit;
  196.     property OnGenerateFontHint;
  197.     property OnKeyDown;
  198.     property OnKeyPress;
  199.     property OnKeyUp;
  200.     property OnMouseEnter;
  201.     property OnMouseLeave;
  202.     property OnMouseDown;
  203.     property OnMouseMove;
  204.     property OnMouseUp;
  205.     property OnSelectionChange;
  206.   end;
  207. implementation
  208. {$r fcFont.res}
  209. type
  210.    TFontImageList = class(TImageList)
  211.       public
  212.          destructor Destroy; override;
  213.    end;
  214. var fcFontImages: TImageList = nil;
  215. destructor TFontImageList.Destroy; { 6/6/99 - RSW - Destroy gets called when DLL is unloaded }
  216. begin
  217.    inherited Destroy;
  218.    fcFontImages:= nil;
  219. end;
  220. function GetFontImages: TImageList;
  221. var bm: Graphics.TBitmap;
  222. begin
  223.   if fcFontImages = nil then
  224.   begin
  225.     bm := Graphics.TBitmap.Create;
  226.     bm.Transparent := True;
  227.     bm.LoadFromResourceName(HINSTANCE, 'FCFONTTRUETYPE');
  228.     fcFontImages := TFontImageList.Create(nil);
  229.     fcFontImages.Width := bm.Width;
  230.     fcFontImages.Height := bm.Height;
  231.     fcFontImages.AddMasked(bm, bm.TransparentColor);
  232.     bm.LoadFromResourceName(HINSTANCE, 'FCFONTPRINTER');
  233.     fcFontImages.AddMasked(bm, bm.TransparentColor);
  234.     fcFontImages.BlendColor := clHighlight;
  235.     bm.Free;
  236.   end;
  237.   result := fcFontImages;
  238. end;
  239. constructor TfcFontPopupTreeView.Create(Owner: TComponent);
  240. begin
  241.   inherited;
  242.   NodeClass := TfcFontPopupNode;
  243. end;
  244. procedure TfcFontPopupTreeView.EndItemPainting(Node: TfcTreeNode; ARect: TRect; AItemState: TfcItemStates);
  245. var r: TRect;
  246. begin
  247.   inherited;
  248.   r := Node.DisplayRect(False);
  249.   { RSW - Separated logic to allow lines to moved down by 1}
  250.   with (TreeCombo as TfcCustomFontCombo).RecentFonts do
  251.     if (Count > 0) and TfcFontPopupNode(Node).RecentFont and (TfcFontPopupNode(Node).GetNext <> nil) and not TfcFontPopupNode(Node.GetNext).RecentFont then
  252.   begin
  253.     Canvas.Pen.Color := clBtnShadow;
  254. //    Canvas.PolyLine([Point(0, r.Bottom - 0), Point(Width, r.Bottom - 0)]);
  255.     Canvas.PolyLine([Point(0, r.Bottom - 2), Point(Width, r.Bottom - 2)]);
  256.   end;
  257.   with (TreeCombo as TfcCustomFontCombo).RecentFonts do
  258.     if (Count > 0) and
  259.        not TfcFontPopupNode(Node).RecentFont and (Node.GetPrev <> nil) and TfcFontPopupNode(Node.GetPrev).RecentFont then
  260.   begin
  261.     Canvas.Pen.Color := clBtnShadow;
  262.     Canvas.PolyLine([Point(0, r.Top), Point(Width, r.Top)]);
  263.   end;
  264. end;
  265. constructor TfcCustomFontCombo.Create(AOwner: TComponent);
  266. begin
  267.   inherited;
  268.   Sorted := True;
  269.   FMaxMRU := 6;
  270.   FShowFontHint := True;
  271.   TreeView.ShowHint := True;
  272.   TreeView.OnMouseMove := TreeViewMouseMove;
  273.   TreeView.OnChange := TreeViewChange;
  274.   FRecentFonts := TStringList.Create;
  275.   FRecentFonts.OnChanging := RecentFontsChanging;
  276.   FRecentFonts.OnChange := RecentFontsChange;
  277.   FCheckMRUChange := True;
  278.   TreeOptions := TreeOptions - [tvoShowLines, tvoShowRoot] + [tvoRowSelect];
  279.   Style:= csDropDownList;
  280. //  {$ifdef fcDelphi4Up}
  281. //  FFontTypes:= fcScreenFonts;
  282. //  {$endif}
  283. end;
  284. destructor TfcCustomFontCombo.Destroy;
  285. begin
  286.   FRecentFonts.Free;
  287.   inherited;
  288. end;
  289. procedure TfcCustomFontCombo.CreateWnd;
  290. begin
  291.   inherited;
  292.   If Images<>GetFontImages then
  293.      Images := GetFontImages;
  294.   if PreLoad then Reload(False);
  295. end;
  296. function fcFontCallBack(lpelf: PEnumLogFont; lpntm: PNewTextMetric; FontType: Integer;
  297.   FontCombo: TfcCustomFontCombo): Integer; stdcall;
  298. begin
  299.   result := FontCombo.FontCallBack(lpelf^, lpntm^, FontType);
  300. end;
  301. function TfcCustomFontCombo.CreatePopupTreeView: TfcPopupTreeView;
  302. begin
  303.   result := TfcFontPopupTreeView.Create(self);
  304. end;
  305. procedure TfcCustomFontCombo.DoAddFont(
  306.   AFontText: string; AFontType: TfcComboFontType;
  307.   EnumLogFont: TEnumLogFont; NewTextMetric: TNewTextMetric;
  308.   var Accept: boolean);
  309. begin
  310.   if Assigned(FOnAddFont) then
  311.     FOnAddFont(self, AFontText, AFontType, EnumLogFont, NewTextMetric, Accept);
  312. end;
  313. function TfcCustomFontCombo.FontCallBack(EnumLogFont: TEnumLogFont; NewTextMetric: TNewTextMetric;
  314.   FontType: Integer): Integer;
  315. var Accept: Boolean;
  316.     FontText: string;
  317.     AFontType: TfcComboFontType;
  318. begin
  319.   result := 1;
  320. //  AFontType := fcGetFontType(FontType);
  321.   Accept := True;
  322.   FontText := EnumLogFont.elfLogFont.lfFaceName;
  323.   { Map to type that is declared in this unit so that developer does not need to add
  324.     an additional unit to the uses clause }
  325.   if FontType = DEVICE_FONTTYPE then AFontType := ftFontPrinter
  326.   else if (FontType and TRUETYPE_FONTTYPE) <> 0 then AFontType := ftFontTrueType
  327.   else if (FontType and RASTER_FONTTYPE) <> 0 then AFontType := ftFontRaster
  328.   else AFontType := ftFontOther;
  329.   DoAddFont(FontText, AFontType, EnumLogFont, NewTextMetric, Accept);
  330.   if Accept and (EnumLogFont.elfLogFont.lfFaceName <> '') then
  331.     with Items.Add(nil, FontText) do
  332.   begin
  333.     case AFontType of
  334.       ftFontTrueType: ImageIndex := 0;
  335.       ftFontPrinter: ImageIndex := 1;
  336.       ftFontRaster: ImageIndex := 2;
  337.       ftFontOther: ImageIndex := -1;
  338.     end;
  339.   end;
  340. end;
  341. function TfcCustomFontCombo.GetStartingNode: TfcTreeNode;
  342. begin
  343.   result := nil;
  344.   if Items.Count > RecentFonts.Count then result := TreeView.Items[RecentFonts.Count];
  345. end;
  346. function TfcCustomFontCombo.GetSelectedFont: string;
  347. begin
  348.   result := '';
  349.   if TreeView.Selected <> nil then result := TreeView.Selected.Text;
  350. end;
  351. procedure TfcCustomFontCombo.SetMaxMRU(Value: Integer);
  352. begin
  353.   if FMaxMRU <> Value then
  354.   begin
  355.     FMaxMRU := Value;
  356.     MaintainMaxMRU;
  357.   end;
  358. end;
  359. procedure TfcCustomFontCombo.SetRecentFonts(Value: TStringList);
  360. begin
  361.   FRecentFonts.Assign(Value);
  362. end;
  363. procedure TfcCustomFontCombo.CMEnter(var Message: TCMEnter);
  364. begin
  365.   inherited;
  366. //  if not PreLoad and (TreeView.Items.Count <= RecentFonts.Count) then Reload(False);
  367. end;
  368. procedure TfcCustomFontCombo.ChangeHint(HintClass: THintWindowClass);
  369. begin
  370.   if HintClass = nil then Exit;
  371.   if (HintWindowClass <> HintClass) and ImmediateHints then
  372.   begin
  373.     if (HintClass = TfcToolTip) then
  374.     begin
  375.       FOldHintPause := Application.HintPause;
  376.       Application.HintPause := 0
  377.     end else Application.HintPause := FOldHintPause;
  378.   end;
  379.   HintWindowClass := HintClass;
  380. end;
  381. procedure TfcCustomFontCombo.CloseUp(Accept: Boolean);
  382. begin
  383.   inherited;
  384.   ChangeHint(FOldHintClass);
  385.   if Accept and (MaxMRU <> -1) and (TreeView.Selected <> nil) then
  386.   begin
  387.     MRUChange(Text);
  388.     TreeView.Selected := TreeView.Items.FindNode(Text, False);
  389.   end;
  390. end;
  391. procedure TfcCustomFontCombo.DropDown;
  392. begin
  393.   if not PreLoad and (TreeView.Items.Count <= RecentFonts.Count) then
  394.      Reload(False); { 4/5/99 - RSW }
  395.   inherited;
  396.   FOldHintClass := HintWindowClass;
  397.   ChangeHint(TfcToolTip);
  398. end;
  399. procedure TfcCustomFontCombo.GenerateFontHint(FontName: string; var AHint: string; AHintFont: TFont);
  400. begin
  401.   if Assigned(FOnGenerateFontHint) then FOnGenerateFontHint(self, FontName, AHint, AHintFont);
  402. end;
  403. procedure TfcCustomFontCombo.MaintainMaxMRU;
  404. begin
  405.   if (MaxMRU <> -1) then while RecentFonts.Count > MaxMRU do
  406.     RecentFonts.Delete(RecentFonts.Count - 1);
  407. end;
  408. procedure TfcCustomFontCombo.MRUChange(FontName: string);
  409. var FontNameIndex: Integer;
  410. begin
  411.   FontNameIndex := RecentFonts.IndexOf(FontName);
  412.   if FontNameIndex <> -1 then RecentFonts.Move(FontNameIndex, 0)
  413.   else begin
  414.     RecentFonts.Insert(0, FontName);
  415.     MaintainMaxMRU;
  416.   end;
  417. end;
  418. procedure TfcCustomFontCombo.Reload(RecentFontsOnly: Boolean);
  419. var OldCursor: TCursor;
  420. begin
  421.   if RecentFontsOnly then
  422.     RecentFontsChanging(RecentFonts)
  423.   else begin
  424. {    if TreeView.FStateChanging then begin
  425.        Treeview.HandleNeeded;
  426.        exit;
  427.     end;
  428. }
  429.     OldCursor:= Cursor;
  430.     if Focused then
  431.       Screen.Cursor:= crHourGlass;
  432.     if Items.Count > 0 then Items.Clear;
  433.     {$ifdef fcDelphi4Up}
  434.     if FFontSelections = fcPrinterFonts then
  435.        EnumFontFamilies(Printers.Printer.Handle, nil, @fcFontCallback, LPARAM(self))
  436.     else
  437.     {$endif}
  438.        EnumFontFamilies(Canvas.Handle, nil, @fcFontCallback, LPARAM(self)); { 6/6/97 - RSW }
  439.     if Sorted then TreeView.AlphaSort;
  440.     Screen.Cursor:= OldCursor;
  441.   end;
  442.   RecentFontsChange(RecentFonts);    // Add the RecentFonts list back into the tree view
  443. end;
  444. procedure TfcCustomFontCombo.KeyDown(var Key: Word; Shift: TShiftState);
  445. begin
  446.   inherited;
  447.   // 10/29/2001- Hide hints or flicker occurs when key is pressed and hint showing.
  448.   if ImmediateHints then ChangeHint(FOldHintClass);
  449. end;
  450. procedure TfcCustomFontcombo.RecentFontsChanging(Sender: TObject);
  451. var Node: TfcTreeNode;
  452. begin
  453.   if TreeView.Selected <> nil then FOldSelectedText := TreeView.Selected.Text;
  454.   Node := TreeView.Items.GetFirstNode;
  455.   while (Node <> nil) and TfcFontPopupNode(Node).RecentFont do
  456.   begin
  457.     Node.Free;
  458.     Node := TreeView.Items.GetFirstNode;
  459.   end;
  460. end;
  461. procedure TfcCustomFontCombo.RecentFontsChange(Sender: TObject);
  462. var i: Integer;
  463.     s: string;
  464. begin
  465.   for i := RecentFonts.Count - 1 downto 0 do
  466.     with TfcFontPopupNode(TreeView.Items.AddFirst(nil, RecentFonts[i])) do
  467.     begin
  468.       RecentFont := True;
  469.       s := ItemsList.Values[Text];
  470.       if s <> '' then ImageIndex := StrToInt(s)
  471.     end;
  472.   if (FOldSelectedText <> '') and ((TreeView.Selected = nil) or
  473.     ((TreeView.Selected <> nil) and (TreeView.Selected.Text <> FOldSelectedText))) then
  474.   begin
  475.     TreeView.Selected := TreeView.Items.FindNode(FOldSelectedText, False);
  476.     FOldSelectedText := ''
  477.   end;
  478. end;
  479. procedure TfcCustomFontCombo.TreeViewChange(Sender: TfcCustomTreeView; Node: TfcTreeNode);
  480. var AHint: string;
  481. begin
  482.   if ShowFontHint then with (Sender as TfcTreeView) do
  483.   begin
  484.     Node := Selected;
  485.     if Node <> nil then with fcHintFont do
  486.     begin
  487.       Application.CancelHint;
  488.       AHint := Node.Text;
  489.       Name := Node.Text;
  490.       Size := 12;
  491.       GenerateFontHint(Node.Text, AHint, fcHintFont);
  492.       TreeView.Hint := AHint;
  493.     end;
  494.   end;
  495. end;
  496. procedure TfcCustomFontCombo.TreeViewMouseMove(TreeView: TfcCustomTreeView;
  497.    Node: TfcTreeNode; Shift: TShiftState; X, Y: Integer);
  498. begin
  499.   if ShowFontHint then
  500.   begin
  501.     if not PtInRect(Rect(0, 0, TreeView.Width, TreeView.Height), Point(x, y)) then
  502.       ChangeHint(FOldHintClass)
  503.     else ChangeHint(TfcToolTip);
  504.   end;
  505. end;
  506. procedure TfcCustomFontCombo.KeyPress(var Key: Char);
  507. begin
  508.   if not PreLoad and (TreeView.Items.Count <= RecentFonts.Count) then Reload(False); { 4/5/99 - RSW }
  509.   inherited;
  510. end;
  511. initialization
  512. finalization
  513.   fcFontImages.Free;
  514.   fcFontImages := nil;
  515. end.