mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-27 00:22:01 +02:00
dockmanager example: improved dock header appearance
git-svn-id: trunk@20039 -
This commit is contained in:
parent
acff2b0a67
commit
9705705ec7
@ -5,6 +5,7 @@
|
||||
<Version Value="7"/>
|
||||
<General>
|
||||
<Flags>
|
||||
<AlwaysBuild Value="False"/>
|
||||
<LRSInOutputDirectory Value="False"/>
|
||||
</Flags>
|
||||
<SessionStorage Value="InProjectDir"/>
|
||||
|
@ -5,7 +5,16 @@ This project can be used instead of the LDockTree manager.
|
||||
|
||||
To be added or ported:
|
||||
- field and method argument names
|
||||
- persistence
|
||||
|
||||
Possible extensions:
|
||||
- separate docking management and dock site layout
|
||||
- various dock headers
|
||||
- multiple splitters (on zones without controls)
|
||||
- persistence (requires application wide management of dock sources!)
|
||||
- purpose of Restore button?
|
||||
|
||||
Known bugs:
|
||||
- Problem with dragging header, seems to interfere with dragmanager (capture)?
|
||||
|
||||
More issues, concerning the rest of the LCL (mainly unit Controls):
|
||||
|
||||
@ -18,11 +27,19 @@ LCL TODO:
|
||||
becomes a DockSite.
|
||||
|
||||
LCL does not handle docking managers as interfaces.
|
||||
(this will most probably never come)
|
||||
|
||||
LCL undocks a control when it just is clicked.
|
||||
LCL undocks a control when it just is clicked. (Delphi flaw)
|
||||
|
||||
LCL controls don't notify the dock manager about visibility changes.
|
||||
|
||||
LCL doesn't handle properly the possible start of a drag operation (WM_LBUTTONDOWN).
|
||||
In DragMode=dmAutomatic the drag manager should capture mouse input.
|
||||
When an LB_UP occurs while waiting for the threshold, a normal Click should
|
||||
occur (perform LB_DOWN and LB_UP).
|
||||
Otherwise dragging starts, and the control has to be reset into "no button down"
|
||||
state.
|
||||
|
||||
done? (unclear whether this is really fixed in the trunk)
|
||||
=====
|
||||
LCL does not notify the docking manager of a resized dock site.
|
||||
@ -31,8 +48,10 @@ done? (unclear whether this is really fixed in the trunk)
|
||||
|
||||
{$H+}
|
||||
|
||||
{$DEFINE splitter_color} //use colored splitter, for debugging?
|
||||
{.$DEFINE splitter_color} //use colored splitter, for debugging?
|
||||
{.$DEFINE NoDrop} //patched dragobject?
|
||||
{.$DEFINE visibility} //handling of invisible clients deserves dock manager notification!
|
||||
{.$DEFINE restore} //restore button?
|
||||
|
||||
interface
|
||||
|
||||
@ -75,7 +94,7 @@ type
|
||||
PartRect: TRect;
|
||||
public
|
||||
constructor Create;
|
||||
class function GetRectOfPart(AHeaderRect: TRect; AOrientation: TDockOrientation; APart: TEasyZonePart; HasSplitter: boolean): TRect; virtual;
|
||||
class function GetRectOfPart(ARect: TRect; AOrientation: TDockOrientation; APart: TEasyZonePart; HasSplitter: boolean): TRect; virtual;
|
||||
function FindPart(AZone: TEasyZone; MousePos: TPoint; fButtonDown: boolean): TEasyZonePart;
|
||||
procedure Draw(AZone: TEasyZone; ACanvas: TCanvas; ACaption: string; const MousePos: TPoint);
|
||||
end;
|
||||
@ -336,10 +355,14 @@ end;
|
||||
procedure TEasyTree.AdjustDockRect(Control: TControl; var ARect: TRect);
|
||||
begin
|
||||
//get the client area within the given zone rectangle
|
||||
{$IFDEF old}
|
||||
if Control.DockOrientation = doVertical then
|
||||
inc(ARect.Top, DockHeaderSize)
|
||||
else
|
||||
inc(ARect.Left, DockHeaderSize);
|
||||
{$ELSE}
|
||||
ARect := FHeader.GetRectOfPart(ARect, Control.DockOrientation, zpClient, true);
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
function TEasyTree.FindControlZone(zone: TEasyZone; Control: TControl): TEasyZone;
|
||||
@ -700,17 +723,25 @@ begin
|
||||
{$ENDIF}
|
||||
zpCloseButton:
|
||||
begin
|
||||
{$IFDEF visibility}
|
||||
//handling of invisible clients deserves dock manager notification!
|
||||
if Control is TCustomForm then
|
||||
TCustomForm(Control).Close
|
||||
else // not a form => doesnot have close => just hide
|
||||
Control.Visible := False;
|
||||
DockSite.Invalidate;
|
||||
{$ELSE}
|
||||
Control.ManualDock(nil, nil, alNone); //do float
|
||||
{$ENDIF}
|
||||
end;
|
||||
end;
|
||||
LM_LBUTTONDOWN:
|
||||
case FindZone(False) of
|
||||
zpCaption: // mouse down on not buttons => start drag
|
||||
Control.BeginDrag(False);
|
||||
begin //problem here - app hangs!
|
||||
DebugLn('start dragging from header: %s', [FDockSite.GetDockCaption(Control)]);
|
||||
Control.BeginDrag(False);
|
||||
end;
|
||||
end;
|
||||
LM_MOUSEMOVE:
|
||||
begin //what's Message.Keys???
|
||||
@ -1290,10 +1321,10 @@ begin
|
||||
*)
|
||||
BR := TLBR.BottomRight;
|
||||
if ChildControl <> nil then begin //is control zone
|
||||
FTree.AdjustDockRect(ChildControl, TLBR);
|
||||
//FTree.AdjustDockRect(ChildControl, TLBR);
|
||||
TLBR := FTree.FHeader.GetRectOfPart(TLBR, ChildControl.DockOrientation, zpClient, HasSizer);
|
||||
ChildControl.BoundsRect := TLBR;
|
||||
end else if FirstChild <> nil then begin
|
||||
//if Orientation = doVertical then TLBR.;
|
||||
z := FirstChild;
|
||||
while z <> nil do begin
|
||||
//resize - for splitter move only!
|
||||
|
@ -37,106 +37,149 @@ end;
|
||||
|
||||
{ TEasyDockHeader }
|
||||
|
||||
const
|
||||
type
|
||||
TZonePartMap = record
|
||||
dTop, dBottom, dLeft, dRight: integer;
|
||||
end;
|
||||
|
||||
const //zone decoration sizes
|
||||
dSizer = 4;
|
||||
dBorder = 2; //frame and inner bevel
|
||||
dDist = 1; //button distance
|
||||
{$IFDEF newsplitter}
|
||||
dHeader = 22 - dSizer; //splitter outside header!
|
||||
dButton = 14; //include some space for themes
|
||||
dHeader = dButton + 2*dBorder; // 22 - dSizer; //splitter outside header!
|
||||
|
||||
(* Zone part map.
|
||||
In portrait mode (header on top), the zone rectangle is adjusted according
|
||||
to the given offsets. In landscape mode (header on the left), the offsets
|
||||
have to be applied to the rotated coordinates.
|
||||
|
||||
Positive offsets mean self-relative adjustment, towards the opposite edge.
|
||||
This operation has highest precedence.
|
||||
Negative offsets mean adjustment relative to the adjusted opposite edge.
|
||||
|
||||
zpAll excludes the splitter and client area.
|
||||
zpCaption excludes borders and buttons from zpAll.
|
||||
*)
|
||||
{$IFDEF newSplitter}
|
||||
(*
|
||||
The map reflects new splitter placement (past client area),
|
||||
and no restore button.
|
||||
*)
|
||||
HeaderPartMap: array[TEasyZonePart] of TZonePartMap = (
|
||||
(), //zpNowhere
|
||||
(dTop:dHeader; dBottom:0), //zpClient
|
||||
(dTop:0; dBottom:-dHeader), //zpAll
|
||||
(dTop:dBorder; dBottom:-dButton; dLeft:dBorder; dRight:dBorder+dButton), //zpCaption
|
||||
(dTop:-dSizer), //zpSizer
|
||||
{$IFDEF restore}
|
||||
(...), //zpRestoreButton
|
||||
{$ENDIF}
|
||||
(dTop:dBorder; dBottom:-dButton; dLeft:-dButton; dRight:dBorder) //zpCloseButton
|
||||
);
|
||||
{$ELSE}
|
||||
dHeader = 22;
|
||||
(* Sizer in header, just before caption
|
||||
*)
|
||||
HeaderPartMap: array[TEasyZonePart] of TZonePartMap = (
|
||||
(), //zpNowhere - not in any zone
|
||||
(dTop:dHeader+dSizer; dBottom:0), //zpClient - on client control
|
||||
(dTop:dSizer; dBottom:-dHeader), //zpAll - total header rect
|
||||
(dTop:dSizer+dBorder; dBottom:-dButton; dLeft:dBorder; dRight:dBorder+dButton), //zpCaption
|
||||
(dTop:0; dBottom:-dSizer), //zpSizer - splitter/sizer
|
||||
{$IFDEF restore}
|
||||
(dTop:dSizer+dBorder; dBottom:-dButton; dLeft:-dButton; dRight:dButton+2*dBorder) //zpRestoreButton, // header restore button
|
||||
{$ENDIF}
|
||||
(dTop:dSizer+dBorder; dBottom:-dButton; dLeft:-dButton; dRight:dBorder) //zpCloseButton // header close button
|
||||
);
|
||||
{$ENDIF}
|
||||
|
||||
constructor TEasyDockHeader.Create;
|
||||
{
|
||||
|
||||
procedure dump;
|
||||
var
|
||||
r, r2: TRect;
|
||||
const
|
||||
hc = true;
|
||||
orn = doVertical;
|
||||
begin
|
||||
r := Rect(0, 0, 200, HeaderSize); //LTBR
|
||||
r2 := GetRectOfPart(r, doVertical, zpCaption);
|
||||
r := Rect(0, 0, 200, 200); //LTBR
|
||||
r2 := GetRectOfPart(r, orn, zpAll, hc);
|
||||
DebugLn('%s (%d,%d)-(%d,%d)', ['header ', r2.Top, r2.Left, r2.Bottom, r2.Right]);
|
||||
r2 := GetRectOfPart(r, orn, zpCaption, hc);
|
||||
DebugLn('%s (%d,%d)-(%d,%d)', ['caption', r2.Top, r2.Left, r2.Bottom, r2.Right]);
|
||||
r2 := GetRectOfPart(r, doVertical, zpCloseButton);
|
||||
r2 := GetRectOfPart(r, orn, zpCloseButton, hc);
|
||||
DebugLn('%s (%d,%d)-(%d,%d)', ['closer ', r2.Top, r2.Left, r2.Bottom, r2.Right]);
|
||||
r2 := GetRectOfPart(r, doVertical, zpSizer);
|
||||
r2 := GetRectOfPart(r, orn, zpClient, hc);
|
||||
DebugLn('%s (%d,%d)-(%d,%d)', ['client ', r2.Top, r2.Left, r2.Bottom, r2.Right]);
|
||||
r2 := GetRectOfPart(r, orn, zpSizer, hc);
|
||||
DebugLn('%s (%d,%d)-(%d,%d)', ['sizer ', r2.Top, r2.Left, r2.Bottom, r2.Right]);
|
||||
end;
|
||||
}
|
||||
|
||||
begin
|
||||
HeaderSize := dHeader; //some meaningful value?
|
||||
//debug
|
||||
//dump;
|
||||
end;
|
||||
|
||||
class function TEasyDockHeader.GetRectOfPart(AHeaderRect: TRect; AOrientation: TDockOrientation;
|
||||
class function TEasyDockHeader.GetRectOfPart(ARect: TRect; AOrientation: TDockOrientation;
|
||||
APart: TEasyZonePart; HasSplitter: boolean): TRect;
|
||||
var
|
||||
d, dRight, dWidth: Integer;
|
||||
begin
|
||||
if (APart = zpNowhere) or (APart = zpClient)
|
||||
or ((APart = zpSizer) and not HasSplitter) then begin
|
||||
(* ARect is (must be) TLBR zone rectangle, on input.
|
||||
*)
|
||||
if (APart = zpNowhere) or ((APart = zpSizer) and not HasSplitter) then begin
|
||||
Result := Rect(0,0,0,0);
|
||||
exit;
|
||||
end;
|
||||
|
||||
Result := AHeaderRect;
|
||||
//if APart = zpAll then Exit; //include sizer?
|
||||
Result := ARect;
|
||||
with HeaderPartMap[APart] do begin
|
||||
if AOrientation = doVertical then begin //portrait
|
||||
if dTop > 0 then
|
||||
inc(Result.Top, dTop);
|
||||
if dBottom > 0 then
|
||||
dec(Result.Bottom, dBottom)
|
||||
else if dBottom < 0 then
|
||||
Result.Bottom := Result.Top - dBottom;
|
||||
if dTop < 0 then
|
||||
Result.Top := Result.Bottom + dTop;
|
||||
if dLeft > 0 then
|
||||
inc(Result.Left, dLeft);
|
||||
if dRight > 0 then
|
||||
dec(Result.Right, dRight)
|
||||
else if dRight < 0 then
|
||||
Result.Right := Result.Left + dRight;
|
||||
if dLeft < 0 then
|
||||
Result.Left := Result.Right + dLeft;
|
||||
{$IFDEF newSplitter}
|
||||
//handle client w/o splitter
|
||||
if (APart = zpClient) and HasSplitter then
|
||||
dec(Result.Bottom, dSizer);
|
||||
{$ELSE}
|
||||
{$ENDIF}
|
||||
end else begin //landscape
|
||||
if dTop > 0 then
|
||||
inc(Result.Left, dTop);
|
||||
if dBottom > 0 then
|
||||
dec(Result.Right, dBottom)
|
||||
else if dBottom < 0 then
|
||||
Result.Right := Result.Left - dBottom;
|
||||
if dTop < 0 then
|
||||
Result.Left := Result.Right + dTop;
|
||||
|
||||
if APart = zpSizer then begin
|
||||
//at top/left - visible only if HasSplitter
|
||||
if AOrientation = doVertical then
|
||||
Result.Bottom := Result.Top + dSizer
|
||||
else
|
||||
Result.Right := Result.Left + dSizer;
|
||||
exit;
|
||||
end;
|
||||
//exclude sizer
|
||||
if not HasSplitter then begin
|
||||
if AOrientation = doVertical then
|
||||
inc(Result.Top, dSizer)
|
||||
else
|
||||
inc(Result.Left, dSizer);
|
||||
end;
|
||||
|
||||
if APart = zpAll then
|
||||
Exit; //exclude sizer
|
||||
|
||||
//exclude border, assume 1 pixel border, 1 pixel inner distance
|
||||
InflateRect(Result, -dBorder, -dBorder); //border(2), remaining = rectangular button width/height
|
||||
//get remaining size for buttons
|
||||
if AOrientation = doVertical then
|
||||
d := Result.Bottom - Result.Top
|
||||
else
|
||||
d := Result.Right - Result.Left;
|
||||
|
||||
dWidth := 0;
|
||||
case APart of
|
||||
//zpAll: - see above
|
||||
zpCloseButton: dRight := dDist;
|
||||
{$IFDEF restore}
|
||||
zpRestoreButton: dRight := d + 2*dDist;
|
||||
zpCaption: dWidth := 2*(d + dDist); //2 * (button + dist)
|
||||
{$ELSE}
|
||||
zpCaption: dWidth := (d + dDist); //1 * (button + dist)
|
||||
{$ENDIF}
|
||||
//zpSizer: - see above
|
||||
//zpClient, //here: invalid argument!
|
||||
//zpNowhere: Result := Rect(0,0,0,0);
|
||||
end;
|
||||
|
||||
if AOrientation = doVertical then begin
|
||||
if dWidth > 0 then begin //caption
|
||||
dec(Result.Right, dBorder+dWidth);
|
||||
end else begin //buttons
|
||||
dec(Result.Right, dBorder+dRight);
|
||||
Result.Left := Result.Right - d;
|
||||
end;
|
||||
end else begin
|
||||
if dWidth > 0 then begin //caption
|
||||
inc(Result.Top, dBorder+dWidth);
|
||||
end else begin //buttons
|
||||
inc(Result.Top, dBorder+dRight);
|
||||
Result.Bottom := Result.Top + d;
|
||||
if dLeft > 0 then
|
||||
dec(Result.Bottom, dLeft);
|
||||
if dRight > 0 then
|
||||
inc(Result.Top, dRight)
|
||||
else if dRight < 0 then
|
||||
Result.Top := Result.Bottom + dRight;
|
||||
if dLeft < 0 then
|
||||
Result.Bottom := Result.Top - dLeft;
|
||||
{$IFDEF newSplitter}
|
||||
//handle client w/o splitter
|
||||
if (APart = zpClient) and HasSplitter then
|
||||
dec(Result.Right, dSizer);
|
||||
{$ELSE}
|
||||
{$ENDIF}
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
@ -163,36 +206,30 @@ begin
|
||||
*)
|
||||
r := AZone.GetBounds;
|
||||
if (AZone.FChildControl = nil) or not PtInRect(r, MousePos) then
|
||||
//possibly empty root zone
|
||||
Result := zpNowhere
|
||||
else begin
|
||||
Control := AZone.FChildControl;
|
||||
if Control.DockOrientation = doVertical then
|
||||
r.Bottom := Control.Top
|
||||
else
|
||||
r.Right := Control.Left;
|
||||
if not PtInRect(r, MousePos) then
|
||||
Part := zpClient //if not in header, must be in control
|
||||
else if MouseInPart(zpSizer) or MouseInPart(zpCloseButton)
|
||||
if MouseInPart(zpSizer) or MouseInPart(zpCloseButton)
|
||||
{$IFDEF restore}
|
||||
or MouseInPart(zpRestoreButton)
|
||||
{$ENDIF}
|
||||
or MouseInPart(zpClient)
|
||||
then
|
||||
//all done
|
||||
//all done, result stored in Part
|
||||
else
|
||||
Part := zpCaption;
|
||||
Part := zpCaption; //include borders
|
||||
end;
|
||||
|
||||
aHandle:=AZone.GetHandle;
|
||||
//check old state changed
|
||||
if (self.MouseZone <> nil)
|
||||
and ((MouseZone <> AZone) or (MousePart <> Part) or (MouseDown <> fButtonDown)) then begin
|
||||
//reset state?
|
||||
if MousePart in HeaderButtons then
|
||||
//check old state changed - buttons also change state on mouse enter/exit
|
||||
if (self.MouseZone <> nil) //else Mouse... invalid
|
||||
and ((MouseZone <> AZone) or (MousePart in HeaderButtons)) then
|
||||
InvalidateRect(aHandle, @PartRect, false); //old button
|
||||
end;
|
||||
//check new state
|
||||
if (MouseDown <> fButtonDown) and (MousePart in HeaderButtons) then
|
||||
InvalidateRect(aHandle, @SubRect, false); //new button
|
||||
if (Part in HeaderButtons) then begin
|
||||
InvalidateRect(aHandle, @SubRect, false); //refresh button
|
||||
end;
|
||||
//set new state
|
||||
MouseZone := AZone;
|
||||
MousePart := Part;
|
||||
@ -205,12 +242,15 @@ end;
|
||||
procedure TEasyDockHeader.Draw(AZone: TEasyZone; ACanvas: TCanvas; ACaption: string; const MousePos: TPoint);
|
||||
(* Problem with colors on other than win32 widgetsets (gtk2...)
|
||||
*)
|
||||
{$DEFINE LDock} //mimic LDockTree?
|
||||
const
|
||||
clBack = clHighlight;
|
||||
clFont = clHighlightText;
|
||||
|
||||
procedure DrawButton(ARect: TRect; IsMouseDown, IsMouseOver: Boolean; ABitmap: TCustomBitmap); inline;
|
||||
var
|
||||
IsMouseDown: Boolean;
|
||||
|
||||
//procedure DrawButton(ARect: TRect; IsMouseDown, IsMouseOver: Boolean; ABitmap: TCustomBitmap); inline;
|
||||
procedure DrawButton(ARect: TRect; ABitmap: TCustomBitmap);
|
||||
const
|
||||
// ------------- Pressed, Hot -----------------------
|
||||
BtnDetail: array[Boolean, Boolean] of TThemedToolBar =
|
||||
@ -221,18 +261,17 @@ const
|
||||
var
|
||||
Details: TThemedElementDetails;
|
||||
dx, dy: integer;
|
||||
IsMouseOver: boolean;
|
||||
begin
|
||||
ACanvas.FillRect(ARect);
|
||||
IsMouseOver := PtInRect(ARect, MousePos);
|
||||
Details := ThemeServices.GetElementDetails(BtnDetail[IsMouseDown, IsMouseOver]);
|
||||
ThemeServices.DrawElement(ACanvas.Handle, Details, ARect);
|
||||
ARect := ThemeServices.ContentRect(ACanvas.Handle, Details, ARect);
|
||||
//zoom button into rect?
|
||||
{$IFDEF LDock}
|
||||
//move button into rect, excluding border
|
||||
dx := (ARect.Right - ARect.Left - ABitmap.Width) div 2;
|
||||
dy := (ARect.Bottom - ARect.Top - ABitmap.Height) div 2;
|
||||
ACanvas.Draw(ARect.Left + dx, ARect.Top + dy, ABitmap);
|
||||
{$ELSE}
|
||||
ACanvas.Draw(ARect.Left, ARect.Top, ABitmap);
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
var
|
||||
@ -242,74 +281,48 @@ var
|
||||
OldFont, RotatedFont: HFONT;
|
||||
OldMode: Integer;
|
||||
ALogFont: TLogFont;
|
||||
IsMouseDown: Boolean; //obsolete
|
||||
AOrientation: TDockOrientation;
|
||||
AControl: TControl;
|
||||
begin
|
||||
(* Some colors inavailable on some widgetsets!
|
||||
(NewSplitter at opposite side of header! - not in this version)
|
||||
*)
|
||||
//IsMouseDown := self.MouseDown; // not always correct?
|
||||
IsMouseDown := (GetKeyState(VK_LBUTTON) and $80) <> 0;
|
||||
//debug
|
||||
AControl := AZone.FChildControl;
|
||||
AOrientation := AControl.DockOrientation;
|
||||
|
||||
ARect := AZone.GetBounds;
|
||||
BtnRect := ARect;
|
||||
if AZone.FChildControl.DockOrientation = doVertical then begin
|
||||
ARect.Bottom := ARect.Top + HeaderSize; //entire header area
|
||||
BtnRect.Top := BtnRect.Bottom - dSizer; //splitter
|
||||
end else begin
|
||||
ARect.Right := ARect.Left + HeaderSize;
|
||||
BtnRect.Left := BtnRect.Right - dSizer;
|
||||
end;
|
||||
DrawRect := ARect;
|
||||
ACanvas.Brush.Color := clBtnFace;
|
||||
|
||||
if AZone.HasSizer then begin
|
||||
{$IFDEF newsplitter}
|
||||
// splitter no more in header! - BtnRect initialized above
|
||||
ACanvas.FillRect(BtnRect);
|
||||
{$ELSE}
|
||||
//draw splitter?
|
||||
BtnRect := GetRectOfPart(ARect, AOrientation, zpSizer, AZone.HasSizer);
|
||||
{$IFDEF LDock}
|
||||
{$ELSE}
|
||||
ACanvas.Brush.Color := clBtnFace;
|
||||
{$ENDIF}
|
||||
ACanvas.FillRect(BtnRect);
|
||||
{$ENDIF}
|
||||
if AZone.HasSizer then begin
|
||||
// border?
|
||||
BtnRect := GetRectOfPart(ARect, AOrientation, zpSizer, AZone.HasSizer);
|
||||
ACanvas.FillRect(BtnRect);
|
||||
end;
|
||||
|
||||
//erase?
|
||||
//erase - which color(s)?
|
||||
DrawRect := GetRectOfPart(ARect, AOrientation, zpAll, AZone.HasSizer);
|
||||
{$IFDEF LDock}
|
||||
{$ELSE}
|
||||
ACanvas.Brush.Color := clBack; // clActiveCaption;
|
||||
{$ENDIF}
|
||||
//ACanvas.Brush.Color := clBack; // clActiveCaption;
|
||||
ACanvas.FillRect(DrawRect);
|
||||
|
||||
//what's this?
|
||||
//border
|
||||
InflateRect(DrawRect, -1, -1); //outer bevel?
|
||||
ACanvas.Brush.Color := clBtnShadow;
|
||||
ACanvas.FrameRect(DrawRect);
|
||||
{$IFDEF LDock}
|
||||
InflateRect(DrawRect, -1, -1); //inner bevel?
|
||||
//the value is not used any more!
|
||||
{$ELSE}
|
||||
{$ENDIF}
|
||||
ACanvas.FrameRect(DrawRect); //1 pixel border
|
||||
//InflateRect(DrawRect, -1, -1); //inner bevel?
|
||||
//the value is not used any more!
|
||||
ACanvas.Brush.Color := clBtnFace;
|
||||
|
||||
// draw caption
|
||||
{$IFDEF LDock}
|
||||
{$ELSE}
|
||||
ACanvas.Font.Color := clFont; //clCaptionText;
|
||||
{$ENDIF}
|
||||
//ACanvas.Font.Color := clFont; //clCaptionText;
|
||||
DrawRect := GetRectOfPart(ARect, AOrientation, zpCaption, AZone.HasSizer);
|
||||
|
||||
OldMode := SetBkMode(ACanvas.Handle, TRANSPARENT);
|
||||
|
||||
//for some reason the caption is not offset properly?
|
||||
if AOrientation = doVertical then begin
|
||||
inc(DrawRect.Left, 2);
|
||||
DrawText(ACanvas.Handle, PChar(ACaption), -1, DrawRect, DT_LEFT or DT_SINGLELINE or DT_VCENTER)
|
||||
end else begin
|
||||
OldFont := 0;
|
||||
@ -321,29 +334,25 @@ begin
|
||||
OldFont := SelectObject(ACanvas.Handle, RotatedFont);
|
||||
end;
|
||||
// from msdn: DrawText doesnot support font with orientation and escapement <> 0
|
||||
TextOut(ACanvas.Handle, DrawRect.Left, DrawRect.Bottom, PChar(ACaption), Length(ACaption));
|
||||
//TextOut(ACanvas.Handle, DrawRect.Left, DrawRect.Bottom, PChar(ACaption), Length(ACaption));
|
||||
TextOut(ACanvas.Handle, DrawRect.Left-2, DrawRect.Bottom-2, PChar(ACaption), Length(ACaption));
|
||||
if OldFont <> 0 then
|
||||
DeleteObject(SelectObject(ACanvas.Handle, OldFont));
|
||||
end;
|
||||
SetBkMode(ACanvas.Handle, OldMode);
|
||||
|
||||
// buttons - which colors to use?
|
||||
{$IFDEF LDock}
|
||||
{$ELSE}
|
||||
ACanvas.Brush.Color := clBtnFace;
|
||||
//ACanvas.Pen.Color := clButtonText;
|
||||
{$ENDIF}
|
||||
|
||||
// draw close button
|
||||
BtnRect := GetRectOfPart(ARect, AOrientation, zpCloseButton, AZone.HasSizer);
|
||||
ACanvas.FillRect(BtnRect);
|
||||
DrawButton(BtnRect, IsMouseDown, PtInRect(BtnRect, MousePos), DockBtnImages[dhiClose]);
|
||||
DrawButton(BtnRect, DockBtnImages[dhiClose]);
|
||||
|
||||
{$IFDEF restore}
|
||||
// draw restore button
|
||||
BtnRect := GetRectOfPart(ARect, AOrientation, zpRestoreButton, AZone.HasSizer);
|
||||
ACanvas.FillRect(BtnRect);
|
||||
DrawButton(BtnRect, IsMouseDown, PtInRect(BtnRect, MousePos), DockBtnImages[dhiRestore]);
|
||||
DrawButton(BtnRect, DockBtnImages[dhiRestore]);
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user