Componentes.Terceros.SpTBXLib/internal/2.4.4/1/Source/SpTBXExtEditors.pas
2010-01-19 16:32:53 +00:00

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.