Files
HeidiSQL/components/virtualtreeview/Source/VirtualTrees.FMX.pas

1782 lines
59 KiB
ObjectPascal

unit VirtualTrees.FMX;
{$SCOPEDENUMS ON}
{***********************************************************}
{ Project : VirtualTrees }
{ }
{ author : Karol Bieniaszewski }
{ year : 2018 }
{ contibutors : }
{***********************************************************}
interface
uses
System.Classes
, System.UITypes
, System.Types
, System.ImageList
, System.Math.Vectors
, FMX.ImgList
, FMX.Graphics
, FMX.Controls
, FMX.Types
, FMX.StdCtrls;
//-------- type aliasing -------------------------------------------------------------------------------------------------------------------
type
TRect = System.Types.TRectF;
PRect = System.Types.PRectF;
TPoint = System.Types.TPointF;
PPoint = System.Types.PPointF;
PSize = System.Types.PSizeF;
TSize = System.Types.TSizeF;
TColor = System.UITypes.TAlphaColor;
PAnsiChar = System.MarshaledAString;
UINT = LongWord;
PUINT = ^UINT;
TCustomControl = TControl; //Alias for VCL compatibility as on FMX there is not TCustomControl
//------- color aliasing -------------------------------------------------------------------------------------------------------------------
const
clBtnFace = TAlphaColor($FFF0F0F0); //TAlphaColorRec.Gray;
clBtnText = TAlphaColorRec.Black;
clBtnHighlight = TAlphaColorRec.DkGray;
clBtnShadow = TAlphaColorRec.Darkgray;
clHighlight = TAlphaColorRec.Lightblue;
clWindow = TAlphaColorRec.White;
clWindowText = TAlphaColorRec.Black;
clHighlightText = TAlphaColorRec.White;
clWhite = TAlphaColorRec.White;
clSilver = TAlphaColorRec.Silver;
clGray = TAlphaColorRec.Gray;
clBlack = TAlphaColorRec.Black;
clGreen = TAlphaColorRec.Green;
clBlue = TAlphaColorRec.Blue;
clGrayText = TAlphaColorRec.DkGray;
clInactiveCaption = TAlphaColorRec.Darkblue; //TODO: color
clInactiveCaptionText = TAlphaColorRec.Yellow; //TODO: color
clDkGray = TAlphaColorRec.DkGray;
//------- needed for migration -------------------------------------------------------------------------------------------------------------
const
{ 3D border styles }
BDR_RAISEDOUTER = 1;
BDR_SUNKENOUTER = 2;
BDR_RAISEDINNER = 4;
BDR_SUNKENINNER = 8;
BDR_OUTER = 3;
BDR_INNER = 12;
BDR_RAISED = 5;
BDR_SUNKEN = 10;
EDGE_RAISED = (BDR_RAISEDOUTER or BDR_RAISEDINNER);
EDGE_SUNKEN = (BDR_SUNKENOUTER or BDR_SUNKENINNER);
EDGE_ETCHED = (BDR_SUNKENOUTER or BDR_RAISEDINNER);
EDGE_BUMP = (BDR_RAISEDOUTER or BDR_SUNKENINNER);
ETO_OPAQUE = 2;
ETO_CLIPPED = 4;
ETO_RTLREADING = $80;
RTLFlag: array[Boolean] of Integer = (0, ETO_RTLREADING);
{ Border flags }
BF_LEFT = 1;
BF_TOP = 2;
BF_RIGHT = 4;
BF_BOTTOM = 8;
BF_TOPLEFT = (BF_TOP or BF_LEFT);
BF_TOPRIGHT = (BF_TOP or BF_RIGHT);
BF_BOTTOMLEFT = (BF_BOTTOM or BF_LEFT);
BF_BOTTOMRIGHT = (BF_BOTTOM or BF_RIGHT);
BF_RECT = (BF_LEFT or BF_TOP or BF_RIGHT or BF_BOTTOM);
BF_MIDDLE = $800; { Fill in the middle }
BF_SOFT = $1000; { For softer buttons }
BF_ADJUST = $2000; { Calculate the space left over }
BF_FLAT = $4000; { For flat rather than 3D borders }
BF_MONO = $8000; { For monochrome borders }
{ DrawText() Format Flags }
DT_TOP = 0;
DT_LEFT = 0;
DT_CENTER = 1;
DT_RIGHT = 2;
DT_VCENTER = 4;
DT_BOTTOM = 8;
DT_WORDBREAK = $10;
DT_SINGLELINE = $20;
DT_EXPANDTABS = $40;
DT_TABSTOP = $80;
DT_NOCLIP = $100;
DT_EXTERNALLEADING = $200;
DT_CALCRECT = $400;
DT_NOPREFIX = $800;
DT_INTERNAL = $1000;
DT_EDITCONTROL = $2000;
DT_PATH_ELLIPSIS = $4000;
DT_END_ELLIPSIS = $8000;
DT_MODIFYSTRING = $10000;
DT_RTLREADING = $20000;
DT_WORD_ELLIPSIS = $40000;
DT_NOFULLWIDTHCHARBREAK = $0080000;
DT_HIDEPREFIX = $00100000;
DT_PREFIXONLY = $00200000;
MAXDWORD = DWORD($FFFFFFFF);
WHEEL_DELTA = 120; { Value for rolling one detent }
WHEEL_PAGESCROLL = MAXDWORD; { Scroll one page }
{ WM_SIZE message wParam values }
SIZE_RESTORED = 0;
SIZE_MINIMIZED = 1;
SIZE_MAXIMIZED = 2;
SIZE_MAXSHOW = 3;
SIZE_MAXHIDE = 4;
{ Scroll Bar Constants }
SB_HORZ = 0;
SB_VERT = 1;
SB_CTL = 2;
SB_BOTH = 3;
SIF_RANGE = 1;
SIF_PAGE = 2;
SIF_POS = 4;
SIF_DISABLENOSCROLL = 8;
SIF_TRACKPOS = $10;
SIF_ALL = (SIF_RANGE or SIF_PAGE or SIF_POS or SIF_TRACKPOS);
{ Scroll Bar Commands }
SB_LINEUP = 0;
SB_LINELEFT = 0;
SB_LINEDOWN = 1;
SB_LINERIGHT = 1;
SB_PAGEUP = 2;
SB_PAGELEFT = 2;
SB_PAGEDOWN = 3;
SB_PAGERIGHT = 3;
SB_THUMBPOSITION = 4;
SB_THUMBTRACK = 5;
SB_TOP = 6;
SB_LEFT = 6;
SB_BOTTOM = 7;
SB_RIGHT = 7;
SB_ENDSCROLL = 8;
{ RedrawWindow() flags }
RDW_INVALIDATE = 1;
RDW_INTERNALPAINT = 2;
RDW_ERASE = 4;
RDW_VALIDATE = 8;
RDW_NOINTERNALPAINT = $10;
RDW_NOERASE = $20;
RDW_NOCHILDREN = $40;
RDW_ALLCHILDREN = $80;
RDW_UPDATENOW = $100;
RDW_ERASENOW = $200;
RDW_FRAME = $400;
RDW_NOFRAME = $800;
{ GetSystemMetrics() codes }
SM_CXVSCROLL = 2;
SM_CYHSCROLL = 3;
var
// Clipboard format IDs used in OLE drag'n drop and clipboard transfers.
CF_VIRTUALTREE,
CF_VTREFERENCE, // A reference to a virtual tree
CF_VTHEADERREFERENCE, // drapg and drop of column headers
CF_VRTF,
CF_VRTFNOOBJS, // Unfortunately CF_RTF* is already defined as being
// registration strings so I have to use different identifiers.
CF_HTML,
CF_CSV: Word;
type
tagSCROLLINFO = record
cbSize: UINT;
fMask: UINT;
nMin: Single;
nMax: Single;
nPage: Single;
nPos: Single;
nTrackPos: Single;
end;
PScrollInfo = ^TScrollInfo;
TScrollInfo = tagSCROLLINFO;
SCROLLINFO = tagSCROLLINFO;
TBorderWidth = Single;
TBevelCut = (bvNone, bvLowered, bvRaised, bvSpace);
TBevelEdge = (beLeft, beTop, beRight, beBottom);
TBevelEdges = set of TBevelEdge;
TBevelKind = (bkNone, bkTile, bkSoft, bkFlat);
TBevelWidth = 1..MaxInt;
TFormBorderStyle = (bsNone, bsSingle, bsSizeable, bsDialog, bsToolWindow, bsSizeToolWin);
TBorderStyle = TFormBorderStyle.bsNone..TFormBorderStyle.bsSingle;
TChangeLink = class(TImageLink)
private
function GetSender: TCustomImageList; inline;
procedure SetSender(const Value: TCustomImageList); inline;
public
constructor Create; override;
property Sender: TCustomImageList read GetSender write SetSender;
end;
INT_PTR = Integer; //do not change on Int64 //System.IntPtr; // NativeInt;
{$EXTERNALSYM INT_PTR}
UINT_PTR = Cardinal; //do not change on Int64 //System.UIntPtr; // NativeUInt;
WPARAM = UINT_PTR;
LPARAM = INT_PTR;
LRESULT = INT_PTR;
TDWordFiller = record
{$IFDEF CPUX64}
Filler: array[1..4] of Byte; // Pad DWORD to make it 8 bytes (4+4) [x64 only]
{$ENDIF}
end;
//--------- Windows messages simulations ---------------------------------------------------------------------------------------------------
const
WM_APP = $8000;
WM_MOUSEFIRST = $0200;
WM_MOUSEMOVE = $0200;
WM_LBUTTONDOWN = $0201;
WM_LBUTTONUP = $0202;
WM_LBUTTONDBLCLK = $0203;
WM_RBUTTONDOWN = $0204;
WM_RBUTTONUP = $0205;
WM_RBUTTONDBLCLK = $0206;
WM_MBUTTONDOWN = $0207;
WM_MBUTTONUP = $0208;
WM_MBUTTONDBLCLK = $0209;
WM_MOUSEWHEEL = $020A;
WM_SIZE = $0005;
WM_NCMBUTTONDOWN = $00A7;
WM_NCMBUTTONUP = $00A8;
WM_NCMBUTTONDBLCLK = $00A9;
WM_NCLBUTTONDBLCLK = $00A3;
WM_NCRBUTTONDOWN = $00A4;
WM_NCRBUTTONUP = $00A5;
WM_NCRBUTTONDBLCLK = $00A6;
WM_NCLBUTTONDOWN = $00A1;
WM_NCLBUTTONUP = $00A2;
WM_NCMOUSEMOVE = $00A0;
WM_KEYDOWN = $0100;
WM_KEYUP = $0101;
WM_SETFOCUS = $0007;
WM_KILLFOCUS = $0008;
WM_SETCURSOR = $0020;
WM_HSCROLL = $0114;
WM_VSCROLL = $0115;
WM_CHANGESTATE = WM_APP + 32;
CM_BASE = $B000;
{$IF DEFINED(CLR)}
CM_CLROFFSET = $100;
{$ELSE}
CM_CLROFFSET = $0; // Only applicable in CLR
{$ENDIF}
CM_ACTIVATE = CM_BASE + 0;
CM_DEACTIVATE = CM_BASE + 1;
CM_GOTFOCUS = CM_BASE + 2;
CM_LOSTFOCUS = CM_BASE + 3;
CM_CANCELMODE = CM_BASE + CM_CLROFFSET + 4;
CM_DIALOGKEY = CM_BASE + 5;
CM_DIALOGCHAR = CM_BASE + 6;
{$IF NOT DEFINED(CLR)}
CM_FOCUSCHANGED = CM_BASE + 7;
{$ENDIF}
CM_PARENTFONTCHANGED = CM_BASE + CM_CLROFFSET + 8;
CM_PARENTCOLORCHANGED = CM_BASE + 9;
CM_BIDIMODECHANGED = CM_BASE + 60;
CM_PARENTBIDIMODECHANGED = CM_BASE + 61;
CM_MOUSEWHEEL = CM_BASE + 67;
VK_ESCAPE = 27;
type
PMessage = ^TMessage;
TMessage = record
Msg: Cardinal; //4
tmp: Integer; //4
case Integer of
0: (
WParam: WPARAM; //4
LParam: LPARAM; //4
Result: LRESULT //4
); //= 12 + 4 = 16
1: (
WParamLo: Word; //2
WParamHi: Word; //2
//WParamFiller: TDWordFiller;
LParamLo: Word; //2
LParamHi: Word; //2
//LParamFiller: TDWordFiller;
ResultLo: Word; //2
ResultHi: Word; //2
//=12 + 8 = 20
);
end;
TWMMouse = record
Msg: Cardinal; //4
Keys: Longint; //TShiftState; //4
//KeysFiller: TDWordFiller;
case Integer of
0: (
XPos: Single; //4
YPos: Single; //4
Result: LRESULT; //4
);
1: (
Pos: TPoint; //8
ResultLo: Word; //2
ResultHi: Word; //2
); //=12 + 8=20
end;
TWMMouseMove = TWMMouse;
TWMNCHitTest = record
Msg: Cardinal;
//MsgFiller: TDWordFiller;
Unused: WPARAM;
case Integer of
0: (
XPos: Single;
YPos: Single;
//XYPosFiller: TDWordFiller
);
1: (
Pos: TPoint;
//PosFiller: TDWordFiller;
Result: LRESULT);
end;
TWMNCHitMessage = record
Msg: Cardinal; //4
//MsgFiller: TDWordFiller;
HitTest: Longint; //4
//HitTestFiller: TDWordFiller;
XCursor: Single; //4
YCursor: Single; //4
//XYCursorFiller: TDWordFiller;
Result: LRESULT; //4
end; //=20
TWMNCLButtonDblClk = TWMNCHitMessage;
TWMNCLButtonDown = TWMNCHitMessage;
TWMNCLButtonUp = TWMNCHitMessage;
TWMNCMButtonDblClk = TWMNCHitMessage;
TWMNCMButtonDown = TWMNCHitMessage;
TWMNCMButtonUp = TWMNCHitMessage;
TWMNCMouseMove = TWMNCHitMessage;
TWMNCRButtonDblClk = TWMNCHitMessage;
TWMNCRButtonDown = TWMNCHitMessage;
TWMNCRButtonUp = TWMNCHitMessage;
TWMLButtonDblClk = TWMMouse;
TWMLButtonDown = TWMMouse;
TWMLButtonUp = TWMMouse;
TWMMButtonDblClk = TWMMouse;
TWMMButtonDown = TWMMouse;
TWMMButtonUp = TWMMouse;
TWMKey = record
Msg: Cardinal; //4
tmp: Integer; //4
CharCode: Word; //4
//Unused: Word; //2
KeyData: Longint; //4
Result: LRESULT; //4
end; //=20
TWMKeyDown = TWMKey;
TWMKeyUp = TWMKey;
TWMSize = record
Msg: Cardinal; //4
//MsgFiller: TDWordFiller;
SizeType: WPARAM; { SIZE_MAXIMIZED, SIZE_MINIMIZED, SIZE_RESTORED, //4
SIZE_MAXHIDE, SIZE_MAXSHOW }
Width: Single; //4
Height: Single; //4
//WidthHeightFiller: TDWordFiller;
Result: LRESULT; //4
end; //=20
TWMScroll = record
Msg: Cardinal; //4
//MsgFiller: TDWordFiller;
ScrollCode: {Smallint}Integer; { SB_xxxx } //4
Pos: Single; //4
//ScrollCodePosFiller: TDWordFiller;
ScrollBar: Integer; //4 nBar
Result: LRESULT; //4
end; //=20
TWMHScroll = TWMScroll;
TWMVScroll = TWMScroll;
TCMMouseWheel = record
Msg: Cardinal; //4
//MsgFiller: TDWordFiller;
ShiftState: TShiftState; //2
WheelDelta: SmallInt; //2
//ShiftStateWheel: TDWordFiller;
case Integer of
0: (
XPos: Single; //4
YPos: Single; //4
//XYPos: TDWordFiller
); //=24!
1: (
Pos: TPoint; //8
//PosFiller: TDWordFiller;
Result: LRESULT //4
); //=28!
end;
procedure FillTWMMouse(Var MM: TWMMouse; Button: TMouseButton; Shift: TShiftState; X: Single; Y: Single; IsNC: Boolean; IsUp: Boolean);
//--------- Text metrics -------------------------------------------------------------------------------------------------------------------
type
TTextMetric = record
tmHeight: Single; //The height (ascent + descent) of characters.
tmAscent: Single; //The ascent (units above the base line) of characters.
tmDescent: Single; //The descent (units below the base line) of characters.
tmInternalLeading: Single; //The amount of leading (space) inside the bounds set by the tmHeight member. Accent marks and other diacritical characters may occur in this area. The designer may set this member to zero
tmExternalLeading: Single; //The amount of extra leading (space) that the application adds between rows. Since this area is outside the font, it contains no marks and is not altered by text output calls in either OPAQUE or TRANSPARENT mode. The designer may set this member to zero.
tmAveCharWidth: Single; //The average width of characters in the font (generally defined as the width of the letter x ). This value does not include the overhang required for bold or italic characters.
tmMaxCharWidth: Single; //The width of the widest character in the font.
tmWeight: Single; //The weight of the font.
tmOverhang: Single;
tmDigitizedAspectX: Single; //The horizontal aspect of the device for which the font was designed.
tmDigitizedAspectY: Single; //The vertical aspect of the device for which the font was designed. The ratio of the tmDigitizedAspectX and tmDigitizedAspectY members is the aspect ratio of the device for which the font was designed.
tmFirstChar: WideChar; //The value of the first character defined in the font.
tmLastChar: WideChar; //The value of the last character defined in the font.
tmDefaultChar: WideChar; //The value of the character to be substituted for characters not in the font.
tmBreakChar: WideChar; //The value of the character that will be used to define word breaks for text justification.
tmItalic: Byte; //Specifies an italic font if it is nonzero.
tmUnderlined: Byte; //Specifies an underlined font if it is nonzero.
tmStruckOut: Byte; //A strikeout font if it is nonzero.
tmPitchAndFamily: Byte; //Specifies information about the pitch, the technology, and the family of a physical font. TMPF_FIXED_PITCH, TMPF_VECTOR, TMPF_TRUETYPE, TMPF_DEVICE
tmCharSet: Byte; //The character set of the font. The character set can be one of the following values. ANSI_CHARSET, GREEK_CHARSET....
end;
procedure GetTextMetrics(ACanvas: TCanvas; var TM: TTextMetric);
//-------- function aliassing --------------------------------------------------------------------------------------------------------------
function Rect(ALeft, ATop, ARight, ABottom: Single): TRect; overload; inline;
function Rect(const ATopLeft, ABottomRight: TPoint): TRect; overload; inline;
function Point(AX, AY: Single): TPoint; overload; inline;
procedure Inc(Var V: Single; OIle: Single=1.0); overload;
procedure Dec(Var V: Single; OIle: Single=1.0); overload;
function MulDiv(const A, B, C: Single): Single; overload;
procedure FillMemory(Destination: Pointer; Length: NativeUInt; Fill: Byte);
procedure ZeroMemory(Destination: Pointer; Length: NativeUInt);
procedure MoveMemory(Destination: Pointer; Source: Pointer; Length: NativeUInt);
procedure CopyMemory(Destination: Pointer; Source: Pointer; Length: NativeUInt);
procedure DrawTextW(ACanvas: TCanvas; CaptionText: String; Len: Integer; Var Bounds: TRect; DrawFormat: Cardinal{this is windows format - must be converted to FMX});
procedure GetTextExtentPoint32W(ACanvas: TCanvas; CaptionText: String; Len: Integer; Var Size: TSize);
procedure DrawEdge(Canvas: TCanvas; R: TRect; edge, grfFlags: Cardinal);
type
THighQualityBitmap = class(TBitmap)
public
constructor Create; override;
end;
//fill system images
procedure FillSystemCheckImages(Parent: TFmxObject; List: TImageList);
type
TCanvasHelper = class helper for TCanvas
private
function GetBrush: TBrush; inline;
function GetPen: TStrokeBrush; inline;
public
property Brush: TBrush read GetBrush;
property Pen: TStrokeBrush read GetPen;
procedure FillRect(const ARect: TRectF); overload; inline;
procedure DrawRect(const ARect: TRectF); overload; inline;
procedure DrawFocusRect(const AFocusRect: TRect);
procedure FrameRect(const AFocusRect: TRect);
procedure RoundRect(X1, Y1, X2, Y2: Single; const XRadius, YRadius: Single); overload;
procedure RoundRect(const Rect: TRect; const XRadius, YRadius: Single); overload;
procedure Polygon(const Points: TPolygon);
procedure Draw(const X, Y: Single; const Bitmap: TBitmap);
end;
TFontHelper = class helper for TFont
private
function GetOnChange: TNotifyEvent;
procedure SetOnChange(const Value: TNotifyEvent);
public
property OnChange: TNotifyEvent read GetOnChange write SetOnChange;
end;
{ Draws a solid triangular arrow that can point in any TScrollDirection }
type
TScrollDirection = (sdLeft, sdRight, sdUp, sdDown);
TArrowType = (atSolid, atArrows);
procedure DrawArrow(ACanvas: TCanvas; Direction: TScrollDirection; Location: TPoint; Size: Single);
procedure ChangeBiDiModeAlignment(var Alignment: TAlignment);
procedure OleUninitialize();
function timeGetTime: Int64;
implementation
uses
System.SysUtils
, FMX.TextLayout
, FMX.MultiResBitmap
, FMX.Objects
, FMX.Effects
, VirtualTrees.Utils
;
//----------------------------------------------------------------------------------------------------------------------
procedure DrawArrow(ACanvas: TCanvas; Direction: TScrollDirection; Location: TPoint; Size: Single);
begin
//TODO: DrawArrow implementation
end;
//----------------------------------------------------------------------------------------------------------------------
{ TCanvasHelper }
procedure TCanvasHelper.Draw(const X, Y: Single; const Bitmap: TBitmap);
begin
DrawBitmap(Bitmap
, Rect(0, 0, Bitmap.Width, Bitmap.Height)
, Rect(X, Y, X+Bitmap.Width, Y+ Bitmap.Height)
, 1.0
);
end;
//----------------------------------------------------------------------------------------------------------------------
procedure TCanvasHelper.DrawFocusRect(const AFocusRect: TRect);
begin
DrawDashRect(AFocusRect, 0, 0, AllCorners, 1.0{?}, $A0909090);
end;
//----------------------------------------------------------------------------------------------------------------------
procedure TCanvasHelper.DrawRect(const ARect: TRectF);
begin
DrawRect(ARect, 0, 0, [], 1.0);
end;
//----------------------------------------------------------------------------------------------------------------------
procedure TCanvasHelper.FillRect(const ARect: TRectF);
begin
FillRect(ARect, 0, 0, [], 1.0);
end;
//----------------------------------------------------------------------------------------------------------------------
procedure TCanvasHelper.FrameRect(const AFocusRect: TRect);
begin
DrawRect(AFocusRect);
end;
//----------------------------------------------------------------------------------------------------------------------
function TCanvasHelper.GetBrush: TBrush;
begin
Result:= Fill;
end;
//----------------------------------------------------------------------------------------------------------------------
function TCanvasHelper.GetPen: TStrokeBrush;
begin
Result:= Stroke;
end;
//----------------------------------------------------------------------------------------------------------------------
procedure TCanvasHelper.Polygon(const Points: TPolygon);
begin
DrawPolygon(Points, 1.0);
end;
//----------------------------------------------------------------------------------------------------------------------
procedure TCanvasHelper.RoundRect(const Rect: TRect; const XRadius, YRadius: Single);
begin
DrawRect(Rect, XRadius, YRadius, allCorners, 1.0);
end;
//----------------------------------------------------------------------------------------------------------------------
procedure TCanvasHelper.RoundRect(X1, Y1, X2, Y2: Single; const XRadius, YRadius: Single);
begin
RoundRect(Rect(X1, Y1, X2, Y2), XRadius, YRadius);
end;
//----------------------------------------------------------------------------------------------------------------------
type
TImageListHelper = class helper for TImageList
function Add(aBitmap: TBitmap): integer;
end;
function TImageListHelper.Add(aBitmap: TBitmap): integer;
const
SCALE = 1;
var
vSource: TCustomSourceItem;
vBitmapItem: TCustomBitmapItem;
vDest: TCustomDestinationItem;
vLayer: TLayer;
begin
Result := -1;
if (aBitmap.Width = 0) or (aBitmap.Height = 0) then exit;
// add source bitmap
vSource := Source.Add;
vSource.MultiResBitmap.TransparentColor := TColorRec.Fuchsia;
vSource.MultiResBitmap.SizeKind := TSizeKind.Source;
vSource.MultiResBitmap.Width := Round(aBitmap.Width / SCALE);
vSource.MultiResBitmap.Height := Round(aBitmap.Height / SCALE);
vBitmapItem := vSource.MultiResBitmap.ItemByScale(SCALE, True, True);
if vBitmapItem = nil then
begin
vBitmapItem := vSource.MultiResBitmap.Add;
vBitmapItem.Scale := Scale;
end;
vBitmapItem.Bitmap.Assign(aBitmap);
vDest := Destination.Add;
vLayer := vDest.Layers.Add;
vLayer.SourceRect.Rect := TRectF.Create(TPoint.Zero, vSource.MultiResBitmap.Width,
vSource.MultiResBitmap.Height);
vLayer.Name := vSource.Name;
Result := vDest.Index;
end;
//----------------------------------------------------------------------------------------------------------------------
//https://stackoverflow.com/questions/22813461/is-there-an-equivalent-to-floodfill-in-fmx-for-a-tbitmap
procedure Bitmap_FloodFill(fBitmap: TBitmap; StartX,StartY : Integer; FillColor: TAlphaColor);
var
fBitmapData : TBitmapData;
X, Y : Integer;
ReplaceColor : TAlphaColor;
Stack : Array of System.Types.TPoint;
fHeight : Integer;
fWidth : Integer;
procedure PutInStack(X, Y: Integer);
begin
SetLength(Stack, Length(Stack)+1);
Stack[Length(Stack)-1] := Point(X, Y);
end;
procedure GetFromStack(var X, Y: Integer);
begin
X := Stack[Length(Stack)-1].X;
Y := Stack[Length(Stack)-1].Y;
SetLength(Stack, Length(Stack)-1);
end;
begin
X := StartX;
Y := StartY;
fHeight := fBitmap.Height;
fWidth := fBitmap.Width;
if (X >= fWidth) or (Y >= fHeight) then Exit;
if fBitmap.Map(TMapAccess.ReadWrite,fBitmapData) then
try
ReplaceColor := fBitmapData.GetPixel(X,Y);
if ReplaceColor <> FillColor then
begin
PutInStack(X,Y);
while Length(Stack) > 0 do
begin
GetFromStack(X,Y);
while (X > 0) and (fBitmapData.GetPixel(X-1, Y) = ReplaceColor) do System.Dec(X);
while (X < fWidth) and (fBitmapData.GetPixel(X , Y) = ReplaceColor) do
begin
if Y > 0 then If fBitmapData.GetPixel(X, Y-1) = ReplaceColor then PutInStack(X, Y-1);
if Y+1 < fHeight then If fBitmapData.GetPixel(X, Y+1) = ReplaceColor then PutInStack(X, Y+1);
fBitmapData.SetPixel(X,Y,FillColor);
System.Inc(X);
end;
end;
end;
finally
fBitmap.Canvas.Bitmap.Unmap(fBitmapData);
end;
end;
//----------------------------------------------------------------------------------------------------------------------
{
ckEmpty = 0; // an empty image used as place holder
// radio buttons
ckRadioUncheckedNormal = 1;
ckRadioUncheckedHot = 2;
ckRadioUncheckedPressed = 3;
ckRadioUncheckedDisabled = 4;
ckRadioCheckedNormal = 5;
ckRadioCheckedHot = 6;
ckRadioCheckedPressed = 7;
ckRadioCheckedDisabled = 8;
// check boxes
ckCheckUncheckedNormal = 9;
ckCheckUncheckedHot = 10;
ckCheckUncheckedPressed = 11;
ckCheckUncheckedDisabled = 12;
ckCheckCheckedNormal = 13;
ckCheckCheckedHot = 14;
ckCheckCheckedPressed = 15;
ckCheckCheckedDisabled = 16;
ckCheckMixedNormal = 17;
ckCheckMixedHot = 18;
ckCheckMixedPressed = 19;
ckCheckMixedDisabled = 20;
// simple button
ckButtonNormal = 21; //???
ckButtonHot = 22; //???
ckButtonPressed = 23; //???
ckButtonDisabled = 24; //???
}
procedure FillSystemCheckImages(Parent: TFmxObject; List: TImageList);
Var cb: TCheckBox;
rb: TRadioButton;
BMP: TBitmap;
eff: TInnerGlowEffect;
procedure AddCtrlBmp(c: TControl);
Var tmpBMP: TBitmap;
begin
tmpBMP:= c.MakeScreenshot;
try
BMP.SetSize(tmpBMP.Height, tmpBMP.Height);
BMP.Clear(TAlphaColorRec.Null); //this somehow can sometimes clear BeginSceneCount and must be before BeginScene
if BMP.Canvas.BeginScene() then
begin
try
BMP.Canvas.DrawBitmap(
tmpBMP
, Rect(2, 2, BMP.Width, BMP.Height)
, Rect(0, 0, BMP.Width-2, BMP.Height-2)
, 1.0
, false
);
finally
BMP.Canvas.EndScene;
end;
end;
finally
FreeAndNil(tmpBMP);
end;
end;
begin
BMP:= TBitmap.Create;
try
BMP.SetSize(16, 16);
BMP.Clear(TAlphaColorRec.Null);
List.Add(BMP); //ckEmpty
rb:= TRadioButton.Create(Parent);
try
rb.Parent:= Parent;
rb.Text:= ' ';
eff:= TInnerGlowEffect.Create(rb); //auto free
eff.Parent:= rb;
eff.GlowColor:= TAlphaColorRec.Teal;
eff.Softness:= 8;
eff.Opacity:= 0.7;
eff.Enabled:= false;
//------------------IsUnChecked--------------------------
rb.IsChecked:= false;
eff.Enabled:= false;
AddCtrlBmp(rb);
List.Add(BMP); //ckRadioUncheckedNormal
eff.Enabled:= false;
AddCtrlBmp(rb);
eff.Enabled:= true;
eff.GlowColor:= TAlphaColorRec.Lightyellow;
List.Add(BMP); //ckRadioUncheckedHot
eff.Enabled:= false;
eff.Enabled:= true;
eff.GlowColor:= TAlphaColorRec.Lightblue;
AddCtrlBmp(rb);
List.Add(BMP); //ckRadioUncheckedPressed
eff.Enabled:= false;
rb.Enabled:= false;
eff.Enabled:= true;
eff.GlowColor:= TAlphaColorRec.Gray;
AddCtrlBmp(rb);
List.Add(BMP); //ckRadioUncheckedDisabled
eff.Enabled:= false;
//------------------IsChecked---------------------------
rb.IsChecked:= true;
//rb.IsPressed:= false;
rb.Enabled:= true;
eff.Enabled:= false;
AddCtrlBmp(rb);
List.Add(BMP); //ckRadioCheckedNormal
eff.Enabled:= false;
eff.Enabled:= true;
eff.GlowColor:= TAlphaColorRec.Lightyellow;
AddCtrlBmp(rb);
List.Add(BMP); //ckRadioCheckedHot
eff.Enabled:= false;
rb.Enabled:= true;
eff.Enabled:= true;
eff.GlowColor:= TAlphaColorRec.Lightblue;
AddCtrlBmp(rb);
List.Add(BMP); //ckRadioCheckedPressed
eff.Enabled:= false;
rb.Enabled:= false;
eff.Enabled:= true;
eff.GlowColor:= TAlphaColorRec.Gray;
AddCtrlBmp(rb);
List.Add(BMP); //ckRadioCheckedDisabled
eff.Enabled:= false;
finally
FreeAndNil(rb);
end;
cb:= TCheckBox.Create(Parent);
try
cb.Parent:= Parent;
cb.Text:= ' ';
eff:= TInnerGlowEffect.Create(cb); //auto free
eff.Parent:= cb;
eff.GlowColor:= TAlphaColorRec.Teal;
eff.Softness:= 8;
eff.Opacity:= 0.7;
eff.Enabled:= false;
//------------------IsUnChecked--------------------------
cb.IsChecked:= false;
eff.Enabled:= false;
AddCtrlBmp(cb);
List.Add(BMP); //ckCheckUncheckedNormal
eff.Enabled:= false;
eff.Enabled:= true;
eff.GlowColor:= TAlphaColorRec.Lightyellow;
AddCtrlBmp(cb);
List.Add(BMP); //ckCheckUncheckedHot
eff.Enabled:= false;
//cb.IsPressed:= true;
eff.Enabled:= true;
eff.GlowColor:= TAlphaColorRec.Lightblue;
AddCtrlBmp(cb);
List.Add(BMP); //ckCheckUncheckedPressed
eff.Enabled:= false;
//cb.IsPressed:= false;
cb.Enabled:= false;
eff.Enabled:= true;
eff.GlowColor:= TAlphaColorRec.Gray;
AddCtrlBmp(cb);
eff.Enabled:= false;
List.Add(BMP); //ckCheckUncheckedDisabled
//------------------IsChecked---------------------------
cb.IsChecked:= true;
cb.Enabled:= true;
eff.Enabled:= false;
AddCtrlBmp(cb);
List.Add(BMP); //ckCheckCheckedNormal
eff.Enabled:= false;
eff.Enabled:= true;
eff.GlowColor:= TAlphaColorRec.Lightyellow;
eff.Opacity:= 0.3;
AddCtrlBmp(cb);
List.Add(BMP); //ckCheckCheckedHot
eff.Opacity:= 0.7;
eff.Enabled:= false;
eff.Enabled:= false;
cb.Enabled:= true;
eff.Enabled:= true;
eff.GlowColor:= TAlphaColorRec.Lightblue;
AddCtrlBmp(cb);
List.Add(BMP); //ckCheckCheckedPressed
eff.Enabled:= false;
cb.Enabled:= false;
eff.Enabled:= true;
eff.GlowColor:= TAlphaColorRec.Gray;
AddCtrlBmp(cb);
List.Add(BMP); //ckCheckCheckedDisabled
eff.Enabled:= false;
//------------------Mixed---------------------------
//how to support mixed style?
//maybe draw unchecked and fill in the center of bitmap???
//i use ~teal for fill
//changed to InnerGlowEffect
cb.IsChecked:= true;
eff.Enabled:= true;
eff.GlowColor:= TAlphaColorRec.Green;
AddCtrlBmp(cb);
List.Add(BMP); //ckCheckMixedNormal
eff.Enabled:= false;
eff.Enabled:= true;
eff.GlowColor:= TAlphaColorRec.Lightyellow;
AddCtrlBmp(cb);
List.Add(BMP); //ckCheckMixedHot
eff.Enabled:= false;
eff.Enabled:= true;
eff.GlowColor:= TAlphaColorRec.Lightblue;
AddCtrlBmp(cb);
List.Add(BMP); //ckCheckMixedPressed
eff.Enabled:= false;
cb.Enabled:= false;
eff.Enabled:= true;
eff.GlowColor:= TAlphaColorRec.Gray;
AddCtrlBmp(cb);
List.Add(BMP); //ckCheckMixedDisabled
eff.Enabled:= false;
finally
FreeAndNil(cb);
end;
eff.Enabled:= false;
eff.Parent:= nil;
finally
FreeAndNil(BMP);
end;
end;
//----------------------------------------------------------------------------------------------------------------------
procedure FillTWMMouse(Var MM: TWMMouse; Button: TMouseButton; Shift: TShiftState; X: Single; Y: Single; IsNC: Boolean; IsUp: Boolean);
begin
MM.Msg:= 0;
if ssDouble in Shift then
begin
if ssLeft in Shift then
begin
if IsNC then
MM.Msg:= WM_NCLBUTTONDBLCLK else
MM.Msg:= WM_LBUTTONDBLCLK;
end else
if ssRight in Shift then
begin
if IsNC then
MM.Msg:= WM_NCRBUTTONDBLCLK else
MM.Msg:= WM_RBUTTONDBLCLK;
end else
if ssMiddle in Shift then
begin
if IsNC then
MM.Msg:= WM_NCMBUTTONDBLCLK else
MM.Msg:= WM_MBUTTONDBLCLK;
end;
end else
begin
if (ssLeft in Shift) or (Button=TMouseButton.mbLeft) then
begin
if IsUp then
begin
if IsNC then
MM.Msg:= WM_NCLBUTTONUP else
MM.Msg:= WM_LBUTTONUP;
end else
begin
if IsNC then
MM.Msg:= WM_NCLBUTTONDOWN else
MM.Msg:= WM_LBUTTONDOWN;
end;
end else
if (ssRight in Shift) or (Button=TMouseButton.mbRight) then
begin
if IsUp then
begin
if IsNC then
MM.Msg:= WM_NCRBUTTONUP else
MM.Msg:= WM_RBUTTONUP;
end else
begin
if IsNC then
MM.Msg:= WM_NCRBUTTONDOWN else
MM.Msg:= WM_RBUTTONDOWN;
end;
end else
if (ssMiddle in Shift) or (Button=TMouseButton.mbMiddle) then
begin
if IsUp then
begin
if IsNC then
MM.Msg:= WM_NCMBUTTONUP else
MM.Msg:= WM_MBUTTONUP;
end else
begin
if IsNC then
MM.Msg:= WM_NCMBUTTONDOWN else
MM.Msg:= WM_MBUTTONDOWN;
end;
end;
end;
MM.XPos:= X;
MM.YPos:= Y;
MM.Keys:= LongInt(Word(Shift));
end;
//----------------------------------------------------------------------------------------------------------------------
procedure DrawTextW(ACanvas: TCanvas; CaptionText: String; Len: Integer; Var Bounds: TRect; DrawFormat: Cardinal{this is windows format - must be converted to FMX});
Var
hAlign: TTextAlign;
vAlign: TTextAlign;
Flags: TFillTextFlags;
begin
//TTextLayout. render
//TODO: DrawFormat: Cardinal{this is windows format - must be converted to FMX}
hAlign:= TTextAlign.Leading;
if DrawFormat and DT_CENTER<>0 then
hAlign:= TTextAlign.Center;
if DrawFormat and DT_RIGHT<>0 then
hAlign:= TTextAlign.Trailing;
vAlign:= TTextAlign.Center;
if DrawFormat and DT_VCENTER<>0 then
vAlign:= TTextAlign.Center;
if DrawFormat and DT_BOTTOM<>0 then
vAlign:= TTextAlign.Trailing;
Flags:= [];
if DrawFormat and DT_RTLREADING<>0 then
Flags:= Flags + [TFillTextFlag.RightToLeft];
ACanvas.FillText(Bounds, CaptionText, false, 1.0, Flags, hAlign, vAlign);
end;
//----------------------------------------------------------------------------------------------------------------------
procedure DrawEdge(Canvas: TCanvas; R: TRect; edge, grfFlags: Cardinal);
Var tmpR: TRect;
IsSoft, IsFlat, IsMono: Boolean;
begin
if grfFlags and BF_SOFT<>0 then
IsSoft:= true else
IsSoft:= false;
if grfFlags and BF_FLAT<>0 then
IsFlat:= true else
IsFlat:= false;
if grfFlags and BF_MONO<>0 then
IsMono:= true else
IsMono:= false;
if grfFlags and BF_MIDDLE<>0 then
begin
Canvas.Fill.Color:= clBtnFace;
Canvas.FillRect(R, 0, 0, [], 1.0);
end;
tmpR:= R;
if grfFlags and BF_LEFT<>0 then
begin
tmpR:= R;
if edge and BDR_RAISEDOUTER<>0 then
begin
if isSoft then
begin
Canvas.Stroke.Color:= TColors.White;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Left, tmpR.Bottom), 1.0);
end else
if IsFlat then
begin
Canvas.Stroke.Color:= $FFA0A0A0;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Left, tmpR.Bottom), 1.0);
end else
if isMono then
begin
Canvas.Stroke.Color:= $FF646464;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Left, tmpR.Bottom), 1.0);
end else
begin
Canvas.Stroke.Color:= $FFE3E3E3;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Left, tmpR.Bottom), 1.0);
end;
InflateRect(tmpR, -1, -1)
end;
if edge and BDR_SUNKENOUTER<>0 then
begin
if isSoft then
begin
Canvas.Stroke.Color:= $FF696969;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Left, tmpR.Bottom), 1.0);
end else
if IsFlat then
begin
Canvas.Stroke.Color:= $FFA0A0A0;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Left, tmpR.Bottom), 1.0);
end else
if isMono then
begin
Canvas.Stroke.Color:= $FF646464;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Left, tmpR.Bottom), 1.0);
end else
begin
Canvas.Stroke.Color:= $FFA0A0A0;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Left, tmpR.Bottom), 1.0);
end;
InflateRect(tmpR, -1, -1)
end;
if edge and BDR_RAISEDINNER<>0 then
begin
if isSoft then
begin
Canvas.Stroke.Color:= $FFE3E3E3;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Left, tmpR.Bottom), 1.0);
end else
if IsFlat then
begin
Canvas.Stroke.Color:= $FFF0F0F0;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Left, tmpR.Bottom), 1.0);
end else
if isMono then
begin
Canvas.Stroke.Color:= TAlphaColorRec.White;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Left, tmpR.Bottom), 1.0);
end else
begin
Canvas.Stroke.Color:= TAlphaColorRec.White;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Left, tmpR.Bottom), 1.0);
end;
end;
if edge and BDR_SUNKENINNER<>0 then
begin
if isSoft then
begin
Canvas.Stroke.Color:= $FFA0A0A0;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Left, tmpR.Bottom), 1.0);
end else
if IsFlat then
begin
Canvas.Stroke.Color:= $FFF0F0F0;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Left, tmpR.Bottom), 1.0);
end else
if isMono then
begin
Canvas.Stroke.Color:= TAlphaColorRec.White;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Left, tmpR.Bottom), 1.0);
end else
begin
Canvas.Stroke.Color:= $FF696969;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Left, tmpR.Bottom), 1.0);
end;
end;
end;
if grfFlags and BF_TOP<>0 then
begin
tmpR:= R;
if edge and BDR_RAISEDOUTER<>0 then
begin
if isSoft then
begin
Canvas.Stroke.Color:= TAlphaColorRec.White;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Right, tmpR.Top), 1.0);
end else
if IsFlat then
begin
Canvas.Stroke.Color:= $FFA0A0A0;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Right, tmpR.Top), 1.0);
end else
if isMono then
begin
Canvas.Stroke.Color:= $FF646464;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Right, tmpR.Top), 1.0);
end else
begin
Canvas.Stroke.Color:= $FFE3E3E3;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Right, tmpR.Top), 1.0);
end;
InflateRect(tmpR, -1, -1)
end;
if edge and BDR_SUNKENOUTER<>0 then
begin
if isSoft then
begin
Canvas.Stroke.Color:= $FF696969;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Right, tmpR.Top), 1.0);
end else
if IsFlat then
begin
Canvas.Stroke.Color:= $FFA0A0A0;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Right, tmpR.Top), 1.0);
end else
if isMono then
begin
Canvas.Stroke.Color:= $FF646464;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Right, tmpR.Top), 1.0);
end else
begin
Canvas.Stroke.Color:= $FFA0A0A0;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Right, tmpR.Top), 1.0);
end;
InflateRect(tmpR, -1, -1)
end;
if edge and BDR_RAISEDINNER<>0 then
begin
if isSoft then
begin
Canvas.Stroke.Color:= $FFE3E3E3;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Right, tmpR.Top), 1.0);
end else
if IsFlat then
begin
Canvas.Stroke.Color:= $FFF0F0F0;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Right, tmpR.Top), 1.0);
end else
if isMono then
begin
Canvas.Stroke.Color:= TAlphaColorRec.White;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Right, tmpR.Top), 1.0);
end else
begin
Canvas.Stroke.Color:= TAlphaColorRec.White;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Right, tmpR.Top), 1.0);
end;
end;
if edge and BDR_SUNKENINNER<>0 then
begin
if isSoft then
begin
Canvas.Stroke.Color:= $FFA0A0A0;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Right, tmpR.Top), 1.0);
end else
if IsFlat then
begin
Canvas.Stroke.Color:= $FFF0F0F0;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Right, tmpR.Top), 1.0);
end else
if isMono then
begin
Canvas.Stroke.Color:= TAlphaColorRec.White;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Right, tmpR.Top), 1.0);
end else
begin
Canvas.Stroke.Color:= $FF696969;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Top), Point(tmpR.Right, tmpR.Top), 1.0);
end;
end;
end;
if grfFlags and BF_RIGHT<>0 then
begin
tmpR:= R;
if edge and BDR_RAISEDOUTER<>0 then
begin
if isSoft then
begin
Canvas.Stroke.Color:= $FF696969;
Canvas.DrawLine(Point(tmpR.Right-1, tmpR.Top), Point(tmpR.Right-1, tmpR.Bottom), 1.0);
end else
if IsFlat then
begin
Canvas.Stroke.Color:= $FFA0A0A0;
Canvas.DrawLine(Point(tmpR.Right-1, tmpR.Top), Point(tmpR.Right-1, tmpR.Bottom), 1.0);
end else
if isMono then
begin
Canvas.Stroke.Color:= $FF646464;
Canvas.DrawLine(Point(tmpR.Right-1, tmpR.Top), Point(tmpR.Right-1, tmpR.Bottom), 1.0);
end else
begin
Canvas.Stroke.Color:= $FF696969;
Canvas.DrawLine(Point(tmpR.Right-1, tmpR.Top), Point(tmpR.Right-1, tmpR.Bottom), 1.0);
end;
InflateRect(tmpR, -1, -1)
end;
if edge and BDR_SUNKENOUTER<>0 then
begin
if isSoft then
begin
Canvas.Stroke.Color:= TAlphaColorRec.White;
Canvas.DrawLine(Point(tmpR.Right-1, tmpR.Top), Point(tmpR.Right-1, tmpR.Bottom), 1.0);
end else
if IsFlat then
begin
Canvas.Stroke.Color:= $FFA0A0A0;
Canvas.DrawLine(Point(tmpR.Right-1, tmpR.Top), Point(tmpR.Right-1, tmpR.Bottom), 1.0);
end else
if isMono then
begin
Canvas.Stroke.Color:= $FF646464;
Canvas.DrawLine(Point(tmpR.Right-1, tmpR.Top), Point(tmpR.Right-1, tmpR.Bottom), 1.0);
end else
begin
Canvas.Stroke.Color:= TAlphaColorRec.White;
Canvas.DrawLine(Point(tmpR.Right-1, tmpR.Top), Point(tmpR.Right-1, tmpR.Bottom), 1.0);
end;
InflateRect(tmpR, -1, -1)
end;
Dec(tmpR.Right);
if edge and BDR_RAISEDINNER<>0 then
begin
if isSoft then
begin
Canvas.Stroke.Color:= $FFA0A0A0;
Canvas.DrawLine(Point(tmpR.Right, tmpR.Top), Point(tmpR.Right, tmpR.Bottom), 1.0);
end else
if IsFlat then
begin
Canvas.Stroke.Color:= $FFF0F0F0;
Canvas.DrawLine(Point(tmpR.Right, tmpR.Top), Point(tmpR.Right, tmpR.Bottom), 1.0);
end else
if isMono then
begin
Canvas.Stroke.Color:= TAlphaColorRec.White;
Canvas.DrawLine(Point(tmpR.Right, tmpR.Top), Point(tmpR.Right, tmpR.Bottom), 1.0);
end else
begin
Canvas.Stroke.Color:= $FFA0A0A0;
Canvas.DrawLine(Point(tmpR.Right, tmpR.Top), Point(tmpR.Right, tmpR.Bottom), 1.0);
end;
end;
if edge and BDR_SUNKENINNER<>0 then
begin
if isSoft then
begin
Canvas.Stroke.Color:= $FFE3E3E3;
Canvas.DrawLine(Point(tmpR.Right, tmpR.Top), Point(tmpR.Right, tmpR.Bottom), 1.0);
end else
if IsFlat then
begin
Canvas.Stroke.Color:= $FFE3E3E3;
Canvas.DrawLine(Point(tmpR.Right, tmpR.Top), Point(tmpR.Right, tmpR.Bottom), 1.0);
end else
if isMono then
begin
Canvas.Stroke.Color:= TAlphaColorRec.White;
Canvas.DrawLine(Point(tmpR.Right, tmpR.Top), Point(tmpR.Right, tmpR.Bottom), 1.0);
end else
begin
Canvas.Stroke.Color:= $FFE3E3E3;
Canvas.DrawLine(Point(tmpR.Right, tmpR.Top), Point(tmpR.Right, tmpR.Bottom), 1.0);
end;
end;
end;
if grfFlags and BF_BOTTOM<>0 then
begin
tmpR:= R;
Dec(tmpR.Bottom);
if edge and BDR_RAISEDOUTER<>0 then
begin
if isSoft then
begin
Canvas.Stroke.Color:= $FF696969;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Bottom), Point(tmpR.Right, tmpR.Bottom), 1.0);
end else
if IsFlat then
begin
Canvas.Stroke.Color:= $FFA0A0A0;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Bottom), Point(tmpR.Right, tmpR.Bottom), 1.0);
end else
if isMono then
begin
Canvas.Stroke.Color:= $FF646464;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Bottom), Point(tmpR.Right, tmpR.Bottom), 1.0);
end else
begin
Canvas.Stroke.Color:= $FF696969;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Bottom), Point(tmpR.Right, tmpR.Bottom), 1.0);
end;
InflateRect(tmpR, -1, -1)
end;
if edge and BDR_SUNKENOUTER<>0 then
begin
if isSoft then
begin
Canvas.Stroke.Color:= TAlphaColorRec.White;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Bottom), Point(tmpR.Right, tmpR.Bottom), 1.0);
end else
if IsFlat then
begin
Canvas.Stroke.Color:= $FFA0A0A0;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Bottom), Point(tmpR.Right, tmpR.Bottom), 1.0);
end else
if isMono then
begin
Canvas.Stroke.Color:= $FF646464;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Bottom), Point(tmpR.Right, tmpR.Bottom), 1.0);
end else
begin
Canvas.Stroke.Color:= TAlphaColorRec.White;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Bottom), Point(tmpR.Right, tmpR.Bottom), 1.0);
end;
InflateRect(tmpR, -1, -1)
end;
if edge and BDR_RAISEDINNER<>0 then
begin
if isSoft then
begin
Canvas.Stroke.Color:= $FFA0A0A0;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Bottom), Point(tmpR.Right, tmpR.Bottom), 1.0);
end else
if IsFlat then
begin
Canvas.Stroke.Color:= $FFF0F0F0;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Bottom), Point(tmpR.Right, tmpR.Bottom), 1.0);
end else
if isMono then
begin
Canvas.Stroke.Color:= TAlphaColorRec.White;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Bottom), Point(tmpR.Right, tmpR.Bottom), 1.0);
end else
begin
Canvas.Stroke.Color:= $FFA0A0A0;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Bottom), Point(tmpR.Right, tmpR.Bottom), 1.0);
end;
end;
if edge and BDR_SUNKENINNER<>0 then
begin
if isSoft then
begin
Canvas.Stroke.Color:= $FFE3E3E3;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Bottom), Point(tmpR.Right, tmpR.Bottom), 1.0);
end else
if IsFlat then
begin
Canvas.Stroke.Color:= $FFE3E3E3;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Bottom), Point(tmpR.Right, tmpR.Bottom), 1.0);
end else
if isMono then
begin
Canvas.Stroke.Color:= $FFE3E3E3;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Bottom), Point(tmpR.Right, tmpR.Bottom), 1.0);
end else
begin
Canvas.Stroke.Color:= $FFE3E3E3;
Canvas.DrawLine(Point(tmpR.Left, tmpR.Bottom), Point(tmpR.Right, tmpR.Bottom), 1.0);
end;
end;
end;
end;
//----------------------------------------------------------------------------------------------------------------------
procedure GetTextExtentPoint32W(ACanvas: TCanvas; CaptionText: String; Len: Integer; Var Size: TSize);
begin
Size.cx:= ACanvas.TextWidth(Copy(CaptionText, 1, Len));
Size.cy:= ACanvas.TextHeight(Copy(CaptionText, 1, Len));
end;
//----------------------------------------------------------------------------------------------------------------------
procedure GetTextMetrics(ACanvas: TCanvas; var TM: TTextMetric);
Var P: TPathData;
tx: TTextLayout;
R: TRectF;
begin
{
tmHeight: Single; //The height (ascent + descent) of characters.
tmAscent: Single; //The ascent (units above the base line) of characters.
tmDescent: Single; //The descent (units below the base line) of characters.
tmInternalLeading: Single; //The amount of leading (space) inside the bounds set by the tmHeight member. Accent marks and other diacritical characters may occur in this area. The designer may set this member to zero
tmExternalLeading: Single; //The amount of extra leading (space) that the application adds between rows. Since this area is outside the font, it contains no marks and is not altered by text output calls in either OPAQUE or TRANSPARENT mode. The designer may set this member to zero.
tmAveCharWidth: Single; //The average width of characters in the font (generally defined as the width of the letter x ). This value does not include the overhang required for bold or italic characters.
tmMaxCharWidth: Single; //The width of the widest character in the font.
tmWeight: Single; //The weight of the font.
tmOverhang: Single;
tmDigitizedAspectX: Single; //The horizontal aspect of the device for which the font was designed.
tmDigitizedAspectY: Single; //The vertical aspect of the device for which the font was designed. The ratio of the tmDigitizedAspectX and tmDigitizedAspectY members is the aspect ratio of the device for which the font was designed.
tmFirstChar: WideChar; //The value of the first character defined in the font.
tmLastChar: WideChar; //The value of the last character defined in the font.
tmDefaultChar: WideChar; //The value of the character to be substituted for characters not in the font.
tmBreakChar: WideChar; //The value of the character that will be used to define word breaks for text justification.
tmItalic: Byte; //Specifies an italic font if it is nonzero.
tmUnderlined: Byte; //Specifies an underlined font if it is nonzero.
tmStruckOut: Byte; //A strikeout font if it is nonzero.
tmPitchAndFamily: Byte; //Specifies information about the pitch, the technology, and the family of a physical font. TMPF_FIXED_PITCH, TMPF_VECTOR, TMPF_TRUETYPE, TMPF_DEVICE
tmCharSet: Byte; //The character set of the font. The character set can be one of the following values. ANSI_CHARSET, GREEK_CHARSET....
}
TM.tmExternalLeading:= 0;
TM.tmWeight:= 0; //boldness???
TM.tmOverhang:= 0;
TM.tmDigitizedAspectX:= 0;
TM.tmDigitizedAspectY:= 0;
TM.tmFirstChar:= 'a'; //???
TM.tmLastChar:= 'z'; //???
TM.tmDefaultChar:= ' ';
TM.tmBreakChar:= ' ';
TM.tmItalic:= 0;
TM.tmUnderlined:= 0;
TM.tmStruckOut:= 0;
TM.tmPitchAndFamily:= 0;
TM.tmCharSet:= 0;
tx:= TTextLayoutManager.DefaultTextLayout.Create(ACanvas);
P:= TPathData.Create;
try
tx.Text:= 'W';
tx.ConvertToPath(p);
R:= P.GetBounds();
TM.tmHeight:= R.Height;
TM.tmMaxCharWidth:= R.Width;
//------------------------------------
tx.Text:= 'Ó';
p.Clear;
tx.ConvertToPath(p);
R:= P.GetBounds();
TM.tmInternalLeading:= R.Height - TM.tmHeight;
//------------------------------------
tx.Text:= 'x';
p.Clear;
tx.ConvertToPath(p);
R:= P.GetBounds();
TM.tmAscent:= R.Height - TM.tmHeight;
TM.tmAveCharWidth:= R.Width;
//------------------------------------
tx.Text:= 'y';
p.Clear;
tx.ConvertToPath(p);
TM.tmDescent:= P.GetBounds().Height - R.Height;
TM.tmHeight:= TM.tmHeight + TM.tmDescent;
finally
FreeAndNil(P);
FreeAndNil(tx);
end;
end;
//----------------------------------------------------------------------------------------------------------------------
function Rect(ALeft, ATop, ARight, ABottom: Single): TRect;
begin
Result:= RectF(ALeft, ATop, ARight, ABottom);
end;
//----------------------------------------------------------------------------------------------------------------------
function Rect(const ATopLeft, ABottomRight: TPoint): TRect;
begin
Result:= RectF(ATopLeft.X, ATopLeft.Y, ABottomRight.X, ABottomRight.Y);
end;
//----------------------------------------------------------------------------------------------------------------------
function Point(AX, AY: Single): TPoint;
begin
Result.X:= AX;
Result.Y:= AY;
end;
//----------------------------------------------------------------------------------------------------------------------
procedure Inc(Var V: Single; OIle: Single=1.0);
begin
V:= V + OIle;
end;
//----------------------------------------------------------------------------------------------------------------------
procedure Dec(Var V: Single; OIle: Single=1.0);
begin
V:= V - OIle;
end;
//----------------------------------------------------------------------------------------------------------------------
function MulDiv(const A, B, C: Single): Single;
begin
Result:= (A * B) / C;
end;
//----------------------------------------------------------------------------------------------------------------------
procedure FillMemory(Destination: Pointer; Length: NativeUInt; Fill: Byte);
begin
FillChar(Destination^, Length, Fill);
end;
//----------------------------------------------------------------------------------------------------------------------
procedure ZeroMemory(Destination: Pointer; Length: NativeUInt);
begin
FillChar(Destination^, Length, 0);
end;
//----------------------------------------------------------------------------------------------------------------------
procedure MoveMemory(Destination: Pointer; Source: Pointer; Length: NativeUInt);
begin
Move(Source^, Destination^, Length);
end;
//----------------------------------------------------------------------------------------------------------------------
procedure CopyMemory(Destination: Pointer; Source: Pointer; Length: NativeUInt);
begin
Move(Source^, Destination^, Length);
end;
//----------------------------------------------------------------------------------------------------------------------
procedure ChangeBiDiModeAlignment(var Alignment: TAlignment);
begin
case Alignment of
taLeftJustify: Alignment := taRightJustify;
taRightJustify: Alignment := taLeftJustify;
end;
end;
//----------------------------------------------------------------------------------------------------------------------
procedure OleUninitialize();
begin
//nothing
end;
//----------------------------------------------------------------------------------------------------------------------
function timeGetTime: Int64;
begin
Result:= TThread.GetTickCount;
end;
{ TChangeLink }
//----------------------------------------------------------------------------------------------------------------------
constructor TChangeLink.Create;
begin
inherited;
IgnoreIndex := True;
IgnoreImages := True;
end;
//----------------------------------------------------------------------------------------------------------------------
function TChangeLink.GetSender: TCustomImageList;
begin
Result := TCustomImageList(Images);
end;
//----------------------------------------------------------------------------------------------------------------------
procedure TChangeLink.SetSender(const Value: TCustomImageList);
begin
Images := TBaseImageList(Value);
end;
{ THighQualityBitmap }
constructor THighQualityBitmap.Create;
begin
inherited;
end;
{ TFontHelper }
function TFontHelper.GetOnChange: TNotifyEvent;
begin
Result:= OnChanged;
end;
procedure TFontHelper.SetOnChange(const Value: TNotifyEvent);
begin
OnChanged:= Value;
end;
end.