2016-07-17 17:39:55 +00:00
|
|
|
{$I vp.inc}
|
2016-07-17 10:22:25 +00:00
|
|
|
|
2016-07-17 17:39:55 +00:00
|
|
|
unit VpNavBarPainter;
|
2016-07-17 10:22:25 +00:00
|
|
|
|
|
|
|
interface
|
|
|
|
|
|
|
|
uses
|
|
|
|
{$IFDEF LCL}
|
2018-05-05 15:01:55 +00:00
|
|
|
LCLProc, LCLType, LCLIntf, LCLVersion,
|
2016-07-17 10:22:25 +00:00
|
|
|
{$ELSE}
|
|
|
|
Windows, Messages, MMSystem,
|
|
|
|
{$ENDIF}
|
|
|
|
Graphics, Classes, SysUtils, Controls, Buttons,
|
|
|
|
VpNavBar;
|
|
|
|
|
|
|
|
type
|
|
|
|
PRect = ^TRect;
|
|
|
|
|
|
|
|
TVpNavBarPainter = class
|
|
|
|
private
|
|
|
|
FNavBar: TVpCustomNavBar;
|
|
|
|
|
|
|
|
// Protected properties of the TVpCustomNavBar.
|
|
|
|
FActiveFolder: Integer;
|
|
|
|
FActiveItem: Integer;
|
|
|
|
FBackgroundColor: TColor;
|
|
|
|
FBackgroundImage: TBitmap;
|
|
|
|
FBackgroundMethod: TVpBackgroundMethod;
|
|
|
|
FButtonHeight: Integer;
|
|
|
|
FClientWidth: Integer;
|
|
|
|
FClientHeight: Integer;
|
|
|
|
FDrawingStyle: TVpFolderDrawingStyle;
|
|
|
|
FHotFolder: Integer;
|
|
|
|
FImages: TImageList;
|
|
|
|
FItemFont: TFont;
|
|
|
|
FItemSpacing: Integer;
|
|
|
|
FSelectedItem: Integer;
|
|
|
|
FSelectedItemFont: TFont;
|
|
|
|
FShowButtons: Boolean;
|
2018-05-04 22:28:03 +00:00
|
|
|
FSmallImagesSize: Integer;
|
|
|
|
FLargeImagesSize: Integer;
|
2016-07-17 10:22:25 +00:00
|
|
|
|
|
|
|
nabItemsRect: PRect;
|
|
|
|
nabLastMouseOverItem: Integer;
|
|
|
|
nabMouseDown: Boolean;
|
|
|
|
nabScrollUpBtn: TSpeedButton;
|
|
|
|
nabScrollDownBtn: TSpeedButton;
|
|
|
|
nabTopItem: Integer;
|
|
|
|
|
|
|
|
FFolderArea: TRect;
|
|
|
|
|
|
|
|
procedure DrawBackground(Canvas: TCanvas; R: TRect);
|
2016-07-17 17:39:55 +00:00
|
|
|
|
2018-05-04 22:28:03 +00:00
|
|
|
function DrawCoolTab(Canvas: TCanvas; R: TRect;
|
|
|
|
ATabIndex: Integer; ATabColor: TColor): TRect;
|
|
|
|
function DrawDefButton(Canvas: TCanvas; R: TRect;
|
|
|
|
ATabIndex: Integer): TRect;
|
|
|
|
function DrawEtchedButton(Canvas: TCanvas; R: TRect;
|
|
|
|
ATabIndex: Integer): TRect;
|
|
|
|
function DrawStandardTab(Canvas: TCanvas; R: TRect;
|
|
|
|
ATabIndex: Integer; ATabColor: TColor): TRect;
|
2016-07-17 17:39:55 +00:00
|
|
|
|
2016-07-17 21:42:20 +00:00
|
|
|
procedure DrawItemHighlight(Canvas: TCanvas; R: TRect; Enable: Boolean);
|
|
|
|
function DrawItemText(Canvas: TCanvas; AItem: TVpNavBtnItem; CurPos: Integer;
|
2018-05-05 15:01:55 +00:00
|
|
|
AText: String; AtLargeIcon: Boolean; out AHeight: Integer): Boolean;
|
2016-07-17 21:42:20 +00:00
|
|
|
function DrawLargeIcon(Canvas: TCanvas; AItem: TVpNavBtnItem;
|
|
|
|
CurPos: Integer): Boolean;
|
|
|
|
function DrawSmallIcon(Canvas: TCanvas; AItem: TVpNavBtnItem;
|
|
|
|
CurPos: Integer): Boolean;
|
|
|
|
|
2016-07-17 17:39:55 +00:00
|
|
|
function IsFocused(ATabIndex: Integer): Boolean;
|
|
|
|
function IsMouseOverFolder(ATabIndex: Integer): Boolean;
|
|
|
|
function IsMouseOverItem(ATabIndex: Integer): Boolean;
|
2016-07-17 10:22:25 +00:00
|
|
|
|
|
|
|
protected
|
|
|
|
procedure DrawActiveFolderItems(Canvas: TCanvas; var CurPos: Integer);
|
|
|
|
procedure DrawBottomFolderButtons(Canvas: TCanvas; ARect: TRect;
|
|
|
|
var CurPos: Integer);
|
2016-07-17 17:39:55 +00:00
|
|
|
procedure DrawTab(Canvas: TCanvas; R: TRect; ATabIndex: Integer);
|
2016-07-17 10:22:25 +00:00
|
|
|
procedure DrawTopFolderButtons(Canvas: TCanvas; ARect: TRect;
|
|
|
|
DrawFolder: Boolean; var CurPos: Integer);
|
|
|
|
|
2016-07-18 20:24:58 +00:00
|
|
|
procedure ProcessScrollButtons;
|
|
|
|
|
2016-07-17 10:22:25 +00:00
|
|
|
public
|
|
|
|
constructor Create(ANavBar: TVpCustomNavBar);
|
|
|
|
procedure Paint;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function GetLargeIconDisplayName(Canvas: TCanvas; Rect: TRect; const Name: string): string;
|
|
|
|
|
|
|
|
implementation
|
|
|
|
|
|
|
|
uses
|
2018-05-05 15:01:55 +00:00
|
|
|
Math, Themes, imglist,
|
2018-05-04 22:28:03 +00:00
|
|
|
VpConst, VpMisc;
|
2016-07-17 10:22:25 +00:00
|
|
|
|
|
|
|
type
|
|
|
|
TVpNavBarOpener = class(TVpCustomNavBar);
|
|
|
|
|
|
|
|
constructor TVpNavBarPainter.Create(ANavBar: TVpCustomNavBar);
|
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
FNavBar := ANavBar;
|
|
|
|
|
|
|
|
FActiveFolder := TVpNavBarOpener(FNavBar).ActiveFolder;
|
|
|
|
FActiveItem := TVpNavBarOpener(FNavBar).ActiveItem;
|
|
|
|
FBackgroundColor := TVpNavBarOpener(FNavBar).BackgroundColor;
|
|
|
|
FBackgroundImage := TVpNavBarOpener(FNavBar).BackgroundImage;
|
|
|
|
FBackgroundMethod := TVpNavBarOpener(FNavBar).BackgroundMethod;
|
2018-05-04 22:28:03 +00:00
|
|
|
FButtonHeight := TVpNavBarOpener(FNavBar).GetRealButtonHeight;
|
2016-07-17 10:22:25 +00:00
|
|
|
FClientWidth := TVpNavBarOpener(FNavBar).ClientWidth;
|
|
|
|
FClientHeight := TVpNavBarOpener(FNavBar).ClientHeight;
|
|
|
|
FDrawingStyle := TVpNavBarOpener(FNavBar).DrawingStyle;
|
|
|
|
FHotFolder := TVpNavBarOpener(FNavBar).FHotFolder;
|
|
|
|
FImages := TVpNavBarOpener(FNavBar).Images;
|
|
|
|
FItemFont := TVpNavBarOpener(FNavBar).FItemFont;
|
|
|
|
FItemSpacing := TVpNavBarOpener(FNavBar).FItemSpacing;
|
|
|
|
FSelectedItem := TVpNavBarOpener(FNavBar).FSelectedItem;
|
|
|
|
FSelectedItemFont := TVpNavBarOpener(FNavBar).FSelectedItemFont;
|
|
|
|
FShowButtons := TVpNavBarOpener(FNavBar).FShowButtons;
|
|
|
|
|
|
|
|
// The nabItemsRect is populated in the Paint procedure, and it is needed in
|
|
|
|
// the NavBar as well. Therefore we use a pointer here!
|
|
|
|
nabItemsRect := @TVpNavBarOpener(FNavBar).nabItemsRect;
|
|
|
|
|
|
|
|
nabLastMouseOverItem := TVpNavBarOpener(FNavBar).nabLastMouseOverItem;
|
|
|
|
nabMouseDown := TVpNavBarOpener(FNavBar).nabMouseDown;
|
|
|
|
nabScrollUpBtn := TVpNavBarOpener(FNavBar).nabScrollUpBtn;
|
|
|
|
nabScrollDownBtn := TVpNavBarOpener(FNavBar).nabScrollDownBtn;
|
|
|
|
nabTopItem := TVpNavBarOpener(FNavBar).nabTopItem;
|
|
|
|
|
|
|
|
FFolderArea := TVpNavBarOpener(FNavBar).nabGetFolderArea(FActiveFolder);
|
|
|
|
end;
|
|
|
|
|
|
|
|
{ Draw the items for the active folder }
|
|
|
|
procedure TVpNavBarPainter.DrawActiveFolderItems(Canvas: TCanvas; var CurPos: Integer);
|
2018-05-04 22:28:03 +00:00
|
|
|
const
|
|
|
|
BUTTON_DISTANCE = 8;
|
2018-05-05 16:09:31 +00:00
|
|
|
LARGE_ICON_TEXT_DISTANCE = 2;
|
2018-05-05 15:01:55 +00:00
|
|
|
SMALL_ICON_TEXT_DISTANCE = 6;
|
2016-07-17 10:22:25 +00:00
|
|
|
var
|
|
|
|
folder: TVpNavFolder;
|
|
|
|
item: TVpNavBtnItem;
|
|
|
|
J: Integer;
|
|
|
|
text: String;
|
2018-05-05 15:01:55 +00:00
|
|
|
h: Integer;
|
2016-07-17 10:22:25 +00:00
|
|
|
R: TRect;
|
2018-05-05 16:09:31 +00:00
|
|
|
dx, dy: Integer;
|
2018-05-05 15:01:55 +00:00
|
|
|
{$IFDEF LCL}
|
|
|
|
{$IF LCL_FullVersion >= 1090000}
|
|
|
|
imgres: TScaledImageListResolution;
|
|
|
|
f: Double;
|
|
|
|
ppi: Integer;
|
|
|
|
{$IFEND}
|
|
|
|
{$ENDIF}
|
2016-07-17 10:22:25 +00:00
|
|
|
begin
|
|
|
|
folder := FNavBar.Folders[FActiveFolder];
|
2018-05-04 22:28:03 +00:00
|
|
|
|
2018-05-05 16:09:31 +00:00
|
|
|
// Distance between icon and text, for large icons vertically, for small icons
|
|
|
|
// horizontally
|
|
|
|
dy := ScaleY(LARGE_ICON_TEXT_DISTANCE, DesignTimeDPI);
|
|
|
|
dx := ScaleX(SMALL_ICON_TEXT_DISTANCE, DesignTimeDPI);
|
|
|
|
|
|
|
|
{ If an image list is assigned then use the image size.
|
|
|
|
If no image list is assinged then assume a 32 x 32 image size.
|
|
|
|
The size of the small images is always half size of the large images. }
|
2018-05-04 22:28:03 +00:00
|
|
|
if FImages <> nil then begin
|
2018-05-05 15:01:55 +00:00
|
|
|
{$IFDEF LCL}{$IF LCL_FullVersion >= 1090000}
|
|
|
|
with TVpNavBarOpener(FNavBar) do begin
|
|
|
|
f := FCanvasScaleFactor;
|
|
|
|
ppi := Font.PixelsPerInch;
|
|
|
|
imgRes := FImages.ResolutionForPPI[FImagesWidth, ppi, f];
|
|
|
|
end;
|
|
|
|
FLargeImagesSize := imgRes.Width;
|
|
|
|
{$ELSE}
|
2018-05-04 22:28:03 +00:00
|
|
|
FLargeImagesSize := FImages.Width;
|
2018-05-05 15:01:55 +00:00
|
|
|
{$ENDIF}{$ENDIF}
|
|
|
|
end else
|
2018-05-04 22:28:03 +00:00
|
|
|
FLargeImagesSize := 32;
|
2018-05-05 15:01:55 +00:00
|
|
|
FSmallImagesSize := FLargeImagesSize div 2;
|
2016-07-17 10:22:25 +00:00
|
|
|
|
|
|
|
if folder.FolderType = ftDefault then begin
|
|
|
|
if folder.ItemCount = 0 then
|
|
|
|
exit;
|
|
|
|
|
2016-07-18 11:46:13 +00:00
|
|
|
// Distance of top-most icon to the last upper button
|
2018-05-04 22:28:03 +00:00
|
|
|
Inc(CurPos, ScaleY(BUTTON_DISTANCE, DesignTimeDPI));
|
2016-07-17 10:22:25 +00:00
|
|
|
|
|
|
|
with nabItemsRect^ do begin
|
|
|
|
Top := CurPos;
|
|
|
|
Left := 0;
|
|
|
|
Right := FNavBar.ClientWidth;
|
2016-07-18 11:46:13 +00:00
|
|
|
Bottom := FNavBar.ClientHeight - (FNavBar.FolderCount - FActiveFolder - 1) * FButtonHeight;
|
2016-07-17 10:22:25 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
for J := 0 to folder.ItemCount-1 do begin
|
|
|
|
R := TVpNavBtnItem(folder.Items[J]).LabelRect;
|
|
|
|
R.Bottom := nabItemsRect^.Bottom + 1;
|
|
|
|
TVpNavBtnItem(folder.Items[J]).LabelRect := R;
|
|
|
|
end;
|
|
|
|
|
|
|
|
for J := nabTopItem to folder.ItemCount-1 do begin
|
|
|
|
if (FSelectedItem = J) then
|
|
|
|
Canvas.Font := FSelectedItemFont
|
|
|
|
else
|
|
|
|
Canvas.Font := FItemFont;
|
|
|
|
|
|
|
|
item := Folder.Items[J];
|
2018-05-05 16:09:31 +00:00
|
|
|
{ If the caption is empty at design time display the item's name instead }
|
2016-07-17 10:22:25 +00:00
|
|
|
if (csDesigning in FNavBar.ComponentState) and (item.Caption = '') then
|
|
|
|
text := item.Name
|
|
|
|
else
|
|
|
|
text := item.Caption;
|
|
|
|
|
|
|
|
if folder.IconSize = isLarge then begin
|
2016-07-17 21:42:20 +00:00
|
|
|
{ Large icons }
|
|
|
|
if not DrawLargeIcon(Canvas, item, CurPos) then
|
|
|
|
Continue;
|
2016-07-17 10:22:25 +00:00
|
|
|
|
2016-07-17 21:42:20 +00:00
|
|
|
{make the icon's bottom blend into the label's top}
|
|
|
|
R := item.IconRect;
|
2018-05-05 16:09:31 +00:00
|
|
|
inc(R.Bottom, dy);
|
2016-07-17 21:42:20 +00:00
|
|
|
item.IconRect := R;
|
|
|
|
CurPos := item.IconRect.Bottom;
|
2016-07-17 10:22:25 +00:00
|
|
|
|
2018-05-05 16:09:31 +00:00
|
|
|
{now draw the text}
|
2018-05-05 15:01:55 +00:00
|
|
|
if not DrawItemText(Canvas, item, CurPos, text, true, h) then
|
2016-07-17 21:42:20 +00:00
|
|
|
Continue;
|
2018-05-05 15:01:55 +00:00
|
|
|
Inc(CurPos, FItemSpacing + h);
|
2016-07-17 21:42:20 +00:00
|
|
|
end else
|
2016-07-17 10:22:25 +00:00
|
|
|
begin
|
2016-07-17 21:42:20 +00:00
|
|
|
{ Small Icons }
|
|
|
|
if not DrawSmallIcon(Canvas, item, CurPos) then
|
|
|
|
Continue;
|
2016-07-17 10:22:25 +00:00
|
|
|
|
|
|
|
{make the icon's right blend into the label's left}
|
|
|
|
R := item.IconRect;
|
2018-05-05 16:09:31 +00:00
|
|
|
inc(R.Right, dx);
|
2016-07-17 10:22:25 +00:00
|
|
|
item.IconRect := R;
|
|
|
|
|
2018-05-05 16:09:31 +00:00
|
|
|
{now draw the text}
|
2018-05-05 15:01:55 +00:00
|
|
|
if not DrawItemText(Canvas, item, CurPos, text, false, h) then
|
2016-07-17 21:42:20 +00:00
|
|
|
Continue;
|
2018-05-05 15:01:55 +00:00
|
|
|
Inc(CurPos, FItemSpacing + h);
|
2016-07-17 21:42:20 +00:00
|
|
|
end; { if folder.IconSize ... }
|
2016-07-17 10:22:25 +00:00
|
|
|
end; { for J }
|
2016-07-17 21:42:20 +00:00
|
|
|
end; { if folder.FolderType = ftDefault ... }
|
2016-07-17 10:22:25 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TVpNavBarPainter.DrawBackground(Canvas: TCanvas; R: TRect);
|
|
|
|
var
|
|
|
|
rowStart: Integer;
|
|
|
|
lLeft, lHeight, lWidth: Integer;
|
|
|
|
begin
|
2018-05-02 15:52:08 +00:00
|
|
|
if FBackgroundImage.Empty or (FBackgroundMethod = bmNone) or (FNavBar.FolderCount = 0) then
|
2016-07-17 10:22:25 +00:00
|
|
|
begin
|
|
|
|
Canvas.Brush.Color := FBackgroundColor;
|
2016-07-18 11:46:13 +00:00
|
|
|
Canvas.FillRect(R.Left, R.Top, R.Right, R.Bottom);
|
2016-07-17 10:22:25 +00:00
|
|
|
end else
|
|
|
|
begin
|
|
|
|
case FBackgroundMethod of
|
|
|
|
bmNormal:
|
2016-07-17 23:01:16 +00:00
|
|
|
begin
|
|
|
|
if (FBackgroundImage.Width < WidthOf(R)) or (FBackgroundImage.Height < HeightOf(R))
|
|
|
|
then begin
|
|
|
|
Canvas.Brush.Color := FBackgroundColor;
|
2016-07-18 11:46:13 +00:00
|
|
|
Canvas.Rectangle(R.Left, R.Top, R.Right, R.Bottom);
|
2016-07-17 23:01:16 +00:00
|
|
|
end;
|
|
|
|
Canvas.Draw(R.Left, R.Top, FBackgroundImage);
|
|
|
|
end;
|
2016-07-17 10:22:25 +00:00
|
|
|
bmStretch:
|
|
|
|
Canvas.StretchDraw(R, FBackgroundImage);
|
|
|
|
bmTile:
|
|
|
|
begin
|
|
|
|
{Tile the background in the default folder}
|
|
|
|
rowStart := 0;
|
|
|
|
lHeight := FBackgroundImage.Height;
|
|
|
|
lWidth := FBackgroundImage.Width;
|
|
|
|
lLeft := 0;
|
|
|
|
while (rowStart < FNavBar.ClientRect.Bottom) do begin
|
|
|
|
while (lLeft < FNavBar.ClientRect.Right) do begin
|
|
|
|
Canvas.Draw(R.Left + lLeft, rowStart, FBackgroundImage);
|
|
|
|
Inc(lLeft, lWidth);
|
|
|
|
end;
|
|
|
|
lLeft := 0;
|
|
|
|
Inc(rowStart, lHeight)
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
{ Draw the folder buttons at the bottom }
|
|
|
|
procedure TVpNavBarPainter.DrawBottomFolderButtons(Canvas: TCanvas; ARect: TRect;
|
|
|
|
var CurPos: Integer);
|
|
|
|
var
|
|
|
|
I: Integer;
|
|
|
|
MyRect: TRect;
|
|
|
|
begin
|
|
|
|
MyRect := ARect;
|
|
|
|
|
|
|
|
Canvas.Font := FNavBar.Font;
|
2016-07-17 17:39:55 +00:00
|
|
|
// SetBkMode(Canvas.Handle, bkMode);
|
2016-07-17 10:22:25 +00:00
|
|
|
// todo---> SetBkColor(Canvas.Handle, bkColor);
|
|
|
|
|
2016-07-17 17:39:55 +00:00
|
|
|
CurPos := FNavBar.ClientHeight - FButtonHeight;
|
2016-07-17 10:22:25 +00:00
|
|
|
|
|
|
|
for I := FNavBar.FolderCount-1 downto FActiveFolder+1 do begin
|
|
|
|
MyRect.Top := CurPos;
|
|
|
|
MyRect.Bottom := CurPos + FButtonHeight;
|
|
|
|
FNavBar.Folders[I].Rect := MyRect;
|
|
|
|
|
|
|
|
{Draw the bottom tabs based on the selected style...}
|
2016-07-17 17:39:55 +00:00
|
|
|
DrawTab(Canvas, MyRect, I);
|
2016-07-17 10:22:25 +00:00
|
|
|
Dec(CurPos, FButtonHeight);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
2016-07-17 17:39:55 +00:00
|
|
|
{ Draw a "cool" tab button.
|
|
|
|
Returns the usable text area inside the tab rect.}
|
|
|
|
function TVpNavBarPainter.DrawCoolTab(Canvas: TCanvas; R: TRect;
|
|
|
|
ATabIndex: Integer; ATabColor: TColor): TRect;
|
2016-07-17 10:22:25 +00:00
|
|
|
var
|
|
|
|
Points: array[1..5] of TPoint;
|
|
|
|
begin
|
2016-07-17 17:39:55 +00:00
|
|
|
Result := R;
|
2016-07-18 11:46:13 +00:00
|
|
|
|
2016-07-17 10:22:25 +00:00
|
|
|
with Canvas do begin
|
2016-07-17 17:39:55 +00:00
|
|
|
{Fill the tab area}
|
|
|
|
Brush.Style := bsSolid;
|
|
|
|
if (ATabIndex = 0) then
|
|
|
|
Brush.Color := clBtnFace
|
|
|
|
else
|
|
|
|
Brush.Color := ATabColor;
|
|
|
|
FillRect(R);
|
2016-07-17 10:22:25 +00:00
|
|
|
|
2016-07-18 11:46:13 +00:00
|
|
|
if IsMouseOverFolder(ATabIndex) then
|
|
|
|
; // do what?
|
|
|
|
|
2016-07-17 10:22:25 +00:00
|
|
|
{Draw the bottom, left line}
|
2016-07-17 17:39:55 +00:00
|
|
|
Pen.Color := clBlack;
|
2016-07-17 10:22:25 +00:00
|
|
|
MoveTo(R.Left, R.Bottom - 1);
|
|
|
|
LineTo(R.Left + 5, R.Bottom - 1);
|
|
|
|
|
|
|
|
{Draw the bottom, left curve}
|
2016-07-17 17:39:55 +00:00
|
|
|
Points[1] := Point(R.Left + 5, R.Bottom - 1); {Start point}
|
|
|
|
Points[2] := Point(R.Left + 11, R.Bottom - 2); {Control point}
|
|
|
|
Points[3] := Point(R.Left + 12, R.Bottom - 7); {Control point}
|
|
|
|
Points[4] := Point(R.Left + 13, R.Bottom - 9); {End point}
|
|
|
|
{$IFNDEF VERSION4}
|
2016-07-17 10:22:25 +00:00
|
|
|
{$IFDEF CBuilder}
|
|
|
|
PolyBezier(Points);
|
|
|
|
{$ELSE}
|
|
|
|
Polyline(Points);
|
|
|
|
{$ENDIF}
|
|
|
|
{$ELSE}
|
2016-07-17 17:39:55 +00:00
|
|
|
PolyBezier([Points[1], Points[2], Points[3], Points[4]]);
|
2016-07-17 10:22:25 +00:00
|
|
|
{$ENDIF}
|
|
|
|
|
|
|
|
{Draw the left side of the tab}
|
|
|
|
MoveTo(R.Left + 13, R.Bottom - 9);
|
2016-07-17 17:39:55 +00:00
|
|
|
LineTo(R.Left + 13, R.Top + 8);
|
2016-07-17 10:22:25 +00:00
|
|
|
|
|
|
|
{Draw the top, left corner of the tab}
|
2016-07-17 17:39:55 +00:00
|
|
|
Points[1] := Point(R.Left + 13, R.Top + 8); {Start point}
|
|
|
|
Points[2] := Point(R.Left + 14, R.Top + 6); {Control point}
|
|
|
|
Points[3] := Point(R.Left + 15, R.Top + 1); {Control point}
|
|
|
|
Points[4] := Point(R.Left + 21, R.Top + 0); {End point}
|
2018-05-04 22:28:03 +00:00
|
|
|
{$IFNDEF VERSION4}
|
2016-07-17 10:22:25 +00:00
|
|
|
{$IFDEF CBuilder}
|
|
|
|
PolyBezier(Points);
|
|
|
|
{$ELSE}
|
|
|
|
Polyline(Points);
|
|
|
|
{$ENDIF}
|
2018-05-04 22:28:03 +00:00
|
|
|
{$ELSE}
|
2016-07-17 17:39:55 +00:00
|
|
|
PolyBezier([Points[1], Points[2], Points[3], Points[4]]);
|
2018-05-04 22:28:03 +00:00
|
|
|
{$ENDIF}
|
2016-07-17 10:22:25 +00:00
|
|
|
|
|
|
|
{Draw the top of the tab}
|
2016-07-17 17:39:55 +00:00
|
|
|
MoveTo(R.Left + 21, R.Top);
|
|
|
|
LineTo(R.Right - 16, R.Top);
|
|
|
|
|
|
|
|
{Draw the top right corner of the tab}
|
|
|
|
Points[1] := Point(R.Right - 16, R.Top);
|
|
|
|
Points[2] := Point(R.Right - 10, R.Top + 1);
|
|
|
|
Points[3] := Point(R.Right - 9, R.Top + 6);
|
|
|
|
Points[4] := Point(R.Right - 8, R.Top + 8);
|
|
|
|
{$IFNDEF VERSION4}
|
2016-07-17 10:22:25 +00:00
|
|
|
{$IFDEF CBuilder}
|
|
|
|
PolyBezier(Points);
|
|
|
|
{$ELSE}
|
|
|
|
Polyline(Points);
|
|
|
|
{$ENDIF}
|
2016-07-17 17:39:55 +00:00
|
|
|
{$ELSE}
|
|
|
|
PolyBezier([Points[1], Points[2], Points[3], Points[4]]);
|
2016-07-17 10:22:25 +00:00
|
|
|
{$ENDIF}
|
|
|
|
|
|
|
|
{Draw the right side of the tab}
|
2016-07-17 17:39:55 +00:00
|
|
|
MoveTo(R.Right - 8, R.Top + 8);
|
2016-07-17 10:22:25 +00:00
|
|
|
LineTo(R.Right - 8, R.Bottom - 9);
|
|
|
|
|
|
|
|
{Draw the bottom, Right curve of the tab which should finish against the
|
|
|
|
right side.}
|
|
|
|
Points[1] := Point(R.Right - 8, R.Bottom - 9);
|
|
|
|
Points[2] := Point(R.Right - 7, R.Bottom - 7);
|
|
|
|
Points[3] := Point(R.Right - 6, R.Bottom - 2);
|
|
|
|
Points[4] := Point(R.Right, R.Bottom - 1);
|
2016-07-17 17:39:55 +00:00
|
|
|
{$IFNDEF VERSION4}
|
2016-07-17 10:22:25 +00:00
|
|
|
{$IFDEF CBuilder}
|
|
|
|
Canvas.PolyBezier(Points);
|
|
|
|
{$ELSE}
|
|
|
|
Canvas.Polyline(Points);
|
|
|
|
{$ENDIF}
|
|
|
|
{$ELSE}
|
2016-07-17 17:39:55 +00:00
|
|
|
PolyBezier([Points[1], Points[2], Points[3], Points[4]]);
|
2016-07-17 10:22:25 +00:00
|
|
|
{$ENDIF}
|
2016-07-17 17:39:55 +00:00
|
|
|
|
|
|
|
if ATabIndex = 0 then begin
|
|
|
|
Brush.Color := ATabColor;
|
|
|
|
FloodFill((R.Left + R.Right) div 2, (R.Top + R.Bottom) div 2, clBtnFace, fsSurface);
|
|
|
|
end;
|
2016-07-17 10:22:25 +00:00
|
|
|
end;
|
2016-07-17 17:39:55 +00:00
|
|
|
|
|
|
|
Result := Rect(R.Left + 1, R.Top + 2, R.Right - 2, R.Bottom);
|
2016-07-17 10:22:25 +00:00
|
|
|
end;
|
|
|
|
|
2016-07-17 17:39:55 +00:00
|
|
|
{ Draw regular buttons
|
|
|
|
Returns the usable text area inside the tab rect.}
|
2016-07-17 10:22:25 +00:00
|
|
|
function TVpNavBarPainter.DrawDefButton(Canvas: TCanvas; R: TRect;
|
2016-07-17 17:39:55 +00:00
|
|
|
ATabIndex: Integer): TRect;
|
2016-07-17 10:22:25 +00:00
|
|
|
var
|
|
|
|
tb: TThemedButton;
|
|
|
|
details: TThemedElementDetails;
|
|
|
|
begin
|
2016-07-17 17:39:55 +00:00
|
|
|
Result := R;
|
|
|
|
|
2016-07-17 10:22:25 +00:00
|
|
|
if ThemeServices.ThemesEnabled then begin
|
2016-07-18 11:46:13 +00:00
|
|
|
// themed button
|
2016-07-17 17:39:55 +00:00
|
|
|
if IsMouseOverFolder(ATabIndex) and nabMouseDown then
|
2016-07-17 10:22:25 +00:00
|
|
|
tb := tbPushButtonPressed
|
2016-07-17 17:39:55 +00:00
|
|
|
else
|
|
|
|
if IsMouseOverFolder(ATabIndex) then
|
|
|
|
tb := tbPushButtonHot
|
2016-07-17 10:22:25 +00:00
|
|
|
else
|
|
|
|
tb := tbPushButtonNormal;
|
|
|
|
details := ThemeServices.GetElementDetails(tb);
|
2016-07-17 17:39:55 +00:00
|
|
|
InflateRect(R, 1, 1);
|
2016-07-17 10:22:25 +00:00
|
|
|
ThemeServices.DrawElement(Canvas.Handle, details, R);
|
2016-07-18 11:46:13 +00:00
|
|
|
end else
|
|
|
|
begin
|
|
|
|
// non-themed button
|
|
|
|
Canvas.Brush.Color := clBtnFace;
|
|
|
|
Canvas.FillRect(R);
|
|
|
|
if nabMouseDown and IsMouseOverFolder(ATabIndex) then
|
|
|
|
begin
|
|
|
|
if R.Top = 0 then R.Top := 1;
|
|
|
|
|
|
|
|
Canvas.Pen.Color := clBtnHighlight; // bright at bottom/right
|
|
|
|
Canvas.MoveTo(R.Left, R.Bottom-1);
|
|
|
|
Canvas.LineTo(R.Right-1, R.Bottom-1);
|
|
|
|
Canvas.LineTo(R.Right-1, R.Top-1);
|
|
|
|
|
|
|
|
Canvas.Pen.Color := clGray; // dark at top/left
|
|
|
|
Canvas.MoveTo(R.Left, R.Bottom-2);
|
|
|
|
Canvas.LineTo(R.Left, R.Top);
|
|
|
|
Canvas.LineTo(R.Right-1, R.Top);
|
|
|
|
|
|
|
|
Canvas.Pen.Color := clBtnShadow; // shadow at top/left
|
|
|
|
Canvas.MoveTo(R.Left+1, R.Bottom-2);
|
|
|
|
Canvas.LineTo(R.Left+1, R.Top);
|
|
|
|
Canvas.LineTo(R.Right-2, R.Top);
|
|
|
|
end else
|
|
|
|
begin
|
|
|
|
Canvas.Pen.Color := clGray; // bottom/right
|
|
|
|
Canvas.MoveTo(R.Left, R.Bottom-1);
|
|
|
|
Canvas.LineTo(R.Right-1, R.Bottom-1);
|
|
|
|
Canvas.LineTo(R.Right-1, R.Top-1);
|
|
|
|
|
|
|
|
Canvas.Pen.Color := clBtnHighlight; // top/left
|
|
|
|
Canvas.MoveTo(R.Left, R.Bottom-2);
|
|
|
|
Canvas.LineTo(R.Left, R.Top);
|
|
|
|
Canvas.LineTo(R.Right-1, R.Top);
|
|
|
|
|
|
|
|
Canvas.Pen.Color := clBtnShadow; // bottom/right shadow
|
|
|
|
Canvas.MoveTo(R.Left+1, R.Bottom-2);
|
|
|
|
Canvas.LineTo(R.Right-2, R.Bottom-2);
|
|
|
|
Canvas.LineTo(R.Right-2, R.Top);
|
|
|
|
end;
|
2016-07-17 10:22:25 +00:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2016-07-17 17:39:55 +00:00
|
|
|
{ Draw regular etched (Win98 style) buttons
|
|
|
|
Returns the usable text area inside the tab rect.}
|
2016-07-17 10:22:25 +00:00
|
|
|
function TVpNavBarPainter.DrawEtchedButton(Canvas: TCanvas; R: TRect;
|
2016-07-17 17:39:55 +00:00
|
|
|
ATabIndex: Integer): TRect;
|
2016-07-17 10:22:25 +00:00
|
|
|
begin
|
|
|
|
with Canvas do begin
|
|
|
|
Brush.Color := clBtnFace;
|
|
|
|
FillRect(R);
|
2016-07-18 11:46:13 +00:00
|
|
|
|
|
|
|
Frame3D(R, 1, bvLowered);
|
|
|
|
if not IsMouseOverFolder(aTabIndex) then
|
|
|
|
Frame3D(R, 1, bvRaised);
|
|
|
|
{
|
2016-07-17 17:39:55 +00:00
|
|
|
// InflateRect(R, -1, -1);
|
|
|
|
if IsMouseOverFolder(ATabIndex) then
|
|
|
|
Frame3D(R, 1, bvLowered) else
|
|
|
|
Frame3D(r, 1, bvRaised);
|
2016-07-18 11:46:13 +00:00
|
|
|
}
|
2016-07-17 10:22:25 +00:00
|
|
|
end;
|
|
|
|
Result := R;
|
|
|
|
end;
|
|
|
|
|
2016-07-17 21:42:20 +00:00
|
|
|
procedure TVpNavBarPainter.DrawItemHighlight(Canvas: TCanvas; R: TRect;
|
|
|
|
Enable: Boolean);
|
2018-05-05 23:21:08 +00:00
|
|
|
const
|
|
|
|
PUSHBUTTON_DETAILS: array[boolean] of TThemedButton = (tbPushButtonHot, tbPushButtonPressed);
|
|
|
|
TOOLBAR_DETAILS: array[boolean] of TThemedToolbar = (ttbButtonHot, ttbButtonPressed);
|
|
|
|
var
|
|
|
|
details: TThemedElementDetails;
|
|
|
|
margin: integer;
|
2016-07-17 21:42:20 +00:00
|
|
|
begin
|
|
|
|
if Enable then begin
|
2018-05-05 23:21:08 +00:00
|
|
|
if ThemeServices.ThemesEnabled and (TVpNavBarOpener(FNavBar).ItemTheme <> itNoTheme) then
|
|
|
|
begin
|
|
|
|
margin := ScaleX(2, DesigntimeDPI);
|
|
|
|
InflateRect(R, margin, margin);
|
|
|
|
case TVpNavBarOpener(FNavBar).ItemTheme of
|
|
|
|
itPushButton:
|
|
|
|
details := ThemeServices.GetElementDetails(PUSHBUTTON_DETAILS[nabMousedown]);
|
|
|
|
itToolbar:
|
|
|
|
details := ThemeServices.GetElementDetails(TOOLBAR_DETAILS[nabMouseDown]);
|
|
|
|
end;
|
|
|
|
ThemeServices.DrawElement(Canvas.Handle, details, R);
|
|
|
|
end else
|
|
|
|
begin
|
|
|
|
if nabMouseDown then
|
|
|
|
Canvas.Pen.Color := clBlack
|
|
|
|
else
|
|
|
|
Canvas.Pen.Color := clWhite;
|
|
|
|
Canvas.MoveTo(R.Left-1, R.Bottom+1);
|
|
|
|
Canvas.LineTo(R.Left-1, R.Top-1);
|
|
|
|
Canvas.LineTo(R.Right+1, R.Top-1);
|
|
|
|
if nabMouseDown then
|
|
|
|
Canvas.Pen.Color := clWhite
|
|
|
|
else
|
|
|
|
Canvas.Pen.Color := clBlack;
|
|
|
|
Canvas.LineTo(R.Right+1, R.Bottom+1);
|
|
|
|
Canvas.LineTo(R.Left-1, R.Bottom+1);
|
|
|
|
Canvas.Brush.Color := FBackgroundColor;
|
|
|
|
end;
|
2016-07-17 21:42:20 +00:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TVpNavBarPainter.DrawItemText(Canvas: TCanvas; AItem: TVpNavBtnItem;
|
2018-05-05 15:01:55 +00:00
|
|
|
CurPos: Integer; AText: String; AtLargeIcon: Boolean; out AHeight: Integer): Boolean;
|
2018-05-04 22:28:03 +00:00
|
|
|
const
|
|
|
|
HOR_MARGIN = 5;
|
2016-07-17 21:42:20 +00:00
|
|
|
var
|
|
|
|
R: TRect;
|
|
|
|
s: String;
|
|
|
|
txtWidth: Integer;
|
|
|
|
bkMode: Integer;
|
2018-05-04 22:28:03 +00:00
|
|
|
horDist: Integer;
|
2016-07-17 21:42:20 +00:00
|
|
|
begin
|
|
|
|
Result := false;
|
2018-05-05 15:01:55 +00:00
|
|
|
horDist := ScaleX(HOR_MARGIN, DesignTimeDPI);
|
2016-07-17 21:42:20 +00:00
|
|
|
|
|
|
|
if AtLargeIcon then
|
|
|
|
begin
|
|
|
|
R.Top := CurPos;
|
2018-05-04 22:28:03 +00:00
|
|
|
R.Bottom := CurPos + FButtonHeight div 2 - 7; // what is -7 good for?
|
2016-07-17 21:42:20 +00:00
|
|
|
R.Left := 0;
|
|
|
|
R.Right := FNavBar.ClientWidth - 1;
|
|
|
|
AItem.LabelRect := R;
|
|
|
|
AItem.DisplayName := GetLargeIconDisplayName(Canvas, R, AText);
|
2018-05-05 15:01:55 +00:00
|
|
|
txtWidth := Canvas.TextWidth(AItem.DisplayName);
|
|
|
|
R.Left := Max(horDist, (FNavBar.ClientWidth - txtWidth) div 2);
|
|
|
|
R.Right := Min(R.Left + txtWidth, FNavBar.ClientWidth - hordist);
|
2016-07-17 21:42:20 +00:00
|
|
|
AItem.LabelRect := R;
|
|
|
|
if R.Top > nabItemsRect^.Bottom then
|
|
|
|
Exit;
|
|
|
|
|
|
|
|
s := AItem.DisplayName;
|
|
|
|
DrawText(Canvas.Handle, PChar(s), Length(s), R, DT_CENTER or DT_VCENTER or DT_WORDBREAK or DT_CALCRECT);
|
|
|
|
txtWidth := WidthOf(R);
|
|
|
|
R.Left := (FNavBar.ClientWidth - txtWidth) div 2;
|
|
|
|
R.Right := R.Left + txtWidth + 1;
|
|
|
|
AItem.LabelRect := R;
|
|
|
|
|
|
|
|
bkMode := SetBkMode(Canvas.Handle, TRANSPARENT);
|
2018-05-05 15:01:55 +00:00
|
|
|
AHeight:= DrawText(Canvas.Handle, PChar(s), Length(s), R, DT_CENTER or DT_VCENTER or DT_WORDBREAK);
|
2016-07-17 21:42:20 +00:00
|
|
|
SetBkMode(Canvas.Handle, bkMode);
|
|
|
|
end else
|
|
|
|
begin
|
|
|
|
R.Top := CurPos;
|
2018-05-05 15:01:55 +00:00
|
|
|
R.Bottom := CurPos + Canvas.TextHeight('Tg');
|
|
|
|
// R.Bottom := CurPos + FButtonHeight div 2 - 7;
|
2016-07-17 21:42:20 +00:00
|
|
|
R.Left := AItem.IconRect.Right;
|
2018-05-05 15:01:55 +00:00
|
|
|
R.Right := FNavBar.ClientWidth - 2*AItem.IconRect.Left; // - 2*horDist;
|
|
|
|
// R.Right := R.Left + FNavBar.ClientWidth - R.Left - ScaleX(7, DesignTimeDPI);
|
2016-07-17 21:42:20 +00:00
|
|
|
AItem.LabelRect := R;
|
|
|
|
if R.Top > nabItemsRect^.Bottom then
|
|
|
|
Exit;
|
|
|
|
|
2018-05-05 15:01:55 +00:00
|
|
|
// Measure size of display string
|
2016-07-17 21:42:20 +00:00
|
|
|
R := AItem.LabelRect;
|
|
|
|
s := GetDisplayString(Canvas, AText, 1, WidthOf(R));
|
|
|
|
AItem.DisplayName := s;
|
2018-05-05 15:01:55 +00:00
|
|
|
DrawText(Canvas.Handle, PChar(s), Length(s), R, DT_LEFT or DT_CALCRECT);
|
2016-07-17 21:42:20 +00:00
|
|
|
txtWidth := WidthOf(R);
|
2018-05-05 15:01:55 +00:00
|
|
|
AHeight := HeightOf(R);
|
2016-07-17 21:42:20 +00:00
|
|
|
R.Right := R.Left + txtWidth + 1;
|
2018-05-05 15:01:55 +00:00
|
|
|
{$IFDEF MSWINDOWS}
|
|
|
|
OffsetRect(R, 0, -1); // Better centering of text
|
|
|
|
{$ENDIF}
|
2016-07-17 21:42:20 +00:00
|
|
|
AItem.LabelRect := R;
|
|
|
|
|
|
|
|
bkMode := SetBkMode(Canvas.Handle, TRANSPARENT);
|
2018-05-05 15:01:55 +00:00
|
|
|
Canvas.TextOut(R.Left, (R.Top + R.Bottom - AHeight) div 2, s);
|
|
|
|
// AHeight := DrawText(Canvas.Handle, PChar(s), Length(s), R, DT_LEFT or DT_VCENTER);
|
2016-07-17 21:42:20 +00:00
|
|
|
SetBkMode(Canvas.Handle, bkMode);
|
|
|
|
|
2018-05-05 15:01:55 +00:00
|
|
|
if AHeight < FSmallImagesSize then
|
|
|
|
AHeight := FSmallImagesSize;
|
2016-07-17 21:42:20 +00:00
|
|
|
end;
|
|
|
|
Result := true;
|
|
|
|
end;
|
|
|
|
|
2018-05-04 22:28:03 +00:00
|
|
|
{ Draw a large icon: centered horizontally, text to be drawn underneath icon.
|
|
|
|
CurPos is upper edge of the icon. }
|
2016-07-17 21:42:20 +00:00
|
|
|
function TVpNavBarPainter.DrawLargeIcon(Canvas: TCanvas; AItem: TVpNavBtnItem;
|
|
|
|
CurPos: Integer): Boolean;
|
2018-05-04 22:28:03 +00:00
|
|
|
const
|
|
|
|
MARGIN = 2;
|
2016-07-17 21:42:20 +00:00
|
|
|
var
|
|
|
|
W, H: Integer;
|
|
|
|
R: TRect;
|
2018-05-04 22:28:03 +00:00
|
|
|
dist: Integer;
|
2018-05-05 15:01:55 +00:00
|
|
|
{$IFDEF LCL}{$IF LCL_FullVersion >= 1090000}
|
|
|
|
imgres: TScaledImageListResolution;
|
|
|
|
f: Double;
|
|
|
|
ppi: Integer;
|
|
|
|
{$ENDIF}{$ENDIF}
|
2016-07-17 21:42:20 +00:00
|
|
|
begin
|
|
|
|
Result := false;
|
|
|
|
|
2018-05-04 22:28:03 +00:00
|
|
|
dist := ScaleX(MARGIN, DesignTimeDPI);
|
2018-05-05 15:01:55 +00:00
|
|
|
W := FLargeImagesSize + 2*dist;
|
|
|
|
H := FLargeImagesSize + 2*dist;
|
2016-07-17 21:42:20 +00:00
|
|
|
|
|
|
|
R.Top := CurPos;
|
|
|
|
R.Bottom := CurPos + H;
|
|
|
|
R.Left := (FNavBar.ClientWidth - W) div 2;
|
|
|
|
R.Right := R.Left + W;
|
|
|
|
if R.Top > nabItemsRect^.Bottom then
|
|
|
|
exit;
|
|
|
|
|
|
|
|
AItem.IconRect := R;
|
|
|
|
|
|
|
|
if FShowButtons then begin
|
|
|
|
DrawItemHighlight(Canvas, R, FActiveItem = AItem.Index);
|
|
|
|
if Assigned(FImages) and (AItem.IconIndex >= 0) and (AItem.IconIndex < FImages.Count) then
|
2018-05-05 15:01:55 +00:00
|
|
|
begin
|
|
|
|
{$IFDEF LCL}{$IF LCL_FullVersion >= 1090000}
|
|
|
|
with TVpNavBarOpener(FNavBar) do begin
|
|
|
|
f := FCanvasScalefactor;
|
|
|
|
ppi := Font.PixelsPerInch;
|
|
|
|
end;
|
|
|
|
imgRes := FImages.ResolutionForPPI[FImages.Width, ppi, f];
|
|
|
|
imgRes.Draw(Canvas, R.Left + dist, R.Top + dist, AItem.IconIndex);
|
|
|
|
{$ELSE}
|
2018-05-04 22:28:03 +00:00
|
|
|
FImages.Draw(Canvas, R.Left + dist, R.Top + dist, AItem.IconIndex);
|
2018-05-05 15:01:55 +00:00
|
|
|
{$ENDIF}{$ENDIF}
|
|
|
|
end;
|
2016-07-17 21:42:20 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
Result := true;
|
|
|
|
end;
|
|
|
|
|
|
|
|
{ Draw a small icon (16x16) }
|
|
|
|
function TVpNavBarPainter.DrawSmallIcon(Canvas: TCanvas; AItem: TVpNavBtnItem;
|
|
|
|
CurPos: Integer): Boolean;
|
|
|
|
const
|
2018-05-04 22:28:03 +00:00
|
|
|
DELTA = 8;
|
2016-07-17 21:42:20 +00:00
|
|
|
var
|
|
|
|
lOffset: Integer;
|
|
|
|
R: TRect;
|
2018-05-04 22:28:03 +00:00
|
|
|
del: Integer;
|
2018-05-05 15:01:55 +00:00
|
|
|
{$IFDEF LCL}{$IF LCL_FullVersion >= 1090000}
|
|
|
|
imgres: TScaledImageListResolution;
|
|
|
|
f: Double;
|
|
|
|
ppi: Integer;
|
|
|
|
{$ELSE}
|
|
|
|
bmp: TBitmap;
|
|
|
|
{$ENDIF}{$ENDIF}
|
2016-07-17 21:42:20 +00:00
|
|
|
begin
|
|
|
|
Result := false;
|
|
|
|
|
|
|
|
{glyph is at the left}
|
|
|
|
R.Top := CurPos;
|
2018-05-04 22:28:03 +00:00
|
|
|
del := ScaleY(DELTA, DesignTimeDPI);
|
2016-07-17 21:42:20 +00:00
|
|
|
lOffset := abs(Canvas.Font.Height) div 2;
|
2018-05-04 22:28:03 +00:00
|
|
|
if lOffset > del then
|
|
|
|
R.Top := R.Top + lOffset - del;
|
|
|
|
R.Bottom := R.Top + FSmallImagesSize;
|
|
|
|
R.Left := del;
|
|
|
|
R.Right := R.Left + FSmallImagesSize;
|
2016-07-17 21:42:20 +00:00
|
|
|
AItem.IconRect := R;
|
|
|
|
if R.Top > nabItemsRect^.Bottom then
|
|
|
|
Exit; // Returns false
|
|
|
|
|
|
|
|
if FShowButtons then begin
|
|
|
|
DrawItemHighlight(Canvas, R, FActiveItem = AItem.Index);
|
|
|
|
if Assigned(FImages) then begin
|
2018-05-05 15:01:55 +00:00
|
|
|
{$IFDEF LCL}{$IF LCL_FullVersion >= 1090000}
|
|
|
|
with TVpNavBarOpener(FNavBar) do begin
|
|
|
|
f := FCanvasScalefactor;
|
|
|
|
ppi := Font.PixelsPerInch;
|
|
|
|
end;
|
|
|
|
imgRes := FImages.ResolutionForPPI[FImages.Width div 2, ppi, f];
|
|
|
|
imgRes.Draw(Canvas, R.Left, R.Top, AItem.IconIndex);
|
|
|
|
{$ELSE}
|
2016-07-17 21:42:20 +00:00
|
|
|
bmp := TBitmap.Create;
|
|
|
|
try
|
2016-07-17 23:01:16 +00:00
|
|
|
FImages.GetBitmap(AItem.IconIndex, bmp);
|
|
|
|
bmp.Transparent := true;
|
|
|
|
Canvas.StretchDraw(AItem.IconRect, bmp);
|
2016-07-17 21:42:20 +00:00
|
|
|
finally
|
|
|
|
bmp.Free;
|
|
|
|
end;
|
2018-05-05 15:01:55 +00:00
|
|
|
{$ENDIF}{$ENDIF}
|
2016-07-17 21:42:20 +00:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
Result := true;
|
|
|
|
end;
|
|
|
|
|
2016-07-17 17:39:55 +00:00
|
|
|
{ Draw a "standard" tab button.
|
|
|
|
Returns the usable text area inside the tab rect.}
|
|
|
|
function TVpNavBarPainter.DrawStandardTab(Canvas: TCanvas; R: TRect;
|
|
|
|
ATabIndex: Integer; ATabColor: TColor): TRect;
|
2018-05-04 22:28:03 +00:00
|
|
|
const
|
|
|
|
_LEFT_DISTANCE = 10;
|
|
|
|
_RIGHT_DISTANCE = 2;
|
|
|
|
_RADIUS = 2;
|
|
|
|
var
|
|
|
|
leftDist: Integer;
|
|
|
|
rightDist: Integer;
|
|
|
|
radius: Integer;
|
2016-07-17 10:22:25 +00:00
|
|
|
begin
|
2016-07-17 17:39:55 +00:00
|
|
|
Result := R;
|
2016-07-17 10:22:25 +00:00
|
|
|
|
2018-05-04 22:28:03 +00:00
|
|
|
leftDist := ScaleX(_LEFT_DISTANCE, DesignTimeDPI);
|
|
|
|
rightDist := ScaleX(_RIGHT_DISTANCE, DesignTimeDPI);
|
|
|
|
radius := ScaleX(_RADIUS, DesignTimeDPI);
|
|
|
|
|
2016-07-17 17:39:55 +00:00
|
|
|
{fill the tab area}
|
|
|
|
Canvas.Brush.Style := bsSolid;
|
|
|
|
Canvas.Brush.Color := clBtnFace;
|
|
|
|
Canvas.FillRect(R);
|
2016-07-17 10:22:25 +00:00
|
|
|
|
2016-07-17 17:39:55 +00:00
|
|
|
{fill the tab area}
|
|
|
|
if ATabIndex > 0 then begin
|
|
|
|
Canvas.Brush.Color := ATabColor;
|
2016-07-17 10:22:25 +00:00
|
|
|
Canvas.Brush.Style := bsSolid;
|
2016-07-17 17:39:55 +00:00
|
|
|
Canvas.Pen.Color := ATabColor;
|
2016-07-17 10:22:25 +00:00
|
|
|
Canvas.Polygon([
|
|
|
|
Point(R.Left, R.Bottom),
|
|
|
|
Point(R.Left, R.Top),
|
|
|
|
Point(R.Right, R.Top),
|
|
|
|
Point(R.Right, R.Bottom)
|
|
|
|
]);
|
|
|
|
end;
|
|
|
|
|
|
|
|
{Draw Tab}
|
2016-07-17 17:39:55 +00:00
|
|
|
Canvas.Brush.Color := ATabColor;
|
|
|
|
Canvas.Brush.Style := bsSolid;
|
|
|
|
Canvas.Pen.Color := ATabColor;
|
2016-07-17 10:22:25 +00:00
|
|
|
Canvas.Polygon([
|
2018-05-04 22:28:03 +00:00
|
|
|
Point(R.Left + leftDist, R.Bottom - 1), // 10 -1
|
|
|
|
Point(R.Left + leftDist, R.Top + radius + 1), // 10 3
|
|
|
|
Point(R.Left + leftDist + radius, R.Top + 1), // 12 1
|
|
|
|
Point(R.Right - rightDist - radius, R.Top + 1), // -4 1
|
|
|
|
Point(R.Right - rightDist, R.Top + radius + 1), // -2 3
|
|
|
|
Point(R.Right - rightDist, R.Bottom - 1) // -2 -1
|
|
|
|
]);
|
|
|
|
{
|
2016-07-17 10:22:25 +00:00
|
|
|
Point(R.Left + 10, R.Bottom - 1),
|
|
|
|
Point(R.Left + 10, R.Top + 3),
|
|
|
|
Point(R.Left + 12, R.Top + 1),
|
|
|
|
Point(R.Right - 4, R.Top + 1),
|
|
|
|
Point(R.Right - 2, R.Top + 3),
|
|
|
|
Point(R.Right - 2, R.Bottom - 1)
|
2018-05-04 22:28:03 +00:00
|
|
|
]); }
|
2016-07-17 10:22:25 +00:00
|
|
|
|
|
|
|
{highlight tab}
|
|
|
|
Canvas.Pen.Color := clBtnHighlight;
|
2018-05-04 22:28:03 +00:00
|
|
|
{
|
2016-07-17 10:22:25 +00:00
|
|
|
Canvas.PolyLine([
|
|
|
|
Point(R.Left, R.Bottom - 2),
|
|
|
|
Point(R.Left + 8, R.Bottom - 2),
|
|
|
|
Point(R.Left + 9, R.Bottom - 3),
|
|
|
|
Point(R.Left + 9, R.Top + 3),
|
|
|
|
Point(R.Left + 11, R.Top + 1),
|
|
|
|
Point(R.Right - 1, R.Top + 1)
|
2018-05-04 22:28:03 +00:00
|
|
|
]);}
|
|
|
|
Canvas.PolyLine([
|
|
|
|
Point(R.Left, R.Bottom - radius), // 0 -2
|
|
|
|
Point(R.Left + leftDist - radius, R.Bottom - radius), // 8 -2
|
|
|
|
Point(R.Left + leftdist - 1, R.Bottom - radius - 1), // 9 -3
|
|
|
|
Point(R.Left + leftDist - 1, R.Top + radius + 1), // 9 3
|
|
|
|
Point(R.Left + leftDist + 1, R.Top + 1), // 11 1
|
|
|
|
Point(R.Right - 1, R.Top + 1) // -1 1
|
2016-07-17 10:22:25 +00:00
|
|
|
]);
|
|
|
|
|
2018-05-04 22:28:03 +00:00
|
|
|
|
2016-07-17 10:22:25 +00:00
|
|
|
{draw border}
|
|
|
|
Canvas.Pen.Color := clBlack;
|
2018-05-04 22:28:03 +00:00
|
|
|
{
|
2016-07-17 10:22:25 +00:00
|
|
|
Canvas.PolyLine([
|
2018-05-04 22:28:03 +00:00
|
|
|
Point(R.Left, R.Bottom - 1),
|
|
|
|
Point(R.Left + 9, R.Bottom - 1),
|
2016-07-17 10:22:25 +00:00
|
|
|
Point(R.Left + 10, R.Bottom - 2),
|
|
|
|
Point(R.Left + 10, R.Top + 4),
|
|
|
|
Point(R.Left + 11, R.Top + 3),
|
|
|
|
Point(R.Left + 12, R.Top + 2),
|
|
|
|
Point(R.Right - 2, R.Top + 2),
|
|
|
|
Point(R.Right - 1, R.Top + 3),
|
2016-07-17 17:39:55 +00:00
|
|
|
Point(R.Right - 1, R.Bottom - 1)
|
2018-05-04 22:28:03 +00:00
|
|
|
]);}
|
|
|
|
Canvas.PolyLine([
|
|
|
|
Point(R.Left, R.Bottom - 1), // 0 -1
|
|
|
|
Point(R.Left + leftDist - 1, R.Bottom - 1), // 9 -1
|
|
|
|
Point(R.Left + leftDist, R.Bottom - radius), // 10 -2
|
|
|
|
Point(R.Left + leftdist, R.Top + radius + 2), // 10 +4
|
|
|
|
Point(R.Left + leftdist + 1, R.Top + radius + 1), // 11 +3
|
|
|
|
Point(R.Left + leftdist + 2, R.Top + radius), // 12 +2
|
|
|
|
Point(R.Right - radius, R.Top + radius), // -2 +2
|
|
|
|
Point(R.Right - radius + 1, R.Top + radius + 1), // -1 +3
|
|
|
|
Point(R.Right -1, R.Bottom - 1) // -1 -1
|
2016-07-17 17:39:55 +00:00
|
|
|
]);
|
2016-07-17 10:22:25 +00:00
|
|
|
|
2016-07-17 17:39:55 +00:00
|
|
|
Result := Rect(R.Left + 1, R.Top + 2, R.Right - 2, R.Bottom);
|
2016-07-17 10:22:25 +00:00
|
|
|
end;
|
|
|
|
|
2016-07-17 17:39:55 +00:00
|
|
|
procedure TVpNavBarPainter.DrawTab(Canvas: TCanvas; R: TRect; ATabIndex: Integer);
|
2016-07-17 10:22:25 +00:00
|
|
|
var
|
2016-07-17 17:39:55 +00:00
|
|
|
displayTxt: String;
|
2016-07-17 10:22:25 +00:00
|
|
|
TR: TRect;
|
|
|
|
Flags: Integer;
|
2016-07-17 17:39:55 +00:00
|
|
|
folder: TVpNavFolder;
|
|
|
|
savedFontstyle: TFontStyles;
|
2016-07-17 10:22:25 +00:00
|
|
|
begin
|
|
|
|
case FDrawingStyle of
|
|
|
|
dsDefButton:
|
2016-07-17 17:39:55 +00:00
|
|
|
TR := DrawDefButton(Canvas, R, ATabIndex);
|
2016-07-17 10:22:25 +00:00
|
|
|
dsEtchedButton:
|
2016-07-17 17:39:55 +00:00
|
|
|
TR := DrawEtchedButton(Canvas, R,ATabIndex);
|
2016-07-17 10:22:25 +00:00
|
|
|
dsCoolTab:
|
2016-07-17 17:39:55 +00:00
|
|
|
TR := DrawCoolTab(Canvas, R, ATabIndex, FBackgroundColor);
|
2016-07-17 10:22:25 +00:00
|
|
|
dsStandardTab:
|
2016-07-17 17:39:55 +00:00
|
|
|
TR := DrawStandardTab(Canvas, R, ATabIndex, FBackgroundColor);
|
2016-07-17 10:22:25 +00:00
|
|
|
end;
|
|
|
|
|
2016-07-17 17:39:55 +00:00
|
|
|
// if IsMouseOverFolder(ATabIndex) then
|
|
|
|
// OffsetRect(TR, -1, -1);
|
|
|
|
|
|
|
|
//inc(TR.Top);
|
|
|
|
|
|
|
|
folder := FNavBar.Folders[ATabIndex];
|
|
|
|
displayTxt := folder.DisplayName;
|
|
|
|
|
|
|
|
savedFontstyle := Canvas.Font.Style;
|
|
|
|
if folder.Enabled then begin
|
|
|
|
SetBkMode(Canvas.Handle, TRANSPARENT);
|
|
|
|
if IsMouseOverFolder(ATabIndex) then
|
|
|
|
Canvas.Font.Style := Canvas.Font.Style + [fsBold];
|
|
|
|
Flags := DT_CENTER or DT_VCENTER or DT_SINGLELINE or DT_NOPREFIX;
|
|
|
|
DrawText(Canvas.Handle, PChar(displayTxt), Length(displayTxt), TR, Flags);
|
2016-07-17 10:22:25 +00:00
|
|
|
|
2016-07-17 17:39:55 +00:00
|
|
|
if IsMouseOverFolder(ATabIndex) and not nabMouseDown then begin
|
2016-07-17 10:22:25 +00:00
|
|
|
case FDrawingStyle of
|
|
|
|
dsDefButton:
|
|
|
|
begin { Regular button style. }
|
2016-07-17 17:39:55 +00:00
|
|
|
// InflateRect(TR, 1, 1);
|
|
|
|
// inc(TR.Left);
|
|
|
|
// Canvas.Frame3D(TR, 1, bvRaised);
|
2016-07-17 10:22:25 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
dsEtchedButton:
|
|
|
|
begin { Etched style (Outlook98). }
|
2016-07-17 17:39:55 +00:00
|
|
|
// InflateRect(TR, 1, 1);
|
|
|
|
// inc(TR.Top);
|
|
|
|
// inc(TR.Left);
|
|
|
|
// Canvas.Frame3D(TR, 1, bvRaised);
|
|
|
|
{
|
|
|
|
|
2016-07-17 10:22:25 +00:00
|
|
|
Canvas.Pen.Color := clWindowFrame;
|
|
|
|
Canvas.MoveTo(TR.Right - 2, TR.Top);
|
|
|
|
Canvas.LineTo(TR.Right - 2, TR.Bottom - 1);
|
|
|
|
Canvas.LineTo(0, TR.Bottom - 1);
|
|
|
|
Canvas.Pen.Color := clBtnShadow;
|
|
|
|
if ATabIndex = FActiveFolder then
|
|
|
|
lOffset := 1
|
|
|
|
else
|
|
|
|
lOffset := 2;
|
|
|
|
Canvas.MoveTo(TR.Right - 3, TR.Top - 2);
|
|
|
|
Canvas.LineTo(TR.Right - 3, TR.Bottom - lOffset);
|
|
|
|
Canvas.LineTo(1, TR.Bottom - lOffset);
|
|
|
|
if ATabIndex = FActiveFolder then
|
|
|
|
Canvas.Pixels[1, TR.Bottom - lOffset] := clBtnHighlight;
|
2016-07-17 17:39:55 +00:00
|
|
|
}
|
2016-07-17 10:22:25 +00:00
|
|
|
end;
|
|
|
|
end; // case
|
|
|
|
end;
|
2016-07-17 17:39:55 +00:00
|
|
|
|
|
|
|
end
|
|
|
|
else
|
2016-07-17 10:22:25 +00:00
|
|
|
begin
|
|
|
|
{use shadow text for inactive folder text}
|
|
|
|
Canvas.Font.Color := clHighlightText;
|
|
|
|
SetBkMode(Canvas.Handle, OPAQUE);
|
2016-07-17 17:39:55 +00:00
|
|
|
DrawText(Canvas.Handle, PChar(displayTxt), Length(displayTxt), TR, Flags);
|
2016-07-17 10:22:25 +00:00
|
|
|
SetBkMode(Canvas.Handle, TRANSPARENT);
|
|
|
|
Canvas.Font.Color := clBtnShadow;
|
|
|
|
OffsetRect(TR, -2, -1);
|
2016-07-17 17:39:55 +00:00
|
|
|
DrawText(Canvas.Handle, PChar(displayTxt), Length(displayTxt), TR, Flags);
|
2016-07-17 10:22:25 +00:00
|
|
|
Canvas.Font.Color := FNavBar.Font.Color;
|
|
|
|
end;
|
2016-07-17 17:39:55 +00:00
|
|
|
Canvas.Font.Style := savedFontStyle;
|
2016-07-17 10:22:25 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TVpNavBarPainter.DrawTopFolderButtons(Canvas: TCanvas;
|
|
|
|
ARect: TRect; DrawFolder: Boolean; var CurPos: Integer);
|
|
|
|
var
|
|
|
|
I: Integer;
|
|
|
|
MyRect: TRect;
|
|
|
|
begin
|
|
|
|
CurPos := 0;
|
|
|
|
MyRect := ARect;
|
|
|
|
|
|
|
|
{ Draw the folder buttons at the top }
|
|
|
|
if DrawFolder then begin
|
|
|
|
for I := 0 to FActiveFolder do begin
|
|
|
|
MyRect.Top := CurPos;
|
|
|
|
MyRect.Bottom := CurPos + FButtonHeight;
|
|
|
|
FNavBar.Folders[I].Rect := MyRect;
|
|
|
|
|
|
|
|
{Draw the top tabs based on the selected style...}
|
2016-07-17 17:39:55 +00:00
|
|
|
DrawTab(Canvas, MyRect, I);
|
2016-07-17 10:22:25 +00:00
|
|
|
Inc(CurPos, FButtonHeight);
|
|
|
|
end;
|
|
|
|
end else begin
|
|
|
|
if FDrawingStyle = dsEtchedButton then begin
|
|
|
|
{ Draw border around control. }
|
|
|
|
Canvas.Pen.Color := clBtnHighlight;
|
|
|
|
Canvas.MoveTo(FNavBar.Width - 1, FNavBar.Top);
|
|
|
|
Canvas.LineTo(FNavBar.Width - 1, FNavBar.Height - 1);
|
|
|
|
Canvas.LineTo(0, FNavBar.Height - 1);
|
|
|
|
Canvas.Pen.Color := clWindowFrame;
|
|
|
|
Canvas.MoveTo(0, FNavBar.Height - 1);
|
|
|
|
Canvas.LineTo(0, 1);
|
|
|
|
Canvas.LineTo(FNavBar.Width - 2, 1);
|
|
|
|
end;
|
|
|
|
CurPos := 0;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2016-07-17 17:39:55 +00:00
|
|
|
function TVpNavBarPainter.IsFocused(ATabIndex: Integer): Boolean;
|
|
|
|
begin
|
|
|
|
Result := ATabIndex = FHotFolder;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TVpNavBarPainter.IsMouseOverFolder(ATabIndex: Integer): Boolean;
|
|
|
|
begin
|
|
|
|
Result := ATabIndex = FHotFolder;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TVpNavBarPainter.IsMouseOverItem(ATabIndex: Integer): Boolean;
|
|
|
|
begin
|
|
|
|
Result := ATabIndex = nabLastMouseOverItem;
|
|
|
|
end;
|
|
|
|
|
2016-07-17 10:22:25 +00:00
|
|
|
procedure TVpNavBarPainter.Paint;
|
|
|
|
var
|
|
|
|
DrawBmp: TBitmap;
|
|
|
|
DrawFolder: Boolean;
|
|
|
|
TR: TRect;
|
2016-07-18 20:40:50 +00:00
|
|
|
CurPos: Integer = 0;
|
2016-07-17 10:22:25 +00:00
|
|
|
MyRect: TRect;
|
|
|
|
begin
|
|
|
|
MyRect := FNavBar.ClientRect;
|
|
|
|
|
|
|
|
DrawBmp := TBitmap.Create;
|
|
|
|
try
|
|
|
|
DrawBmp.Width := FClientWidth;
|
|
|
|
DrawBmp.Height := FClientHeight;
|
2018-05-02 15:52:08 +00:00
|
|
|
DrawBmp.Transparent := false;
|
2016-07-17 10:22:25 +00:00
|
|
|
|
|
|
|
DrawBmp.Canvas.Font := FNavBar.Font;
|
|
|
|
DrawBmp.Canvas.Pen.Color := FBackgroundColor;
|
|
|
|
DrawBmp.Canvas.Brush.Color := FBackgroundColor;
|
|
|
|
|
|
|
|
DrawFolder := (FNavBar.FolderCount > 0);
|
|
|
|
if DrawFolder then
|
|
|
|
TR := FFolderArea
|
|
|
|
else
|
|
|
|
TR := FNavBar.ClientRect;
|
|
|
|
|
|
|
|
DrawBackground(DrawBmp.Canvas, TR);
|
|
|
|
|
2018-05-04 22:28:03 +00:00
|
|
|
{ Draw background }
|
2016-07-17 10:22:25 +00:00
|
|
|
if FNavBar.FolderCount = 0 then begin
|
|
|
|
nabScrollUpBtn.Visible := False;
|
|
|
|
nabScrollDownBtn.Visible := False;
|
2018-05-02 15:52:08 +00:00
|
|
|
FNavBar.Canvas.CopyMode := cmSrcCopy;
|
|
|
|
FNavBar.Canvas.CopyRect(MyRect, DrawBmp.Canvas, Rect(0, 0, DrawBmp.Width,DrawBmp.Height));
|
2016-07-17 10:22:25 +00:00
|
|
|
Exit;
|
|
|
|
end;
|
|
|
|
|
|
|
|
{ Draw the folder buttons at the top }
|
|
|
|
DrawTopFolderButtons(DrawBmp.Canvas, MyRect, DrawFolder, CurPos);
|
|
|
|
|
|
|
|
{ Draw active folder items }
|
|
|
|
DrawActiveFolderItems(DrawBmp.Canvas, CurPos);
|
|
|
|
|
|
|
|
{ Draw the folder buttons at the bottom }
|
|
|
|
DrawBottomFolderButtons(DrawBmp.Canvas, MyRect, CurPos);
|
|
|
|
|
2016-07-17 17:39:55 +00:00
|
|
|
{ Copy the buffer bitmap to the control }
|
2016-07-17 10:22:25 +00:00
|
|
|
FNavBar.Canvas.CopyMode := cmSrcCopy;
|
2018-05-04 22:28:03 +00:00
|
|
|
FNavBar.Canvas.CopyRect(MyRect, DrawBmp.Canvas, Rect(0, 0, DrawBmp.Width, DrawBmp.Height));
|
2016-07-17 10:22:25 +00:00
|
|
|
|
2016-07-18 20:24:58 +00:00
|
|
|
{ Show/hide scroll buttons }
|
|
|
|
ProcessScrollButtons;
|
|
|
|
|
|
|
|
finally
|
2016-07-17 10:22:25 +00:00
|
|
|
DrawBmp.Free;
|
|
|
|
end;
|
|
|
|
end;
|
2016-07-17 17:39:55 +00:00
|
|
|
|
2016-07-18 20:24:58 +00:00
|
|
|
procedure TVpNavBarPainter.ProcessScrollButtons;
|
2018-05-04 22:28:03 +00:00
|
|
|
const
|
|
|
|
DISTANCE = 5;
|
|
|
|
var
|
|
|
|
dist: Integer;
|
|
|
|
w, h: Integer;
|
2016-07-18 20:24:58 +00:00
|
|
|
begin
|
|
|
|
if not (csDesigning in FNavBar.ComponentState) then begin
|
2018-05-04 22:28:03 +00:00
|
|
|
dist := ScaleY(DISTANCE, DesignTimeDPI);
|
|
|
|
|
2016-07-18 20:24:58 +00:00
|
|
|
{show the top scroll button}
|
|
|
|
if TVpNavBarOpener(FNavBar).nabShowScrollUp() then begin
|
2018-05-04 22:28:03 +00:00
|
|
|
w := nabScrollUpBtn.Width;
|
|
|
|
nabScrollUpBtn.Top := FNavBar.Folders[FActiveFolder].Rect.Bottom + dist;
|
|
|
|
nabScrollUpBtn.Left := FNavBar.ClientWidth - w - dist;
|
2016-07-18 20:24:58 +00:00
|
|
|
nabScrollUpBtn.Visible := True;
|
|
|
|
end else
|
|
|
|
nabScrollUpBtn.Visible := False;
|
|
|
|
|
|
|
|
{show the bottom scroll button}
|
|
|
|
if TVpNavBarOpener(FnavBar).nabShowScrollDown() then begin
|
2018-05-04 22:28:03 +00:00
|
|
|
w := nabScrollDownBtn.Width;
|
|
|
|
h := nabScrollDownBtn.Height;
|
2016-07-18 20:24:58 +00:00
|
|
|
if FActiveFolder = FNavBar.FolderCount-1 then
|
|
|
|
{there are no folders beyond the active one}
|
2018-05-04 22:28:03 +00:00
|
|
|
nabScrollDownBtn.Top := FNavBar.ClientHeight - h - dist
|
2016-07-18 20:24:58 +00:00
|
|
|
else
|
2018-05-04 22:28:03 +00:00
|
|
|
nabScrollDownBtn.Top := FNavBar.Folders[FActiveFolder+1].Rect.Top - h - dist;
|
|
|
|
nabScrollDownBtn.Left := FNavBar.ClientWidth - w - dist;
|
2016-07-18 20:24:58 +00:00
|
|
|
nabScrollDownBtn.Visible := True;
|
|
|
|
end else
|
|
|
|
nabScrollDownBtn.Visible := False;
|
|
|
|
end;
|
|
|
|
end;
|
2016-07-17 10:22:25 +00:00
|
|
|
|
|
|
|
{ Given a string, and a rectangle, find the string that can be displayed
|
|
|
|
using two lines. Add ellipsis to the end of each line if necessary and
|
|
|
|
possible}
|
|
|
|
function GetLargeIconDisplayName(Canvas: TCanvas; Rect: TRect;
|
|
|
|
const Name: string): string;
|
|
|
|
var
|
|
|
|
TestRect: TRect;
|
|
|
|
SH, DH: Integer;
|
|
|
|
Buf: array[0..255] of Char;
|
|
|
|
I: Integer;
|
|
|
|
TempName: string;
|
|
|
|
Temp2: string;
|
|
|
|
begin
|
|
|
|
TempName := Trim(Name);
|
|
|
|
{get single line height}
|
|
|
|
with TestRect do begin
|
|
|
|
Left := 0;
|
|
|
|
Top := 0;
|
|
|
|
Right := 1;
|
|
|
|
Bottom := 1;
|
|
|
|
end;
|
|
|
|
SH := DrawText(Canvas.Handle, 'W W', 3, TestRect, DT_SINGLELINE or DT_CALCRECT);
|
|
|
|
|
|
|
|
{get double line height}
|
|
|
|
with TestRect do begin
|
|
|
|
Left := 0;
|
|
|
|
Top := 0;
|
|
|
|
Right := 1;
|
|
|
|
Bottom := 1;
|
|
|
|
end;
|
|
|
|
DH := DrawText(Canvas.Handle, 'W W', 3, TestRect, DT_WORDBREAK or DT_CALCRECT);
|
|
|
|
|
|
|
|
{see if the text can fit within the existing rect without growing}
|
|
|
|
TestRect := Rect;
|
|
|
|
StrPLCopy(Buf, TempName, 255);
|
|
|
|
DrawText(Canvas.Handle, Buf, Length(TempName), TestRect, DT_WORDBREAK or DT_CALCRECT);
|
|
|
|
I := Pos(' ', TempName);
|
|
|
|
if (HeightOf(TestRect) = SH) or (I < 2) then
|
|
|
|
Result := GetDisplayString(Canvas, TempName, 1, WidthOf(Rect))
|
|
|
|
else begin
|
|
|
|
{the first line only has ellipsis if there's only one word on it and
|
|
|
|
that word won't fit}
|
|
|
|
Temp2 := GetDisplayString(Canvas, Copy(TempName, 1, I-1), 1, WidthOf(Rect));
|
|
|
|
if CompareStr(Temp2, Copy(TempName, 1, I-1)) <> 0 then begin
|
|
|
|
Result := GetDisplayString(Canvas, Copy(TempName, 1, I-1), 1, WidthOf(Rect)) + ' ' +
|
|
|
|
GetDisplayString(Canvas, Copy(TempName, I+1, Length(TempName) - I), 1, WidthOf(Rect));
|
|
|
|
end else begin
|
|
|
|
{2 or more lines, and the first line isn't getting an ellipsis}
|
|
|
|
if (HeightOf(TestRect) = DH) and (WidthOF(TestRect) <= WidthOf(Rect)) then
|
|
|
|
{it will fit}
|
|
|
|
Result := TempName
|
|
|
|
else begin
|
|
|
|
{it won't fit, but the first line wraps OK - 2nd line needs an ellipsis}
|
|
|
|
TestRect.Right := Rect.Right + 1;
|
|
|
|
while (WidthOf(TestRect) > WidthOf(Rect)) or (HeightOf(TestRect) > DH) do
|
|
|
|
begin
|
|
|
|
if Length(TempName) > 1 then begin
|
|
|
|
TestRect := Rect;
|
|
|
|
Delete(TempName, Length(TempName), 1);
|
|
|
|
TempName := Trim(TempName);
|
|
|
|
StrPLCopy(Buf, TempName + '...', 255);
|
|
|
|
DrawText(Canvas.Handle, Buf, Length(TempName) + 3, TestRect, DT_WORDBREAK or DT_CALCRECT);
|
|
|
|
Result := TempName + '...';
|
|
|
|
end else begin
|
|
|
|
Result := TempName + '..';
|
|
|
|
TestRect := Rect;
|
|
|
|
StrPLCopy(Buf, Result, 255);
|
|
|
|
DrawText(Canvas.Handle, Buf, Length(Result), TestRect, DT_WORDBREAK or DT_CALCRECT);
|
|
|
|
if (WidthOf(TestRect) <= WidthOf(Rect)) and (HeightOf(TestRect) > DH) then
|
|
|
|
Break;
|
|
|
|
Result := TempName + '.';
|
|
|
|
TestRect := Rect;
|
|
|
|
StrPLCopy(Buf, Result, 255);
|
|
|
|
DrawText(Canvas.Handle, Buf, Length(Result), TestRect, DT_WORDBREAK or DT_CALCRECT);
|
|
|
|
if (WidthOf(TestRect) <= WidthOf(Rect)) and (HeightOf(TestRect) > DH) then
|
|
|
|
Break;
|
|
|
|
Result := TempName;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
end.
|
|
|
|
|