Is it possible to control how tabs are displayed in the JvDockServer component?
If you run the AdvanceDemo in the JVCL's JvDocking example code, with VSNetStyle selected, you can drag a second form onto the main form; a tab with the second form's title will be displayed. If you then drag a another form onto the same side of the main form, another tab will be created. The two 开发者_开发技巧tabs will overlap:
Is there a way to control how much these two tabs overlap? I'd like the tabs to be separated enough so that users can read the text on both tabs.
Thanks, as always -- Al C.
As ain commented, I also think it is a bug. More precisely a bug in TJvDockVSChannel.Paint which draws the tabs (internally the tabs are called blocks). Such a block has a protected property InactiveBlockWidth whose name suggest controlling its width. The property works fine for the tab itself, but the caption is shifted by that same amount again in TJvDockVSChannel.Paint, which seems to me to be the problem.
You can experiment as follows, by assigning the OnFinishSetDockPanelSize event of the DockServer:
type
TJvDockVSBlockAccess = class(TJvDockVSBlock);
procedure TMainForm.lbDockServer1FinishSetDockPanelSize(
DockPanel: TJvDockPanel);
var
Channel: TJvDockVSChannel;
Block: TJvDockVSBlockAccess;
i: Integer;
begin
if DockPanel is TJvDockVSNETPanel then
begin
Channel := TJvDockVSNETPanel(DockPanel).VSChannel;
for i := 0 to Channel.BlockCount - 1 do
begin
Block := TJvDockVSBlockAccess(Channel.Block[i]);
Block.InactiveBlockWidth := 100;
end;
end;
end;
Since this is a protected property for now, it might indicate its functionality being under construction. I suppose Jedi's dev team have decided for now to draw only the glyph of each inactive tab, because there lacks a full implementation for dynamic handling of the tab widths. E.g. you should be able to set a minimum width of each tab, and when the bar (i.e. the container in which it resides) changes height, all tabs should widen or narrow accordingly.
Edit:
Thanks to the flexible design, you can work around the bug by setting the DockPanelClass property of the DockServer. I suppose that property has to be set befóre setting the Style property. It involves rewriting the whole Paint routine, because InactiveBlockWidth is also used in GetBlockRect, which in turn is not virtual:
type
TJvDockVSBlockAccess = class(TJvDockVSBlock);
THackJvDockVSNETPanel = class(TJvDockVSNETPanel)
public
constructor Create(AOwner: TComponent); override;
end;
THackJvDockVSChannel = class(TJvDockVSChannel)
protected
procedure Paint; override;
procedure ResetBlock; override;
procedure Resize; override;
end;
const
InactiveTabWidth = 100;
{ TMainForm }
procedure TMainForm.FormCreate(Sender: TObject);
begin
...
JvDockVSNetStyle1.DockPanelClass := THackJvDockVSNETPanel;
end;
{ THackJvDockVSNETPanel }
constructor THackJvDockVSNETPanel.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
VSChannelClass := THackJvDockVSChannel;
end;
{ THackJvDockVSChannel }
procedure THackJvDockVSChannel.Paint;
var
I: Integer;
procedure DrawSingleBlock(Block: TJvDockVSBlockAccess);
var
DrawRect: TRect;
I: Integer;
OldGraphicsMode: Integer;
VisiblePaneCount: Integer;
procedure AdjustImagePos;
begin
if Align = alLeft then
begin
Inc(DrawRect.Left, 3);
Inc(DrawRect.Top, 4);
end
else if Align = alTop then
begin
Inc(DrawRect.Left, 4);
Inc(DrawRect.Top, 2);
end
else if Align = alRight then
begin
Inc(DrawRect.Left, 4);
Inc(DrawRect.Top, 4);
end
else if Align = alBottom then
begin
Inc(DrawRect.Left, 4);
Inc(DrawRect.Top, 3);
end;
end;
begin
VisiblePaneCount := 0;
for I := 0 to Block.VSPaneCount - 1 do
begin
if not Block.VSPane[I].Visible then
Continue;
GetBlockRect(Block, I, DrawRect);
Canvas.Brush.Color := TabColor;
Canvas.FillRect(DrawRect);
Canvas.Brush.Color := clGray;
Canvas.FrameRect(DrawRect);
AdjustImagePos;
Block.ImageList.Draw(Canvas, DrawRect.Left, DrawRect.Top, I);
if Align in [alTop, alBottom] then
Inc(DrawRect.Left, 24)
else if Align in [alLeft, alRight] then
begin
Inc(DrawRect.Top, 24);
if Align = alLeft then
DrawRect.Left := 15
else
DrawRect.Left := 20;
DrawRect.Right := DrawRect.Left + (DrawRect.Bottom - DrawRect.Top);
end;
Canvas.Brush.Color := TabColor;
Canvas.Pen.Color := clBlack;
Dec(DrawRect.Right, 3);
OldGraphicsMode := SetGraphicsMode(Canvas.Handle, GM_ADVANCED);
Canvas.Brush.Style := bsClear;
DrawText(Canvas.Handle, PChar(Block.VSPane[I].DockForm.Caption), -1,
DrawRect, DT_END_ELLIPSIS or DT_NOCLIP);
SetGraphicsMode(Canvas.Handle, OldGraphicsMode);
Inc(VisiblePaneCount);
end;
if VisiblePaneCount > 0 then
CurrentPos := CurrentPos + BlockInterval;
end;
begin
ResetBlock;
CurrentPos := BlockStartOffset;
for I := 0 to BlockCount - 1 do
DrawSingleBlock(TJvDockVSBlockAccess(Block[I]));
end;
procedure THackJvDockVSChannel.ResetBlock;
var
I: Integer;
begin
inherited ResetBlock;
for I := 0 to BlockCount - 1 do
TJvDockVSBlockAccess(Block[I]).InactiveBlockWidth := InactiveTabWidth;
end;
procedure THackJvDockVSChannel.Resize;
begin
{ Here you could widen or narrow the tabs according the total space and
depending on the number of tabs }
inherited Resize;
end;
精彩评论