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

Delphi控件源码

开发平台:

Delphi

  1. {*******************************************************}
  2. {                                                       }
  3. {         Delphi VCL Extensions (RX)                    }
  4. {                                                       }
  5. {         Copyright (c) 1995, 1996 AO ROSNO             }
  6. {         Copyright (c) 1997, 1998 Master-Bank          }
  7. {                                                       }
  8. {*******************************************************}
  9. unit RxCombos;
  10. {.$DEFINE GXE}
  11. { Activate this define to use RxCombos in the GXExplorer Open Source project }
  12. {$I RX.INC}
  13. {$W-,T-}
  14. interface
  15. uses {$IFDEF WIN32} Windows, {$ELSE} WinTypes, WinProcs, {$ENDIF}
  16.   Messages, Classes, Controls, Graphics, StdCtrls, Forms, Menus;
  17. type
  18. { TOwnerDrawComboBox }
  19.   TOwnerDrawComboStyle = csDropDown..csDropDownList;
  20.   TOwnerDrawComboBox = class(TCustomComboBox)
  21.   private
  22.     FStyle: TOwnerDrawComboStyle;
  23.     FItemHeightChanging: Boolean;
  24.     procedure SetComboStyle(Value: TOwnerDrawComboStyle);
  25.     procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
  26. {$IFDEF WIN32}
  27.     procedure CMRecreateWnd(var Message: TMessage); message CM_RECREATEWND;
  28. {$ENDIF}
  29.   protected
  30.     procedure CreateParams(var Params: TCreateParams); override;
  31.     procedure CreateWnd; override;
  32.     procedure ResetItemHeight;
  33.     function MinItemHeight: Integer; virtual;
  34.     property Style: TOwnerDrawComboStyle read FStyle write SetComboStyle
  35.       default csDropDownList;
  36.   public
  37.     constructor Create(AOwner: TComponent); override;
  38.   end;
  39. { TColorComboBox }
  40.   TColorComboBox = class(TOwnerDrawComboBox)
  41.   private
  42.     FColorValue: TColor;
  43.     FDisplayNames: Boolean;
  44.     FColorNames: TStrings;
  45.     FOnChange: TNotifyEvent;
  46.     function GetColorValue: TColor;
  47.     procedure SetColorValue(NewValue: TColor);
  48.     procedure SetDisplayNames(Value: Boolean);
  49.     procedure SetColorNames(Value: TStrings);
  50.     procedure ColorNamesChanged(Sender: TObject);
  51.   protected
  52.     procedure CreateWnd; override;
  53.     procedure DrawItem(Index: Integer; Rect: TRect; State: TOwnerDrawState); override;
  54.     procedure Click; override;
  55.     procedure Change; override;
  56.     procedure PopulateList; virtual;
  57.     procedure DoChange; dynamic;
  58.   public
  59.     constructor Create(AOwner: TComponent); override;
  60.     destructor Destroy; override;
  61.     property Text;
  62.   published
  63.     property ColorValue: TColor read GetColorValue write SetColorValue
  64.       default clBlack;
  65.     property ColorNames: TStrings read FColorNames write SetColorNames;
  66.     property DisplayNames: Boolean read FDisplayNames write SetDisplayNames
  67.       default True;
  68.     property Color;
  69.     property Ctl3D;
  70.     property DragMode;
  71.     property DragCursor;
  72.     property Enabled;
  73.     property Font;
  74. {$IFDEF RX_D4}
  75.     property Anchors;
  76.     property BiDiMode;
  77.     property Constraints;
  78.     property DragKind;
  79.     property ParentBiDiMode;
  80. {$ENDIF}
  81. {$IFDEF WIN32}
  82.   {$IFNDEF VER90}
  83.     property ImeMode;
  84.     property ImeName;
  85.   {$ENDIF}
  86. {$ENDIF}
  87.     property ParentColor;
  88.     property ParentCtl3D;
  89.     property ParentFont;
  90.     property ParentShowHint;
  91.     property PopupMenu;
  92.     property ShowHint;
  93.     property Style;
  94.     property TabOrder;
  95.     property TabStop;
  96.     property Visible;
  97.     property OnChange: TNotifyEvent read FOnChange write FOnChange;
  98.     property OnClick;
  99.     property OnDblClick;
  100.     property OnDragDrop;
  101.     property OnDragOver;
  102.     property OnDropDown;
  103.     property OnEndDrag;
  104.     property OnEnter;
  105.     property OnExit;
  106.     property OnKeyDown;
  107.     property OnKeyPress;
  108.     property OnKeyUp;
  109. {$IFDEF WIN32}
  110.     property OnStartDrag;
  111. {$ENDIF}
  112. {$IFDEF RX_D5}
  113.     property OnContextPopup;
  114. {$ENDIF}
  115. {$IFDEF RX_D4}
  116.     property OnEndDock;
  117.     property OnStartDock;
  118. {$ENDIF}
  119.   end;
  120. { TFontComboBox }
  121.   TFontDevice = (fdScreen, fdPrinter, fdBoth);
  122.   TFontListOption = (foAnsiOnly, foTrueTypeOnly, foFixedPitchOnly,
  123.     foNoOEMFonts, foOEMFontsOnly, foScalableOnly, foNoSymbolFonts);
  124.   TFontListOptions = set of TFontListOption;
  125.   TFontComboBox = class(TOwnerDrawComboBox)
  126.   private
  127.     FTrueTypeBMP: TBitmap;
  128.     FDeviceBMP: TBitmap;
  129.     FOnChange: TNotifyEvent;
  130.     FDevice: TFontDevice;
  131.     FUpdate: Boolean;
  132.     FUseFonts: Boolean;
  133.     FOptions: TFontListOptions;
  134.     procedure SetFontName(const NewFontName: TFontName);
  135.     function GetFontName: TFontName;
  136.     function GetTrueTypeOnly: Boolean;
  137.     procedure SetDevice(Value: TFontDevice);
  138.     procedure SetOptions(Value: TFontListOptions);
  139.     procedure SetTrueTypeOnly(Value: Boolean);
  140.     procedure SetUseFonts(Value: Boolean);
  141.     procedure Reset;
  142.     procedure WMFontChange(var Message: TMessage); message WM_FONTCHANGE;
  143.   protected
  144.     procedure PopulateList; virtual;
  145.     procedure Change; override;
  146.     procedure Click; override;
  147.     procedure DoChange; dynamic;
  148.     procedure CreateWnd; override;
  149.     procedure DrawItem(Index: Integer; Rect: TRect; State: TOwnerDrawState); override;
  150.     function MinItemHeight: Integer; override;
  151.   public
  152.     constructor Create(AOwner: TComponent); override;
  153.     destructor Destroy; override;
  154.     property Text;
  155.   published
  156.     property Device: TFontDevice read FDevice write SetDevice default fdScreen;
  157.     property FontName: TFontName read GetFontName write SetFontName;
  158.     property Options: TFontListOptions read FOptions write SetOptions default [];
  159.     property TrueTypeOnly: Boolean read GetTrueTypeOnly write SetTrueTypeOnly
  160.       stored False; { obsolete, use Options instead }
  161.     property UseFonts: Boolean read FUseFonts write SetUseFonts default False;
  162.     property Color;
  163.     property Ctl3D;
  164.     property DragMode;
  165.     property DragCursor;
  166.     property Enabled;
  167.     property Font;
  168. {$IFDEF RX_D4}
  169.     property Anchors;
  170.     property BiDiMode;
  171.     property Constraints;
  172.     property DragKind;
  173.     property ParentBiDiMode;
  174. {$ENDIF}
  175. {$IFDEF WIN32}
  176.   {$IFNDEF VER90}
  177.     property ImeMode;
  178.     property ImeName;
  179.   {$ENDIF}
  180. {$ENDIF}
  181.     property ParentColor;
  182.     property ParentCtl3D;
  183.     property ParentFont;
  184.     property ParentShowHint;
  185.     property PopupMenu;
  186.     property ShowHint;
  187.     property Style;
  188.     property TabOrder;
  189.     property TabStop;
  190.     property Visible;
  191.     property OnChange: TNotifyEvent read FOnChange write FOnChange;
  192.     property OnClick;
  193.     property OnDblClick;
  194.     property OnDragDrop;
  195.     property OnDragOver;
  196.     property OnDropDown;
  197.     property OnEndDrag;
  198.     property OnEnter;
  199.     property OnExit;
  200.     property OnKeyDown;
  201.     property OnKeyPress;
  202.     property OnKeyUp;
  203. {$IFDEF WIN32}
  204.     property OnStartDrag;
  205. {$ENDIF}
  206. {$IFDEF RX_D5}
  207.     property OnContextPopup;
  208. {$ENDIF}
  209. {$IFDEF RX_D4}
  210.     property OnEndDock;
  211.     property OnStartDock;
  212. {$ENDIF}
  213.   end;
  214. {$IFDEF GXE}
  215. procedure Register;
  216. {$ENDIF}
  217. implementation
  218. {$IFDEF WIN32}
  219.  {$R *.R32}
  220. {$ELSE}
  221.  {$R *.R16}
  222. {$ENDIF}
  223. uses SysUtils, Printers {$IFNDEF GXE}, VCLUtils {$ENDIF};
  224. {$IFDEF GXE}
  225. procedure Register;
  226. begin
  227.   RegisterComponents('Additional', [TFontComboBox, TColorComboBox]);
  228. end;
  229. {$ENDIF GXE}
  230. {$IFNDEF WIN32}
  231. type
  232.   DWORD = Longint;
  233. {$ENDIF}
  234. { Utility routines }
  235. function CreateBitmap(ResName: PChar): TBitmap;
  236. begin
  237. {$IFDEF GXE}
  238.   Result := TBitmap.Create;
  239.   Result.Handle := LoadBitmap(HInstance, ResName);
  240. {$ELSE}
  241.   Result := MakeModuleBitmap(HInstance, ResName);
  242.   if Result = nil then ResourceNotFound(ResName);
  243. {$ENDIF GXE}
  244. end;
  245. function GetItemHeight(Font: TFont): Integer;
  246. var
  247.   DC: HDC;
  248.   SaveFont: HFont;
  249.   Metrics: TTextMetric;
  250. begin
  251.   DC := GetDC(0);
  252.   try
  253.     SaveFont := SelectObject(DC, Font.Handle);
  254.     GetTextMetrics(DC, Metrics);
  255.     SelectObject(DC, SaveFont);
  256.   finally
  257.     ReleaseDC(0, DC);
  258.   end;
  259.   Result := Metrics.tmHeight + 1;
  260. end;
  261. { TOwnerDrawComboBox }
  262. constructor TOwnerDrawComboBox.Create(AOwner: TComponent);
  263. begin
  264.   inherited Create(AOwner);
  265.   inherited Style := csDropDownList;
  266.   FStyle := csDropDownList;
  267. end;
  268. procedure TOwnerDrawComboBox.SetComboStyle(Value: TOwnerDrawComboStyle);
  269. begin
  270.   if FStyle <> Value then begin
  271.     FStyle := Value;
  272.     inherited Style := Value;
  273.   end;
  274. end;
  275. function TOwnerDrawComboBox.MinItemHeight: Integer;
  276. begin
  277.   Result := GetItemHeight(Font);
  278.   if Result < 9 then Result := 9;
  279. end;
  280. procedure TOwnerDrawComboBox.ResetItemHeight;
  281. var
  282.   H: Integer;
  283. begin
  284.   H := MinItemHeight;
  285.   FItemHeightChanging := True;
  286.   try
  287.     inherited ItemHeight := H;
  288.   finally
  289.     FItemHeightChanging := False;
  290.   end;
  291.   if HandleAllocated then SendMessage(Handle, CB_SETITEMHEIGHT, 0, H);
  292. end;
  293. procedure TOwnerDrawComboBox.CreateParams(var Params: TCreateParams);
  294. const
  295.   ComboBoxStyles: array[TOwnerDrawComboStyle] of DWORD =
  296.     (CBS_DROPDOWN, CBS_SIMPLE, CBS_DROPDOWNLIST);
  297. begin
  298.   inherited CreateParams(Params);
  299.   with Params do
  300.     Style := (Style and not CBS_DROPDOWNLIST) or CBS_OWNERDRAWFIXED or
  301.       ComboBoxStyles[FStyle];
  302. end;
  303. procedure TOwnerDrawComboBox.CreateWnd;
  304. begin
  305.   inherited CreateWnd;
  306.   ResetItemHeight;
  307. end;
  308. procedure TOwnerDrawComboBox.CMFontChanged(var Message: TMessage);
  309. begin
  310.   inherited;
  311.   ResetItemHeight;
  312.   RecreateWnd;
  313. end;
  314. {$IFDEF WIN32}
  315. procedure TOwnerDrawComboBox.CMRecreateWnd(var Message: TMessage);
  316. begin
  317.   if not FItemHeightChanging then
  318.     inherited;
  319. end;
  320. {$ENDIF}
  321. { TColorComboBox }
  322. const
  323.   ColorsInList = 16;
  324.   ColorValues: array [0..ColorsInList - 1] of TColor = (
  325.     clBlack, clMaroon, clGreen, clOlive, clNavy, clPurple, clTeal, clGray,
  326.     clSilver, clRed, clLime, clYellow, clBlue, clFuchsia, clAqua, clWhite);
  327. constructor TColorComboBox.Create(AOwner: TComponent);
  328. begin
  329.   inherited Create(AOwner);
  330.   FColorValue := clBlack;  { make default color selected }
  331.   FColorNames := TStringList.Create;
  332.   TStringList(FColorNames).OnChange := ColorNamesChanged;
  333.   FDisplayNames := True;
  334. end;
  335. destructor TColorComboBox.Destroy;
  336. begin
  337.   TStringList(FColorNames).OnChange := nil;
  338.   FColorNames.Free;
  339.   FColorNames := nil;
  340.   inherited Destroy;
  341. end;
  342. procedure TColorComboBox.CreateWnd;
  343. begin
  344.   inherited CreateWnd;
  345.   PopulateList;
  346.   SetColorValue(FColorValue);
  347. end;
  348. procedure TColorComboBox.PopulateList;
  349. var
  350.   I: Integer;
  351.   ColorName: string;
  352. begin
  353.   Items.BeginUpdate;
  354.   try
  355.     Clear;
  356.     for I := 0 to Pred(ColorsInList) do begin
  357.       if (I <= Pred(FColorNames.Count)) and (FColorNames[I] <> '') then
  358.         ColorName := FColorNames[I]
  359.       else
  360.         { delete two first characters which prefix "cl" educated }
  361.         ColorName := Copy(ColorToString(ColorValues[I]), 3, MaxInt);
  362.       Items.AddObject(ColorName, TObject(ColorValues[I]));
  363.     end;
  364.   finally
  365.     Items.EndUpdate;
  366.   end;
  367. end;
  368. procedure TColorComboBox.ColorNamesChanged(Sender: TObject);
  369. begin
  370.   if HandleAllocated then begin
  371.     FColorValue := ColorValue;
  372.     RecreateWnd;
  373.   end;
  374. end;
  375. procedure TColorComboBox.SetColorNames(Value: TStrings);
  376. begin
  377.   FColorNames.Assign(Value);
  378. end;
  379. procedure TColorComboBox.SetDisplayNames(Value: Boolean);
  380. begin
  381.   if DisplayNames <> Value then begin
  382.     FDisplayNames := Value;
  383.     Invalidate;
  384.   end;
  385. end;
  386. function TColorComboBox.GetColorValue: TColor;
  387. var
  388.   I: Integer;
  389. begin
  390.   Result := FColorValue;
  391.   if (Style <> csDropDownList) and (ItemIndex < 0) then begin
  392.     I := Items.IndexOf(inherited Text);
  393.     if I >= 0 then Result := TColor(Items.Objects[I])
  394.     else begin
  395.       Val(inherited Text, Result, I);
  396.       if I <> 0 then Result := FColorValue;
  397.     end;
  398.   end;
  399. end;
  400. procedure TColorComboBox.SetColorValue(NewValue: TColor);
  401. var
  402.   Item: Integer;
  403.   CurrentColor: TColor;
  404.   S: string;
  405. begin
  406.   if (ItemIndex < 0) or (NewValue <> FColorValue) then begin
  407.     FColorValue := NewValue;
  408.     { change selected item }
  409.     for Item := 0 to Pred(Items.Count) do begin
  410.       CurrentColor := TColor(Items.Objects[Item]);
  411.       if CurrentColor = NewValue then begin
  412.         if ItemIndex <> Item then ItemIndex := Item;
  413.         DoChange;
  414.         Exit;
  415.       end;
  416.     end;
  417.     if Style = csDropDownList then
  418.       ItemIndex := -1
  419.     else begin
  420.       S := ColorToString(NewValue);
  421.       if Pos('cl', S) = 1 then System.Delete(S, 1, 2);
  422.       inherited Text := S;
  423.     end;
  424.     DoChange;
  425.   end;
  426. end;
  427. procedure TColorComboBox.DrawItem(Index: Integer; Rect: TRect;
  428.   State: TOwnerDrawState);
  429. const
  430.   ColorWidth = 22;
  431. var
  432.   ARect: TRect;
  433.   Text: array[0..255] of Char;
  434.   Safer: TColor;
  435. begin
  436.   ARect := Rect;
  437.   Inc(ARect.Top, 2);
  438.   Inc(ARect.Left, 2);
  439.   Dec(ARect.Bottom, 2);
  440.   if FDisplayNames then ARect.Right := ARect.Left + ColorWidth
  441.   else Dec(ARect.Right, 3);
  442.   with Canvas do begin
  443.     FillRect(Rect);
  444.     Safer := Brush.Color;
  445.     Pen.Color := clWindowText;
  446.     Rectangle(ARect.Left, ARect.Top, ARect.Right, ARect.Bottom);
  447.     Brush.Color := TColor(Items.Objects[Index]);
  448.     try
  449.       InflateRect(ARect, -1, -1);
  450.       FillRect(ARect);
  451.     finally
  452.       Brush.Color := Safer;
  453.     end;
  454.     if FDisplayNames then begin
  455.       StrPCopy(Text, Items[Index]);
  456.       Rect.Left := Rect.Left + ColorWidth + 6;
  457.       DrawText(Canvas.Handle, Text, StrLen(Text), Rect,
  458. {$IFDEF RX_D4}
  459.         DrawTextBiDiModeFlags(DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX));
  460. {$ELSE}
  461.         DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX);
  462. {$ENDIF}
  463.     end;
  464.   end;
  465. end;
  466. procedure TColorComboBox.Change;
  467. var
  468.   AColor: TColor;
  469. begin
  470.   inherited Change;
  471.   AColor := GetColorValue;
  472.   if FColorValue <> AColor then begin
  473.     FColorValue := AColor;
  474.     DoChange;
  475.   end;
  476. end;
  477. procedure TColorComboBox.Click;
  478. begin
  479.   if ItemIndex >= 0 then ColorValue := TColor(Items.Objects[ItemIndex]);
  480.   inherited Click;
  481. end;
  482. procedure TColorComboBox.DoChange;
  483. begin
  484.   if not (csReading in ComponentState) then
  485.     if Assigned(FOnChange) then FOnChange(Self);
  486. end;
  487. { TFontComboBox }
  488. const
  489.   WRITABLE_FONTTYPE = 256;
  490. function IsValidFont(Box: TFontComboBox; LogFont: TLogFont;
  491.   FontType: Integer): Boolean;
  492. begin
  493.   Result := True;
  494.   if (foAnsiOnly in Box.Options) then
  495.     Result := Result and (LogFont.lfCharSet = ANSI_CHARSET);
  496.   if (foTrueTypeOnly in Box.Options) then
  497.     Result := Result and (FontType and TRUETYPE_FONTTYPE = TRUETYPE_FONTTYPE);
  498.   if (foFixedPitchOnly in Box.Options) then
  499.     Result := Result and (LogFont.lfPitchAndFamily and FIXED_PITCH = FIXED_PITCH);
  500.   if (foOEMFontsOnly in Box.Options) then
  501.     Result := Result and (LogFont.lfCharSet = OEM_CHARSET);
  502.   if (foNoOEMFonts in Box.Options) then
  503.     Result := Result and (LogFont.lfCharSet <> OEM_CHARSET);
  504.   if (foNoSymbolFonts in Box.Options) then
  505.     Result := Result and (LogFont.lfCharSet <> SYMBOL_CHARSET);
  506.   if (foScalableOnly in Box.Options) then
  507.     Result := Result and (FontType and RASTER_FONTTYPE = 0);
  508. end;
  509. {$IFDEF WIN32}
  510. function EnumFontsProc(var EnumLogFont: TEnumLogFont;
  511.   var TextMetric: TNewTextMetric; FontType: Integer; Data: LPARAM): Integer;
  512.   export; stdcall;
  513. var
  514.   FaceName: string;
  515. begin
  516.   FaceName := StrPas(EnumLogFont.elfLogFont.lfFaceName);
  517.   with TFontComboBox(Data) do
  518.     if (Items.IndexOf(FaceName) < 0) and
  519.       IsValidFont(TFontComboBox(Data), EnumLogFont.elfLogFont, FontType) then
  520.     begin
  521.       if EnumLogFont.elfLogFont.lfCharSet <> SYMBOL_CHARSET then
  522.         FontType := FontType or WRITABLE_FONTTYPE;
  523.       Items.AddObject(FaceName, TObject(FontType));
  524.     end;
  525.   Result := 1;
  526. end;
  527. {$ELSE}
  528. function EnumFontsProc(var LogFont: TLogFont; var TextMetric: TTextMetric;
  529.   FontType: Integer; Data: Pointer): Integer; export;
  530. begin
  531.   with TFontComboBox(Data) do
  532.     if (Items.IndexOf(StrPas(LogFont.lfFaceName)) < 0) and
  533.       IsValidFont(TFontComboBox(Data), LogFont, FontType) then
  534.     begin
  535.       if LogFont.lfCharSet = SYMBOL_CHARSET then
  536.         FontType := FontType or WRITABLE_FONTTYPE;
  537.       Items.AddObject(StrPas(LogFont.lfFaceName), TObject(FontType));
  538.     end;
  539.   Result := 1;
  540. end;
  541. {$ENDIF WIN32}
  542. constructor TFontComboBox.Create(AOwner: TComponent);
  543. begin
  544.   inherited Create(AOwner);
  545.   FTrueTypeBMP := CreateBitmap('TRUETYPE_FNT');
  546.   FDeviceBMP := CreateBitmap('DEVICE_FNT');
  547.   FDevice := fdScreen;
  548.   Sorted := True;
  549.   inherited ItemHeight := MinItemHeight;
  550. end;
  551. destructor TFontComboBox.Destroy;
  552. begin
  553.   FTrueTypeBMP.Free;
  554.   FDeviceBMP.Free;
  555.   inherited Destroy;
  556. end;
  557. procedure TFontComboBox.CreateWnd;
  558. var
  559.   OldFont: TFontName;
  560. begin
  561.   OldFont := FontName;
  562.   inherited CreateWnd;
  563.   FUpdate := True;
  564.   try
  565.     PopulateList;
  566.     inherited Text := '';
  567.     SetFontName(OldFont);
  568.   finally
  569.     FUpdate := False;
  570.   end;
  571.   if AnsiCompareText(FontName, OldFont) <> 0 then DoChange;
  572. end;
  573. procedure TFontComboBox.PopulateList;
  574. var
  575.   DC: HDC;
  576. {$IFNDEF WIN32}
  577.   Proc: TFarProc;
  578. {$ENDIF}
  579. begin
  580.   if not HandleAllocated then Exit;
  581.   Items.BeginUpdate;
  582.   try
  583.     Clear;
  584.     DC := GetDC(0);
  585.     try
  586. {$IFDEF WIN32}
  587.       if (FDevice = fdScreen) or (FDevice = fdBoth) then
  588.         EnumFontFamilies(DC, nil, @EnumFontsProc, Longint(Self));
  589.       if (FDevice = fdPrinter) or (FDevice = fdBoth) then
  590.       try
  591.         EnumFontFamilies(Printer.Handle, nil, @EnumFontsProc, Longint(Self));
  592.       except
  593.         { skip any errors }
  594.       end;
  595. {$ELSE}
  596.       Proc := MakeProcInstance(@EnumFontsProc, HInstance);
  597.       try
  598.         if (FDevice = fdScreen) or (FDevice = fdBoth) then
  599.           EnumFonts(DC, nil, Proc, PChar(Self));
  600.         if (FDevice = fdPrinter) or (FDevice = fdBoth) then
  601.           try
  602.             EnumFonts(Printer.Handle, nil, Proc, PChar(Self));
  603.           except
  604.             { skip any errors }
  605.           end;
  606.       finally
  607.         FreeProcInstance(Proc);
  608.       end;
  609. {$ENDIF}
  610.     finally
  611.       ReleaseDC(0, DC);
  612.     end;
  613.   finally
  614.     Items.EndUpdate;
  615.   end;
  616. end;
  617. procedure TFontComboBox.SetFontName(const NewFontName: TFontName);
  618. var
  619.   Item: Integer;
  620. begin
  621.   if FontName <> NewFontName then begin
  622.     if not (csLoading in ComponentState) then begin
  623.       HandleNeeded;
  624.       { change selected item }
  625.       for Item := 0 to Items.Count - 1 do
  626.         if AnsiCompareText(Items[Item], NewFontName) = 0 then begin
  627.           ItemIndex := Item;
  628.           DoChange;
  629.           Exit;
  630.         end;
  631.       if Style = csDropDownList then ItemIndex := -1
  632.       else inherited Text := NewFontName;
  633.     end
  634.     else inherited Text := NewFontName;
  635.     DoChange;
  636.   end;
  637. end;
  638. function TFontComboBox.GetFontName: TFontName;
  639. begin
  640.   Result := inherited Text;
  641. end;
  642. function TFontComboBox.GetTrueTypeOnly: Boolean;
  643. begin
  644.   Result := foTrueTypeOnly in FOptions;
  645. end;
  646. procedure TFontComboBox.SetOptions(Value: TFontListOptions);
  647. begin
  648.   if Value <> Options then begin
  649.     FOptions := Value;
  650.     Reset;
  651.   end;
  652. end;
  653. procedure TFontComboBox.SetTrueTypeOnly(Value: Boolean);
  654. begin
  655.   if Value <> TrueTypeOnly then begin
  656.     if Value then FOptions := FOptions + [foTrueTypeOnly]
  657.     else FOptions := FOptions - [foTrueTypeOnly];
  658.     Reset;
  659.   end;
  660. end;
  661. procedure TFontComboBox.SetDevice(Value: TFontDevice);
  662. begin
  663.   if Value <> FDevice then begin
  664.     FDevice := Value;
  665.     Reset;
  666.   end;
  667. end;
  668. procedure TFontComboBox.SetUseFonts(Value: Boolean);
  669. begin
  670.   if Value <> FUseFonts then begin
  671.     FUseFonts := Value;
  672.     Invalidate;
  673.   end;
  674. end;
  675. procedure TFontComboBox.DrawItem(Index: Integer; Rect: TRect;
  676.   State: TOwnerDrawState);
  677. var
  678.   Bitmap: TBitmap;
  679.   BmpWidth: Integer;
  680.   Text: array[0..255] of Char;
  681. begin
  682.   with Canvas do begin
  683.     FillRect(Rect);
  684.     BmpWidth  := 20;
  685.     if (Integer(Items.Objects[Index]) and TRUETYPE_FONTTYPE) <> 0 then
  686.       Bitmap := FTrueTypeBMP
  687.     else if (Integer(Items.Objects[Index]) and DEVICE_FONTTYPE) <> 0 then
  688.       Bitmap := FDeviceBMP
  689.     else Bitmap := nil;
  690.     if Bitmap <> nil then begin
  691.       BmpWidth := Bitmap.Width;
  692.       BrushCopy(Bounds(Rect.Left + 2, (Rect.Top + Rect.Bottom - Bitmap.Height)
  693.         div 2, Bitmap.Width, Bitmap.Height), Bitmap, Bounds(0, 0, Bitmap.Width,
  694.         Bitmap.Height), Bitmap.TransparentColor);
  695.     end;
  696.     { uses DrawText instead of TextOut in order to get clipping against
  697.       the combo box button }
  698.     {TextOut(Rect.Left + bmpWidth + 6, Rect.Top, Items[Index])}
  699.     StrPCopy(Text, Items[Index]);
  700.     Rect.Left := Rect.Left + BmpWidth + 6;
  701.     if FUseFonts and (Integer(Items.Objects[Index]) and WRITABLE_FONTTYPE <> 0) then
  702.       Font.Name := Items[Index];
  703.     DrawText(Handle, Text, StrLen(Text), Rect,
  704. {$IFDEF RX_D4}
  705.       DrawTextBiDiModeFlags(DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX));
  706. {$ELSE}
  707.       DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX);
  708. {$ENDIF}
  709.   end;
  710. end;
  711. procedure TFontComboBox.WMFontChange(var Message: TMessage);
  712. begin
  713.   inherited;
  714.   Reset;
  715. end;
  716. function TFontComboBox.MinItemHeight: Integer;
  717. begin
  718.   Result := inherited MinItemHeight;
  719.   if Result < FTrueTypeBMP.Height - 1 then
  720.     Result := FTrueTypeBMP.Height - 1;
  721. end;
  722. procedure TFontComboBox.Change;
  723. var
  724.   I: Integer;
  725. begin
  726.   inherited Change;
  727.   if Style <> csDropDownList then begin
  728.     I := Items.IndexOf(inherited Text);
  729.     if (I >= 0) and (I <> ItemIndex) then begin
  730.       ItemIndex := I;
  731.       DoChange;
  732.     end;
  733.   end;
  734. end;
  735. procedure TFontComboBox.Click;
  736. begin
  737.   inherited Click;
  738.   DoChange;
  739. end;
  740. procedure TFontComboBox.DoChange;
  741. begin
  742.   if not (csReading in ComponentState) then
  743.     if not FUpdate and Assigned(FOnChange) then FOnChange(Self);
  744. end;
  745. procedure TFontComboBox.Reset;
  746. var
  747.   SaveName: TFontName;
  748. begin
  749.   if HandleAllocated then begin
  750.     FUpdate := True;
  751.     try
  752.       SaveName := FontName;
  753.       PopulateList;
  754.       FontName := SaveName;
  755.     finally
  756.       FUpdate := False;
  757.       if FontName <> SaveName then DoChange;
  758.     end;
  759.   end;
  760. end;
  761. end.