📄 spagecontrol.pas
字号:
var
i, j : integer;
begin
if UpDown = nil then Exit;
UpDown.Left := Width - UpDown.Width;
if TabPosition = tpTop then UpDown.Top := 0 else UpDown.Top := Height - UpDown.Height;
j := 0;
for i := 0 to PageCount - 1 do if Pages[i].TabVisible and (TabRect(i).Left > 0) then Break else inc(j);
UpDown.Max := GetInvisibleItemCount;
UpDown.Position := j;
end;
function TsPageControl.VisibleTabsCount: integer;
var
i : integer;
begin
Result := 0;
for i := 0 to PageCount - 1 do if Pages[i].TabVisible then inc(Result);
end;
procedure TsPageControl.WMPaint(var Message: TWMPaint);
var
DC, SavedDC, SavedDC2, TabDC : hdc;
PS : TPaintStruct;
ci : TCacheInfo;
R : TRect;
i : integer;
begin
if not FCommonData.Skinned or (csDestroying in Parent.ComponentState) or (csLoading in ComponentState) then begin inherited; Exit end;
SavedDC := 0;
TabDC := 0;
BeginPaint(Handle, PS);
try
FCommonData.Updating := FCommonData.Updating;
if not FCommonData.Updating and not TabsChanging then begin
if Message.Unused = 1 then DC := Message.DC else begin
DC := GetDC(Handle);
SavedDC := SaveDC(DC);
end;
try
// If transparent and form resizing processed
FCommonData.BGChanged := FCommonData.BGChanged or FCommonData.HalfVisible or GetBoolMsg(Parent, AC_GETHALFVISIBLE);
FCommonData.HalfVisible := not (PtInRect(Parent.ClientRect, Point(Left, Top)) and
PtInRect(Parent.ClientRect, Point(Left + Width, Top + Height)));
if FCommonData.SkinSection = s_PageControl then case TabPosition of
tpTop : ChangedSkinSection := s_PageControl;
tpLeft : ChangedSkinSection := s_PageControl + 'LEFT';
tpRight : ChangedSkinSection := s_PageControl + 'RIGHT';
tpBottom : ChangedSkinSection := s_PageControl + 'BOTTOM';
end
else ChangedSkinSection := FCommonData.SkinSection;
FCommonData.SkinIndex := FCommonData.SkinManager.GetSkinIndex(ChangedSkinSection);
CI := GetParentCache(FCommonData);
FCommonData.InitCacheBmp;
if FCommonData.BGChanged then begin
if Tabs.Count > 0 then DrawSkinTabs(CI);
R := PageRect;
CtrlParentColor := ColorToRGB(TsHackedControl(Parent).Color);
PaintItem(FCommonData.SkinIndex, ChangedSkinSection, CI, False, 0, R, Point(Left + R.Left, Top + r.Top), FCommonData.FCacheBmp, FCommonData.SkinManager);
CtrlParentColor := clFuchsia;
FCommonData.BGChanged := False;
end;
if (Tabs.Count > 0) and (ActivePage <> nil) then begin
R := SkinTabRect(ActivePage.TabIndex, True);
TabDC := SaveDC(DC);
ExcludeClipRect(DC, R.Left, R.Top, R.Right, R.Bottom);
end;
SavedDC2 := 0;
if FShowCloseBtns then begin
SavedDC2 := SaveDC(DC);
for i := 0 to PageCount - 1 do if Pages[i].TabVisible and TsTabSheet(Pages[i]).UseCloseBtn and (Pages[i] <> ActivePage) then begin
R := SkinTabRect(Pages[i].TabIndex, False);
ExcludeClipRect(DC, R.Right - BtnWidth - BtnOffs, R.Top + BtnOffs, R.Right - BtnOffs, R.Top + BtnHeight + BtnOffs);
end;
end;
CopyWinControlCache(Self, FCommonData, Rect(0, 0, 0, 0), Rect(0, 0, Width, Height), DC, True);
if FShowCloseBtns then RestoreDC(DC, SavedDC2);
PaintButtons(DC);
sVCLUtils.PaintControls(DC, Self, True, Point(0, 0)); // Painting of the skinned TGraphControls
if (Tabs.Count > 0) and (ActivePage <> nil) then begin
RestoreDC(DC, TabDC);
if Message.Unused <> 1 then begin
RestoreDC(DC, SavedDC);
SavedDC := SaveDC(DC);
end;
DrawSkinTab(ActivePage.PageIndex, 2, DC);
if Message.Unused = 1 then begin
SavedDC := SaveDC(TWMPaint(Message).DC);
MoveWindowOrg(TWMPaint(Message).DC, ActivePage.Left, ActivePage.Top);
end;
ActivePage.Perform(WM_PAINT, longint(Message.DC), Message.Unused);
if Message.Unused = 1 then begin
RestoreDC(TWMPaint(Message).DC, SavedDC);
end;
end;
finally
if Message.Unused = 0 then begin
RestoreDC(DC, SavedDC);
ReleaseDC(Handle, DC);
end;
end;
end
finally
EndPaint(Handle, PS);
end;
StoredVisiblePageCount := VisibleTabsCount;
end;
procedure TsPageControl.WndProc(var Message: TMessage);
var
DC, SavedDC : hdc;
R : TRect;
p : TPoint;
NewItem, i, j : integer;
b : boolean;
Act : TacCloseAction;
SavedDC2 : hdc;
begin
{$IFDEF LOGGED}
AddToLog(Message);
{$ENDIF}
if (Message.Msg = cardinal(SM_ALPHACMD)) and Assigned(FCommonData) then case Message.WParamHi of
AC_CTRLHANDLED : begin Message.LParam := 1 end;
AC_GETAPPLICATION : begin Message.Result := longint(Application); Exit end;
AC_REMOVESKIN : begin
if Message.LParam = LongInt(SkinData.SkinManager) then begin
CommonWndProc(Message, FCommonData);
CheckUpDown;
ArrangeButtons;
RedrawWindow(Handle, nil, 0, RDW_ERASE + RDW_INVALIDATE + RDW_UPDATENOW + RDW_FRAME);
if (UpDown <> nil) and UpDown.Visible then SendMessage(UpDown.Handle, WM_PRINT, Message.WParam, Message.LParam);
end;
AlphaBroadcast(Self, Message)
end;
AC_REFRESH : begin
if (Message.LParam = LongInt(SkinData.SkinManager)) then begin
CommonWndProc(Message, FCommonData);
if Showing then begin
RedrawWindow(Handle, nil, 0, RDW_ERASE + RDW_INVALIDATE + RDW_UPDATENOW + RDW_FRAME);
Perform(WM_PAINT, 0, 0);
end;
if ActivePage <> nil then AddToAdapter(ActivePage);
CheckUpDown;
ArrangeButtons;
if (UpDown <> nil) then begin
if SkinData.SkinManager.GetSkinIndex(s_UpDown) < 0
then UpDown.ButtonSkin := s_Button
else UpDown.ButtonSkin := s_UpDown;
UpdateUpDownRgn(True);
end;
end;
AlphaBroadcast(Self, Message);
Exit;
end;
AC_SETNEWSKIN : begin
AlphaBroadcast(Self, Message);
if (Message.LParam = LongInt(SkinData.SkinManager)) then CommonWndProc(Message, FCommonData);
UpdateBtnData;
Exit;
end;
AC_PREPARING : begin
Message.LParam := integer(SkinData.Updating or TabsChanging{ or SkinData.BGChanged}); // To optimize here !!!
Exit;
end;
AC_ENDPARENTUPDATE : if FCommonData.Updating then begin
FCommonData.Updating := False;
if Assigned(ActivePage) then SendMessage(ActivePage.Handle, Message.Msg, Message.WParam, Message.LParam);
Perform(WM_PAINT, 0, 0);
Perform(WM_NCPAINT, 0, 0);
end;
AC_GETCACHE : if FCommonData.Skinned then begin
GlobalCacheInfo.X := 0;
GlobalCacheInfo.Y := 0;
if SkinData.Skinned
then GlobalCacheInfo.Bmp := FCommonData.FCacheBmp
else GlobalCacheInfo.Bmp := nil;
GlobalCacheInfo.Ready := GlobalCacheInfo.Bmp <> nil;
end;
AC_PREPARECACHE : ;
end
else if FCommonData.Skinned(True) then case Message.Msg of
4871 : FCommonData.BGChanged := True; // Items was added
WM_KILLFOCUS, WM_SETFOCUS : if not (csDesigning in ComponentState) then begin
b := FCommonData.BGChanged;
inherited;
FCommonData.BGChanged := b;
Exit;
end else exit;
WM_MOUSELEAVE, CM_MOUSELEAVE : if not (csDesigning in ComponentState) and (HotTrack or FShowCloseBtns) then begin
inherited;
if (CurItem <> -1) and (Pages[CurItem] <> ActivePage) then begin
if HotTrack then RepaintTab(CurItem, 0);
if FShowCloseBtns then begin
if TsTabSheet(Pages[CurItem]).UseCloseBtn then PaintButtonEx(CurItem, 0, 0);
if ActivePage <> nil then PaintButtonEx(ActivePage.PageIndex, 0, 2);
end;
end
else if ActivePage <> nil then PaintButtonEx(ActivePage.PageIndex, 0, 2);
acBtnPressed := False;
CurItem := -1;
Exit;
end;
WM_MOUSEMOVE : if not (csDesigning in ComponentState) then begin
if (DefaultManager <> nil) and not (csDesigning in DefaultManager.ComponentState) then DefaultManager.ActiveControl := 0;
b := (HotTrack or (Style <> tsTabs));
if b or FShowCloseBtns then begin
p.x := TCMHitTest(Message).XPos; p.y := TCMHitTest(Message).YPos;
if PtInRect(TabsRect, p) then begin
Application.ProcessMessages;
NewItem := GetTabUnderMouse(p);
if (NewItem <> CurItem) then begin // if changed
if (CurItem <> -1) then begin
if (HotTrack or FShowCloseBtns) then begin
if b then RepaintTab(CurItem, 0);
PaintButtonEx(CurItem, 0, 0);
end;
end
else if FShowCloseBtns and (ActivePage <> nil) and (NewItem <> ActivePage.PageIndex) then PaintButtonEx(ActivePage.PageIndex, 0, 2);
inherited;
CurItem := NewItem;
if (CurItem <> -1) and (HotTrack or FShowCloseBtns) then begin
if (Pages[CurItem] <> ActivePage) then begin
if b then begin
RepaintTab(CurItem, integer(HotTrack));
end;
end
else begin
CurItem := -1;
if FShowCloseBtns and (ActivePage <> nil) and PtInRect(BtnRect(ActivePage.PageIndex), p) then begin
PaintButtonEx(ActivePage.PageIndex, 1, 2);
Exit;
end
else begin
if ActivePage <> nil then PaintButtonEx(ActivePage.PageIndex, 0, 2);
// Exit;
end;
end;
end;
if FShowCloseBtns and (CurItem <> -1) then begin
R := BtnRect(Pages[CurItem].TabIndex);
if PtInRect(R, p) then begin
PaintButtonEx(CurItem, 1, 1);
if ActivePage <> nil then PaintButtonEx(ActivePage.PageIndex, 0, 2);
Exit;
end;
end;
// Exit;
end
else begin
if FShowCloseBtns and (CurItem <> -1) then begin
PaintButtonEx(Pages[CurItem].PageIndex, integer(PtInRect(BtnRect(Pages[CurItem].TabIndex), p)), integer(HotTrack));
Exit;
end;
end;
end
else if (CurItem <> -1) then begin
if b then RepaintTab(CurItem, 0);
PaintButtonEx(CurItem, 0, 0);
CurItem := -1;
acBtnPressed := False;
end;
end;
end;
WM_LBUTTONUP, WM_LBUTTONDOWN : if not (csDesigning in ComponentState) and FShowCloseBtns then begin
p.x := TCMHitTest(Message).XPos; p.y := TCMHitTest(Message).YPos;
if PtInRect(TabsRect, p) then begin
j := 0;
for i := 0 to PageCount - 1 do if Pages[i].TabVisible then begin
R := SkinTabRect(j, Pages[i] = ActivePage);
if PtInRect(R, p) then begin
if TsTabSheet(Pages[i]).UseCloseBtn then begin
if PtInRect(Rect(R.Right - BtnWidth - BtnOffs, R.Top + BtnOffs, R.Right - BtnOffs, R.Top + BtnHeight + BtnOffs), p) then begin
PaintButtonEx(i, 1 + integer(WM_LBUTTONDOWN = Message.Msg), integer(HotTrack) + (2 - integer(HotTrack)) * integer(ActivePage = Pages[i]));
if (WM_LBUTTONUP = Message.Msg) then begin
if not acBtnPressed then Exit;
b := True;
Act := acaFree;
if Assigned(OnCloseBtnClick) then OnCloseBtnClick(Self, i, b, Act);
if b and (Pages[i] <> nil) then begin
Perform(WM_SETREDRAW, 0, 0);
if Act = acaFree then Pages[i].Free else Pages[i].TabVisible := False;
Perform(WM_SETREDRAW, 1, 0);
FCommonData.BGChanged := True;
RedrawWindow(Handle, nil, 0, RDW_ERASE or RDW_INVALIDATE or RDW_UPDATENOW);
end;
acBtnPressed := False;
end
else acBtnPressed := True;
Exit;
end;
end;
end;
inc(j);
end;
end;
end;
end;
if Assigned(FCommonData) and FCommonData.Skinned then begin
CommonWndProc(Message, FCommonData);
case Message.Msg of
WM_PRINT : begin
CheckUpDown;
ArrangeButtons;
SkinData.Updating := False;
SendMessage(Handle, WM_PAINT, longint(TWMPaint(Message).DC), 1);
Exit;
end;
WM_NCPAINT : if ActivePage <> nil then begin
FCommonData.Updating := FCommonData.Updating;
if FCommonData.Updating then Exit;
DC := GetDC(Handle);
SavedDC := SaveDC(DC);
try
R := TabsRect;
ExcludeClipRect(DC, R.Left, R.Top, R.Right, R.Bottom);
R := ActivePage.BoundsRect;
ExcludeClipRect(DC, R.Left, R.Top, R.Right, R.Bottom);
if (Tabs.Count > 0) and (ActivePage <> nil) then begin
R := SkinTabRect(ActivePage.TabIndex, True);
ExcludeClipRect(DC, R.Left, R.Top, R.Right, R.Bottom);
end;
CopyWinControlCache(Self, FCommonData, Rect(0, 0, 0, 0), Rect(0, 0, Width, Height), DC, True);
finally
RestoreDC(DC, SavedDC);
ReleaseDC(Handle, DC);
end;
end;
TCM_SETCURSEL : SkinData.BGChanged := True;
WM_ERASEBKGND : begin Message.Result := 1; Exit end;
WM_STYLECHANGED, WM_STYLECHANGING, WM_HSCROLL : begin FCommonData.BGChanged := True; Repaint end;
TCM_SETITEMSIZE : TabsChanging := True;
end;
end;
inherited;
if Assigned(FCommonData) and FCommonData.Skinned then begin
case Message.Msg of
WM_PARENTNOTIFY : if (Message.WParam and $FFFF = WM_CREATE) or (Message.WParam and $FFFF = WM_DESTROY) then begin
if Message.WParamLo = WM_CREATE then AddToAdapter(Self);
end;
CM_CONTROLLISTCHANGE : begin
CheckUpDown;
ArrangeButtons;
AddToAdapter(Self);
end;
WM_SIZE : if not (csLoading in ComponentState) then begin
CheckUpDown;
ArrangeButtons;
end;
TCM_DELETEITEM : if not SkinData.Updating then begin
SkinData.BGChanged := True;
end;
WM_LBUTTONDOWN : if (Style <> tsTabs) and (CurItem <> -1) then begin
RepaintTab(CurItem, 1);
end;
WM_WINDOWPOSCHANGING : if TabsChanging then begin
if not FCommonData.Updating then begin
DC := GetDC(Handle);
SavedDC := SaveDC(DC);
try
R := TabsRect; // Instant restoring of BG
BitBlt(DC, R.Left, R.Top, WidthOf(R), HeightOf(R), FCommonData.FCacheBmp.Canvas.Handle, R.Left, R.Top, SRCCOPY);
// Preparing of new tabs
if Tabs.Count > 0 then DrawSkinTabs(GetParentCache(FCommonData));
R := TabsRect;
SavedDC2 := 0;
if FShowCloseBtns then begin
SavedDC2 := SaveDC(DC);
for i := 0 to PageCount - 1 do if Pages[i].TabVisible and TsTabSheet(Pages[i]).UseCloseBtn and (Pages[i] <> ActivePage) then begin
R := SkinTabRect(Pages[i].TabIndex, False);
ExcludeClipRect(DC, R.Right - BtnWidth - BtnOffs, R.Top + BtnOffs, R.Right - BtnOffs, R.Top + BtnHeight + BtnOffs);
end;
end;
CopyWinControlCache(Self, FCommonData, Rect(R.Left, R.Top, R.Left, R.Top), R, DC, False);
if FShowCloseBtns then RestoreDC(DC, SavedDC2);
case TabPosition of
tpTop : BitBlt(DC, R.Left, R.Bottom, WidthOf(R), 4, FCommonData.FCacheBmp.Canvas.Handle, R.Left, R.Bottom, SRCCOPY);
tpLeft : BitBlt(DC, R.Left, R.Top, 4, HeightOf(R), FCommonData.FCacheBmp.Canvas.Handle, R.Left, R.Top, SRCCOPY);
tpBottom : BitBlt(DC, R.Left, R.Top - 4, WidthOf(R), 4, FCommonData.FCacheBmp.Canvas.Handle, R.Left, R.Top - 4, SRCCOPY);
tpRight : BitBlt(DC, R.Left - 4, R.Top, 4, HeightOf(R), FCommonData.FCacheBmp.Canvas.Handle, R.Left - 4, R.Top, SRCCOPY);
end;
finally
RestoreDC(DC, SavedDC);
ReleaseDC(Handle, DC);
end;
end;
TabsChanging := False;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -