123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778 |
- //---------------------------------------------------------------------------
- #pragma warn -pch // WORKAROUND (see My.cpp)
- #include <vcl.h>
- #pragma hdrstop
- #include <Common.h>
- #include <vsstyle.h>
- #include <memory>
- #include <PasTools.hpp>
- #include <TBXOfficeXPTheme.hpp>
- #include <TBX.hpp>
- #include <StrUtils.hpp>
- #include <CustomWinConfiguration.h>
- #include "ThemePageControl.h"
- #include <algorithm>
- //---------------------------------------------------------------------------
- #pragma package(smart_init)
- //---------------------------------------------------------------------------
- // Based on
- // https://www.codeproject.com/articles/XP-Themes-Tab-Control-in-any-orientation
- //---------------------------------------------------------------------------
- #define IDS_UTIL_TAB L"TAB"
- //---------------------------------------------------------------------------
- namespace Themepagecontrol
- {
- void __fastcall PACKAGE Register()
- {
- TComponentClass classes[2] = {__classid(TThemePageControl), __classid(TThemeTabSheet)};
- RegisterComponents(L"Scp", classes, 1);
- }
- }
- //----------------------------------------------------------------------------------------------------------
- __fastcall TThemeTabSheet::TThemeTabSheet(TComponent * Owner) :
- TTabSheet(Owner)
- {
- FShadowed = false;
- FButton = ttbNone;
- FCaptionTruncation = tttNone;
- }
- //----------------------------------------------------------------------------------------------------------
- TThemePageControl * TThemeTabSheet::GetParentPageControl()
- {
- return DebugNotNull(dynamic_cast<TThemePageControl *>(Parent));
- }
- //----------------------------------------------------------------------------------------------------------
- void __fastcall TThemeTabSheet::Invalidate()
- {
- TThemePageControl * ThemePageControl = GetParentPageControl();
- if (DebugAlwaysTrue(ThemePageControl != NULL))
- {
- ThemePageControl->InvalidateTab(TabIndex);
- }
- else
- {
- Parent->Invalidate();
- }
- }
- //----------------------------------------------------------------------------------------------------------
- void __fastcall TThemeTabSheet::SetShadowed(bool Value)
- {
- if (Shadowed != Value)
- {
- FShadowed = Value;
- Invalidate();
- }
- }
- //----------------------------------------------------------------------------------------------------------
- void __fastcall TThemeTabSheet::SetButton(TThemeTabSheetButtons Value)
- {
- if (Button != Value)
- {
- FButton = Value;
- Invalidate();
- }
- }
- //----------------------------------------------------------------------------------------------------------
- void TThemeTabSheet::SetBaseCaption(const UnicodeString & value)
- {
- if (FBaseCaption != value)
- {
- FBaseCaption = value;
- UpdateCaption();
- }
- }
- //----------------------------------------------------------------------------------------------------------
- UnicodeString TThemeTabSheet::TruncatedCaption()
- {
- UnicodeString Result = FBaseCaption;
- TThemePageControl * ParentPageControl = GetParentPageControl();
- if (ParentPageControl->FSessionTabShrink > 0)
- {
- if (FCaptionTruncation == tttNone)
- {
- // noop
- }
- else if (FCaptionTruncation == tttEllipsis)
- {
- if (ParentPageControl->FSessionTabShrink == 1)
- {
- Result = Result.SubString(1, 1);
- }
- else if (ParentPageControl->FSessionTabShrink < Result.Length())
- {
- Result = Result.SubString(1, ParentPageControl->FSessionTabShrink - 1) + Ellipsis;
- }
- }
- else if (DebugAlwaysTrue(FCaptionTruncation == tttNoText))
- {
- Result = EmptyStr;
- }
- }
- return Result;
- }
- //----------------------------------------------------------------------------------------------------------
- void TThemeTabSheet::UpdateCaption()
- {
- UnicodeString ACaption = TruncatedCaption();
- TThemePageControl * ParentPageControl = GetParentPageControl();
- if (UseThemes() && (Button != ttbNone))
- {
- ParentPageControl->Canvas->Font = ParentPageControl->Font;
- int OrigWidth = ParentPageControl->Canvas->TextWidth(ACaption);
- int TabButtonWidth = ParentPageControl->TabButtonSize();
- int Padding = ScaleByTextHeight(this, 2);
- while (ParentPageControl->Canvas->TextWidth(ACaption) < OrigWidth + Padding + TabButtonWidth)
- {
- ACaption += L" ";
- }
- }
- Caption = ACaption;
- ParentPageControl->TabChanged(TabIndex);
- }
- //----------------------------------------------------------------------------------------------------------
- UnicodeString TThemeTabSheet::GetBaseCaption()
- {
- DebugAssert(StartsStr(FBaseCaption, Caption));
- DebugAssert(RightStr(Caption, Caption.Length() - FBaseCaption.Length()).Trim().Length() == 0);
- return FBaseCaption;
- }
- //----------------------------------------------------------------------------------------------------------
- void TThemeTabSheet::SetCaptionTruncation(TThemeTabCaptionTruncation Value)
- {
- if (FCaptionTruncation != Value)
- {
- FCaptionTruncation = Value;
- UpdateCaption();
- }
- }
- //----------------------------------------------------------------------------------------------------------
- //----------------------------------------------------------------------------------------------------------
- __fastcall TThemePageControl::TThemePageControl(TComponent * Owner) :
- TPageControl(Owner)
- {
- FOldTabIndex = -1;
- FHotTabButton = -1;
- FClickedButton = -1;
- FSessionTabShrink = 0;
- FOnTabButtonClick = NULL;
- FOnTabHint = NULL;
- FTabTheme = NULL;
- FActiveTabTheme = NULL;
- FTextHeight = -1;
- }
- //----------------------------------------------------------------------------------------------------------
- int __fastcall TThemePageControl::GetTabsHeight()
- {
- // The Calculated height includes tab/contents separator line on Windows 7/8,
- // but not on Windows XP
- TRect Rect = GetClientRect();
- ::SendMessage(Handle, TCM_ADJUSTRECT, FALSE, (LPARAM)&Rect);
- int Result = Rect.Top - 1;
- // Two different ways to calculate the same, not sure which one is more reliable,
- // so we want to know in case they differ.
- if (DebugAlwaysTrue(PageCount >= 0))
- {
- TRect Rect2 = TabRect(0);
- int Result2 = Rect2.Bottom + 1;
- // On Windows 10 with 200% scaling, the first is 40, the second is 42.
- // With 250% scaling it's 50 vs 53.
- // Using the larger.
- if (Result2 > Result)
- {
- DebugAssert(IsWin10());
- Result = Result2;
- }
- }
- return Result;
- }
- //----------------------------------------------------------------------------------------------------------
- void __fastcall TThemePageControl::PaintWindow(HDC DC)
- {
- // Themes not enabled, give up
- if (!UseThemes())
- {
- TPageControl::PaintWindow(DC);
- return;
- }
- HTHEME Theme = OpenThemeData(NULL, IDS_UTIL_TAB);
- // TODO use GetClipBox
- TRect PageRect = GetClientRect();
- // 1st paint the tab body
- TRect ClientRect = PageRect;
- ::SendMessage(Handle, TCM_ADJUSTRECT, FALSE, (LPARAM)&PageRect);
- ClientRect.Top = PageRect.Top - 2;
- DrawThemeBackground(Theme, DC, TABP_PANE, 0, &ClientRect, NULL);
- // 2nd paint the inactive tabs
- int SelectedIndex = TabIndex; // optimization
- std::unique_ptr<TCanvas> ACanvas(new TCanvas());
- ACanvas->Handle = DC;
- ACanvas->Font = Font;
- FTextHeight = CalculateTextHeight(ACanvas.get());
- for (int Tab = 0; Tab < PageCount; Tab++)
- {
- if (Tab != SelectedIndex)
- {
- DrawThemesXpTab(DC, Theme, Tab);
- }
- }
- if (SelectedIndex >= 0)
- {
- DrawThemesXpTab(DC, Theme, SelectedIndex);
- }
- CloseThemeData(Theme);
- }
- //----------------------------------------------------------------------------------------------------------
- TThemeTabSheetButtons __fastcall TThemePageControl::GetTabButton(int Index)
- {
- TThemeTabSheet * ThemeTabSheet = dynamic_cast<TThemeTabSheet *>(Pages[Index]);
- return (UseThemes() && (ThemeTabSheet != NULL)) ? ThemeTabSheet->Button : ttbNone;
- }
- //----------------------------------------------------------------------------------------------------------
- void __fastcall TThemePageControl::DrawThemesXpTab(HDC DC, HTHEME Theme, int Tab)
- {
- TThemeTabSheet * ThemeTabSheet = dynamic_cast<TThemeTabSheet *>(Pages[Tab]);
- bool Shadowed = (ThemeTabSheet != NULL) ? ThemeTabSheet->Shadowed : false;
- TRect Rect = TabRect(Tab);
- ItemTabRect(Tab, Rect);
- int State;
- TTBXTheme * ATabTheme;
- if (Tab != TabIndex)
- {
- TPoint Point = ScreenToClient(Mouse->CursorPos);
- int HotIndex = IndexOfTabAt(Point.X, Point.Y);
- State = (Tab == HotIndex ? TIS_HOT : (Shadowed ? TIS_DISABLED : TIS_NORMAL));
- ATabTheme = TabTheme;
- }
- else
- {
- State = TIS_SELECTED;
- ATabTheme = (ActiveTabTheme != NULL) ? ActiveTabTheme : TabTheme;
- }
- DrawThemesXpTabItem(DC, Theme, Tab, Rect, State, Shadowed, ATabTheme);
- }
- //----------------------------------------------------------------------------------------------------------
- static TTBXItemInfo GetItemInfo(int State)
- {
- TTBXItemInfo ItemInfo;
- memset(&ItemInfo, 0, sizeof(ItemInfo));
- ItemInfo.Enabled = true;
- ItemInfo.ViewType =
- VT_TOOLBAR | TVT_EMBEDDED |
- FLAGMASK(State == TIS_SELECTED, ISF_SELECTED);
- return ItemInfo;
- }
- //----------------------------------------------------------------------------------------------------------
- void __fastcall TThemePageControl::DrawThemesXpTabItem(
- HDC DC, HTHEME Theme, int Item, const TRect & Rect, int State, bool Shadowed, TTBXTheme * ATabTheme)
- {
- TRect PaintRect = Rect;
- if ((State == TIS_SELECTED) || (ATabTheme != NULL))
- {
- PaintRect.Bottom++;
- }
- if (ATabTheme != NULL)
- {
- std::unique_ptr<TCanvas> CanvasMem(new TCanvas());
- CanvasMem->Handle = DC;
- ATabTheme->PaintFrame(CanvasMem.get(), PaintRect, GetItemInfo(State));
- }
- else
- {
- int PartID = (Item == 0) ? TABP_TABITEMLEFTEDGE : TABP_TABITEM;
- DrawThemeBackground(Theme, DC, PartID, State, &PaintRect, NULL);
- }
- if (Item >= 0)
- {
- DrawTabItem(DC, Item, Rect, State, Shadowed, ATabTheme);
- }
- }
- //----------------------------------------------------------------------------------------------------------
- void __fastcall TThemePageControl::ItemTabRect(int Item, TRect & Rect)
- {
- if (Item == TabIndex)
- {
- // Countered in TabButtonRect
- Rect.Inflate(2, 2);
- Rect.Bottom--;
- }
- }
- //----------------------------------------------------------------------------------------------------------
- void __fastcall TThemePageControl::ItemContentsRect(int Item, TRect & Rect)
- {
- Rect.Left += 6;
- Rect.Right -= 3;
- if (Item == TabIndex)
- {
- // to counter the ItemTabRect
- Rect.Left += 2;
- Rect.Right -= 2;
- Rect.Bottom++;
- Rect.Bottom -= 2;
- }
- }
- //----------------------------------------------------------------------------------------------------------
- bool __fastcall TThemePageControl::HasItemImage(int Item)
- {
- return (Images != NULL) && (Pages[Item]->ImageIndex >= 0);
- }
- //----------------------------------------------------------------------------------------------------------
- void TThemePageControl::DrawCross(HDC DC, int Width, COLORREF Color, const TRect & Rect)
- {
- HPEN Pen = CreatePen(PS_SOLID, Width, Color);
- HPEN OldPen = static_cast<HPEN>(SelectObject(DC, Pen));
- // To-and-back - to make both ends look the same
- MoveToEx(DC, Rect.Left, Rect.Bottom - 1, NULL);
- LineTo(DC, Rect.Right - 1, Rect.Top);
- LineTo(DC, Rect.Left, Rect.Bottom - 1);
- MoveToEx(DC, Rect.Left, Rect.Top, NULL);
- LineTo(DC, Rect.Right - 1, Rect.Bottom - 1);
- LineTo(DC, Rect.Left, Rect.Top);
- SelectObject(DC, OldPen);
- DeleteObject(Pen);
- }
- //----------------------------------------------------------------------------------------------------------
- void TThemePageControl::DrawDropDown(HDC DC, int Radius, int X, int Y, COLORREF Color, int Grow)
- {
- // Optimized for even-sized Rect (100% scaling), may need adjustments for even-sized to correctly center
- TPoint Points[] = {
- Point(X - Radius - 1 - Grow, Y), Point(X + Radius + Grow, Y),
- Point(X, Y + Radius + Grow), Point(X - 1, Y + Radius + Grow)
- };
- HBRUSH Brush = CreateSolidBrush(Color);
- HPEN Pen = CreatePen(PS_SOLID, 1, Color);
- HGDIOBJ OldBrush = SelectObject(DC, Brush);
- HGDIOBJ OldPen = SelectObject(DC, Pen);
- Polygon(DC, Points, LENOF(Points));
- SelectObject(DC, OldPen);
- SelectObject(DC, OldBrush);
- DeleteObject(Brush);
- DeleteObject(Pen);
- }
- //----------------------------------------------------------------------------------------------------------
- static int VCenter(const TRect & Rect, int Height)
- {
- int A = (Rect.Top + Rect.Bottom - Height);
- return (A / 2) + (A % 2);
- }
- //----------------------------------------------------------------------------------------------------------
- // Draw tab item context: possible icon and text
- void __fastcall TThemePageControl::DrawTabItem(HDC DC, int Item, TRect Rect, int State, bool Shadowed, TTBXTheme * ATabTheme)
- {
- TRect OrigRect = Rect;
- ItemContentsRect(Item, Rect);
- UnicodeString Text = Pages[Item]->Caption;
- std::unique_ptr<TCanvas> Canvas(new TCanvas());
- Canvas->Handle = DC;
- if (HasItemImage(Item))
- {
- int Left;
- if (!Text.IsEmpty())
- {
- Left = Rect.Left;
- Rect.Left += Images->Width + 3;
- }
- else
- {
- Left = OrigRect.Left + (OrigRect.Right - Images->Width - OrigRect.Left) / 2;
- }
- int Top = VCenter(Rect, Images->Height);
- Images->Draw(Canvas.get(), Left, Top, Pages[Item]->ImageIndex, !Shadowed);
- }
- int OldMode = SetBkMode(DC, TRANSPARENT);
- if (!Text.IsEmpty())
- {
- if (ATabTheme != NULL)
- {
- SetTextColor(DC, static_cast<COLORREF>(ATabTheme->GetItemTextColor(GetItemInfo(State))));
- }
- HFONT OldFont = (HFONT)SelectObject(DC, Font->Handle);
- wchar_t * Buf = new wchar_t[static_cast<size_t>(Text.Length() + 1 + 4)];
- wcscpy(Buf, Text.c_str());
- TRect TextRect(0, 0, Rect.Width(), 20);
- // Truncates too long texts with ellipsis
- ::DrawText(DC, Buf, -1, &TextRect, DT_CALCRECT | DT_SINGLELINE | DT_MODIFYSTRING | DT_END_ELLIPSIS);
- DebugAssert(FTextHeight == TextRect.Height());
- Rect.Top = VCenter(Rect, FTextHeight);
- DrawText(DC, Buf, -1, &Rect, DT_NOPREFIX | DT_CENTER);
- delete[] Buf;
- TThemeTabSheetButtons Button = GetTabButton(Item);
- if (Button != ttbNone)
- {
- Rect = TabButtonRect(Item);
- TTBXItemInfo ButtonItemInfo = GetItemInfo(State);
- if (IsHotButton(Item))
- {
- ButtonItemInfo.HoverKind = hkMouseHover;
- CurrentTheme->PaintFrame(Canvas.get(), Rect, ButtonItemInfo);
- }
- COLORREF BackColor = GetPixel(DC, Rect.Left + (Rect.Width() / 2), Rect.Top + (Rect.Height() / 2));
- COLORREF ShapeColor;
- if (ATabTheme != NULL)
- {
- ShapeColor = static_cast<COLORREF>(ColorToRGB(ATabTheme->GetItemTextColor(ButtonItemInfo)));
- }
- else
- {
- ShapeColor = static_cast<COLORREF>(ColorToRGB(Font->Color));
- }
- #define BlendValue(FN) (((4 * static_cast<int>(FN(BackColor))) + static_cast<int>(FN(ShapeColor))) / 5)
- COLORREF BlendColor = RGB(BlendValue(GetRValue), BlendValue(GetGValue), BlendValue(GetBValue));
- #undef BlendValue
- if (Button == ttbClose)
- {
- int CrossPadding = GetCrossPadding();
- TRect CrossRect(Rect);
- CrossRect.Inflate(-CrossPadding, -CrossPadding);
- int CrossWidth = ScaleByTextHeight(this, 1);
- DrawCross(DC, CrossWidth + 1, BlendColor, CrossRect);
- DrawCross(DC, CrossWidth, ShapeColor, CrossRect);
- }
- else if (DebugAlwaysTrue(Button == ttbDropDown))
- {
- // See TTBXOfficeXPTheme.PaintDropDownArrow
- int Radius = ScaleByTextHeight(this, 2);
- int X = ((Rect.Left + Rect.Right)) / 2;
- int Y = ((Rect.Top + Rect.Bottom) / 2) - (Radius * 2 / 3);
- DrawDropDown(DC, Radius, X, Y, BlendColor, 1);
- DrawDropDown(DC, Radius, X, Y, ShapeColor, 0);
- }
- }
- SelectObject(DC, OldFont);
- }
- SetBkMode(DC, OldMode);
- }
- //----------------------------------------------------------------------------------------------------------
- int __fastcall TThemePageControl::TabButtonSize()
- {
- return MulDiv(GetTabsHeight(), 8, 13);
- }
- //----------------------------------------------------------------------------------------------------------
- int __fastcall TThemePageControl::GetCrossPadding()
- {
- return MulDiv(GetTabsHeight(), 2, 13);
- }
- //----------------------------------------------------------------------------------------------------------
- TRect __fastcall TThemePageControl::TabButtonRect(int Index)
- {
- TRect Rect = TabRect(Index);
- ItemTabRect(Index, Rect);
- ItemContentsRect(Index, Rect);
- int ATabButtonSize = TabButtonSize();
- Rect.Top = VCenter(Rect, ATabButtonSize);
- Rect.Left = Rect.Right - ATabButtonSize - ScaleByTextHeight(this, 1);
- Rect.Right = Rect.Left + ATabButtonSize;
- Rect.Bottom = Rect.Top + ATabButtonSize;
- return Rect;
- }
- //----------------------------------------------------------------------------------------------------------
- bool TThemePageControl::IsHotButton(int Index)
- {
- // This was an attempt to allow tracking close buttons, even while drop down button menu is popped,
- // but MouseMove does not trigger then.
- return (Index == FClickedButton) || (Index == FHotTabButton);
- }
- //----------------------------------------------------------------------------------------------------------
- void TThemePageControl::TabChanged(int Index)
- {
- // When the "clicked" tab changes, it's probably not anymore the tab that was actually clicked.
- // For example, when the last tab is closed, it's replaced with either local-local tab (without the X button),
- // or removed altogether. The Login dialog pops up and when new session is opened, its tab's X button is rendered clicked,
- // until connection openning finishes (and WMLButtonDown finishes).
- if (Index == FClickedButton)
- {
- UpdateHotButton(FClickedButton, -1);
- }
- }
- //----------------------------------------------------------------------------------------------------------
- void TThemePageControl::UpdateHotButton(int & Ref, int Index)
- {
- if (Ref != Index)
- {
- bool WasHot = (Index >= 0) && IsHotButton(Index);
- int Prev = Ref;
- Ref = Index;
- if ((Prev >= 0) && !IsHotButton(Prev))
- {
- InvalidateTab(Prev);
- }
- if ((Index >= 0) && !WasHot)
- {
- InvalidateTab(Index);
- }
- }
- }
- //----------------------------------------------------------------------------------------------------------
- void __fastcall TThemePageControl::MouseMove(TShiftState Shift, int X, int Y)
- {
- TPageControl::MouseMove(Shift, X, Y);
- UpdateHotButton(FHotTabButton, IndexOfTabButtonAt(X, Y));
- }
- //----------------------------------------------------------------------------------------------------------
- int __fastcall TThemePageControl::IndexOfTabButtonAt(int X, int Y)
- {
- int Result = IndexOfTabAt(X, Y);
- if ((Result < 0) ||
- !GetTabButton(Result) ||
- !TabButtonRect(Result).Contains(TPoint(X, Y)))
- {
- Result = -1;
- }
- return Result;
- }
- //----------------------------------------------------------------------------------------------------------
- bool __fastcall TThemePageControl::CanChange()
- {
- FOldTabIndex = ActivePageIndex;
- return TPageControl::CanChange();
- }
- //----------------------------------------------------------------------------------------------------------
- void __fastcall TThemePageControl::InvalidateTab(int Index)
- {
- if (HandleAllocated())
- {
- TRect Rect = TabRect(Index);
- if (Index == TabIndex)
- {
- Rect.Inflate(2, 2);
- }
- // Original code was invalidating range against parent window
- // (recalculating coordinates first)
- InvalidateRect(Handle, &Rect, true);
- }
- }
- //----------------------------------------------------------------------------------------------------------
- void __fastcall TThemePageControl::Change()
- {
- // note that TabIndex yields correct value already here,
- // while ActivePageIndex is not updated yet
- if ((FOldTabIndex >= 0) && (FOldTabIndex != TabIndex) && UseThemes())
- {
- InvalidateTab(FOldTabIndex);
- }
- TPageControl::Change();
- }
- //---------------------------------------------------------------------------
- void __fastcall TThemePageControl::WMLButtonDown(TWMLButtonDown & Message)
- {
- int Index = IndexOfTabButtonAt(Message.XPos, Message.YPos);
- if (Index >= 0)
- {
- Message.Result = 1;
- if (FOnTabButtonClick != NULL)
- {
- UpdateHotButton(FClickedButton, Index);
- try
- {
- FOnTabButtonClick(this, Index);
- }
- __finally
- {
- UpdateHotButton(FClickedButton, -1);
- }
- }
- }
- else
- {
- TPageControl::Dispatch(&Message);
- }
- }
- //---------------------------------------------------------------------------
- void TThemePageControl::CMHintShow(TCMHintShow & HintShow)
- {
- TPageControl::Dispatch(&HintShow);
- if (OnTabHint != NULL)
- {
- int Tab = IndexOfTabAt(HintShow.HintInfo->CursorPos.x, HintShow.HintInfo->CursorPos.y);
- OnTabHint(this, Tab, HintShow.HintInfo->HintStr);
- HintShow.HintInfo->CursorRect = TabRect(Tab);
- }
- }
- //---------------------------------------------------------------------------
- void __fastcall TThemePageControl::Dispatch(void * Message)
- {
- TMessage * M = reinterpret_cast<TMessage*>(Message);
- if (M->Msg == CM_MOUSELEAVE)
- {
- UpdateHotButton(FHotTabButton, -1);
- TPageControl::Dispatch(Message);
- }
- else if (M->Msg == WM_LBUTTONDOWN)
- {
- WMLButtonDown(*reinterpret_cast<TWMLButtonDown *>(M));
- }
- else if (M->Msg == WM_WANTS_SCREEN_TIPS)
- {
- M->Result = 1;
- }
- else if (M->Msg == CM_HINTSHOW)
- {
- CMHintShow(*reinterpret_cast<TCMHintShow *>(M));
- }
- else
- {
- TPageControl::Dispatch(Message);
- }
- }
- //----------------------------------------------------------------------------------------------------------
- TThemeTabSheet * TThemePageControl::GetPage(int Index)
- {
- return DebugNotNull(dynamic_cast<TThemeTabSheet *>(TPageControl::Pages[Index]));
- }
- //----------------------------------------------------------------------------------------------------------
- TThemeTabSheet * TThemePageControl::GetActivePage()
- {
- TTabSheet * TabSheet = TPageControl::ActivePage;
- TThemeTabSheet * Result = NULL;
- if (TabSheet != NULL)
- {
- Result = DebugNotNull(dynamic_cast<TThemeTabSheet *>(TabSheet));
- }
- return Result;
- }
- //----------------------------------------------------------------------------------------------------------
- int TThemePageControl::TotalTabsWidth()
- {
- TRect FirstTabRect = TabRect(0);
- TRect LastTabRect = TabRect(PageCount - 1);
- return -FirstTabRect.Left + LastTabRect.Right;
- }
- //----------------------------------------------------------------------------------------------------------
- void TThemePageControl::UpdateTabsCaptionTruncation()
- {
- DisableAlign();
- Tabs->BeginUpdate();
- try
- {
- FSessionTabShrink = 0;
- for (int Index = 0; Index < PageCount; Index++)
- {
- Pages[Index]->UpdateCaption();
- }
- int TabsWidth = TotalTabsWidth();
- int MaxWidth = ClientWidth - ScaleByTextHeight(this, 8); // arbitrary margin to avoid left/right buttons flicker
- Canvas->Font = Font;
- if (TabsWidth > MaxWidth)
- {
- int NeedWidth = (TabsWidth - MaxWidth);
- int MaxLen = 0;
- int CaptionsWidth = 0;
- for (int Index = 0; Index < PageCount; Index++)
- {
- UnicodeString TabCaption = Pages[Index]->BaseCaption;
- MaxLen = std::max(MaxLen, TabCaption.Length());
- CaptionsWidth += Canvas->TextWidth(TabCaption);
- }
- bool Repeat;
- do
- {
- int NewShrink;
- if (FSessionTabShrink == 0)
- {
- NewShrink = MaxLen; // remove only new tab caption
- }
- else
- {
- NewShrink = FSessionTabShrink - 1;
- }
- if (NewShrink < 1)
- {
- Repeat = false;
- }
- else
- {
- FSessionTabShrink = NewShrink;
- int NewCaptionsWidth = 0;
- for (int Index = 0; Index < PageCount; Index++)
- {
- UnicodeString TabCaption = Pages[Index]->TruncatedCaption();
- NewCaptionsWidth += Canvas->TextWidth(TabCaption);
- }
- int GainedWidth = (CaptionsWidth - NewCaptionsWidth);
- Repeat = (GainedWidth < NeedWidth);
- }
- }
- while (Repeat);
- for (int Index = 0; Index < PageCount; Index++)
- {
- Pages[Index]->UpdateCaption();
- }
- }
- }
- __finally
- {
- Tabs->BeginUpdate();
- EnableAlign();
- }
- }
- //----------------------------------------------------------------------------------------------------------
- void TThemePageControl::SetActiveTabTheme(TTBXTheme * value)
- {
- if (FActiveTabTheme != value)
- {
- FActiveTabTheme = value;
- if (ActivePage != NULL)
- {
- ActivePage->Invalidate();
- }
- }
- }
- //----------------------------------------------------------------------------------------------------------
- void TThemePageControl::SetTabTheme(TTBXTheme * value)
- {
- if (FTabTheme != value)
- {
- FTabTheme = value;
- Invalidate();
- }
- }
- //----------------------------------------------------------------------------------------------------------
- #ifdef _DEBUG
- void __fastcall TThemePageControl::RequestAlign()
- {
- TPageControl::RequestAlign();
- }
- #endif
- //----------------------------------------------------------------------------------------------------------
|