git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.SpTBXLib@4 aa3591e4-a9f2-482a-ba07-9d38a056ee4e
1077 lines
32 KiB
ObjectPascal
1077 lines
32 KiB
ObjectPascal
unit SpTBXExtEditors;
|
|
|
|
{==============================================================================
|
|
Version 2.4.4
|
|
|
|
The contents of this file are subject to the SpTBXLib License; you may
|
|
not use or distribute this file except in compliance with the
|
|
SpTBXLib License.
|
|
A copy of the SpTBXLib License may be found in SpTBXLib-LICENSE.txt or at:
|
|
http://www.silverpointdevelopment.com/sptbxlib/SpTBXLib-LICENSE.htm
|
|
|
|
Alternatively, the contents of this file may be used under the terms of the
|
|
Mozilla Public License Version 1.1 (the "MPL v1.1"), in which case the provisions
|
|
of the MPL v1.1 are applicable instead of those in the SpTBXLib License.
|
|
A copy of the MPL v1.1 may be found in MPL-LICENSE.txt or at:
|
|
http://www.mozilla.org/MPL/
|
|
|
|
If you wish to allow use of your version of this file only under the terms of
|
|
the MPL v1.1 and not to allow others to use your version of this file under the
|
|
SpTBXLib License, indicate your decision by deleting the provisions
|
|
above and replace them with the notice and other provisions required by the
|
|
MPL v1.1. If you do not delete the provisions above, a recipient may use your
|
|
version of this file under either the SpTBXLib License or the MPL v1.1.
|
|
|
|
Software distributed under the License is distributed on an "AS IS" basis,
|
|
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
|
|
the specific language governing rights and limitations under the License.
|
|
|
|
The initial developer of this code is Robert Lee.
|
|
|
|
Requirements:
|
|
For Delphi/C++Builder 2009 or newer:
|
|
- Jordan Russell's Toolbar 2000
|
|
http://www.jrsoftware.org
|
|
For Delphi/C++Builder 7-2007:
|
|
- Jordan Russell's Toolbar 2000
|
|
http://www.jrsoftware.org
|
|
- Troy Wolbrink's TNT Unicode Controls
|
|
http://www.tntware.com/delphicontrols/unicode/
|
|
|
|
Development notes:
|
|
- All the Windows and Delphi bugs fixes are marked with '[Bugfix]'.
|
|
- All the theme changes and adjustments are marked with '[Theme-Change]'.
|
|
|
|
To Do:
|
|
- Rotated caption painting.
|
|
|
|
Known Issues:
|
|
-
|
|
|
|
History:
|
|
2 December 2009 - version 2.4.4
|
|
- No changes.
|
|
|
|
13 September 2009 - version 2.4.3
|
|
- Fixed incorrect TSpTBXColorEdit behavior, when the focus
|
|
was changed the text wasn't validated, thanks to Stephan
|
|
for reporting this.
|
|
|
|
8 May 2009 - version 2.4.2
|
|
- No changes.
|
|
|
|
15 March 2009 - version 2.4.1
|
|
- No changes.
|
|
|
|
17 January 2009 - version 2.4
|
|
- Initial release.
|
|
|
|
==============================================================================}
|
|
|
|
interface
|
|
|
|
{$BOOLEVAL OFF} // Unit depends on short-circuit boolean evaluation
|
|
|
|
uses
|
|
Windows, Messages, Classes, SysUtils, Controls, Graphics, ImgList, Forms,
|
|
Menus, StdCtrls, ExtCtrls,
|
|
SpTBXSkins, SpTBXItem, SpTBXEditors;
|
|
|
|
type
|
|
TSpTBXColorListBoxStyle = (
|
|
clbsStandardColors, // First 16 RGBI colors + 4 additional extended colors
|
|
clbsSystemColors, // System colors
|
|
clbsIncludeNone, // Include clNone color
|
|
clbsIncludeDefault, // Include clDefault color
|
|
clbsCustomColor, // First color is customizable
|
|
clbsPrettyNames, // Draw text with pretty names
|
|
clbsNoneAsTransparent // Draw clNone as transparent color
|
|
);
|
|
TSpTBXColorListBoxStyles = set of TSpTBXColorListBoxStyle;
|
|
|
|
{ TSpTBXColorEditButton }
|
|
|
|
TSpTBXColorEditButton = class(TSpTBXEditButton)
|
|
private
|
|
FSelectedColor: TColor;
|
|
procedure SetSelectedColor(const Value: TColor);
|
|
protected
|
|
function DoDrawItem(ACanvas: TCanvas; ARect: TRect; const PaintStage: TSpTBXPaintStage): Boolean; override;
|
|
function GetInternalDropDownMenu: TPopupMenu; override;
|
|
public
|
|
property SelectedColor: TColor read FSelectedColor write SetSelectedColor;
|
|
end;
|
|
|
|
{ TSpTBXColorEdit }
|
|
|
|
TSpTBXColorEdit = class(TSpTBXEdit)
|
|
private
|
|
FColorButton: TSpTBXColorEditButton;
|
|
FSelectedFormat: TSpTBXColorTextType;
|
|
FOnSelectedColorChanged: TNotifyEvent;
|
|
function GetSelectedColor: TColor;
|
|
procedure SetSelectedColor(const Value: TColor);
|
|
procedure SetSelectedFormat(const Value: TSpTBXColorTextType);
|
|
procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS;
|
|
protected
|
|
procedure KeyPress(var Key: Char); override;
|
|
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
|
|
procedure DoSelectedColorChanged; virtual;
|
|
procedure UpdateTextFromValue;
|
|
procedure UpdateValueFromText(RevertWhenInvalid: Boolean = True);
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
property ColorButton: TSpTBXColorEditButton read FColorButton;
|
|
published
|
|
property Text stored False;
|
|
property SelectedColor: TColor read GetSelectedColor write SetSelectedColor;
|
|
property SelectedFormat: TSpTBXColorTextType read FSelectedFormat write SetSelectedFormat default cttIdentAndHTML;
|
|
property OnSelectedColorChanged: TNotifyEvent read FOnSelectedColorChanged write FOnSelectedColorChanged;
|
|
end;
|
|
|
|
{ TSpTBXFontComboBox }
|
|
|
|
TSpTBXFontComboBoxPreview = class(TCustomControl)
|
|
private
|
|
FPreviewPanel: TPanel;
|
|
protected
|
|
procedure CreateParams(var Params: TCreateParams); override;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
property PreviewPanel: TPanel read FPreviewPanel;
|
|
end;
|
|
|
|
TSpTBXFontComboBox = class(TSpTBXComboBox)
|
|
private
|
|
FFontPreview: Boolean;
|
|
FFontNamePreview: Boolean;
|
|
FMaxMRUItems: Integer;
|
|
FMRUCount: Integer;
|
|
FPreviewWindow: TSpTBXFontComboBoxPreview;
|
|
FSelectedFont: TFontName;
|
|
FOnFontPreview: TSpTBXEditGetTextEvent;
|
|
procedure UpdateSelectedFont(AddMRU: Boolean);
|
|
procedure SetFontNamePreview(const Value: Boolean);
|
|
procedure SetSelectedFont(const Value: TFontName);
|
|
procedure SetMaxMRUItems(Value: Integer);
|
|
procedure SetFontPreview(const Value: Boolean);
|
|
protected
|
|
procedure Click; override;
|
|
procedure CloseUp; override;
|
|
procedure DoCalcMaxDropDownWidth; override;
|
|
procedure DoDrawItem(ACanvas: TCanvas; var ARect: TRect; Index: Integer; const State: TOwnerDrawState;
|
|
const PaintStage: TSpTBXPaintStage; var PaintDefault: Boolean); override;
|
|
procedure DropDown; override;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
procedure MRUAdd(AFontName: TFontName);
|
|
function MRUDelete(AFontName: TFontName): Boolean;
|
|
property MRUCount: Integer read FMRUCount;
|
|
published
|
|
property Items stored False;
|
|
property AutoDropDownWidth default True;
|
|
property AutoItemHeight default False;
|
|
property FontPreview: Boolean read FFontPreview write SetFontPreview default True;
|
|
property FontNamePreview: Boolean read FFontNamePreview write SetFontNamePreview default True;
|
|
property MaxMRUItems: Integer read FMaxMRUItems write SetMaxMRUItems default 5;
|
|
property SelectedFont: TFontName read FSelectedFont write SetSelectedFont;
|
|
property OnFontPreview: TSpTBXEditGetTextEvent read FOnFontPreview write FOnFontPreview;
|
|
end;
|
|
|
|
{ TSpTBXColorListBox }
|
|
|
|
TSpTBXColorListBox = class(TSpTBXListBox)
|
|
private
|
|
FItems: Boolean;
|
|
FNeedToPopulate: Boolean;
|
|
FSelectedColor: TColor;
|
|
FStyle: TSpTBXColorListBoxStyles;
|
|
procedure ColorCallBack(const AName: string);
|
|
function GetColorName(Index: Integer): string;
|
|
function GetColor(Index: Integer): TColor;
|
|
function GetSelected: TColor;
|
|
procedure SetSelected(const Value: TColor);
|
|
procedure SetStyle(const Value: TSpTBXColorListBoxStyles);
|
|
protected
|
|
procedure CreateWnd; override;
|
|
procedure Loaded; override;
|
|
procedure DblClick; override;
|
|
procedure KeyPress(var Key: Char); override;
|
|
procedure DoDrawItem(ACanvas: TCanvas; var ARect: TRect; Index: Integer; const State: TOwnerDrawState;
|
|
const PaintStage: TSpTBXPaintStage; var PaintDefault: Boolean); override;
|
|
function PickCustomColor: Boolean;
|
|
procedure PopulateList;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
procedure AddColor(AColor: TColor; AColorName: string);
|
|
function ColorCount: Integer;
|
|
property Colors[Index: Integer]: TColor read GetColor;
|
|
property ColorNames[Index: Integer]: string read GetColorName;
|
|
published
|
|
property Items: Boolean read FItems; // Hides inherited Items property
|
|
property Selected: TColor read GetSelected write SetSelected default clBlack;
|
|
property Style: TSpTBXColorListBoxStyles read FStyle write SetStyle default [clbsStandardColors, clbsSystemColors, clbsNoneAsTransparent]; // Hides inherited Style property
|
|
end;
|
|
|
|
{ Helpers }
|
|
procedure SpFillFontNames(ADest: TStrings);
|
|
|
|
{ Painting helpers }
|
|
procedure SpDrawCheckeredBackground(ACanvas: TCanvas; ARect: TRect);
|
|
procedure SpDrawColorDropDownButton(ACanvas: TCanvas; ARect: TRect; Pushed: Boolean; AColor: TColor; CheckeredBkgndWhenTransparent: Boolean = True);
|
|
|
|
var
|
|
FontGlyphImgList: TImageList = nil;
|
|
|
|
implementation
|
|
|
|
uses
|
|
Dialogs, TB2Common, SpTBXFormPopupMenu, SpTBXColorPickerForm;
|
|
|
|
var
|
|
DefaultColorPickerDropDownMenu: TSpTBXColorEditPopupMenu = nil;
|
|
|
|
//WMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWM
|
|
{ Helpers }
|
|
|
|
procedure SpFillFontNames(ADest: TStrings);
|
|
// This will only work on Windows 2000 and above, more info on:
|
|
// http://www.delphipraxis.net/post712587.html&sid=945c12fa9fb826d76e51c80b42109a21#712587
|
|
|
|
function EnumFontsProcWin9x(EnumLogFontEx: PEnumLogFontEx; NewTextMetric: PNewTextMetric;
|
|
FontType: DWORD; LParam: LPARAM): Integer; stdcall;
|
|
var
|
|
S: string;
|
|
GlyphIndex: Integer;
|
|
L: TStrings;
|
|
const
|
|
NTM_PS_OPENTYPE = $00020000;
|
|
NTM_TT_OPENTYPE = $00040000;
|
|
begin
|
|
L := TStrings(LParam);
|
|
if FontType = TRUETYPE_FONTTYPE then
|
|
GlyphIndex := 1
|
|
else
|
|
GlyphIndex := 0;
|
|
|
|
S := EnumLogFontEx.elfLogFont.lfFaceName;
|
|
|
|
if (S[1] <> '@') then
|
|
if (L.Count = 0) or not SameText(S, L[L.Count - 1]) then
|
|
L.AddObject(S, Pointer(GlyphIndex));
|
|
|
|
Result := 1;
|
|
end;
|
|
|
|
function EnumFontsProc(EnumLogFontExDV: PEnumLogFontExDV; EnumTextMetric: PEnumTextMetric;
|
|
FontType: DWORD; LParam: LPARAM): Integer; stdcall;
|
|
var
|
|
S: string;
|
|
GlyphIndex: Integer;
|
|
L: TStrings;
|
|
const
|
|
NTM_PS_OPENTYPE = $00020000;
|
|
NTM_TT_OPENTYPE = $00040000;
|
|
begin
|
|
L := TStrings(LParam);
|
|
GlyphIndex := 0;
|
|
if ((EnumTextMetric.etmNewTextMetricEx.ntmTm.ntmFlags and NTM_TT_OPENTYPE) = NTM_TT_OPENTYPE) or
|
|
((EnumTextMetric.etmNewTextMetricEx.ntmTm.ntmFlags and NTM_PS_OPENTYPE) = NTM_PS_OPENTYPE) then
|
|
GlyphIndex := 2
|
|
else
|
|
if FontType = TRUETYPE_FONTTYPE then
|
|
GlyphIndex := 1;
|
|
|
|
S := EnumLogFontExDV.elfEnumLogfontEx.elfLogFont.lfFaceName;
|
|
|
|
if (S[1] <> '@') then
|
|
if (L.Count = 0) or not SameText(S, L[L.Count - 1]) then
|
|
L.AddObject(S, Pointer(GlyphIndex));
|
|
|
|
Result := 1;
|
|
end;
|
|
|
|
var
|
|
DC: HDC;
|
|
LFont: TLogFont;
|
|
L: TStringList;
|
|
begin
|
|
L := TStringList.Create;
|
|
DC := GetDC(0);
|
|
try
|
|
FillChar(LFont, SizeOf(LFont), 0);
|
|
LFont.lfCharset := DEFAULT_CHARSET;
|
|
if Win32Platform = VER_PLATFORM_WIN32_WINDOWS then
|
|
EnumFontFamiliesEx(DC, LFont, @EnumFontsProcWin9x, LongInt(L), 0)
|
|
else
|
|
EnumFontFamiliesEx(DC, LFont, @EnumFontsProc, LongInt(L), 0);
|
|
L.Sort;
|
|
ADest.Assign(L);
|
|
finally
|
|
ReleaseDC(0, DC);
|
|
L.Free;
|
|
end;
|
|
end;
|
|
|
|
//WMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWM
|
|
{ Painting helpers }
|
|
|
|
procedure SpDrawCheckeredBackground(ACanvas: TCanvas; ARect: TRect);
|
|
// Draws a 2x2 white and silver checkered background
|
|
var
|
|
R: TRect;
|
|
I, J, HCount, WCount: Integer;
|
|
const
|
|
Size = 2;
|
|
begin
|
|
WCount := (ARect.Right - ARect.Left) div Size;
|
|
HCount := (ARect.Bottom - ARect.Top) div Size;
|
|
for J := 0 to HCount do
|
|
for I := 0 to WCount do begin
|
|
R := Bounds(ARect.Left + (I * Size), ARect.Top + (J * Size), Size, Size);
|
|
if R.Right > ARect.Right then
|
|
R.Right := ARect.Right;
|
|
if R.Bottom > ARect.Bottom then
|
|
R.Bottom := ARect.Bottom;
|
|
if (I + J) mod 2 = 0 then
|
|
ACanvas.Brush.Color := clWhite
|
|
else
|
|
ACanvas.Brush.Color := clSilver;
|
|
ACanvas.FillRect(R);
|
|
end;
|
|
end;
|
|
|
|
procedure SpDrawColorDropDownButton(ACanvas: TCanvas; ARect: TRect;
|
|
Pushed: Boolean; AColor: TColor; CheckeredBkgndWhenTransparent: Boolean);
|
|
// Draws a button used for color editboxes
|
|
var
|
|
R: TRect;
|
|
begin
|
|
R := ARect;
|
|
|
|
ACanvas.Brush.Color := clBtnFace;
|
|
ACanvas.FillRect(R);
|
|
if not Pushed then
|
|
SpDrawRectangle(ACanvas, R, 0, clBtnHighlight, clBtnShadow);
|
|
|
|
InflateRect(R, -2, -2);
|
|
if (AColor = clNone) and CheckeredBkgndWhenTransparent then begin
|
|
// Draw a checkered background when clNone is used
|
|
SpDrawCheckeredBackground(ACanvas, R);
|
|
end
|
|
else begin
|
|
ACanvas.Brush.Color := AColor;
|
|
ACanvas.FillRect(R);
|
|
end;
|
|
SpDrawRectangle(ACanvas, R, 0, clBtnShadow, clBtnHighlight);
|
|
|
|
R := ARect;
|
|
R.Left := R.Right - 9;
|
|
R.Top := R.Bottom - 7;
|
|
ACanvas.Brush.Color := clBtnFace;
|
|
ACanvas.FillRect(R);
|
|
if Pushed then
|
|
SpDrawRectangle(ACanvas, R, 0, clBtnHighlight, clBtnFace)
|
|
else
|
|
SpDrawRectangle(ACanvas, R, 0, clBtnHighlight, clBtnShadow);
|
|
SpDrawArrow(ACanvas, R.Left + (R.Right - R.Left) div 2, R.Top + (R.Bottom - R.Top) div 2 - 1, clBlack, True, False, 2);
|
|
|
|
R := ARect;
|
|
InflateRect(R, -1, -1);
|
|
SpDrawRectangle(ACanvas, R, 0, clBtnFace, clBtnFace);
|
|
end;
|
|
|
|
//WMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWM
|
|
{ TSpTBXColorEditButton }
|
|
|
|
function TSpTBXColorEditButton.DoDrawItem(ACanvas: TCanvas; ARect: TRect;
|
|
const PaintStage: TSpTBXPaintStage): Boolean;
|
|
begin
|
|
if (PaintStage = pstPrePaint) and not BitmapValid then begin
|
|
Result := True;
|
|
if Assigned(OnDraw) then OnDraw(Self, ACanvas, ARect, PaintStage, Result);
|
|
if Result then
|
|
SpDrawColorDropDownButton(ACanvas, ARect, Pushed, FSelectedColor);
|
|
end
|
|
else
|
|
Result := inherited DoDrawItem(ACanvas, ARect, PaintStage);
|
|
end;
|
|
|
|
function TSpTBXColorEditButton.GetInternalDropDownMenu: TPopupMenu;
|
|
begin
|
|
if Assigned(DropDownMenu) then
|
|
Result := DropDownMenu
|
|
else
|
|
Result := DefaultColorPickerDropDownMenu;
|
|
end;
|
|
|
|
procedure TSpTBXColorEditButton.SetSelectedColor(const Value: TColor);
|
|
begin
|
|
if FSelectedColor <> Value then begin
|
|
FSelectedColor := Value;
|
|
Invalidate;
|
|
if Owner is TSpTBXColorEdit then begin
|
|
TSpTBXColorEdit(Owner).UpdateTextFromValue;
|
|
TSpTBXColorEdit(Owner).DoSelectedColorChanged;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
//WMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWM
|
|
{ TSpTBXColorEdit }
|
|
|
|
constructor TSpTBXColorEdit.Create(AOwner: TComponent);
|
|
begin
|
|
inherited;
|
|
|
|
FSelectedFormat := cttIdentAndHTML;
|
|
|
|
FColorButton := TSpTBXColorEditButton.Create(Self);
|
|
FColorButton.Parent := Self;
|
|
FColorButton.FreeNotification(Self);
|
|
FColorButton.Align := alRight;
|
|
FColorButton.Width := 19;
|
|
UpdateEditRect;
|
|
|
|
Text := 'clBlack';
|
|
end;
|
|
|
|
destructor TSpTBXColorEdit.Destroy;
|
|
begin
|
|
FreeAndNil(FColorButton);
|
|
inherited;
|
|
end;
|
|
|
|
procedure TSpTBXColorEdit.DoSelectedColorChanged;
|
|
begin
|
|
if Assigned(FOnSelectedColorChanged) then FOnSelectedColorChanged(Self);
|
|
end;
|
|
|
|
procedure TSpTBXColorEdit.KeyPress(var Key: Char);
|
|
begin
|
|
inherited;
|
|
if Key = #13 then begin
|
|
Key := #0;
|
|
UpdateValueFromText;
|
|
if FColorButton.IsDroppedDown and Assigned(ActiveFormPopupMenu) then
|
|
ActiveFormPopupMenu.ClosePopup(False);
|
|
end;
|
|
end;
|
|
|
|
procedure TSpTBXColorEdit.Notification(AComponent: TComponent;
|
|
Operation: TOperation);
|
|
begin
|
|
inherited;
|
|
if (AComponent = FColorButton) and (Operation = opRemove) then
|
|
FColorButton := nil;
|
|
end;
|
|
|
|
function TSpTBXColorEdit.GetSelectedColor: TColor;
|
|
begin
|
|
Result := FColorButton.SelectedColor;
|
|
end;
|
|
|
|
procedure TSpTBXColorEdit.SetSelectedColor(const Value: TColor);
|
|
begin
|
|
FColorButton.SelectedColor := Value;
|
|
end;
|
|
|
|
procedure TSpTBXColorEdit.SetSelectedFormat(const Value: TSpTBXColorTextType);
|
|
begin
|
|
if FSelectedFormat <> Value then begin
|
|
FSelectedFormat := Value;
|
|
UpdateTextFromValue;
|
|
end;
|
|
end;
|
|
|
|
procedure TSpTBXColorEdit.UpdateTextFromValue;
|
|
begin
|
|
if (SelectedColor = clNone) or (SelectedColor = clDefault) then
|
|
Text := ColorToString(SelectedColor)
|
|
else
|
|
Text := SpColorToString(SelectedColor, FSelectedFormat);
|
|
SelStart := Length(Text);
|
|
end;
|
|
|
|
procedure TSpTBXColorEdit.UpdateValueFromText(RevertWhenInvalid: Boolean = True);
|
|
var
|
|
WS: WideString;
|
|
PrevValue, NewValue, C: TColor;
|
|
begin
|
|
PrevValue := SelectedColor;
|
|
NewValue := SelectedColor;
|
|
WS := Text;
|
|
|
|
// Try to parse the text to get the value
|
|
WS := Trim(WS);
|
|
if SpStringToColor(WS, C) then
|
|
NewValue := C;
|
|
|
|
if RevertWhenInvalid or (NewValue <> PrevValue) then begin
|
|
SetSelectedColor(NewValue);
|
|
UpdateTextFromValue;
|
|
end;
|
|
end;
|
|
|
|
procedure TSpTBXColorEdit.WMKillFocus(var Message: TWMKillFocus);
|
|
begin
|
|
inherited;
|
|
UpdateValueFromText;
|
|
end;
|
|
|
|
//WMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWM
|
|
{ TSpTBXFontComboBoxPreview }
|
|
|
|
constructor TSpTBXFontComboBoxPreview.Create(AOwner: TComponent);
|
|
begin
|
|
inherited;
|
|
|
|
Visible := False;
|
|
SetBounds(0, 0, 0, 0);
|
|
Color := clWindow;
|
|
FPreviewPanel := TPanel.Create(Self);
|
|
FPreviewPanel.Parent := Self;
|
|
FPreviewPanel.Color := clWindow;
|
|
FPreviewPanel.BevelOuter := bvNone;
|
|
FPreviewPanel.Align := alClient;
|
|
end;
|
|
|
|
procedure TSpTBXFontComboBoxPreview.CreateParams(var Params: TCreateParams);
|
|
const
|
|
CS_DROPSHADOW = $00020000;
|
|
begin
|
|
inherited;
|
|
with Params do begin
|
|
Style := (Style and not (WS_CHILD or WS_GROUP or WS_TABSTOP)) or WS_POPUP;
|
|
ExStyle := ExStyle or WS_EX_TOPMOST or WS_EX_TOOLWINDOW;
|
|
WindowClass.Style := WindowClass.Style or CS_SAVEBITS;
|
|
if IsWindowsXP then
|
|
WindowClass.Style := WindowClass.Style or CS_DROPSHADOW;
|
|
end;
|
|
end;
|
|
|
|
destructor TSpTBXFontComboBoxPreview.Destroy;
|
|
begin
|
|
FreeAndNil(FPreviewPanel);
|
|
|
|
inherited;
|
|
end;
|
|
|
|
//WMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWM
|
|
{ TSpTBXFontComboBox }
|
|
|
|
constructor TSpTBXFontComboBox.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FAutoDropDownWidthRightMargin := 60;
|
|
FFontNamePreview := True;
|
|
FFontPreview := True;
|
|
FMaxMRUItems := 5;
|
|
FMRUCount := 0;
|
|
AutoItemHeight := False;
|
|
AutoDropDownWidth := True;
|
|
ItemHeight := 23;
|
|
end;
|
|
|
|
destructor TSpTBXFontComboBox.Destroy;
|
|
begin
|
|
FreeAndNil(FPreviewWindow);
|
|
inherited;
|
|
end;
|
|
|
|
procedure TSpTBXFontComboBox.Click;
|
|
begin
|
|
UpdateSelectedFont(False);
|
|
inherited;
|
|
end;
|
|
|
|
procedure TSpTBXFontComboBox.CloseUp;
|
|
begin
|
|
UpdateSelectedFont(True);
|
|
inherited;
|
|
FreeAndNil(FPreviewWindow);
|
|
end;
|
|
|
|
procedure TSpTBXFontComboBox.DropDown;
|
|
var
|
|
W: Integer;
|
|
P: TPoint;
|
|
Sz: TSize;
|
|
WS: WideString;
|
|
begin
|
|
inherited;
|
|
|
|
if FFontPreview then begin
|
|
WS := 'AaBbYyZz';
|
|
FPreviewWindow := TSpTBXFontComboBoxPreview.Create(Self);
|
|
FPreviewWindow.ParentWindow := Application.Handle;
|
|
FPreviewWindow.PreviewPanel.Font.Size := 14;
|
|
|
|
if Assigned(FOnFontPreview) then FOnFontPreview(Self, WS);
|
|
|
|
FPreviewWindow.PreviewPanel.Caption := WS;
|
|
Sz := SpGetControlTextSize(FPreviewWindow.PreviewPanel, FPreviewWindow.PreviewPanel.Font, WS);
|
|
Inc(Sz.cx, 100);
|
|
Inc(Sz.cy, 20);
|
|
|
|
W := SendMessage(Handle, CB_GETDROPPEDWIDTH, 0, 0);
|
|
P := Parent.ClientToScreen(Point(Left, Top));
|
|
|
|
if P.X + W + Sz.cx > Screen.Width then
|
|
Dec(P.X, Sz.cx)
|
|
else
|
|
Inc(P.X, W);
|
|
if P.Y + Height + Sz.cy > Screen.Height then
|
|
Dec(P.Y, Sz.cy)
|
|
else
|
|
Inc(P.Y, Height);
|
|
FPreviewWindow.SetBounds(P.X, P.Y, Sz.cx, Sz.cy);
|
|
FPreviewWindow.Visible := True;
|
|
ShowWindow(FPreviewWindow.Handle, SW_SHOWNA);
|
|
end;
|
|
end;
|
|
|
|
procedure TSpTBXFontComboBox.DoCalcMaxDropDownWidth;
|
|
begin
|
|
if Items.Count <= 0 then begin
|
|
{$IFNDEF UNICODE}
|
|
SpFillFontNames(Items.AnsiStrings);
|
|
{$ELSE}
|
|
SpFillFontNames(Items);
|
|
{$ENDIF}
|
|
end;
|
|
|
|
inherited;
|
|
end;
|
|
|
|
procedure TSpTBXFontComboBox.DoDrawItem(ACanvas: TCanvas; var ARect: TRect;
|
|
Index: Integer; const State: TOwnerDrawState;
|
|
const PaintStage: TSpTBXPaintStage; var PaintDefault: Boolean);
|
|
var
|
|
Flags, ImageIndex: Integer;
|
|
R: TRect;
|
|
const
|
|
Spacing = 4;
|
|
begin
|
|
inherited DoDrawItem(ACanvas, ARect, Index, State, PaintStage, PaintDefault);
|
|
if (PaintStage = pstPrePaint) and PaintDefault then begin
|
|
PaintDefault := False; // Override the default painting
|
|
// Draw the item glyph if the font is TrueType/OpenType
|
|
R := ARect;
|
|
R.Left := Spacing;
|
|
R.Top := R.Top + ((R.Bottom - R.Top) - FontGlyphImgList.Height) div 2;
|
|
ImageIndex := Integer(Items.Objects[Index]) - 1;
|
|
if ImageIndex > -1 then
|
|
FontGlyphImgList.Draw(ACanvas, R.Left, R.Top, ImageIndex);
|
|
|
|
// Draw the item text
|
|
R := ARect;
|
|
R.Left := Spacing + FontGlyphImgList.Width + Spacing;
|
|
if FFontNamePreview then
|
|
ACanvas.Font.Name := Items[Index];
|
|
Flags := DrawTextBiDiModeFlags(DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX);
|
|
SpDrawXPText(ACanvas, Items[Index], R, Flags);
|
|
|
|
// Draw the MRU separator line
|
|
if FMaxMRUItems > 0 then begin
|
|
if Index = MRUCount - 1 then
|
|
SpDrawLine(ACanvas, ARect.Left, ARect.Bottom - 1, ARect.Right, ARect.Bottom - 1, $C0C0C0);
|
|
if Index = MRUCount then
|
|
SpDrawLine(ACanvas, ARect.Left, ARect.Top, ARect.Right, ARect.Top, $C0C0C0);
|
|
end;
|
|
|
|
// Update the Font of the PreviewWindow
|
|
if Assigned(FPreviewWindow) and (odSelected in State) then
|
|
FPreviewWindow.PreviewPanel.Font.Name := Items[Index];
|
|
end;
|
|
end;
|
|
|
|
procedure TSpTBXFontComboBox.MRUAdd(AFontName: TFontName);
|
|
var
|
|
I, AFontNameIndex: Integer;
|
|
begin
|
|
AFontNameIndex := Items.IndexOf(AFontName);
|
|
if (AFontNameIndex > -1) and (FMRUCount < Items.Count) and (FMaxMRUItems > 0) then begin
|
|
// Exit if it's already on the list
|
|
for I := 0 to FMRUCount - 1 do
|
|
if SameText(AFontName, Items[I]) then Exit;
|
|
|
|
// Add the font to the top and delete the last MRU item if necessary
|
|
Items.InsertObject(0, Items[AFontNameIndex], Items.Objects[AFontNameIndex]);
|
|
if FMRUCount >= FMaxMRUItems then
|
|
Items.Delete(FMRUCount)
|
|
else
|
|
Inc(FMRUCount);
|
|
end;
|
|
end;
|
|
|
|
function TSpTBXFontComboBox.MRUDelete(AFontName: TFontName): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := False;
|
|
for I := 0 to FMRUCount - 1 do
|
|
if SameText(AFontName, Items[I]) then begin
|
|
Items.Delete(I);
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
end;
|
|
|
|
procedure TSpTBXFontComboBox.SetMaxMRUItems(Value: Integer);
|
|
begin
|
|
if Value < 0 then Value := 0;
|
|
if FMaxMRUItems <> Value then begin
|
|
FMaxMRUItems := Value;
|
|
while FMRUCount > FMaxMRUItems do begin
|
|
Items.Delete(FMRUCount);
|
|
Dec(FMRUCount);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TSpTBXFontComboBox.SetFontNamePreview(const Value: Boolean);
|
|
begin
|
|
if FFontNamePreview <> Value then begin
|
|
FFontNamePreview := Value;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure TSpTBXFontComboBox.SetFontPreview(const Value: Boolean);
|
|
begin
|
|
FFontPreview := Value;
|
|
end;
|
|
|
|
procedure TSpTBXFontComboBox.SetSelectedFont(const Value: TFontName);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
I := Items.IndexOf(Value);
|
|
if ItemIndex <> I then
|
|
ItemIndex := I;
|
|
UpdateSelectedFont(True);
|
|
|
|
// If the Value is not valid clear the text and call the click events
|
|
if I = -1 then begin
|
|
Click;
|
|
Select;
|
|
end;
|
|
end;
|
|
|
|
procedure TSpTBXFontComboBox.UpdateSelectedFont(AddMRU: Boolean);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
I := ItemIndex;
|
|
if I > -1 then begin
|
|
FSelectedFont := Items[I];
|
|
if AddMRU then
|
|
MRUAdd(FSelectedFont);
|
|
end
|
|
else
|
|
FSelectedFont := '';
|
|
end;
|
|
|
|
//WMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWM
|
|
{ TSpTBXColorListBox }
|
|
|
|
constructor TSpTBXColorListBox.Create(AOwner: TComponent);
|
|
begin
|
|
inherited;
|
|
FStyle := [clbsStandardColors, clbsSystemColors, clbsNoneAsTransparent];
|
|
FSelectedColor := clBlack;
|
|
PopulateList;
|
|
end;
|
|
|
|
procedure TSpTBXColorListBox.CreateWnd;
|
|
begin
|
|
inherited CreateWnd;
|
|
if FNeedToPopulate then
|
|
PopulateList;
|
|
end;
|
|
|
|
procedure TSpTBXColorListBox.DblClick;
|
|
begin
|
|
inherited;
|
|
if ItemIndex = 0 then
|
|
PickCustomColor;
|
|
end;
|
|
|
|
procedure TSpTBXColorListBox.Loaded;
|
|
begin
|
|
inherited;
|
|
Selected := FSelectedColor;
|
|
if FNeedToPopulate then
|
|
PopulateList;
|
|
end;
|
|
|
|
procedure TSpTBXColorListBox.AddColor(AColor: TColor; AColorName: string);
|
|
begin
|
|
(inherited Items).AddObject(AColorName, TObject(AColor));
|
|
end;
|
|
|
|
procedure TSpTBXColorListBox.ColorCallBack(const AName: string);
|
|
var
|
|
I, LStart: Integer;
|
|
LColor: TColor;
|
|
LName: string;
|
|
begin
|
|
LColor := StringToColor(AName);
|
|
if clbsPrettyNames in Style then begin
|
|
if AName = 'clBtnFace' then LName := 'Button Face'
|
|
else if AName = 'clBtnHighlight' then LName := 'Button Highlight'
|
|
else if AName = 'clBtnShadow' then LName := 'Button Shadow'
|
|
else if AName = 'clBtnText' then LName := 'Button Text'
|
|
else if AName = 'clMedGray' then LName := 'Medium Gray'
|
|
else if AName = 'clInfoBk' then LName := 'Info Background'
|
|
else if AName = 'cl3DDkShadow' then LName := '3D Dark Shadow'
|
|
else if AName = 'cl3DLight' then LName := '3D Light'
|
|
else begin
|
|
// Remove the 'cl' prefix and separate the words with a space
|
|
if Copy(AName, 1, 2) = 'cl' then
|
|
LStart := 3
|
|
else
|
|
LStart := 1;
|
|
LName := '';
|
|
for I := LStart to Length(AName) do begin
|
|
case AName[I] of
|
|
'A'..'Z':
|
|
if LName <> '' then
|
|
LName := LName + ' ';
|
|
end;
|
|
LName := LName + AName[I];
|
|
end;
|
|
end;
|
|
end
|
|
else
|
|
LName := AName;
|
|
|
|
AddColor(LColor, LName);
|
|
end;
|
|
|
|
function TSpTBXColorListBox.ColorCount: Integer;
|
|
begin
|
|
Result := (inherited Items).Count;
|
|
end;
|
|
|
|
procedure TSpTBXColorListBox.DoDrawItem(ACanvas: TCanvas; var ARect: TRect;
|
|
Index: Integer; const State: TOwnerDrawState;
|
|
const PaintStage: TSpTBXPaintStage; var PaintDefault: Boolean);
|
|
var
|
|
R: TRect;
|
|
SavedBrushColor: TColor;
|
|
begin
|
|
if PaintStage = pstPrePaint then begin
|
|
// Paint the color glyphs
|
|
R := ARect;
|
|
R.Right := R.Left + 16 + 5;
|
|
ARect.Left := R.Right + 1;
|
|
inherited DoDrawItem(ACanvas, ARect, Index, State, PaintStage, PaintDefault);
|
|
if PaintDefault then begin
|
|
SavedBrushColor := ACanvas.Brush.Color;
|
|
try
|
|
InflateRect(R, -1, -1);
|
|
|
|
ACanvas.Brush.Color := Colors[Index];
|
|
if (ACanvas.Brush.Color = clNone) and (clbsNoneAsTransparent in Style) then
|
|
SpDrawCheckeredBackground(ACanvas, R)
|
|
else
|
|
ACanvas.FillRect(R);
|
|
|
|
if odSelected in State then
|
|
ACanvas.Brush.Color := clWhite
|
|
else
|
|
ACanvas.Brush.Color := clBlack;
|
|
ACanvas.FrameRect(R);
|
|
finally
|
|
ACanvas.Brush.Color := SavedBrushColor;
|
|
end;
|
|
end;
|
|
end
|
|
else
|
|
inherited DoDrawItem(ACanvas, ARect, Index, State, PaintStage, PaintDefault);
|
|
end;
|
|
|
|
function TSpTBXColorListBox.GetColor(Index: Integer): TColor;
|
|
begin
|
|
Result := TColor((inherited Items).Objects[Index]);
|
|
end;
|
|
|
|
function TSpTBXColorListBox.GetColorName(Index: Integer): string;
|
|
begin
|
|
Result := (inherited Items)[Index];
|
|
end;
|
|
|
|
function TSpTBXColorListBox.GetSelected: TColor;
|
|
begin
|
|
if HandleAllocated then
|
|
if ItemIndex <> -1 then
|
|
Result := Colors[ItemIndex]
|
|
else
|
|
Result := clNone
|
|
else
|
|
Result := FSelectedColor;
|
|
end;
|
|
|
|
procedure TSpTBXColorListBox.KeyPress(var Key: Char);
|
|
begin
|
|
inherited KeyPress(Key);
|
|
if (clbsCustomColor in Style) and (Key = #13) and (ItemIndex = 0) then begin
|
|
Key := #0;
|
|
PickCustomColor;
|
|
end;
|
|
end;
|
|
|
|
function TSpTBXColorListBox.PickCustomColor: Boolean;
|
|
var
|
|
LColor: TColor;
|
|
CD: TColorDialog;
|
|
begin
|
|
Result := False;
|
|
if not (clbsCustomColor in Style) then Exit;
|
|
|
|
CD := TColorDialog.Create(nil);
|
|
try
|
|
LColor := ColorToRGB(Colors[0]);
|
|
CD.Color := LColor;
|
|
CD.CustomColors.Text := Format('ColorA=%.8x', [LColor]);
|
|
CD.Options := CD.Options + [cdFullOpen];
|
|
Result := CD.Execute;
|
|
if Result then begin
|
|
(inherited Items).Objects[0] := TObject(CD.Color);
|
|
Invalidate;
|
|
end;
|
|
finally
|
|
CD.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TSpTBXColorListBox.PopulateList;
|
|
|
|
procedure DeleteRange(const AMin, AMax: Integer);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := AMax downto AMin do
|
|
(inherited Items).Delete(I);
|
|
end;
|
|
|
|
procedure DeleteColor(const AColor: TColor);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
I := (inherited Items).IndexOfObject(TObject(AColor));
|
|
if I <> -1 then
|
|
(inherited Items).Delete(I);
|
|
end;
|
|
|
|
var
|
|
LSelectedColor, LCustomColor: TColor;
|
|
begin
|
|
if HandleAllocated and not (csLoading in ComponentState) then begin
|
|
(inherited Items).BeginUpdate;
|
|
try
|
|
// Get the custom color
|
|
LCustomColor := clBlack;
|
|
if (clbsCustomColor in Style) and ((inherited Items).Count > 0) then
|
|
LCustomColor := TColor((inherited Items).Objects[0]);
|
|
|
|
LSelectedColor := FSelectedColor;
|
|
(inherited Items).Clear;
|
|
|
|
GetColorValues(ColorCallBack);
|
|
if not (clbsIncludeNone in Style) then
|
|
DeleteColor(clNone);
|
|
if not (clbsIncludeDefault in Style) then
|
|
DeleteColor(clDefault);
|
|
if not (clbsSystemColors in Style) then
|
|
DeleteRange(StandardColorsCount + ExtendedColorsCount, (inherited Items).Count - 1);
|
|
if not (clbsStandardColors in Style) then
|
|
DeleteRange(0, StandardColorsCount + ExtendedColorsCount - 1);
|
|
|
|
if clbsCustomColor in Style then
|
|
(inherited Items).InsertObject(0, '...', TObject(LCustomColor));
|
|
|
|
Selected := LSelectedColor;
|
|
finally
|
|
(inherited Items).EndUpdate;
|
|
FNeedToPopulate := False;
|
|
end;
|
|
end
|
|
else
|
|
FNeedToPopulate := True;
|
|
end;
|
|
|
|
procedure TSpTBXColorListBox.SetSelected(const Value: TColor);
|
|
var
|
|
I, J: Integer;
|
|
begin
|
|
if HandleAllocated then begin
|
|
I := (inherited Items).IndexOfObject(TObject(Value));
|
|
if (I = -1) and (clbsCustomColor in Style) then begin
|
|
// If the color is not on the list add it and select it
|
|
(inherited Items).Objects[0] := TObject(Value);
|
|
I := 0;
|
|
end
|
|
else
|
|
if (clbsCustomColor in Style) and (I = 0) then begin
|
|
// Try to find the color on the list before selecting the 1st custom color
|
|
for J := 1 to (inherited Items).Count - 1 do
|
|
if (inherited Items).Objects[J] = TObject(Value) then begin
|
|
I := J;
|
|
Break;
|
|
end;
|
|
end;
|
|
|
|
if (ItemIndex = 0) and (I = 0) then
|
|
Invalidate
|
|
else
|
|
ItemIndex := I;
|
|
end;
|
|
|
|
FSelectedColor := Value;
|
|
end;
|
|
|
|
procedure TSpTBXColorListBox.SetStyle(const Value: TSpTBXColorListBoxStyles);
|
|
begin
|
|
if Style <> Value then begin
|
|
FStyle := Value;
|
|
Enabled := ([clbsStandardColors, clbsSystemColors, clbsCustomColor] * FStyle) <> [];
|
|
PopulateList;
|
|
if (ColorCount > 0) and (ItemIndex = -1) then
|
|
ItemIndex := 0;
|
|
end;
|
|
end;
|
|
|
|
//WMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWM
|
|
{ Stock Objects }
|
|
|
|
procedure InitializeStock;
|
|
begin
|
|
Screen.Cursors[crSpTBXEyeDropper] := LoadCursor(HInstance, 'CZEYEDROPPER');
|
|
|
|
FontGlyphImgList := TImageList.CreateSize(12, 12);
|
|
FontGlyphImgList.ResInstLoad(HInstance, rtBitmap, 'SPTBXTRUETYPE', clFuchsia);
|
|
FontGlyphImgList.ResInstLoad(HInstance, rtBitmap, 'SPTBXOPENTYPE', clFuchsia);
|
|
|
|
DefaultColorPickerDropDownMenu := TSpTBXColorEditPopupMenu.Create(nil);
|
|
end;
|
|
|
|
procedure FinalizeStock;
|
|
begin
|
|
FreeAndNil(FontGlyphImgList);
|
|
FreeAndNil(DefaultColorPickerDropDownMenu);
|
|
end;
|
|
|
|
initialization
|
|
InitializeStock;
|
|
|
|
finalization
|
|
FinalizeStock;
|
|
|
|
end.
|