TTabSet 这是一个很老的控件! 但是学习自制控件的好地方! ( 积分: 0 )

  • 主题发起人 主题发起人 snb_ywx
  • 开始时间 开始时间
S

snb_ywx

Unregistered / Unconfirmed
GUEST, unregistred user!
这是TTabSet 的Paint,再看看他的备注![:D]
procedure TTabSet.Paint;
var
TabStart, LastTabPos: Integer;
TabPos: TTabPos;
Tab: Integer;
Leading: TEdgeType;
Trailing: TEdgeType;
isFirst, isLast, isSelected, isPrevSelected: Boolean;
R: TRect;
begin
if not HandleAllocated then Exit;

{ Set the size of the off-screen bitmap. Make sure that it is tall enough to
display the entire tab, even if the screen won't display it all. This is
required to avoid problems with using FloodFill. }
MemBitmap.Width := ClientWidth;
if ClientHeight < FTabHeight + 5 then MemBitmap.Height := FTabHeight + 5
else MemBitmap.Height := ClientHeight;

MemBitmap.Canvas.Font := Self.Canvas.Font;

TabStart := StartMargin + EdgeWidth; { where does first text appear? }
LastTabPos := Width - EndMargin; { tabs draw until this position }
Scroller.Left := Width - Scroller.Width - 2;

{ do initial calculations for how many tabs are visible }
FVisibleTabs := CalcTabPositions(TabStart, LastTabPos, MemBitmap.Canvas,
FirstIndex);

{ enable the scroller if FAutoScroll = True and not all tabs are visible }
if AutoScroll and (FVisibleTabs < Tabs.Count) then
begin
Dec(LastTabPos, Scroller.Width - 4);
{ recalc the tab positions }
FVisibleTabs := CalcTabPositions(TabStart, LastTabPos, MemBitmap.Canvas,
FirstIndex);

{ set the scroller's range }
Scroller.Visible := True;
ShowWindow(Scroller.Handle, SW_SHOW);
Scroller.Min := 0;
Scroller.Max := Tabs.Count - VisibleTabs;
Scroller.Position := FirstIndex;
end
else
if VisibleTabs >= Tabs.Count then
begin
Scroller.Visible := False;
ShowWindow(Scroller.Handle, SW_HIDE);
end;

if FDoFix then
begin
FixTabPos;
FVisibleTabs := CalcTabPositions(TabStart, LastTabPos, MemBitmap.Canvas,
FirstIndex);
end;
FDoFix := False;

{ draw background of tab area }
with MemBitmap.Canvas do
begin
Brush.Bitmap := BrushBitmap;
if ThemeServices.ThemesEnabled and ParentBackground then
Perform(WM_ERASEBKGND, MemBitmap.Canvas.Handle, 0)
else
FillRect(Rect(0, 0, MemBitmap.Width, MemBitmap.Height));

// draw top edget
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
// / /--------------/
// / // /
// /___________/ /___________/
if not ThemeServices.ThemesEnabled then
begin
Pen.Width := 1;
Pen.Color := clBtnShadow;
MoveTo(0, 0);
LineTo(MemBitmap.Width + 1, 0);
end;

if not FSoftTop then
begin
Pen.Color := clWindowFrame;
MoveTo(0, 1);
LineTo(MemBitmap.Width + 1, 1);
end;
end;

for Tab := 0 to TabPositions.Count - 1 do
begin
Pointer(TabPos) := TabPositions[Tab];

isFirst := Tab = 0;
isLast := Tab = VisibleTabs - 1;
isSelected := Tab + FirstIndex = TabIndex;
isPrevSelected := (Tab + FirstIndex) - 1 = TabIndex;

{ Rule: every tab paints its leading edge, only the last tab paints a
trailing edge }
Trailing := etNone;

if isLast then
begin
if isSelected then Trailing := etLastIsSel
else Trailing := etLastNotSel;
end;

if isFirst then
begin
if isSelected then Leading := etFirstIsSel
else Leading := etFirstNotSel;
end
else { not first }
begin
if isPrevSelected then Leading := etSelToNotSel
else
if isSelected then Leading := etNotSelToSel
else Leading := etNotSelToNotSel;
end;

{ draw leading edge }
// |XXXX|================================
// | X | /--------------/
// | X | // /
// | X|___________/ /___________/
if Leading <> etNone then
PaintEdge(TabPos.StartPos - EdgeWidth, 0, FTabHeight - 1, Leading);

{ set up the canvas }
R := Rect(TabPos.StartPos, 0, TabPos.StartPos + TabPos.Size, FTabHeight);
with MemBitmap.Canvas do
begin
if isSelected then Brush.Color := SelectedColor
else Brush.Color := UnselectedColor;
ExtTextOut(Handle, TabPos.StartPos, 2, ETO_OPAQUE, @R,
nil, 0, nil);
end;

{ restore font for drawing the text }
MemBitmap.Canvas.Font := Self.Canvas.Font;

{ Owner }
if (FStyle = tsOwnerDraw) then
DrawTab(MemBitmap.Canvas, R, Tab + FirstIndex, isSelected)
else
begin
with MemBitmap.Canvas do
begin
Inc(R.Top, 2);
DrawText(Handle, PChar(Tabs[Tab + FirstIndex]),
Length(Tabs[Tab + FirstIndex]), R, DT_CENTER);
end;
end;

{ draw trailing edge }
// ===============|XXXX|=================
// / | XX|-------------/
// / | XX | /
// /___________|X X|___________/
// or
// ==============================|XXXX|==
// / /------------|XXX |
// / // | X |
// /___________/ /___________|X |
if Trailing <> etNone then
PaintEdge(TabPos.StartPos + TabPos.Size, 0, FTabHeight - 1, Trailing);

{ draw connecting lines above and below the text }
// ====================================
// / /-XXXXXXXXXXX--/
// / // /
// /XXXXXXXXXXX/ /XXXXXXXXXXX/
with MemBitmap.Canvas do
begin
Pen.Color := clWindowFrame;
MoveTo(TabPos.StartPos, FTabHeight - 1);
LineTo(TabPos.StartPos + TabPos.Size, FTabHeight - 1);

if isSelected then
begin
Pen.Color := clBtnShadow;
MoveTo(TabPos.StartPos, FTabHeight - 2);
LineTo(TabPos.StartPos + TabPos.Size + 1, FTabHeight - 2);
end
else
begin
if SoftTop then
Pen.Color := BackgroundColor
else
Pen.Color := clWindowFrame;
MoveTo(TabPos.StartPos, 1);
LineTo(TabPos.StartPos + TabPos.Size, 1);

Pen.Color := clBtnShadow;
MoveTo(TabPos.StartPos, 0);
LineTo(TabPos.StartPos + TabPos.Size + 1, 0);
end;
end;
end;

{ draw onto the screen }
Canvas.Draw(0, 0, MemBitmap);
end;
 
这是TTabSet 的Paint,再看看他的备注![:D]
procedure TTabSet.Paint;
var
TabStart, LastTabPos: Integer;
TabPos: TTabPos;
Tab: Integer;
Leading: TEdgeType;
Trailing: TEdgeType;
isFirst, isLast, isSelected, isPrevSelected: Boolean;
R: TRect;
begin
if not HandleAllocated then Exit;

{ Set the size of the off-screen bitmap. Make sure that it is tall enough to
display the entire tab, even if the screen won't display it all. This is
required to avoid problems with using FloodFill. }
MemBitmap.Width := ClientWidth;
if ClientHeight < FTabHeight + 5 then MemBitmap.Height := FTabHeight + 5
else MemBitmap.Height := ClientHeight;

MemBitmap.Canvas.Font := Self.Canvas.Font;

TabStart := StartMargin + EdgeWidth; { where does first text appear? }
LastTabPos := Width - EndMargin; { tabs draw until this position }
Scroller.Left := Width - Scroller.Width - 2;

{ do initial calculations for how many tabs are visible }
FVisibleTabs := CalcTabPositions(TabStart, LastTabPos, MemBitmap.Canvas,
FirstIndex);

{ enable the scroller if FAutoScroll = True and not all tabs are visible }
if AutoScroll and (FVisibleTabs < Tabs.Count) then
begin
Dec(LastTabPos, Scroller.Width - 4);
{ recalc the tab positions }
FVisibleTabs := CalcTabPositions(TabStart, LastTabPos, MemBitmap.Canvas,
FirstIndex);

{ set the scroller's range }
Scroller.Visible := True;
ShowWindow(Scroller.Handle, SW_SHOW);
Scroller.Min := 0;
Scroller.Max := Tabs.Count - VisibleTabs;
Scroller.Position := FirstIndex;
end
else
if VisibleTabs >= Tabs.Count then
begin
Scroller.Visible := False;
ShowWindow(Scroller.Handle, SW_HIDE);
end;

if FDoFix then
begin
FixTabPos;
FVisibleTabs := CalcTabPositions(TabStart, LastTabPos, MemBitmap.Canvas,
FirstIndex);
end;
FDoFix := False;

{ draw background of tab area }
with MemBitmap.Canvas do
begin
Brush.Bitmap := BrushBitmap;
if ThemeServices.ThemesEnabled and ParentBackground then
Perform(WM_ERASEBKGND, MemBitmap.Canvas.Handle, 0)
else
FillRect(Rect(0, 0, MemBitmap.Width, MemBitmap.Height));

// draw top edget
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
// / /--------------/
// / // /
// /___________/ /___________/
if not ThemeServices.ThemesEnabled then
begin
Pen.Width := 1;
Pen.Color := clBtnShadow;
MoveTo(0, 0);
LineTo(MemBitmap.Width + 1, 0);
end;

if not FSoftTop then
begin
Pen.Color := clWindowFrame;
MoveTo(0, 1);
LineTo(MemBitmap.Width + 1, 1);
end;
end;

for Tab := 0 to TabPositions.Count - 1 do
begin
Pointer(TabPos) := TabPositions[Tab];

isFirst := Tab = 0;
isLast := Tab = VisibleTabs - 1;
isSelected := Tab + FirstIndex = TabIndex;
isPrevSelected := (Tab + FirstIndex) - 1 = TabIndex;

{ Rule: every tab paints its leading edge, only the last tab paints a
trailing edge }
Trailing := etNone;

if isLast then
begin
if isSelected then Trailing := etLastIsSel
else Trailing := etLastNotSel;
end;

if isFirst then
begin
if isSelected then Leading := etFirstIsSel
else Leading := etFirstNotSel;
end
else { not first }
begin
if isPrevSelected then Leading := etSelToNotSel
else
if isSelected then Leading := etNotSelToSel
else Leading := etNotSelToNotSel;
end;

{ draw leading edge }
// |XXXX|================================
// | X | /--------------/
// | X | // /
// | X|___________/ /___________/
if Leading <> etNone then
PaintEdge(TabPos.StartPos - EdgeWidth, 0, FTabHeight - 1, Leading);

{ set up the canvas }
R := Rect(TabPos.StartPos, 0, TabPos.StartPos + TabPos.Size, FTabHeight);
with MemBitmap.Canvas do
begin
if isSelected then Brush.Color := SelectedColor
else Brush.Color := UnselectedColor;
ExtTextOut(Handle, TabPos.StartPos, 2, ETO_OPAQUE, @R,
nil, 0, nil);
end;

{ restore font for drawing the text }
MemBitmap.Canvas.Font := Self.Canvas.Font;

{ Owner }
if (FStyle = tsOwnerDraw) then
DrawTab(MemBitmap.Canvas, R, Tab + FirstIndex, isSelected)
else
begin
with MemBitmap.Canvas do
begin
Inc(R.Top, 2);
DrawText(Handle, PChar(Tabs[Tab + FirstIndex]),
Length(Tabs[Tab + FirstIndex]), R, DT_CENTER);
end;
end;

{ draw trailing edge }
// ===============|XXXX|=================
// / | XX|-------------/
// / | XX | /
// /___________|X X|___________/
// or
// ==============================|XXXX|==
// / /------------|XXX |
// / // | X |
// /___________/ /___________|X |
if Trailing <> etNone then
PaintEdge(TabPos.StartPos + TabPos.Size, 0, FTabHeight - 1, Trailing);

{ draw connecting lines above and below the text }
// ====================================
// / /-XXXXXXXXXXX--/
// / // /
// /XXXXXXXXXXX/ /XXXXXXXXXXX/
with MemBitmap.Canvas do
begin
Pen.Color := clWindowFrame;
MoveTo(TabPos.StartPos, FTabHeight - 1);
LineTo(TabPos.StartPos + TabPos.Size, FTabHeight - 1);

if isSelected then
begin
Pen.Color := clBtnShadow;
MoveTo(TabPos.StartPos, FTabHeight - 2);
LineTo(TabPos.StartPos + TabPos.Size + 1, FTabHeight - 2);
end
else
begin
if SoftTop then
Pen.Color := BackgroundColor
else
Pen.Color := clWindowFrame;
MoveTo(TabPos.StartPos, 1);
LineTo(TabPos.StartPos + TabPos.Size, 1);

Pen.Color := clBtnShadow;
MoveTo(TabPos.StartPos, 0);
LineTo(TabPos.StartPos + TabPos.Size + 1, 0);
end;
end;
end;

{ draw onto the screen }
Canvas.Draw(0, 0, MemBitmap);
end;
 
后退
顶部