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}
|
|
|
|
LMessages, LCLProc, LCLType, LCLIntf,
|
|
|
|
{$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;
|
|
|
|
|
|
|
|
nabItemsRect: PRect;
|
|
|
|
nabLastMouseOverItem: Integer;
|
|
|
|
nabMouseDown: Boolean;
|
|
|
|
nabScrollUpBtn: TSpeedButton;
|
|
|
|
nabScrollDownBtn: TSpeedButton;
|
|
|
|
nabTopItem: Integer;
|
|
|
|
|
|
|
|
FFolderArea: TRect;
|
|
|
|
bkMode: Integer;
|
|
|
|
|
|
|
|
procedure DrawBackground(Canvas: TCanvas; R: TRect);
|
2016-07-17 17:39:55 +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;
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
public
|
|
|
|
constructor Create(ANavBar: TVpCustomNavBar);
|
|
|
|
procedure Paint;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function GetLargeIconDisplayName(Canvas: TCanvas; Rect: TRect; const Name: string): string;
|
|
|
|
|
|
|
|
implementation
|
|
|
|
|
|
|
|
uses
|
|
|
|
Themes,
|
|
|
|
VpMisc;
|
|
|
|
|
|
|
|
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;
|
|
|
|
FButtonHeight := TVpNavBarOpener(FNavBar).ButtonHeight;
|
|
|
|
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);
|
|
|
|
var
|
|
|
|
folder: TVpNavFolder;
|
|
|
|
item: TVpNavBtnItem;
|
|
|
|
J: Integer;
|
|
|
|
text: String;
|
|
|
|
W, H, X: Integer;
|
|
|
|
R: TRect;
|
|
|
|
Buf: array[0..255] of Char;
|
|
|
|
labelWidth: Integer;
|
|
|
|
lOffset: Integer;
|
|
|
|
bmp: TBitmap;
|
|
|
|
begin
|
|
|
|
folder := FNavBar.Folders[FActiveFolder];
|
|
|
|
|
|
|
|
if folder.FolderType = ftDefault then begin
|
|
|
|
if folder.ItemCount = 0 then
|
|
|
|
exit;
|
|
|
|
|
|
|
|
Inc(CurPos, 8);
|
|
|
|
|
|
|
|
with nabItemsRect^ do begin
|
|
|
|
Top := CurPos;
|
|
|
|
Left := 0;
|
|
|
|
Right := FNavBar.ClientWidth;
|
|
|
|
Bottom := FNavBar.ClientHeight - (FNavBar.FolderCount - FActiveFolder - 1) * FButtonHeight + 1;
|
|
|
|
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];
|
|
|
|
{ If the caption is empty at designtime then display the item's name instead }
|
|
|
|
if (csDesigning in FNavBar.ComponentState) and (item.Caption = '') then
|
|
|
|
text := item.Name
|
|
|
|
else
|
|
|
|
text := item.Caption;
|
|
|
|
|
|
|
|
{ Large icons }
|
|
|
|
if folder.IconSize = isLarge then begin
|
|
|
|
if Assigned(FImages) then begin
|
|
|
|
W := FImages.Width + 2;
|
|
|
|
H := FImages.Height + 2;
|
|
|
|
end else begin
|
|
|
|
W := 32;
|
|
|
|
H := 32;
|
|
|
|
end;
|
|
|
|
{ glyph is at the top }
|
|
|
|
{ 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. }
|
|
|
|
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
|
|
|
|
break;
|
|
|
|
item.IconRect := R;
|
|
|
|
|
|
|
|
if FShowButtons then begin
|
|
|
|
if FActiveItem = J then 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);
|
|
|
|
end else begin
|
|
|
|
Canvas.Pen.Color := FBackgroundColor;
|
|
|
|
Canvas.Brush.Color := FBackgroundColor;
|
|
|
|
end;
|
|
|
|
|
|
|
|
if Assigned(FImages) and (item.IconIndex >= 0) and (item.IconIndex < FImages.Count) then
|
|
|
|
FImages.Draw(Canvas, R.Left + 2, R.Top + 2, item.IconIndex);
|
|
|
|
|
|
|
|
{make the icon's bottom blend into the label's top}
|
|
|
|
R := item.IconRect;
|
|
|
|
inc(R.Bottom, 4);
|
|
|
|
item.IconRect := R;
|
|
|
|
end;
|
|
|
|
|
|
|
|
Inc(CurPos, H + 4);
|
|
|
|
|
|
|
|
{now, draw the text}
|
|
|
|
R.Top := CurPos;
|
|
|
|
R.Bottom := CurPos + FButtonHeight div 2 - 7;
|
|
|
|
R.Left := 0;
|
|
|
|
R.Right := FNavBar.ClientWidth - 1;
|
|
|
|
item.LabelRect := R;
|
|
|
|
item.DisplayName := GetLargeIconDisplayName(Canvas, R, text);
|
|
|
|
X := Canvas.TextWidth(item.DisplayName);
|
|
|
|
R.Left := (FNavBar.ClientWidth - X) div 2;
|
|
|
|
if R.Left < 5 then
|
|
|
|
R.Left := 5;
|
|
|
|
R.Right := R.Left + X;
|
|
|
|
if R.Right > FnavBar.ClientWidth - 5 then
|
|
|
|
R.Right := FNavBar.ClientWidth - 5;
|
|
|
|
item.LabelRect := R;
|
|
|
|
if R.Top > nabItemsRect^.Bottom then
|
|
|
|
Break;
|
|
|
|
|
|
|
|
StrPLCopy(Buf, item.DisplayName, 255);
|
|
|
|
DrawText(Canvas.Handle, Buf, Length(item.DisplayName), R,
|
|
|
|
DT_CENTER or DT_VCENTER or DT_WORDBREAK or DT_CALCRECT);
|
|
|
|
labelWidth := WidthOf(R);
|
|
|
|
R.Left := (FNavBar.ClientWidth - labelWidth) div 2;
|
|
|
|
R.Right := R.Left + labelWidth + 1;
|
|
|
|
item.LabelRect := R;
|
|
|
|
|
|
|
|
bkMode := SetBkMode(Canvas.Handle, TRANSPARENT);
|
|
|
|
X := DrawText(Canvas.Handle, Buf, Length(item.DisplayName), R, DT_CENTER or DT_VCENTER or DT_WORDBREAK);
|
|
|
|
inc(CurPos, X);
|
|
|
|
SetBkMode(Canvas.Handle, bkMode);
|
|
|
|
|
|
|
|
Inc(CurPos, FItemSpacing);
|
|
|
|
end
|
|
|
|
else
|
|
|
|
{ Small Icons }
|
|
|
|
begin
|
|
|
|
W := 16;
|
|
|
|
H := 16;
|
|
|
|
{glyph is at the left}
|
|
|
|
R.Top := CurPos;
|
|
|
|
lOffset := abs(Canvas.Font.Height) div 2;
|
|
|
|
if lOffset > 8 then
|
|
|
|
R.Top := R.Top + lOffset - 8;
|
|
|
|
R.Bottom := R.Top + H;
|
|
|
|
R.Left := 8;
|
|
|
|
R.Right := R.Left + W;
|
|
|
|
item.IconRect := R;
|
|
|
|
if R.Top > nabItemsRect^.Bottom then
|
|
|
|
Break;
|
|
|
|
|
|
|
|
if FShowButtons then begin
|
|
|
|
if FActiveItem = J then 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 else begin
|
|
|
|
Canvas.Pen.Color := FBackgroundColor;
|
|
|
|
Canvas.Brush.Color := FBackgroundColor;
|
|
|
|
Canvas.Rectangle(R.Left - 1, R.Top - 1, R.Right + 1, R.Bottom + 1);
|
|
|
|
end;
|
|
|
|
if Assigned(FImages) then begin
|
|
|
|
bmp := TBitmap.Create;
|
|
|
|
try
|
|
|
|
bmp.Width := FImages.Width;
|
|
|
|
bmp.Height := FImages.Height;
|
|
|
|
FImages.Draw(bmp.Canvas, 0, 0, item.IconIndex);
|
|
|
|
Canvas.BrushCopy(item.IconRect, bmp, Rect(0, 0, bmp.Width, bmp.Height), bmp.Canvas.Pixels[0, bmp.Height-1]);
|
|
|
|
|
|
|
|
//TODO: DrawBmp.Canvas.BrushCopy(Item.FIconRect, BM,
|
|
|
|
// Rect(0, 0, BM.Width, BM.Height), BM.Canvas.Pixels[0,
|
|
|
|
// BM.Height-1]);
|
|
|
|
finally
|
|
|
|
bmp.Free;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
{make the icon's right blend into the label's left}
|
|
|
|
R := item.IconRect;
|
|
|
|
inc(R.Right, 3);
|
|
|
|
item.IconRect := R;
|
|
|
|
|
|
|
|
{now, draw the text}
|
|
|
|
R.Top := CurPos;
|
|
|
|
R.Bottom := CurPos + FButtonHeight div 2 - 7;
|
|
|
|
R.Left := item.IconRect.Right;
|
|
|
|
X := FNavBar.ClientWidth - R.Left - 7;
|
|
|
|
R.Right := R.Left + X;
|
|
|
|
item.LabelRect := R;
|
|
|
|
if R.Top > nabItemsRect^.Bottom then
|
|
|
|
Break;
|
|
|
|
|
|
|
|
R := item.LabelRect;
|
|
|
|
item.DisplayName := GetDisplayString(Canvas, Text, 1, WidthOf(R));
|
|
|
|
StrPLCopy(Buf, item.DisplayName, 255);
|
|
|
|
DrawText(Canvas.Handle, Buf, Length(item.DisplayName), R, DT_LEFT or DT_VCENTER or DT_CALCRECT);
|
|
|
|
labelWidth := WidthOf(R);
|
|
|
|
R.Right := R.Left + labelWidth + 1;
|
|
|
|
item.LabelRect := R;
|
2016-07-17 20:05:36 +00:00
|
|
|
X := DrawText(Canvas.Handle, Buf, Length(item.DisplayName), R, DT_LEFT or DT_VCENTER);
|
|
|
|
if X < H then X := H;
|
2016-07-17 10:22:25 +00:00
|
|
|
|
2016-07-17 20:05:36 +00:00
|
|
|
Inc(CurPos, FItemSpacing + X);
|
2016-07-17 10:22:25 +00:00
|
|
|
end; { Small icons }
|
|
|
|
end; { for J }
|
|
|
|
end; { if folder.FolderType = ftDefault }
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TVpNavBarPainter.DrawBackground(Canvas: TCanvas; R: TRect);
|
|
|
|
var
|
|
|
|
rowStart: Integer;
|
|
|
|
lLeft, lHeight, lWidth: Integer;
|
|
|
|
begin
|
|
|
|
if FBackgroundImage.Empty or (FBackgroundMethod = bmNone) then
|
|
|
|
begin
|
|
|
|
Canvas.Pen.Color := FBackgroundColor;
|
|
|
|
Canvas.Brush.Color := FBackgroundColor;
|
|
|
|
Canvas.Rectangle(R.Left, R.Top, R.Right, R.Bottom);
|
|
|
|
end else
|
|
|
|
begin
|
|
|
|
case FBackgroundMethod of
|
|
|
|
bmNormal:
|
|
|
|
Canvas.Draw(R.Left, R.Top, FBackgroundImage);
|
|
|
|
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-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
|
|
|
|
|
|
|
{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}
|
|
|
|
{$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 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-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);
|
|
|
|
end;
|
|
|
|
//TODO: TR := DrawButtonFace(DrawBmp.Canvas, MyRect, 1, bsNew, False,
|
|
|
|
// (I = FHotFolder) and nabMouseDown, False);
|
|
|
|
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-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-17 10:22:25 +00:00
|
|
|
end;
|
|
|
|
Result := R;
|
|
|
|
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;
|
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
|
|
|
|
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([
|
|
|
|
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)
|
|
|
|
]);
|
|
|
|
|
|
|
|
{highlight tab}
|
|
|
|
Canvas.Pen.Color := clBtnHighlight;
|
|
|
|
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)
|
|
|
|
]);
|
|
|
|
|
|
|
|
{draw border}
|
|
|
|
Canvas.Pen.Color := clBlack;
|
|
|
|
Canvas.PolyLine([
|
|
|
|
Point(R.Left, R.Bottom - 1),
|
|
|
|
Point(R.Left + 9, R.Bottom - 1),
|
|
|
|
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)
|
|
|
|
]);
|
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;
|
|
|
|
lOffset: 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;
|
|
|
|
CurPos: Integer;
|
|
|
|
I: Integer;
|
|
|
|
MyRect: TRect;
|
|
|
|
begin
|
|
|
|
MyRect := FNavBar.ClientRect;
|
|
|
|
|
|
|
|
DrawBmp := TBitmap.Create;
|
|
|
|
try
|
|
|
|
DrawBmp.Width := FClientWidth;
|
|
|
|
DrawBmp.Height := FClientHeight;
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
{ Draw background }
|
|
|
|
DrawBackground(DrawBmp.Canvas, TR);
|
|
|
|
|
|
|
|
if FNavBar.FolderCount = 0 then begin
|
|
|
|
nabScrollUpBtn.Visible := False;
|
|
|
|
nabScrollDownBtn.Visible := False;
|
|
|
|
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;
|
2016-07-17 17:39:55 +00:00
|
|
|
FNavBar.Canvas.CopyRect(MyRect, DrawBmp.Canvas, MyRect);
|
2016-07-17 10:22:25 +00:00
|
|
|
|
|
|
|
finally
|
|
|
|
DrawBmp.Free;
|
|
|
|
end;
|
|
|
|
end;
|
2016-07-17 17:39:55 +00:00
|
|
|
|
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.
|
|
|
|
|