1902 lines
53 KiB
ObjectPascal
1902 lines
53 KiB
ObjectPascal
{-----------------------------------------------------------------------------
|
|
The contents of this file are subject to the Mozilla Public License
|
|
Version 1.1 (the "License"); you may not use this file except in compliance
|
|
with the License. You may obtain a copy of the License at
|
|
http://www.mozilla.org/MPL/MPL-1.1.html
|
|
|
|
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 Original Code is: JvButtons.PAS, released on 2002-07-04.
|
|
|
|
The Initial Developers of the Original Code are: Andrei Prygounkov <a dott prygounkov att gmx dott de>
|
|
Copyright (c) 1999, 2002 Andrei Prygounkov
|
|
All Rights Reserved.
|
|
|
|
Contributor(s):
|
|
Andreas Hausladen
|
|
|
|
You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
|
|
located at http://jvcl.sourceforge.net
|
|
|
|
components : TJvaCaptionButton,
|
|
TJvaColorButton,
|
|
TJvNoFrameButton,
|
|
TJvHTButton
|
|
description : Buttons
|
|
|
|
Known Issues:
|
|
Maciej Kaczkowski:
|
|
[X] Height of JvHTComboBox - on design time you cannot use mouse for resize
|
|
[X] alignment not work correctly on JvHTButtonGlyph
|
|
[X] not tested on BCB & Kylix
|
|
|
|
Create label with caption:
|
|
<ALIGN CENTER>Item 1 <b>bold</b> <u>underline</u><br><ALIGN RIGHT><FONT COLOR="clRed">red <FONT COLOR="clgreen">green <FONT COLOR="clblue">blue</i><br><ALIGN LEFT><FONT COLOR="clTeal">Item 2 <i>italic ITALIC</i> <s>strikeout STRIKEOUT </s><hr><br><ALIGN CENTER><FONT COLOR="clRed" BGCOLOR="clYellow">red with yellow background</FONT><FONT COLOR="clwhite"> white <FONT COLOR="clnavy"><b><i>navy</i></b>
|
|
|
|
Some information about coding:
|
|
[?] If you want use few times function <ALIGN> you must use before next <ALIGN>
|
|
function <BR>
|
|
[?] After <HR> must be <BR>
|
|
|
|
Changes:
|
|
========
|
|
Maciej Kaczkowski:
|
|
[+] <BR> - new line
|
|
[+] <HR> - horizontal line
|
|
[+] <S> and </S> - StrikeOut
|
|
[+] Multiline for JvHTListBox, JvHTComboBox
|
|
TJvHTButton
|
|
[+] You can change Height of JvHTComboBox
|
|
[+] Tags: & " ® © ™
|
|
< >
|
|
[+] <ALIGN [CENTER, LEFT, RIGHT]>
|
|
[*] <C:color> was changed to ex.:
|
|
<FONT COLOR="clRed" BGCOLOR="clWhite">
|
|
</FONT>
|
|
[*] procedure ItemHtDrawEx - rewrited
|
|
[*] function ItemHtPlain - optimized
|
|
-----------------------------------------------------------------------------}
|
|
// $Id: JvButtons.pas 10893 2006-08-17 20:27:39Z ahuser $
|
|
|
|
unit JvButtons;
|
|
|
|
{$I jvcl.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$IFDEF UNITVERSIONING}
|
|
JclUnitVersioning,
|
|
{$ENDIF UNITVERSIONING}
|
|
Windows, Messages,
|
|
Classes, Graphics, Controls, Forms, Buttons, ExtCtrls,
|
|
{$IFDEF VisualCLX}
|
|
QImgList,
|
|
{$ENDIF VisualCLX}
|
|
{$IFDEF VCL}
|
|
JvWndProcHook,
|
|
{$ENDIF VCL}
|
|
JvJCLUtils, JvComponentBase, JvExButtons;
|
|
|
|
type
|
|
{ VCL Buttons unit does not publish TJvButtonGlyph class,
|
|
so we do it for other programers (Delphi 3 version) }
|
|
TJvButtonGlyph = class(TObject)
|
|
private
|
|
FGlyphList: TImageList;
|
|
FIndexs: array [TButtonState] of Integer;
|
|
FTransparentColor: TColor;
|
|
FNumGlyphs: TNumGlyphs;
|
|
FOnChange: TNotifyEvent;
|
|
FColor: TColor;
|
|
{$IFDEF VCL}
|
|
FBiDiMode: TBiDiMode; {o}
|
|
FParentBiDiMode: Boolean;
|
|
procedure SetBiDiMode(Value: TBiDiMode);
|
|
procedure SetParentBiDiMode(Value: Boolean);
|
|
{$ENDIF VCL}
|
|
procedure GlyphChanged(Sender: TObject);
|
|
procedure SetGlyph(Value: TBitmap);
|
|
procedure SetNumGlyphs(Value: TNumGlyphs);
|
|
procedure SetColor(Value: TColor);
|
|
procedure Invalidate;
|
|
function CreateButtonGlyph(State: TButtonState): Integer;
|
|
procedure DrawButtonGlyph(Canvas: TCanvas; const GlyphPos: TPoint;
|
|
State: TButtonState; Transparent: Boolean);
|
|
procedure DrawButtonText(Canvas: TCanvas; const Caption: string;
|
|
TextBounds: TRect; State: TButtonState); virtual;
|
|
procedure CalcButtonLayout(Canvas: TCanvas; const Client: TRect;
|
|
const Offset: TPoint; const Caption: string; Layout: TButtonLayout;
|
|
Margin, Spacing: Integer; var GlyphPos: TPoint; var TextBounds: TRect);
|
|
protected
|
|
FOriginal: TBitmap;
|
|
procedure CalcTextRect(Canvas: TCanvas; var TextRect: TRect;
|
|
Caption: string); virtual;
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
{ return the text rectangle }
|
|
function Draw(Canvas: TCanvas; const Client: TRect; const Offset: TPoint;
|
|
const Caption: string; Layout: TButtonLayout; Margin, Spacing: Integer;
|
|
State: TButtonState; Transparent: Boolean): TRect;
|
|
{ DrawExternal draws any glyph (not glyph property) -
|
|
if you don't needed to save previous glyph set IgnoreOld to True -
|
|
this increases performance }
|
|
function DrawExternal(AGlyph: TBitmap; ANumGlyphs: TNumGlyphs; AColor: TColor; IgnoreOld: Boolean;
|
|
Canvas: TCanvas; const Client: TRect; const Offset: TPoint; const Caption: string;
|
|
Layout: TButtonLayout; Margin, Spacing: Integer; State: TButtonState; Transparent: Boolean): TRect;
|
|
{$IFDEF VCL}
|
|
property BiDiMode: TBiDiMode read FBiDiMode write SetBiDiMode;
|
|
property ParentBiDiMode: Boolean read FParentBiDiMode write SetParentBiDiMode;
|
|
{$ENDIF VCL}
|
|
property Glyph: TBitmap read FOriginal write SetGlyph;
|
|
property NumGlyphs: TNumGlyphs read FNumGlyphs write SetNumGlyphs;
|
|
property Color: TColor read FColor write SetColor;
|
|
property OnChange: TNotifyEvent read FOnChange write FOnChange;
|
|
end;
|
|
|
|
TJvHTButtonGlyph = class(TJvButtonGlyph)
|
|
private
|
|
procedure DrawButtonText(Canvas: TCanvas; const Caption: string;
|
|
TextBounds: TRect; State: TButtonState); override;
|
|
protected
|
|
procedure CalcTextRect(Canvas: TCanvas; var TextRect: TRect;
|
|
Caption: string); override;
|
|
end;
|
|
|
|
{$IFDEF VCL}
|
|
TJvaCaptionButton = class(TJvComponent)
|
|
private
|
|
FGlyph: TJvButtonGlyph;
|
|
FCaption: string;
|
|
FLayout: TButtonLayout;
|
|
FSpacing: Integer;
|
|
FMargin: Integer;
|
|
FRect: TRect;
|
|
FMouseLButtonDown: Boolean;
|
|
FPress: Boolean;
|
|
FOnClick: TNotifyEvent;
|
|
FBPos: Integer;
|
|
FWidth: Integer;
|
|
WHook: TJvWindowHook;
|
|
FActive: Boolean;
|
|
FFont: TFont;
|
|
FVisible: Boolean;
|
|
procedure DoBeforeMsg(Sender: TObject; var Msg: TMessage; var Handled: Boolean);
|
|
procedure DoAfterMsg(Sender: TObject; var Msg: TMessage; var Handled: Boolean);
|
|
// procedure HookWndProc(var Msg: TMessage);
|
|
procedure Draw;
|
|
function MouseOnButton(X, Y: Integer): Boolean;
|
|
procedure Resize;
|
|
procedure GlyphChanged(Sender: TObject);
|
|
|
|
function GetHeight: Integer;
|
|
function GetWidth: Integer;
|
|
function GetLeft: Integer;
|
|
|
|
procedure SetCaption(Value: string);
|
|
function IsCaptionStored: Boolean;
|
|
function GetGlyph: TBitmap;
|
|
procedure SetGlyph(Value: TBitmap);
|
|
function GetNumGlyphs: TNumGlyphs;
|
|
procedure SetNumGlyphs(Value: TNumGlyphs);
|
|
procedure SetBPos(const Value: Integer);
|
|
procedure SetLayout(Value: TButtonLayout);
|
|
procedure SetSpacing(Value: Integer);
|
|
procedure SetMargin(Value: Integer);
|
|
procedure SetWidth(const Value: Integer);
|
|
procedure SetFont(Value: TFont);
|
|
procedure FontChange(Sender: TObject);
|
|
procedure SetDown(const Value: Boolean);
|
|
procedure SetVisible(const Value: Boolean);
|
|
protected
|
|
FState: TButtonState;
|
|
function CalcOffset: TPoint;
|
|
procedure Changed; dynamic;
|
|
function BorderStyle: TFormBorderStyle;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
procedure Click; dynamic;
|
|
procedure Update;
|
|
published
|
|
property Position: Integer read FBPos write SetBPos;
|
|
property Spacing: Integer read FSpacing write SetSpacing default 4;
|
|
property Layout: TButtonLayout read FLayout write SetLayout default blGlyphLeft;
|
|
property Margin: Integer read FMargin write SetMargin default -1;
|
|
property Caption: string read FCaption write SetCaption stored IsCaptionStored;
|
|
property Width: Integer read FWidth write SetWidth default -1;
|
|
property Font: TFont read FFont write SetFont;
|
|
property Glyph: TBitmap read GetGlyph write SetGlyph;
|
|
property NumGlyphs: TNumGlyphs read GetNumGlyphs write SetNumGlyphs default 1;
|
|
property Down: Boolean read FPress write SetDown default False;
|
|
property Visible: Boolean read FVisible write SetVisible default True;
|
|
property OnClick: TNotifyEvent read FOnClick write FOnClick;
|
|
end;
|
|
{$ENDIF VCL}
|
|
|
|
TPaintButtonEvent = procedure(Sender: TObject; IsDown, IsDefault: Boolean; State: TButtonState) of object;
|
|
|
|
TJvaColorButton = class(TJvExBitBtn)
|
|
private
|
|
{$IFDEF VisualCLX}
|
|
FCanvas: TCanvas; // asn: never created
|
|
{$ENDIF VisualCLX}
|
|
FGlyphDrawer: TJvButtonGlyph;
|
|
FOnPaint: TPaintButtonEvent;
|
|
{$IFDEF VCL}
|
|
FCanvas: TControlCanvas ;
|
|
function GetCanvas: TCanvas;
|
|
procedure CNDrawItem(var Msg: TWMDrawItem); message CN_DRAWITEM;
|
|
{$ENDIF VCL}
|
|
protected
|
|
IsFocused: Boolean;
|
|
{$IFDEF VCL}
|
|
procedure SetButtonStyle(ADefault: Boolean); override;
|
|
{$ENDIF VCL}
|
|
{$IFDEF VisualCLX}
|
|
procedure Paint; override;
|
|
{$ENDIF VisualCLX}
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
procedure DefaultDrawing(const IsDown, IsDefault: Boolean; const State: TButtonState);
|
|
{$IFDEF VCL}
|
|
property Canvas: TCanvas read GetCanvas;
|
|
{$ENDIF VCL}
|
|
published
|
|
property Color;
|
|
property ParentColor;
|
|
property OnPaint: TPaintButtonEvent read FOnPaint write FOnPaint;
|
|
end;
|
|
|
|
TJvNoFrameButton = class(TJvExSpeedButton)
|
|
private
|
|
FGlyphDrawer: TJvButtonGlyph;
|
|
FNoBorder: Boolean;
|
|
FOnPaint: TPaintButtonEvent;
|
|
FRepeatedClick: Boolean;
|
|
FRepeatTimer: TTimer;
|
|
FInitRepeatPause: Integer;
|
|
FRepeatPause: Integer;
|
|
FClicked: Boolean;
|
|
procedure SetNoBorder(Value: Boolean);
|
|
procedure TimerExpired(Sender: TObject);
|
|
protected
|
|
procedure Paint; override;
|
|
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X: Integer; Y: Integer); override;
|
|
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X: Integer; Y: Integer); override;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
procedure DefaultDrawing(const IsDown: Boolean; const State: TButtonState);
|
|
property Canvas;
|
|
published
|
|
property Color;
|
|
property ParentColor;
|
|
property NoBorder: Boolean read FNoBorder write SetNoBorder default True;
|
|
property RepeatedClick: Boolean read FRepeatedClick write FRepeatedClick default False;
|
|
property InitRepeatPause: Integer read FInitRepeatPause write FInitRepeatPause default 400;
|
|
property RepeatPause: Integer read FRepeatPause write FRepeatPause default 100;
|
|
property OnPaint: TPaintButtonEvent read FOnPaint write FOnPaint;
|
|
end;
|
|
|
|
TJvHTButton = class(TJvaColorButton)
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
end;
|
|
|
|
{$IFDEF UNITVERSIONING}
|
|
const
|
|
UnitVersioning: TUnitVersionInfo = (
|
|
RCSfile: '$URL: https://jvcl.svn.sourceforge.net/svnroot/jvcl/tags/JVCL3_32/run/JvButtons.pas $';
|
|
Revision: '$Revision: 10893 $';
|
|
Date: '$Date: 2006-08-17 22:27:39 +0200 (jeu., 17 août 2006) $';
|
|
LogPath: 'JVCL\run'
|
|
);
|
|
{$ENDIF UNITVERSIONING}
|
|
|
|
implementation
|
|
|
|
uses
|
|
{$IFDEF VCL}
|
|
CommCtrl,
|
|
{$ENDIF VCL}
|
|
SysUtils, Math,
|
|
JvHtControls, JvDsgnIntf, JvConsts, JvResources, JvTypes, JvThemes;
|
|
|
|
type
|
|
TJvGlyphList = class(TImageList)
|
|
private
|
|
FUsed: TBits;
|
|
FCount: Integer;
|
|
function AllocateIndex: Integer;
|
|
public
|
|
constructor CreateSize(AWidth, AHeight: Integer);
|
|
destructor Destroy; override;
|
|
function AddMasked(Image: TBitmap; MaskColor: TColor): Integer;
|
|
{$IFDEF VisualCLX} reintroduce; {$ENDIF}
|
|
procedure Delete(Index: Integer);
|
|
property Count: Integer read FCount;
|
|
end;
|
|
|
|
TJvGlyphCache = class(TObject)
|
|
private
|
|
FGlyphLists: TList;
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
function GetList(AWidth, AHeight: Integer): TJvGlyphList;
|
|
procedure ReturnList(List: TJvGlyphList);
|
|
function Empty: Boolean;
|
|
end;
|
|
|
|
//=== { TJvGlyphList } =======================================================
|
|
|
|
constructor TJvGlyphList.CreateSize(AWidth, AHeight: Integer);
|
|
begin
|
|
inherited CreateSize(AWidth, AHeight);
|
|
FUsed := TBits.Create;
|
|
end;
|
|
|
|
destructor TJvGlyphList.Destroy;
|
|
begin
|
|
FUsed.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJvGlyphList.AllocateIndex: Integer;
|
|
begin
|
|
Result := FUsed.OpenBit;
|
|
if Result >= FUsed.Size then
|
|
begin
|
|
Result := inherited Add(nil, nil);
|
|
FUsed.Size := Result + 1;
|
|
end;
|
|
FUsed[Result] := True;
|
|
end;
|
|
|
|
function TJvGlyphList.AddMasked(Image: TBitmap; MaskColor: TColor): Integer;
|
|
begin
|
|
Result := AllocateIndex;
|
|
ReplaceMasked(Result, Image, MaskColor);
|
|
Inc(FCount);
|
|
end;
|
|
|
|
procedure TJvGlyphList.Delete(Index: Integer);
|
|
begin
|
|
if FUsed[Index] then
|
|
begin
|
|
Dec(FCount);
|
|
FUsed[Index] := False;
|
|
end;
|
|
end;
|
|
|
|
//=== { TJvGlyphCache } ======================================================
|
|
|
|
constructor TJvGlyphCache.Create;
|
|
begin
|
|
inherited Create;
|
|
FGlyphLists := TList.Create;
|
|
end;
|
|
|
|
destructor TJvGlyphCache.Destroy;
|
|
begin
|
|
FGlyphLists.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJvGlyphCache.GetList(AWidth, AHeight: Integer): TJvGlyphList;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := FGlyphLists.Count - 1 downto 0 do
|
|
begin
|
|
Result := FGlyphLists[I];
|
|
with Result do
|
|
if (AWidth = Width) and (AHeight = Height) then
|
|
Exit;
|
|
end;
|
|
Result := TJvGlyphList.CreateSize(AWidth, AHeight);
|
|
FGlyphLists.Add(Result);
|
|
end;
|
|
|
|
procedure TJvGlyphCache.ReturnList(List: TJvGlyphList);
|
|
begin
|
|
if List = nil then
|
|
Exit;
|
|
if List.Count = 0 then
|
|
begin
|
|
FGlyphLists.Remove(List);
|
|
List.Free;
|
|
end;
|
|
end;
|
|
|
|
function TJvGlyphCache.Empty: Boolean;
|
|
begin
|
|
Result := FGlyphLists.Count = 0;
|
|
end;
|
|
|
|
//=== { TJvButtonGlyph } =====================================================
|
|
|
|
var
|
|
GlyphCache: TJvGlyphCache = nil;
|
|
Pattern: TBitmap = nil;
|
|
|
|
procedure CreateBrushPattern(FaceColor, HighLightColor: TColor);
|
|
var
|
|
X, Y: Integer;
|
|
begin
|
|
Pattern := TBitmap.Create;
|
|
Pattern.Width := 8;
|
|
Pattern.Height := 8;
|
|
with Pattern.Canvas do
|
|
begin
|
|
Brush.Style := bsSolid;
|
|
Brush.Color := FaceColor; // clBtnFace
|
|
FillRect(Rect(0, 0, Pattern.Width, Pattern.Height));
|
|
for Y := 0 to 7 do
|
|
for X := 0 to 7 do
|
|
if (Y mod 2) = (X mod 2) then { toggles between even/odd pixels }
|
|
Pixels[X, Y] := HighLightColor; {clBtnHighlight}; { on even/odd rows }
|
|
end;
|
|
end;
|
|
|
|
constructor TJvButtonGlyph.Create;
|
|
var
|
|
I: TButtonState;
|
|
begin
|
|
inherited Create;
|
|
FOriginal := TBitmap.Create;
|
|
FOriginal.OnChange := GlyphChanged;
|
|
FTransparentColor := clOlive;
|
|
FNumGlyphs := 1;
|
|
for I := Low(I) to High(I) do
|
|
FIndexs[I] := -1;
|
|
if GlyphCache = nil then
|
|
GlyphCache := TJvGlyphCache.Create;
|
|
end;
|
|
|
|
destructor TJvButtonGlyph.Destroy;
|
|
begin
|
|
FOriginal.Free;
|
|
Invalidate;
|
|
if Assigned(GlyphCache) and GlyphCache.Empty then
|
|
begin
|
|
GlyphCache.Free;
|
|
GlyphCache := nil;
|
|
end;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJvButtonGlyph.Invalidate;
|
|
var
|
|
I: TButtonState;
|
|
begin
|
|
for I := Low(I) to High(I) do
|
|
begin
|
|
if FIndexs[I] <> -1 then
|
|
TJvGlyphList(FGlyphList).Delete(FIndexs[I]);
|
|
FIndexs[I] := -1;
|
|
end;
|
|
GlyphCache.ReturnList(TJvGlyphList(FGlyphList));
|
|
FGlyphList := nil;
|
|
end;
|
|
|
|
procedure TJvButtonGlyph.GlyphChanged(Sender: TObject);
|
|
begin
|
|
if Sender = FOriginal then
|
|
begin
|
|
FTransparentColor := FOriginal.TransparentColor;
|
|
Invalidate;
|
|
if Assigned(FOnChange) then
|
|
FOnChange(Self);
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF VCL}
|
|
|
|
procedure TJvButtonGlyph.SetBiDiMode(Value: TBiDiMode);
|
|
begin
|
|
if FBiDiMode <> Value then
|
|
begin
|
|
FBiDiMode := Value;
|
|
FParentBiDiMode := False;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvButtonGlyph.SetParentBiDiMode(Value: Boolean);
|
|
begin
|
|
if FParentBiDiMode <> Value then
|
|
begin
|
|
FParentBiDiMode := Value;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
{$ENDIF VCL}
|
|
|
|
procedure TJvButtonGlyph.SetGlyph(Value: TBitmap);
|
|
var
|
|
Glyphs: Integer;
|
|
begin
|
|
Invalidate;
|
|
FOriginal.Assign(Value);
|
|
if (Value <> nil) and (Value.Height > 0) then
|
|
begin
|
|
FTransparentColor := Value.TransparentColor;
|
|
if Value.Width mod Value.Height = 0 then
|
|
begin
|
|
Glyphs := Value.Width div Value.Height;
|
|
if Glyphs > 4 then
|
|
Glyphs := 1;
|
|
SetNumGlyphs(Glyphs);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvButtonGlyph.SetNumGlyphs(Value: TNumGlyphs);
|
|
begin
|
|
if (Value <> FNumGlyphs) and (Value > 0) then
|
|
begin
|
|
Invalidate;
|
|
FNumGlyphs := Value;
|
|
GlyphChanged(Glyph);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvButtonGlyph.SetColor(Value: TColor);
|
|
begin
|
|
if FColor <> Value then
|
|
begin
|
|
FColor := Value;
|
|
GlyphChanged(Glyph);
|
|
end;
|
|
end;
|
|
|
|
|
|
function TJvButtonGlyph.CreateButtonGlyph(State: TButtonState): Integer;
|
|
var
|
|
TmpImage, DDB, MonoBmp: TBitmap;
|
|
IWidth, IHeight: Integer;
|
|
IRect, ORect: TRect;
|
|
I: TButtonState;
|
|
DestDC: HDC;
|
|
begin
|
|
if (State = bsDown) and (NumGlyphs < 3) then
|
|
State := bsUp;
|
|
Result := FIndexs[State];
|
|
if Result <> -1 then
|
|
Exit;
|
|
if (FOriginal.Width or FOriginal.Height) = 0 then
|
|
Exit;
|
|
IWidth := FOriginal.Width div FNumGlyphs;
|
|
IHeight := FOriginal.Height;
|
|
if FGlyphList = nil then
|
|
begin
|
|
if GlyphCache = nil then
|
|
GlyphCache := TJvGlyphCache.Create;
|
|
FGlyphList := GlyphCache.GetList(IWidth, IHeight);
|
|
end;
|
|
TmpImage := TBitmap.Create;
|
|
try
|
|
TmpImage.Width := IWidth;
|
|
TmpImage.Height := IHeight;
|
|
IRect := Rect(0, 0, IWidth, IHeight);
|
|
TmpImage.Canvas.Brush.Color := Color {clBtnFace};
|
|
{$IFDEF VCL}
|
|
TmpImage.Palette := CopyPalette(FOriginal.Palette);
|
|
{$ENDIF VCL}
|
|
I := State;
|
|
if Ord(I) >= NumGlyphs then
|
|
I := bsUp;
|
|
ORect := Rect(Ord(I) * IWidth, 0, (Ord(I) + 1) * IWidth, IHeight);
|
|
case State of
|
|
bsUp, bsDown,
|
|
bsExclusive:
|
|
begin
|
|
TmpImage.Canvas.CopyRect(IRect, FOriginal.Canvas, ORect);
|
|
if FOriginal.TransparentMode = tmFixed then
|
|
FIndexs[State] := TJvGlyphList(FGlyphList).AddMasked(TmpImage, FTransparentColor)
|
|
else
|
|
FIndexs[State] := TJvGlyphList(FGlyphList).AddMasked(TmpImage, clDefault);
|
|
end;
|
|
bsDisabled:
|
|
begin
|
|
MonoBmp := nil;
|
|
DDB := nil;
|
|
try
|
|
MonoBmp := TBitmap.Create;
|
|
DDB := TBitmap.Create;
|
|
DDB.Assign(FOriginal);
|
|
{$IFDEF VCL}
|
|
DDB.HandleType := bmDDB;
|
|
{$ENDIF VCL}
|
|
if NumGlyphs > 1 then
|
|
with TmpImage.Canvas do
|
|
begin { Change white & gray to clBtnHighlight and clBtnShadow }
|
|
{$IFDEF VisualCLX}
|
|
Start;
|
|
{$ENDIF VisualCLX}
|
|
CopyRect(IRect, DDB.Canvas, ORect);
|
|
{$IFDEF VCL}
|
|
MonoBmp.Monochrome := True;
|
|
{$ENDIF VCL}
|
|
MonoBmp.Width := IWidth;
|
|
MonoBmp.Height := IHeight;
|
|
|
|
{ Convert white to clBtnHighlight }
|
|
DDB.Canvas.Brush.Color := clWhite;
|
|
MonoBmp.Canvas.CopyRect(IRect, DDB.Canvas, ORect);
|
|
Brush.Color := clBtnHighlight;
|
|
DestDC := Handle;
|
|
SetTextColor(DestDC, clBlack);
|
|
SetBkColor(DestDC, clWhite);
|
|
BitBlt(DestDC, 0, 0, IWidth, IHeight,
|
|
MonoBmp.Canvas.Handle, 0, 0, ROP_DSPDxax);
|
|
|
|
{ Convert gray to clBtnShadow }
|
|
DDB.Canvas.Brush.Color := clGray;
|
|
MonoBmp.Canvas.CopyRect(IRect, DDB.Canvas, ORect);
|
|
Brush.Color := clBtnShadow;
|
|
DestDC := Handle;
|
|
SetTextColor(DestDC, clBlack);
|
|
SetBkColor(DestDC, clWhite);
|
|
BitBlt(DestDC, 0, 0, IWidth, IHeight,
|
|
MonoBmp.Canvas.Handle, 0, 0, ROP_DSPDxax);
|
|
|
|
{ Convert transparent color to clBtnFace }
|
|
DDB.Canvas.Brush.Color := ColorToRGB(FTransparentColor);
|
|
MonoBmp.Canvas.CopyRect(IRect, DDB.Canvas, ORect);
|
|
Brush.Color := Color {clBtnFace};
|
|
DestDC := Handle;
|
|
SetTextColor(DestDC, clBlack);
|
|
SetBkColor(DestDC, clWhite);
|
|
BitBlt(DestDC, 0, 0, IWidth, IHeight,
|
|
MonoBmp.Canvas.Handle, 0, 0, ROP_DSPDxax);
|
|
{$IFDEF VisualCLX}
|
|
Stop;
|
|
{$ENDIF VisualCLX}
|
|
end
|
|
else
|
|
begin
|
|
{ Create a disabled version }
|
|
with MonoBmp do
|
|
begin
|
|
Assign(FOriginal);
|
|
{$IFDEF VCL}
|
|
HandleType := bmDDB;
|
|
{$ENDIF VCL}
|
|
Canvas.Brush.Color := clBlack;
|
|
Width := IWidth;
|
|
if Monochrome then
|
|
begin
|
|
Canvas.Font.Color := clWhite;
|
|
Monochrome := False;
|
|
Canvas.Brush.Color := clWhite;
|
|
end;
|
|
Monochrome := True;
|
|
end;
|
|
with TmpImage.Canvas do
|
|
begin
|
|
{$IFDEF VisualCLX}
|
|
Start;
|
|
{$ENDIF VisualCLX}
|
|
Brush.Color := Color {clBtnFace};
|
|
FillRect(IRect);
|
|
Brush.Color := clBtnHighlight;
|
|
SetTextColor(Handle, clBlack);
|
|
SetBkColor(Handle, clWhite);
|
|
BitBlt(Handle, 1, 1, IWidth, IHeight,
|
|
MonoBmp.Canvas.Handle, 0, 0, ROP_DSPDxax);
|
|
Brush.Color := clBtnShadow;
|
|
SetTextColor(Handle, clBlack);
|
|
SetBkColor(Handle, clWhite);
|
|
BitBlt(Handle, 0, 0, IWidth, IHeight,
|
|
MonoBmp.Canvas.Handle, 0, 0, ROP_DSPDxax);
|
|
{$IFDEF VisualCLX}
|
|
Stop;
|
|
{$ENDIF VisualCLX}
|
|
end;
|
|
end;
|
|
finally
|
|
DDB.Free;
|
|
MonoBmp.Free;
|
|
end;
|
|
FIndexs[State] := TJvGlyphList(FGlyphList).AddMasked(TmpImage, clDefault);
|
|
end;
|
|
end;
|
|
finally
|
|
TmpImage.Free;
|
|
end;
|
|
Result := FIndexs[State];
|
|
FOriginal.Dormant;
|
|
end;
|
|
|
|
procedure TJvButtonGlyph.DrawButtonGlyph(Canvas: TCanvas; const GlyphPos: TPoint;
|
|
State: TButtonState; Transparent: Boolean);
|
|
var
|
|
Index: Integer;
|
|
begin
|
|
if FOriginal = nil then
|
|
Exit;
|
|
if (FOriginal.Width = 0) or (FOriginal.Height = 0) then
|
|
Exit;
|
|
Index := CreateButtonGlyph(State);
|
|
{$IFDEF VCL}
|
|
with GlyphPos do
|
|
if Transparent or (State = bsExclusive) then
|
|
ImageList_DrawEx(FGlyphList.Handle, Index, Canvas.Handle, X, Y, 0, 0,
|
|
clNone, clNone, ILD_Transparent)
|
|
else
|
|
ImageList_DrawEx(FGlyphList.Handle, Index, Canvas.Handle, X, Y, 0, 0,
|
|
ColorToRGB(Color {clBtnFace}), clNone, ILD_Normal);
|
|
{$ENDIF VCL}
|
|
{$IFDEF VisualCLX}
|
|
with GlyphPos do
|
|
if Transparent or (State = bsExclusive) then
|
|
begin
|
|
FGlyphList.Masked := True;
|
|
FGlyphList.BkColor := clNone;
|
|
FGlyphList.Draw(Canvas, X, Y, Index, itImage); // (ahuser) VisualCLX missing Transparent draw method
|
|
end
|
|
else
|
|
begin
|
|
FGlyphList.Masked := False;
|
|
FGlyphList.BkColor := Color;
|
|
FGlyphList.Draw(Canvas, X, Y, Index, itImage);
|
|
end;
|
|
{$ENDIF VisualCLX}
|
|
end;
|
|
|
|
procedure TJvButtonGlyph.DrawButtonText(Canvas: TCanvas; const Caption: string;
|
|
TextBounds: TRect; State: TButtonState);
|
|
var
|
|
Flags: Longint;
|
|
begin
|
|
Flags := 0;
|
|
{$IFDEF VCL}
|
|
if FBiDiMode <> bdLeftToRight then
|
|
Flags := DT_RTLREADING;
|
|
{$ENDIF VCL}
|
|
with Canvas do
|
|
begin
|
|
Brush.Style := bsClear;
|
|
if State = bsDisabled then
|
|
begin
|
|
OffsetRect(TextBounds, 1, 1);
|
|
Font.Color := clBtnHighlight;
|
|
DrawText(Canvas, Caption, Length(Caption), TextBounds, Flags);
|
|
OffsetRect(TextBounds, -1, -1);
|
|
Font.Color := clBtnShadow;
|
|
DrawText(Canvas, Caption, Length(Caption), TextBounds, Flags);
|
|
end
|
|
else
|
|
DrawText(Canvas, Caption, Length(Caption), TextBounds,
|
|
DT_CENTER or DT_VCENTER or DT_SINGLELINE or Flags);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvButtonGlyph.CalcButtonLayout(Canvas: TCanvas; const Client: TRect;
|
|
const Offset: TPoint; const Caption: string; Layout: TButtonLayout; Margin,
|
|
Spacing: Integer; var GlyphPos: TPoint; var TextBounds: TRect);
|
|
var
|
|
TextPos: TPoint;
|
|
ClientSize, GlyphSize, TextSize: TPoint;
|
|
TotalSize: TPoint;
|
|
begin
|
|
{ calculate the item sizes }
|
|
ClientSize := Point(Client.Right - Client.Left, Client.Bottom -
|
|
Client.Top);
|
|
|
|
if FOriginal <> nil then
|
|
GlyphSize := Point(FOriginal.Width div FNumGlyphs, FOriginal.Height)
|
|
else
|
|
GlyphSize := Point(0, 0);
|
|
|
|
if Length(Caption) > 0 then
|
|
begin
|
|
CalcTextRect(Canvas, TextBounds, Caption);
|
|
TextSize := Point(TextBounds.Right - TextBounds.Left, TextBounds.Bottom -
|
|
TextBounds.Top);
|
|
end
|
|
else
|
|
begin
|
|
TextBounds := Rect(0, 0, 0, 0);
|
|
TextSize := Point(0, 0);
|
|
end;
|
|
|
|
{ If the layout has the glyph on the right or the left, then both the
|
|
text and the glyph are centered vertically. If the glyph is on the top
|
|
or the bottom, then both the text and the glyph are centered horizontally.}
|
|
if Layout in [blGlyphLeft, blGlyphRight] then
|
|
begin
|
|
GlyphPos.Y := (ClientSize.Y - GlyphSize.Y + 1) div 2;
|
|
TextPos.Y := (ClientSize.Y - TextSize.Y + 1) div 2;
|
|
end
|
|
else
|
|
begin
|
|
GlyphPos.X := (ClientSize.X - GlyphSize.X + 1) div 2;
|
|
TextPos.X := (ClientSize.X - TextSize.X + 1) div 2;
|
|
end;
|
|
|
|
{ if there is no text or no bitmap, then Spacing is irrelevant }
|
|
if (TextSize.X = 0) or (GlyphSize.X = 0) then
|
|
Spacing := 0;
|
|
|
|
{ adjust Margin and Spacing }
|
|
if Margin = -1 then
|
|
begin
|
|
if Spacing = -1 then
|
|
begin
|
|
TotalSize := Point(GlyphSize.X + TextSize.X, GlyphSize.Y + TextSize.Y);
|
|
if Layout in [blGlyphLeft, blGlyphRight] then
|
|
Margin := (ClientSize.X - TotalSize.X) div 3
|
|
else
|
|
Margin := (ClientSize.Y - TotalSize.Y) div 3;
|
|
Spacing := Margin;
|
|
end
|
|
else
|
|
begin
|
|
TotalSize := Point(GlyphSize.X + Spacing + TextSize.X, GlyphSize.Y +
|
|
Spacing + TextSize.Y);
|
|
if Layout in [blGlyphLeft, blGlyphRight] then
|
|
Margin := (ClientSize.X - TotalSize.X + 1) div 2
|
|
else
|
|
Margin := (ClientSize.Y - TotalSize.Y + 1) div 2;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
if Spacing = -1 then
|
|
begin
|
|
TotalSize := Point(ClientSize.X - (Margin + GlyphSize.X), ClientSize.Y -
|
|
(Margin + GlyphSize.Y));
|
|
if Layout in [blGlyphLeft, blGlyphRight] then
|
|
Spacing := (TotalSize.X - TextSize.X) div 2
|
|
else
|
|
Spacing := (TotalSize.Y - TextSize.Y) div 2;
|
|
end;
|
|
end;
|
|
|
|
case Layout of
|
|
blGlyphLeft:
|
|
begin
|
|
GlyphPos.X := Margin;
|
|
TextPos.X := GlyphPos.X + GlyphSize.X + Spacing;
|
|
end;
|
|
blGlyphRight:
|
|
begin
|
|
GlyphPos.X := ClientSize.X - Margin - GlyphSize.X;
|
|
TextPos.X := GlyphPos.X - Spacing - TextSize.X;
|
|
end;
|
|
blGlyphTop:
|
|
begin
|
|
GlyphPos.Y := Margin;
|
|
TextPos.Y := GlyphPos.Y + GlyphSize.Y + Spacing;
|
|
end;
|
|
blGlyphBottom:
|
|
begin
|
|
GlyphPos.Y := ClientSize.Y - Margin - GlyphSize.Y;
|
|
TextPos.Y := GlyphPos.Y - Spacing - TextSize.Y;
|
|
end;
|
|
end;
|
|
|
|
{ fixup the result variables }
|
|
with GlyphPos do
|
|
begin
|
|
Inc(X, Client.Left + Offset.X);
|
|
Inc(Y, Client.Top + Offset.Y);
|
|
end;
|
|
OffsetRect(TextBounds, TextPos.X + Client.Left + Offset.X,
|
|
TextPos.Y + Client.Top + Offset.Y);
|
|
end;
|
|
|
|
function TJvButtonGlyph.Draw(Canvas: TCanvas; const Client: TRect;
|
|
const Offset: TPoint; const Caption: string; Layout: TButtonLayout;
|
|
Margin, Spacing: Integer; State: TButtonState; Transparent: Boolean): TRect;
|
|
var
|
|
GlyphPos: TPoint;
|
|
begin
|
|
CalcButtonLayout(Canvas, Client, Offset, Caption, Layout, Margin, Spacing,
|
|
GlyphPos, Result);
|
|
DrawButtonGlyph(Canvas, GlyphPos, State, Transparent);
|
|
DrawButtonText(Canvas, Caption, Result, State);
|
|
end;
|
|
|
|
function TJvButtonGlyph.DrawExternal(AGlyph: TBitmap; ANumGlyphs: TNumGlyphs; AColor: TColor; IgnoreOld: Boolean;
|
|
Canvas: TCanvas; const Client: TRect; const Offset: TPoint; const Caption: string;
|
|
Layout: TButtonLayout; Margin, Spacing: Integer; State: TButtonState; Transparent: Boolean): TRect;
|
|
var
|
|
OldGlyph: TBitmap;
|
|
OldNumGlyphs: TNumGlyphs;
|
|
OldColor: TColor;
|
|
begin
|
|
OldGlyph := FOriginal;
|
|
OldNumGlyphs := NumGlyphs;
|
|
OldColor := FColor;
|
|
try
|
|
FOriginal := AGlyph;
|
|
NumGlyphs := ANumGlyphs;
|
|
FColor := AColor;
|
|
GlyphChanged(FOriginal);
|
|
Result := Draw(Canvas, Client, Offset, Caption, Layout, Margin,
|
|
Spacing, State, Transparent);
|
|
finally
|
|
FOriginal := OldGlyph;
|
|
NumGlyphs := OldNumGlyphs;
|
|
FColor := OldColor;
|
|
if not IgnoreOld then
|
|
GlyphChanged(FOriginal);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvButtonGlyph.CalcTextRect(Canvas: TCanvas; var TextRect: TRect;
|
|
Caption: string);
|
|
begin
|
|
TextRect := Rect(0, 0, TextRect.Right - TextRect.Left, 0);
|
|
DrawText(Canvas, Caption, Length(Caption), TextRect, DT_CALCRECT);
|
|
end;
|
|
|
|
procedure TJvHTButtonGlyph.DrawButtonText(Canvas: TCanvas; const Caption: string;
|
|
TextBounds: TRect; State: TButtonState);
|
|
var
|
|
Cap: string;
|
|
begin
|
|
Cap := '<ALIGN CENTER>' + Caption; // Kaczkowski
|
|
with Canvas do
|
|
begin
|
|
Brush.Style := bsClear;
|
|
if State = bsDisabled then
|
|
begin
|
|
OffsetRect(TextBounds, 1, 1);
|
|
Font.Color := clBtnHighlight;
|
|
ItemHtDraw(Canvas, TextBounds, [], Cap);
|
|
OffsetRect(TextBounds, -1, -1);
|
|
Font.Color := clBtnShadow;
|
|
ItemHtDraw(Canvas, TextBounds, [], Cap);
|
|
end
|
|
else
|
|
ItemHtDraw(Canvas, TextBounds, [], Cap);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvHTButtonGlyph.CalcTextRect(Canvas: TCanvas; var TextRect: TRect;
|
|
Caption: string);
|
|
begin
|
|
TextRect := Rect(0, 0, ItemHtWidth(Canvas, TextRect, [], Caption),
|
|
ItemHtHeight(Canvas, Caption)); // Kaczkowski
|
|
end;
|
|
|
|
//=== { TJvaCaptionButton } ==================================================
|
|
|
|
{$IFDEF VCL}
|
|
|
|
constructor TJvaCaptionButton.Create(AOwner: TComponent);
|
|
|
|
function FindButtonPos: Integer;
|
|
var
|
|
I: Integer;
|
|
B: TComponent;
|
|
begin
|
|
Result := 4;
|
|
for I := 0 to Owner.ComponentCount - 1 do
|
|
begin
|
|
B := Owner.Components[I];
|
|
if B is TJvaCaptionButton then
|
|
Result := Max(Result, (B as TJvaCaptionButton).FBPos + 1);
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
if not (AOwner is TForm) then
|
|
raise EJVCLException.CreateResFmt(@RsEOwnerMustBeForm, [ClassName]);
|
|
inherited Create(AOwner);
|
|
|
|
FGlyph := TJvButtonGlyph.Create;
|
|
TJvButtonGlyph(FGlyph).OnChange := GlyphChanged;
|
|
FFont := TFont.Create;
|
|
FFont.OnChange := FontChange;
|
|
FBPos := FindButtonPos;
|
|
FMouseLButtonDown := False;
|
|
FPress := False;
|
|
FWidth := -1;
|
|
FMargin := -1;
|
|
FVisible := True;
|
|
WHook := TJvWindowHook.Create(nil);
|
|
WHook.BeforeMessage := DoBeforeMsg;
|
|
WHook.AfterMessage := DoAfterMsg;
|
|
WHook.Control := (Owner as TForm);
|
|
WHook.Active := True;
|
|
Resize;
|
|
end;
|
|
|
|
destructor TJvaCaptionButton.Destroy;
|
|
begin
|
|
WHook.Free;
|
|
if Owner <> nil then
|
|
RedrawWindow((Owner as TForm).Handle, PRect(0), 0, RDW_FRAME or RDW_NOINTERNALPAINT or RDW_INVALIDATE);
|
|
TJvButtonGlyph(FGlyph).Free;
|
|
FFont.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJvaCaptionButton.BorderStyle: TFormBorderStyle;
|
|
begin
|
|
if csDesigning in ComponentState then
|
|
Result := bsSizeable
|
|
else
|
|
Result := (Owner as TForm).BorderStyle;
|
|
end;
|
|
|
|
function TJvaCaptionButton.GetHeight: Integer;
|
|
begin
|
|
if BorderStyle in [bsSizeToolWin, bsToolWindow] then
|
|
Result := GetSystemMetrics(SM_CYSMSIZE)
|
|
else
|
|
Result := GetSystemMetrics(SM_CYSIZE);
|
|
end;
|
|
|
|
function TJvaCaptionButton.GetWidth: Integer;
|
|
begin
|
|
if FWidth <> -1 then
|
|
Result := FWidth
|
|
else
|
|
if BorderStyle in [bsSizeToolWin, bsToolWindow] then
|
|
Result := GetSystemMetrics(SM_CXSMSIZE)
|
|
else
|
|
Result := GetSystemMetrics(SM_CXSIZE);
|
|
end;
|
|
|
|
function TJvaCaptionButton.GetLeft: Integer;
|
|
var
|
|
F: Integer;
|
|
|
|
function FirstButtonPos: Integer;
|
|
var
|
|
I: Integer;
|
|
B: TComponent;
|
|
begin
|
|
Result := FBPos;
|
|
for I := 0 to Owner.ComponentCount - 1 do
|
|
begin
|
|
B := Owner.Components[I];
|
|
if B is TJvaCaptionButton then
|
|
Result := Min(Result, (B as TJvaCaptionButton).FBPos);
|
|
end;
|
|
end;
|
|
|
|
function RightButtonWidth: Integer;
|
|
var
|
|
I: Integer;
|
|
B: TComponent;
|
|
begin
|
|
Result := 0;
|
|
for I := 0 to Owner.ComponentCount - 1 do
|
|
begin
|
|
B := Owner.Components[I];
|
|
if (B is TJvaCaptionButton) and
|
|
((B as TJvaCaptionButton).FBPos <= FBPos) then
|
|
Inc(Result, (B as TJvaCaptionButton).GetWidth);
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
if BorderStyle in [bsSizeToolWin, bsToolWindow] then
|
|
F := GetSystemMetrics(SM_CXSMSIZE)
|
|
else
|
|
F := GetSystemMetrics(SM_CXSIZE);
|
|
Result := (Owner as TForm).Width - CalcOffset.X * 2 - F * FirstButtonPos;
|
|
Result := Result - RightButtonWidth;
|
|
// Result := 100;
|
|
end;
|
|
|
|
procedure TJvaCaptionButton.Resize;
|
|
begin
|
|
FRect := Bounds(GetLeft, 0, GetWidth, GetHeight);
|
|
RedrawWindow((Owner as TForm).Handle, PRect(0), 0, RDW_FRAME or RDW_NOINTERNALPAINT or RDW_INVALIDATE);
|
|
end;
|
|
|
|
function TJvaCaptionButton.CalcOffset: TPoint;
|
|
begin
|
|
case BorderStyle of
|
|
bsSingle:
|
|
begin
|
|
{ Result.X := GetSystemMetrics(SM_CXBORDER) + 1;
|
|
Result.Y := GetSystemMetrics(SM_CYBORDER) + 1; }
|
|
Result.X := GetSystemMetrics(SM_CXDLGFRAME);
|
|
Result.Y := GetSystemMetrics(SM_CYDLGFRAME);
|
|
end;
|
|
bsDialog:
|
|
begin
|
|
Result.X := GetSystemMetrics(SM_CXDLGFRAME) - 1 {?};
|
|
Result.Y := GetSystemMetrics(SM_CYDLGFRAME);
|
|
end;
|
|
bsSizeable:
|
|
begin
|
|
Result.X := GetSystemMetrics(SM_CXFRAME);
|
|
Result.Y := GetSystemMetrics(SM_CYFRAME);
|
|
end;
|
|
bsNone:
|
|
begin
|
|
Result.X := 0;
|
|
Result.Y := 0;
|
|
end;
|
|
bsToolWindow:
|
|
begin
|
|
Result.X := GetSystemMetrics(SM_CXDLGFRAME);
|
|
Result.Y := GetSystemMetrics(SM_CYDLGFRAME);
|
|
end;
|
|
bsSizeToolWin:
|
|
begin
|
|
Result.X := GetSystemMetrics(SM_CXFRAME);
|
|
Result.Y := GetSystemMetrics(SM_CYFRAME);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvaCaptionButton.Draw;
|
|
var
|
|
DC: HDC;
|
|
R: TRect;
|
|
Canvas: TCanvas;
|
|
Offset: TPoint;
|
|
const
|
|
CaptionColor: array [Boolean] of TColor = (clInactiveCaption, clActiveCaption);
|
|
begin
|
|
if not FVisible then
|
|
Exit;
|
|
Offset := CalcOffset;
|
|
DC := GetWindowDC((Owner as TForm).Handle);
|
|
Canvas := TCanvas.Create;
|
|
Canvas.Font := FFont;
|
|
try
|
|
SetWindowOrgEx(DC, -Offset.X, -Offset.Y, nil);
|
|
R := FRect;
|
|
Canvas.Handle := DC;
|
|
Canvas.Brush.Color := CaptionColor[FActive];
|
|
//Canvas.FillRect(R); { commented for Windows98 gradient caption compatibility }
|
|
Inc(R.Left, 2);
|
|
Inc(R.Top, 2);
|
|
Dec(R.Bottom, 2);
|
|
if FPress then
|
|
DrawThemedFrameControl(WHook.Control, DC, R, DFC_BUTTON, DFCS_BUTTONPUSH or DFCS_PUSHED)
|
|
else
|
|
DrawThemedFrameControl(WHook.Control, DC, R, DFC_BUTTON, DFCS_BUTTONPUSH);
|
|
|
|
R := Rect(R.Left + 1, R.Top + 1, R.Right - 2, R.Bottom - 2);
|
|
if FPress then
|
|
OffsetRect(R, 1, 1);
|
|
|
|
if FPress then
|
|
TJvButtonGlyph(FGlyph).Draw(Canvas, R, Point(0, 0),
|
|
FCaption, FLayout, FMargin, FSpacing, bsDown, True)
|
|
else
|
|
TJvButtonGlyph(FGlyph).Draw(Canvas, R, Point(0, 0),
|
|
FCaption, FLayout, FMargin, FSpacing, bsUp, True);
|
|
finally
|
|
Canvas.Handle := 0;
|
|
Canvas.Free;
|
|
ReleaseDC((Owner as TForm).Handle, DC);
|
|
end;
|
|
end;
|
|
|
|
(*
|
|
procedure TJvaCaptionButton.HookWndProc(var Msg: TMessage);
|
|
var
|
|
P: TPoint;
|
|
OldPress: Boolean;
|
|
begin
|
|
if Owner = nil then
|
|
Exit;
|
|
case Msg.Msg of
|
|
WM_NCACTIVATE: // after
|
|
begin
|
|
FActive := Boolean(Msg.wParam);
|
|
WHook.CallOldProc(Msg);
|
|
Draw;
|
|
end;
|
|
WM_SETTEXT, WM_NCPAINT: // after
|
|
begin
|
|
WHook.CallOldProc(Msg);
|
|
Draw;
|
|
end;
|
|
WM_SIZE: // after
|
|
begin
|
|
WHook.CallOldProc(Msg);
|
|
Resize;
|
|
end;
|
|
WM_NCLBUTTONDOWN: // before
|
|
if FVisible and
|
|
MouseOnButton(TWMNCHitMessage(Msg).XCursor, TWMNCHitMessage(Msg).YCursor) then
|
|
begin
|
|
SetCapture((Owner as TForm).Handle);
|
|
FMouseLButtonDown := True;
|
|
FPress := True;
|
|
Draw;
|
|
end
|
|
else
|
|
WHook.CallOldProc(Msg);
|
|
WM_NCLBUTTONDBLCLK: // before
|
|
if FVisible and
|
|
MouseOnButton(TWMNCHitMessage(Msg).XCursor, TWMNCHitMessage(Msg).YCursor) then
|
|
begin
|
|
{ FPress := True;
|
|
Draw;
|
|
FPress := False;
|
|
Draw;}
|
|
end
|
|
else
|
|
WHook.CallOldProc(Msg);
|
|
WM_LBUTTONUP: // before
|
|
if FVisible and FMouseLButtonDown then
|
|
begin
|
|
ReleaseCapture;
|
|
FMouseLButtonDown := False;
|
|
FPress := False;
|
|
Draw;
|
|
P := (Owner as TForm).ClientToScreen(Point(TWMNCHitMessage(Msg).XCursor, TWMNCHitMessage(Msg).YCursor));
|
|
if MouseOnButton(P.X, P.Y) then
|
|
Click;
|
|
end
|
|
else
|
|
WHook.CallOldProc(Msg);
|
|
WM_MOUSEMOVE: // before
|
|
if FMouseLButtonDown then
|
|
begin
|
|
P := (Owner as TForm).ClientToScreen(Point(TWMNCHitMessage(Msg).XCursor, TWMNCHitMessage(Msg).YCursor));
|
|
OldPress := FPress;
|
|
FPress := MouseOnButton(P.X, P.Y);
|
|
if OldPress <> FPress then
|
|
Draw;
|
|
end
|
|
else
|
|
WHook.CallOldProc(Msg);
|
|
WM_NCHITTEST: // before
|
|
if FVisible and
|
|
MouseOnButton(TWMNCHitMessage(Msg).XCursor, TWMNCHitMessage(Msg).YCursor) then
|
|
Msg.Result := HTBORDER
|
|
else
|
|
WHook.CallOldProc(Msg);
|
|
WM_NCRBUTTONDOWN: // before
|
|
{ if FVisible and
|
|
MouseOnButton(TWMNCHitMessage(Msg).XCursor, TWMNCHitMessage(Msg).YCursor) then
|
|
WHook.CallOldProc(Msg)
|
|
else} WHook.CallOldProc(Msg);
|
|
WM_SETTINGCHANGE: // after
|
|
begin
|
|
WHook.CallOldProc(Msg);
|
|
Changed;
|
|
end;
|
|
else
|
|
WHook.CallOldProc(Msg);
|
|
end;
|
|
end;
|
|
*)
|
|
|
|
procedure TJvaCaptionButton.Changed;
|
|
var
|
|
I: Integer;
|
|
B: TComponent;
|
|
begin
|
|
for I := 0 to Owner.ComponentCount - 1 do
|
|
begin
|
|
B := Owner.Components[I];
|
|
if (B is TJvaCaptionButton) then
|
|
begin
|
|
(B as TJvaCaptionButton).Resize;
|
|
(B as TJvaCaptionButton).Draw;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TJvaCaptionButton.MouseOnButton(X, Y: Integer): Boolean;
|
|
begin
|
|
with (Owner as TForm) do
|
|
Result := PtInRect(FRect, Point(X - Left - CalcOffset.X, Y - Top - CalcOffset.Y));
|
|
end;
|
|
|
|
procedure TJvaCaptionButton.Click;
|
|
begin
|
|
if csDesigning in ComponentState then
|
|
DesignerSelectComponent(Self);
|
|
if Assigned(FOnClick) then
|
|
FOnClick(Self);
|
|
end;
|
|
|
|
procedure TJvaCaptionButton.GlyphChanged(Sender: TObject);
|
|
begin
|
|
Changed;
|
|
end;
|
|
|
|
procedure TJvaCaptionButton.SetCaption(Value: string);
|
|
begin
|
|
if FCaption <> Value then
|
|
begin
|
|
FCaption := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
function TJvaCaptionButton.IsCaptionStored: Boolean;
|
|
begin
|
|
Result := FCaption <> '';
|
|
end;
|
|
|
|
procedure TJvaCaptionButton.SetFont(Value: TFont);
|
|
begin
|
|
if FFont <> Value then
|
|
begin
|
|
FFont.Assign(Value);
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvaCaptionButton.FontChange(Sender: TObject);
|
|
begin
|
|
Changed;
|
|
end;
|
|
|
|
function TJvaCaptionButton.GetGlyph: TBitmap;
|
|
begin
|
|
Result := FGlyph.Glyph;
|
|
end;
|
|
|
|
procedure TJvaCaptionButton.SetGlyph(Value: TBitmap);
|
|
begin
|
|
if FGlyph.Glyph <> Value then
|
|
begin
|
|
FGlyph.Glyph := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
function TJvaCaptionButton.GetNumGlyphs: TNumGlyphs;
|
|
begin
|
|
Result := FGlyph.NumGlyphs;
|
|
end;
|
|
|
|
procedure TJvaCaptionButton.SetNumGlyphs(Value: TNumGlyphs);
|
|
begin
|
|
if Value < 0 then
|
|
Value := 1
|
|
else
|
|
if Value > 4 then
|
|
Value := 4;
|
|
if Value <> FGlyph.NumGlyphs then
|
|
begin
|
|
FGlyph.NumGlyphs := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvaCaptionButton.SetBPos(const Value: Integer);
|
|
begin
|
|
if FBPos <> Value then
|
|
begin
|
|
FBPos := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvaCaptionButton.SetLayout(Value: TButtonLayout);
|
|
begin
|
|
if FLayout <> Value then
|
|
begin
|
|
FLayout := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvaCaptionButton.SetMargin(Value: Integer);
|
|
begin
|
|
if (Value <> FMargin) and (Value >= -1) then
|
|
begin
|
|
FMargin := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvaCaptionButton.SetSpacing(Value: Integer);
|
|
begin
|
|
if Value <> FSpacing then
|
|
begin
|
|
FSpacing := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvaCaptionButton.SetWidth(const Value: Integer);
|
|
begin
|
|
if FWidth <> Value then
|
|
begin
|
|
FWidth := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvaCaptionButton.Update;
|
|
begin
|
|
Draw;
|
|
end;
|
|
|
|
procedure TJvaCaptionButton.SetDown(const Value: Boolean);
|
|
begin
|
|
if FPress <> Value then
|
|
begin
|
|
FPress := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvaCaptionButton.SetVisible(const Value: Boolean);
|
|
begin
|
|
if FVisible <> Value then
|
|
begin
|
|
FVisible := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvaCaptionButton.DoAfterMsg(Sender: TObject; var Msg: TMessage;
|
|
var Handled: Boolean);
|
|
begin
|
|
if Owner = nil then
|
|
Exit;
|
|
case Msg.Msg of
|
|
WM_NCACTIVATE:
|
|
begin
|
|
FActive := Boolean(Msg.wParam);
|
|
Draw;
|
|
end;
|
|
WM_SETTEXT, WM_NCPAINT:
|
|
Draw;
|
|
WM_SIZE:
|
|
Resize;
|
|
WM_SETTINGCHANGE:
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvaCaptionButton.DoBeforeMsg(Sender: TObject; var Msg: TMessage;
|
|
var Handled: Boolean);
|
|
var
|
|
P: TPoint;
|
|
OldPress: Boolean;
|
|
begin
|
|
if Owner = nil then
|
|
Exit;
|
|
case Msg.Msg of
|
|
WM_NCLBUTTONDOWN:
|
|
if FVisible and
|
|
MouseOnButton(TWMNCHitMessage(Msg).XCursor, TWMNCHitMessage(Msg).YCursor) then
|
|
begin
|
|
SetCapture((Owner as TForm).Handle);
|
|
FMouseLButtonDown := True;
|
|
FPress := True;
|
|
Handled := True;
|
|
Draw;
|
|
end;
|
|
WM_NCLBUTTONDBLCLK:
|
|
if FVisible and
|
|
MouseOnButton(TWMNCHitMessage(Msg).XCursor, TWMNCHitMessage(Msg).YCursor) then
|
|
begin
|
|
{ FPress := True;
|
|
Draw;
|
|
FPress := False;
|
|
Draw;}
|
|
Handled := True;
|
|
end;
|
|
WM_LBUTTONUP:
|
|
if FVisible and FMouseLButtonDown then
|
|
begin
|
|
ReleaseCapture;
|
|
FMouseLButtonDown := False;
|
|
FPress := False;
|
|
Draw;
|
|
P := (Owner as TForm).ClientToScreen(Point(TWMNCHitMessage(Msg).XCursor, TWMNCHitMessage(Msg).YCursor));
|
|
if MouseOnButton(P.X, P.Y) then
|
|
Click;
|
|
Handled := True;
|
|
end;
|
|
WM_MOUSEMOVE:
|
|
if FMouseLButtonDown then
|
|
begin
|
|
P := (Owner as TForm).ClientToScreen(Point(TWMNCHitMessage(Msg).XCursor, TWMNCHitMessage(Msg).YCursor));
|
|
OldPress := FPress;
|
|
FPress := MouseOnButton(P.X, P.Y);
|
|
if OldPress <> FPress then
|
|
Draw;
|
|
Handled := True;
|
|
end;
|
|
WM_NCHITTEST:
|
|
if FVisible and
|
|
MouseOnButton(TWMNCHitMessage(Msg).XCursor, TWMNCHitMessage(Msg).YCursor) then
|
|
begin
|
|
Msg.Result := HTBORDER;
|
|
Handled := True;
|
|
end;
|
|
WM_NCRBUTTONDOWN:
|
|
{ if FVisible and
|
|
MouseOnButton(TWMNCHitMessage(Msg).XCursor, TWMNCHitMessage(Msg).YCursor) then
|
|
WHook.CallOldProc(Msg)
|
|
else}
|
|
;
|
|
end;
|
|
end;
|
|
|
|
{$ENDIF VCL}
|
|
|
|
//=== { TJvaColorButton } ====================================================
|
|
|
|
constructor TJvaColorButton.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FGlyphDrawer := TJvButtonGlyph.Create;
|
|
{$IFDEF VCL}
|
|
FCanvas := TControlCanvas.Create;
|
|
// (rom) destroy Canvas AFTER inherited Destroy
|
|
FCanvas.Control := Self;
|
|
{$ENDIF VCL}
|
|
{$IFDEF VisualCLX}
|
|
FCanvas := Canvas;
|
|
{$ENDIF VisualCLX}
|
|
end;
|
|
|
|
destructor TJvaColorButton.Destroy;
|
|
begin
|
|
FreeAndNil(FGlyphDrawer);
|
|
inherited Destroy;
|
|
{$IFDEF VCL}
|
|
FreeAndNil(FCanvas);
|
|
{$ENDIF VCL}
|
|
end;
|
|
|
|
{$IFDEF VCL}
|
|
|
|
function TJvaColorButton.GetCanvas: TCanvas;
|
|
begin
|
|
Result := FCanvas;
|
|
end;
|
|
|
|
procedure TJvaColorButton.SetButtonStyle(ADefault: Boolean);
|
|
begin
|
|
if ADefault <> IsFocused then
|
|
IsFocused := ADefault;
|
|
inherited SetButtonStyle(ADefault);
|
|
end;
|
|
|
|
procedure TJvaColorButton.CNDrawItem(var Msg: TWMDrawItem);
|
|
var
|
|
DrawItemStruct: TDrawItemStruct;
|
|
IsDown, IsDefault: Boolean;
|
|
State: TButtonState;
|
|
begin
|
|
if csDestroying in ComponentState then
|
|
Exit;
|
|
DrawItemStruct := Msg.DrawItemStruct^;
|
|
FCanvas.Handle := DrawItemStruct.hDC;
|
|
with DrawItemStruct do
|
|
begin
|
|
IsDown := itemState and ODS_SELECTED <> 0;
|
|
IsDefault := itemState and ODS_FOCUS <> 0;
|
|
|
|
if not Enabled then
|
|
State := bsDisabled
|
|
else
|
|
if IsDown then
|
|
State := bsDown
|
|
else
|
|
State := bsUp;
|
|
end;
|
|
|
|
if Assigned(FOnPaint) then
|
|
FOnPaint(Self, IsDown, IsDefault, State)
|
|
else
|
|
DefaultDrawing(IsDown, IsDefault, State);
|
|
|
|
FCanvas.Handle := 0;
|
|
end;
|
|
|
|
{$ENDIF VCL}
|
|
|
|
{$IFDEF VisualCLX}
|
|
procedure TJvaColorButton.Paint;
|
|
var
|
|
IsDown, IsDefault: Boolean;
|
|
State: TButtonState;
|
|
begin
|
|
if csDestroying in ComponentState then
|
|
Exit;
|
|
IsDown := Down;
|
|
IsDefault := Focused;
|
|
if not Enabled then
|
|
State := bsDisabled
|
|
else
|
|
if IsDown then
|
|
State := bsDown
|
|
else
|
|
State := bsUp;
|
|
if Assigned(FOnPaint) then
|
|
FOnPaint(Self, IsDown, IsDefault, State)
|
|
else
|
|
DefaultDrawing(IsDown, IsDefault, State);
|
|
end;
|
|
{$ENDIF VisualCLX}
|
|
|
|
procedure TJvaColorButton.DefaultDrawing(const IsDown, IsDefault: Boolean; const State: TButtonState);
|
|
var
|
|
R: TRect;
|
|
Flags: Longint;
|
|
begin
|
|
{$IFDEF VCL}
|
|
if (csDestroying in ComponentState) or (FCanvas.Handle = 0) then
|
|
Exit;
|
|
{$ENDIF VCL}
|
|
{$IFDEF VisualCLX}
|
|
if (csDestroying in ComponentState) or (FCanvas.Handle = nil) then
|
|
Exit;
|
|
{$ENDIF VisualCLX}
|
|
R := ClientRect;
|
|
Flags := DFCS_BUTTONPUSH or DFCS_ADJUSTRECT;
|
|
if IsDown then
|
|
Flags := Flags or DFCS_PUSHED;
|
|
if State = bsDisabled then
|
|
Flags := Flags or DFCS_INACTIVE;
|
|
|
|
{$IFDEF JVCLThemesEnabled}
|
|
if ThemeServices.ThemesEnabled then
|
|
begin
|
|
if IsFocused or IsDefault then
|
|
Flags := Flags or DFCS_MONO; // mis-used
|
|
if MouseOver then
|
|
Flags := Flags or DFCS_HOT;
|
|
DrawThemedFrameControl(Self, FCanvas.Handle, R, DFC_BUTTON, Flags);
|
|
end
|
|
else
|
|
{$ENDIF JVCLThemesEnabled}
|
|
begin
|
|
{ DrawFrameControl doesn't allow for drawing a button as the
|
|
default button, so it must be done here. }
|
|
if IsFocused or IsDefault then
|
|
begin
|
|
FCanvas.Pen.Color := clWindowFrame;
|
|
FCanvas.Pen.Width := 1;
|
|
FCanvas.Brush.Style := bsClear;
|
|
FCanvas.Rectangle(R.Left, R.Top, R.Right, R.Bottom);
|
|
|
|
{ DrawFrameControl must draw within this border }
|
|
InflateRect(R, -1, -1);
|
|
end;
|
|
|
|
{ DrawFrameControl does not draw a pressed button correctly }
|
|
if IsDown then
|
|
begin
|
|
FCanvas.Pen.Color := clBtnShadow;
|
|
FCanvas.Pen.Width := 1;
|
|
FCanvas.Brush.Color := Color {clBtnFace};
|
|
FCanvas.Rectangle(R.Left, R.Top, R.Right, R.Bottom);
|
|
InflateRect(R, -1, -1);
|
|
end
|
|
else
|
|
begin
|
|
DrawFrameControl(FCanvas.Handle, R, DFC_BUTTON, Flags);
|
|
FCanvas.Pen.Style := psSolid;
|
|
FCanvas.Pen.Color := Color {clBtnShadow};
|
|
FCanvas.Pen.Width := 1;
|
|
FCanvas.Brush.Color := Color;
|
|
FCanvas.Rectangle(R.Left, R.Top, R.Right, R.Bottom);
|
|
end;
|
|
end;
|
|
|
|
if IsFocused then
|
|
begin
|
|
R := ClientRect;
|
|
InflateRect(R, -1, -1);
|
|
end;
|
|
|
|
FCanvas.Font := Self.Font;
|
|
if IsDown then
|
|
OffsetRect(R, 1, 1);
|
|
|
|
FGlyphDrawer.DrawExternal(Glyph, NumGlyphs, Color, True, FCanvas, R, Point(0, 0), Caption, Layout, Margin,
|
|
Spacing, State, False {True});
|
|
|
|
{$IFDEF JVCLThemesEnabled}
|
|
if not ThemeServices.ThemesEnabled then
|
|
{$ENDIF JVCLThemesEnabled}
|
|
if IsFocused and IsDefault then
|
|
begin
|
|
R := ClientRect;
|
|
InflateRect(R, -4, -4);
|
|
FCanvas.Pen.Color := clWindowFrame;
|
|
FCanvas.Brush.Color := Color; {clBtnFace}
|
|
DrawFocusRect(FCanvas.Handle, R);
|
|
end;
|
|
end;
|
|
|
|
//=== { TJvNoFrameButton } ===================================================
|
|
|
|
constructor TJvNoFrameButton.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FGlyphDrawer := TJvButtonGlyph.Create;
|
|
FNoBorder := True;
|
|
FInitRepeatPause := 400;
|
|
FRepeatPause := 100;
|
|
end;
|
|
|
|
destructor TJvNoFrameButton.Destroy;
|
|
begin
|
|
FRepeatTimer.Free;
|
|
FGlyphDrawer.Free;
|
|
FGlyphDrawer := nil;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJvNoFrameButton.MouseDown(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer);
|
|
begin
|
|
inherited MouseDown(Button, Shift, X, Y);
|
|
if (Button = mbLeft) and Enabled and RepeatedClick then
|
|
begin
|
|
if FRepeatTimer = nil then
|
|
FRepeatTimer := TTimer.Create(Self);
|
|
FRepeatTimer.OnTimer := TimerExpired;
|
|
FRepeatTimer.Interval := InitRepeatPause;
|
|
FRepeatTimer.Enabled := True;
|
|
FClicked := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvNoFrameButton.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
var
|
|
OrgMouseUp: TMouseEvent;
|
|
begin
|
|
if FClicked then
|
|
begin
|
|
// prevent the OnClick event to trigger again
|
|
if Assigned(OnMouseUp) then
|
|
OnMouseUp(Self, Button, Shift, X, Y);
|
|
OrgMouseUp := OnMouseUp;
|
|
try
|
|
OnMouseUp := nil;
|
|
inherited MouseUp(Button, Shift, -1, -1)
|
|
finally
|
|
OnMouseUp := OrgMouseUp;
|
|
end;
|
|
end
|
|
else
|
|
inherited MouseUp(Button, Shift, X, Y);
|
|
FreeAndNil(FRepeatTimer);
|
|
end;
|
|
|
|
procedure TJvNoFrameButton.TimerExpired(Sender: TObject);
|
|
begin
|
|
FRepeatTimer.Interval := RepeatPause;
|
|
if (FState = bsDown) and Enabled and MouseCapture then
|
|
begin
|
|
try
|
|
FClicked := True;
|
|
Click;
|
|
except
|
|
FRepeatTimer.Enabled := False;
|
|
raise;
|
|
end;
|
|
end
|
|
else
|
|
FreeAndNil(FRepeatTimer);
|
|
end;
|
|
|
|
procedure TJvNoFrameButton.Paint;
|
|
begin
|
|
if not Enabled then
|
|
begin
|
|
FState := bsDisabled;
|
|
// FDragging := False;
|
|
end
|
|
else
|
|
if FState = bsDisabled then
|
|
if Down and (GroupIndex <> 0) then
|
|
FState := bsExclusive
|
|
else
|
|
FState := bsUp;
|
|
if Assigned(FOnPaint) then
|
|
FOnPaint(Self, Down, False, FState)
|
|
else
|
|
DefaultDrawing(Down, FState);
|
|
end;
|
|
|
|
procedure TJvNoFrameButton.DefaultDrawing(const IsDown: Boolean; const State: TButtonState);
|
|
const
|
|
DownStyles: array [Boolean] of Integer = (BDR_RAISEDINNER, BDR_SUNKENOUTER);
|
|
FillStyles: array [Boolean] of Integer = (BF_MIDDLE, 0);
|
|
var
|
|
PaintRect: TRect;
|
|
Offset: TPoint;
|
|
begin
|
|
if Flat and not NoBorder then
|
|
inherited Paint
|
|
else
|
|
begin
|
|
Canvas.Font := Self.Font;
|
|
PaintRect := Rect(0, 0, Width, Height);
|
|
if not NoBorder then
|
|
begin
|
|
DrawEdge(Canvas.Handle, PaintRect, DownStyles[FState in [bsDown, bsExclusive]],
|
|
FillStyles[Transparent] or BF_RECT);
|
|
InflateRect(PaintRect, -1, -1);
|
|
end;
|
|
Canvas.Brush.Style := bsSolid;
|
|
Canvas.Brush.Color := Color;
|
|
Canvas.FillRect(PaintRect);
|
|
if NoBorder and (csDesigning in ComponentState) then
|
|
DrawDesignFrame(Canvas, PaintRect);
|
|
InflateRect(PaintRect, -1, -1);
|
|
|
|
if FState in [bsDown, bsExclusive] then
|
|
begin
|
|
if (FState = bsExclusive) then
|
|
begin
|
|
if Pattern = nil then
|
|
CreateBrushPattern(clBtnFace, clBtnHighlight);
|
|
Canvas.Brush.Bitmap := Pattern;
|
|
Canvas.FillRect(PaintRect);
|
|
end;
|
|
Offset.X := 1;
|
|
Offset.Y := 1;
|
|
end
|
|
else
|
|
begin
|
|
Offset.X := 0;
|
|
Offset.Y := 0;
|
|
end;
|
|
{O}
|
|
{$IFDEF VCL}
|
|
FGlyphDrawer.BiDiMode := BiDiMode;
|
|
{$ENDIF VCL}
|
|
FGlyphDrawer.DrawExternal(Glyph, NumGlyphs, Color, True, Canvas, PaintRect, Offset, Caption, Layout, Margin,
|
|
Spacing, FState, False {True});
|
|
end;
|
|
end;
|
|
|
|
procedure TJvNoFrameButton.SetNoBorder(Value: Boolean);
|
|
begin
|
|
if FNoBorder <> Value then
|
|
begin
|
|
FNoBorder := Value;
|
|
Refresh;
|
|
end;
|
|
end;
|
|
|
|
//=== { TJvHTButton } ========================================================
|
|
|
|
constructor TJvHTButton.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FGlyphDrawer.Free;
|
|
FGlyphDrawer := TJvHTButtonGlyph.Create;
|
|
end;
|
|
|
|
destructor TJvHTButton.Destroy;
|
|
begin
|
|
TJvHTButtonGlyph(FGlyphDrawer).Free;
|
|
FGlyphDrawer := nil;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
{$IFDEF UNITVERSIONING}
|
|
initialization
|
|
RegisterUnitVersion(HInstance, UnitVersioning);
|
|
|
|
finalization
|
|
UnregisterUnitVersion(HInstance);
|
|
{$ENDIF UNITVERSIONING}
|
|
|
|
end.
|
|
|