ThemePageControl.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include <Common.h>
  5. #include <vsstyle.h>
  6. #include <memory>
  7. #include <PasTools.hpp>
  8. #include <TBXOfficeXPTheme.hpp>
  9. #include "ThemePageControl.h"
  10. //---------------------------------------------------------------------------
  11. #pragma package(smart_init)
  12. //---------------------------------------------------------------------------
  13. // Based on
  14. // https://www.codeproject.com/Articles/6355/XP-Themes-Tab-Control-in-any-orientation
  15. //---------------------------------------------------------------------------
  16. #define IDS_UTIL_TAB L"TAB"
  17. //---------------------------------------------------------------------------
  18. static inline void ValidCtrCheck(TThemePageControl *)
  19. {
  20. new TThemePageControl(NULL);
  21. }
  22. //---------------------------------------------------------------------------
  23. namespace Themepagecontrol
  24. {
  25. void __fastcall PACKAGE Register()
  26. {
  27. TComponentClass classes[2] = {__classid(TThemePageControl), __classid(TThemeTabSheet)};
  28. RegisterComponents(L"Scp", classes, 1);
  29. }
  30. }
  31. //----------------------------------------------------------------------------------------------------------
  32. __fastcall TThemeTabSheet::TThemeTabSheet(TComponent * Owner) :
  33. TTabSheet(Owner)
  34. {
  35. FShadowed = false;
  36. FButton = ttbNone;
  37. }
  38. //----------------------------------------------------------------------------------------------------------
  39. void __fastcall TThemeTabSheet::Invalidate()
  40. {
  41. TThemePageControl * ThemePageControl = dynamic_cast<TThemePageControl *>(Parent);
  42. if (DebugAlwaysTrue(ThemePageControl != NULL))
  43. {
  44. ThemePageControl->InvalidateTab(TabIndex);
  45. }
  46. else
  47. {
  48. Parent->Invalidate();
  49. }
  50. }
  51. //----------------------------------------------------------------------------------------------------------
  52. void __fastcall TThemeTabSheet::SetShadowed(bool Value)
  53. {
  54. if (Shadowed != Value)
  55. {
  56. FShadowed = Value;
  57. Invalidate();
  58. }
  59. }
  60. //----------------------------------------------------------------------------------------------------------
  61. void __fastcall TThemeTabSheet::SetButton(TThemeTabSheetButtons Value)
  62. {
  63. if (Button != Value)
  64. {
  65. FButton = Value;
  66. Invalidate();
  67. }
  68. }
  69. //----------------------------------------------------------------------------------------------------------
  70. //----------------------------------------------------------------------------------------------------------
  71. __fastcall TThemePageControl::TThemePageControl(TComponent * Owner) :
  72. TPageControl(Owner)
  73. {
  74. FOldTabIndex = -1;
  75. FHotTabButton = -1;
  76. FClickedButton = -1;
  77. }
  78. //----------------------------------------------------------------------------------------------------------
  79. int __fastcall TThemePageControl::GetTabsHeight()
  80. {
  81. // Calculated height includes tab/contents separator line on Windows 7/8,
  82. // but not on Windows XP
  83. TRect Rect = GetClientRect();
  84. ::SendMessage(Handle, TCM_ADJUSTRECT, FALSE, (LPARAM)&Rect);
  85. int Result = Rect.Top - 1;
  86. // Two different ways to calculate the same, not sure which one is more reliable,
  87. // so we want to know in case they differ.
  88. if (DebugAlwaysTrue(PageCount >= 0))
  89. {
  90. TRect Rect = TabRect(0);
  91. int Result2 = Rect.Bottom + 1;
  92. // On Windows 10 with 200% scaling, the first is 40, the second is 42.
  93. // With 250% scaling its 50 vs 53.
  94. // Using the larger.
  95. if (Result2 > Result)
  96. {
  97. DebugAssert(IsWin10());
  98. Result = Result2;
  99. }
  100. }
  101. return Result;
  102. }
  103. //----------------------------------------------------------------------------------------------------------
  104. void __fastcall TThemePageControl::PaintWindow(HDC DC)
  105. {
  106. // Themes not enabled, give up
  107. if (!UseThemes())
  108. {
  109. TPageControl::PaintWindow(DC);
  110. return;
  111. }
  112. // TODO use GetClipBox
  113. TRect PageRect = GetClientRect();
  114. // 1st paint the tab body
  115. TRect ClientRect = PageRect;
  116. ::SendMessage(Handle, TCM_ADJUSTRECT, FALSE, (LPARAM)&PageRect);
  117. ClientRect.Top = PageRect.Top - 2;
  118. DrawThemesXpTabItem(DC, -1, ClientRect, true, 0, false);
  119. // 2nd paint the inactive tabs
  120. int SelectedIndex = TabIndex; // optimization
  121. for (int Tab = 0; Tab < PageCount; Tab++)
  122. {
  123. if (Tab != SelectedIndex)
  124. {
  125. DrawThemesXpTab(DC, Tab);
  126. }
  127. }
  128. if (SelectedIndex >= 0)
  129. {
  130. DrawThemesXpTab(DC, TabIndex);
  131. }
  132. }
  133. //----------------------------------------------------------------------------------------------------------
  134. TThemeTabSheetButtons __fastcall TThemePageControl::GetTabButton(int Index)
  135. {
  136. TThemeTabSheet * ThemeTabSheet = dynamic_cast<TThemeTabSheet *>(Pages[Index]);
  137. return (UseThemes() && (ThemeTabSheet != NULL)) ? ThemeTabSheet->Button : ttbNone;
  138. }
  139. //----------------------------------------------------------------------------------------------------------
  140. void __fastcall TThemePageControl::DrawThemesXpTab(HDC DC, int Tab)
  141. {
  142. TThemeTabSheet * ThemeTabSheet = dynamic_cast<TThemeTabSheet *>(Pages[Tab]);
  143. bool Shadowed = (ThemeTabSheet != NULL) ? ThemeTabSheet->Shadowed : false;
  144. TRect Rect = TabRect(Tab);
  145. ItemTabRect(Tab, Rect);
  146. int State;
  147. if (Tab != TabIndex)
  148. {
  149. TPoint Point = ScreenToClient(Mouse->CursorPos);
  150. int HotIndex = IndexOfTabAt(Point.X, Point.Y);
  151. State = (Tab == HotIndex ? TIS_HOT : (Shadowed ? TIS_DISABLED : TIS_NORMAL));
  152. }
  153. else
  154. {
  155. State = TIS_SELECTED;
  156. }
  157. DrawThemesXpTabItem(DC, Tab, Rect, false, State, Shadowed);
  158. }
  159. //----------------------------------------------------------------------------------------------------------
  160. // This function draws Themes Tab control parts: a) Tab-Body and b) Tab-tabs
  161. void __fastcall TThemePageControl::DrawThemesXpTabItem(HDC DC, int Item,
  162. const TRect & Rect, bool Body, int State, bool Shadowed)
  163. {
  164. TSize Size = Rect.Size;
  165. // Draw background
  166. HDC DCMem = CreateCompatibleDC(DC);
  167. HBITMAP BitmapMem = CreateCompatibleBitmap(DC, Size.Width, Size.Height);
  168. HBITMAP BitmapOld = (HBITMAP)SelectObject(DCMem, BitmapMem);
  169. TRect RectMem(0, 0, Size.Width, Size.Height);
  170. TRect RectItemMem(RectMem);
  171. if (!Body && (State == TIS_SELECTED))
  172. {
  173. RectMem.Bottom++;
  174. }
  175. if (Body)
  176. {
  177. DrawThemesPart(DCMem, TABP_PANE, State, IDS_UTIL_TAB, &RectMem);
  178. }
  179. else
  180. {
  181. DrawThemesPart(DCMem, TABP_TABITEM, State, IDS_UTIL_TAB, &RectMem);
  182. }
  183. // Init some extra parameters
  184. BITMAPINFO BitmapInfo;
  185. // Fill local pixel arrays
  186. ZeroMemory(&BitmapInfo, sizeof(BITMAPINFO));
  187. BITMAPINFOHEADER & BitmapInfoHeader = BitmapInfo.bmiHeader;
  188. BitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
  189. BitmapInfoHeader.biCompression = BI_RGB;
  190. BitmapInfoHeader.biPlanes = 1;
  191. // force as RGB: 3 bytes,24 bits -> good for rotating bitmap in any resolution
  192. BitmapInfoHeader.biBitCount = 24;
  193. BitmapInfoHeader.biWidth = Size.Width;
  194. BitmapInfoHeader.biHeight = Size.Height;
  195. if (!Body && (Item >= 0))
  196. {
  197. DrawTabItem(DCMem, Item, Rect, RectItemMem, (State == TIS_SELECTED), Shadowed);
  198. }
  199. // Blit image to the screen
  200. BitBlt(DC, Rect.Left, Rect.Top, Size.Width, Size.Height, DCMem, 0, 0, SRCCOPY);
  201. SelectObject(DCMem, BitmapOld);
  202. DeleteObject(BitmapMem);
  203. DeleteDC(DCMem);
  204. }
  205. //----------------------------------------------------------------------------------------------------------
  206. void __fastcall TThemePageControl::ItemTabRect(int Item, TRect & Rect)
  207. {
  208. if (Item == TabIndex)
  209. {
  210. // Countered in TabButtonRect
  211. Rect.Inflate(2, 2);
  212. Rect.Bottom--;
  213. }
  214. }
  215. //----------------------------------------------------------------------------------------------------------
  216. void __fastcall TThemePageControl::ItemContentsRect(int Item, TRect & Rect)
  217. {
  218. bool Selected = (Item == TabIndex);
  219. Rect.Left += 6;
  220. Rect.Top += 2;
  221. if (Selected)
  222. {
  223. Rect.Bottom -= 2;
  224. Rect.Top += 1;
  225. }
  226. else
  227. {
  228. Rect.Bottom += 2;
  229. Rect.Top += 3;
  230. }
  231. }
  232. //----------------------------------------------------------------------------------------------------------
  233. bool __fastcall TThemePageControl::HasItemImage(int Item)
  234. {
  235. return (Images != NULL) && (Pages[Item]->ImageIndex >= 0);
  236. }
  237. //----------------------------------------------------------------------------------------------------------
  238. void __fastcall TThemePageControl::ItemTextRect(int Item, TRect & Rect)
  239. {
  240. if (HasItemImage(Item))
  241. {
  242. Rect.Left += Images->Width + 3;
  243. }
  244. else
  245. {
  246. Rect.Left -= 2;
  247. }
  248. Rect.Right -= 3;
  249. OffsetRect(&Rect, 0, ((Item == TabIndex) ? 0 : -2));
  250. }
  251. //----------------------------------------------------------------------------------------------------------
  252. void TThemePageControl::DrawCross(HDC DC, int Width, COLORREF Color, const TRect & Rect)
  253. {
  254. HPEN Pen = CreatePen(PS_SOLID, Width, Color);
  255. HPEN OldPen = static_cast<HPEN>(SelectObject(DC, Pen));
  256. // To-and-back - to make both ends look the same
  257. MoveToEx(DC, Rect.Left, Rect.Bottom - 1, NULL);
  258. LineTo(DC, Rect.Right - 1, Rect.Top);
  259. LineTo(DC, Rect.Left, Rect.Bottom - 1);
  260. MoveToEx(DC, Rect.Left, Rect.Top, NULL);
  261. LineTo(DC, Rect.Right - 1, Rect.Bottom - 1);
  262. LineTo(DC, Rect.Left, Rect.Top);
  263. SelectObject(DC, OldPen);
  264. DeleteObject(Pen);
  265. }
  266. //----------------------------------------------------------------------------------------------------------
  267. void TThemePageControl::DrawDropDown(HDC DC, int Radius, int X, int Y, COLORREF Color, int Grow)
  268. {
  269. // Optimized for even-sized Rect (100% scaling), may need adjustments for even-sized to correctly center
  270. TPoint Points[] = {
  271. Point(X - Radius - 1 - Grow, Y), Point(X + Radius + Grow, Y),
  272. Point(X, Y + Radius + Grow), Point(X - 1, Y + Radius + Grow)
  273. };
  274. HBRUSH Brush = CreateSolidBrush(Color);
  275. HPEN Pen = CreatePen(PS_SOLID, 1, Color);
  276. HGDIOBJ OldBrush = SelectObject(DC, Brush);
  277. HGDIOBJ OldPen = SelectObject(DC, Pen);
  278. Polygon(DC, Points, LENOF(Points));
  279. SelectObject(DC, OldPen);
  280. SelectObject(DC, OldBrush);
  281. }
  282. //----------------------------------------------------------------------------------------------------------
  283. // draw tab item context: possible icon and text
  284. void __fastcall TThemePageControl::DrawTabItem(
  285. HDC DC, int Item, TRect TabRect, TRect Rect, bool Selected, bool Shadowed)
  286. {
  287. ItemContentsRect(Item, Rect);
  288. UnicodeString Text = Pages[Item]->Caption;
  289. if (HasItemImage(Item))
  290. {
  291. int Left;
  292. if (!Text.IsEmpty())
  293. {
  294. Left = Rect.Left + (Selected ? 2 : 0);
  295. }
  296. else
  297. {
  298. Left = (Rect.Right - Images->Width - Rect.Left) / 2;
  299. }
  300. int Y = ((Rect.Top + Rect.Bottom - Images->Height) / 2) - 1 + (Selected ? 0 : -2);
  301. std::unique_ptr<TCanvas> Canvas(new TCanvas());
  302. Canvas->Handle = DC;
  303. Images->Draw(Canvas.get(), Left, Y, Pages[Item]->ImageIndex, !Shadowed);
  304. }
  305. int TextHeight = 20;
  306. int OldMode = SetBkMode(DC, TRANSPARENT);
  307. if (!Text.IsEmpty())
  308. {
  309. ItemTextRect(Item, Rect);
  310. HFONT OldFont = (HFONT)SelectObject(DC, Font->Handle);
  311. wchar_t * Buf = new wchar_t[Text.Length() + 1 + 4];
  312. wcscpy(Buf, Text.c_str());
  313. TRect TextRect(0, 0, Rect.Right - Rect.Left, TextHeight);
  314. // Truncates too long texts with ellipsis
  315. ::DrawText(DC, Buf, -1, &TextRect, DT_CALCRECT | DT_SINGLELINE | DT_MODIFYSTRING | DT_END_ELLIPSIS);
  316. DrawText(DC, Buf, -1, &Rect, DT_NOPREFIX | DT_CENTER);
  317. delete[] Buf;
  318. TThemeTabSheetButtons Button = GetTabButton(Item);
  319. if (Button != ttbNone)
  320. {
  321. Rect = TabButtonRect(Item);
  322. Rect.Offset(-TabRect.Left, -TabRect.Top);
  323. if (IsHotButton(Item))
  324. {
  325. HBRUSH Brush = CreateSolidBrush(GetSelectedBodyColor());
  326. FillRect(DC, &Rect, Brush);
  327. DeleteObject(Brush);
  328. HPEN Pen = CreatePen(PS_SOLID, 1, ColorToRGB(clHighlight));
  329. HPEN OldPen = static_cast<HPEN>(SelectObject(DC, Pen));
  330. Rectangle(DC, Rect.Left, Rect.Top, Rect.Right, Rect.Bottom);
  331. SelectObject(DC, OldPen);
  332. DeleteObject(Pen);
  333. }
  334. COLORREF BackColor = GetPixel(DC, Rect.Left + (Rect.Width() / 2), Rect.Top + (Rect.Height() / 2));
  335. COLORREF ShapeColor = ColorToRGB(Font->Color);
  336. #define BlendValue(FN) (((4 * static_cast<int>(FN(BackColor))) + static_cast<int>(FN(ShapeColor))) / 5)
  337. COLORREF BlendColor = RGB(BlendValue(GetRValue), BlendValue(GetGValue), BlendValue(GetBValue));
  338. #undef BlendValue
  339. if (Button == ttbClose)
  340. {
  341. int CrossPadding = GetCrossPadding();
  342. TRect CrossRect(Rect);
  343. CrossRect.Inflate(-CrossPadding, -CrossPadding);
  344. int CrossWidth = ScaleByTextHeight(this, 1);
  345. DrawCross(DC, CrossWidth + 1, BlendColor, CrossRect);
  346. DrawCross(DC, CrossWidth, ShapeColor, CrossRect);
  347. }
  348. else if (DebugAlwaysTrue(Button == ttbDropDown))
  349. {
  350. // See TTBXOfficeXPTheme.PaintDropDownArrow
  351. int Radius = ScaleByTextHeight(this, 2);
  352. int X = ((Rect.Left + Rect.Right)) / 2;
  353. int Y = ((Rect.Top + Rect.Bottom) / 2) - (Radius * 2 / 3);
  354. DrawDropDown(DC, Radius, X, Y, BlendColor, 1);
  355. DrawDropDown(DC, Radius, X, Y, ShapeColor, 0);
  356. }
  357. }
  358. SelectObject(DC, OldFont);
  359. }
  360. SetBkMode(DC, OldMode);
  361. }
  362. //----------------------------------------------------------------------------------------------------------
  363. int __fastcall TThemePageControl::TabButtonSize()
  364. {
  365. return ScaleByTextHeight(this, 16);
  366. }
  367. //----------------------------------------------------------------------------------------------------------
  368. int __fastcall TThemePageControl::GetCrossPadding()
  369. {
  370. return ScaleByTextHeight(this, 4);
  371. }
  372. //----------------------------------------------------------------------------------------------------------
  373. TRect __fastcall TThemePageControl::TabButtonRect(int Index)
  374. {
  375. TRect Rect = TabRect(Index);
  376. ItemTabRect(Index, Rect);
  377. ItemContentsRect(Index, Rect);
  378. ItemTextRect(Index, Rect);
  379. int ATabButtonSize = TabButtonSize();
  380. int CrossPadding = GetCrossPadding();
  381. TEXTMETRIC TextMetric;
  382. Canvas->Font = Font;
  383. GetTextMetrics(Canvas->Handle, &TextMetric);
  384. Rect.Top += TextMetric.tmAscent - ATabButtonSize + CrossPadding;
  385. Rect.Left = Rect.Right - ATabButtonSize - ScaleByTextHeight(this, 1);
  386. if (Index == TabIndex)
  387. {
  388. // To counter Inflate(2, 2) in ItemTabRect
  389. Rect.Left -= 2;
  390. }
  391. Rect.Right = Rect.Left + ATabButtonSize;
  392. Rect.Bottom = Rect.Top + ATabButtonSize;
  393. return Rect;
  394. }
  395. //----------------------------------------------------------------------------------------------------------
  396. bool TThemePageControl::IsHotButton(int Index)
  397. {
  398. // This was an attempt to allow tracking close buttons, even while drop down button menu is popped,
  399. // but MouseMove does not trigger then.
  400. return (Index == FClickedButton) || (Index == FHotTabButton);
  401. }
  402. //----------------------------------------------------------------------------------------------------------
  403. void TThemePageControl::UpdateHotButton(int & Ref, int Index)
  404. {
  405. if (Ref != Index)
  406. {
  407. bool WasHot = (Index >= 0) && IsHotButton(Index);
  408. int Prev = Ref;
  409. Ref = Index;
  410. if ((Prev >= 0) && !IsHotButton(Prev))
  411. {
  412. InvalidateTab(Prev);
  413. }
  414. if ((Index >= 0) && !WasHot)
  415. {
  416. InvalidateTab(Index);
  417. }
  418. }
  419. }
  420. //----------------------------------------------------------------------------------------------------------
  421. void __fastcall TThemePageControl::MouseMove(TShiftState Shift, int X, int Y)
  422. {
  423. TPageControl::MouseMove(Shift, X, Y);
  424. UpdateHotButton(FHotTabButton, IndexOfTabButtonAt(X, Y));
  425. }
  426. //----------------------------------------------------------------------------------------------------------
  427. int __fastcall TThemePageControl::IndexOfTabButtonAt(int X, int Y)
  428. {
  429. int Result = IndexOfTabAt(X, Y);
  430. if ((Result < 0) ||
  431. !GetTabButton(Result) ||
  432. !TabButtonRect(Result).Contains(TPoint(X, Y)))
  433. {
  434. Result = -1;
  435. }
  436. return Result;
  437. }
  438. //----------------------------------------------------------------------------------------------------------
  439. void __fastcall TThemePageControl::DrawThemesPart(HDC DC, int PartId,
  440. int StateId, LPCWSTR PartNameID, LPRECT Rect)
  441. {
  442. HTHEME Theme = OpenThemeData(NULL, PartNameID);
  443. if (Theme != 0)
  444. {
  445. DrawThemeBackground(Theme, DC, PartId, StateId, Rect, NULL);
  446. CloseThemeData(Theme);
  447. }
  448. }
  449. //----------------------------------------------------------------------------------------------------------
  450. bool __fastcall TThemePageControl::CanChange()
  451. {
  452. FOldTabIndex = ActivePageIndex;
  453. return TPageControl::CanChange();
  454. }
  455. //----------------------------------------------------------------------------------------------------------
  456. void __fastcall TThemePageControl::InvalidateTab(int Index)
  457. {
  458. if (HandleAllocated())
  459. {
  460. TRect Rect = TabRect(Index);
  461. if (Index == TabIndex)
  462. {
  463. Rect.Inflate(2, 2);
  464. }
  465. // Original code was invalidating range against parent window
  466. // (recalculating coordinates first)
  467. InvalidateRect(Handle, &Rect, true);
  468. }
  469. }
  470. //----------------------------------------------------------------------------------------------------------
  471. void __fastcall TThemePageControl::Change()
  472. {
  473. // note that TabIndex yields correct value already here,
  474. // while ActivePageIndex is not updated yet
  475. if ((FOldTabIndex >= 0) && (FOldTabIndex != TabIndex) && UseThemes())
  476. {
  477. InvalidateTab(FOldTabIndex);
  478. }
  479. TPageControl::Change();
  480. }
  481. //----------------------------------------------------------------------------------------------------------
  482. UnicodeString __fastcall TThemePageControl::FormatCaptionWithTabButton(const UnicodeString & Caption)
  483. {
  484. UnicodeString Result = Caption;
  485. if (UseThemes())
  486. {
  487. int OrigWidth = Canvas->TextWidth(Caption);
  488. int TabButtonWidth = TabButtonSize();
  489. while (Canvas->TextWidth(Result) < OrigWidth + TabButtonWidth)
  490. {
  491. Result += L" ";
  492. }
  493. }
  494. return Result;
  495. }
  496. //---------------------------------------------------------------------------
  497. void __fastcall TThemePageControl::WMLButtonDown(TWMLButtonDown & Message)
  498. {
  499. int Index = IndexOfTabButtonAt(Message.XPos, Message.YPos);
  500. if (Index >= 0)
  501. {
  502. Message.Result = 1;
  503. if (FOnTabButtonClick != NULL)
  504. {
  505. UpdateHotButton(FClickedButton, Index);
  506. try
  507. {
  508. FOnTabButtonClick(this, Index);
  509. }
  510. __finally
  511. {
  512. UpdateHotButton(FClickedButton, -1);
  513. }
  514. }
  515. }
  516. else
  517. {
  518. TPageControl::Dispatch(&Message);
  519. }
  520. }
  521. //---------------------------------------------------------------------------
  522. void __fastcall TThemePageControl::Dispatch(void * Message)
  523. {
  524. TMessage * M = reinterpret_cast<TMessage*>(Message);
  525. if (M->Msg == CM_MOUSELEAVE)
  526. {
  527. UpdateHotButton(FHotTabButton, -1);
  528. TPageControl::Dispatch(Message);
  529. }
  530. else if (M->Msg == WM_LBUTTONDOWN)
  531. {
  532. WMLButtonDown(*reinterpret_cast<TWMLButtonDown *>(M));
  533. }
  534. else
  535. {
  536. TPageControl::Dispatch(Message);
  537. }
  538. }
  539. //----------------------------------------------------------------------------------------------------------
  540. TThemeTabSheet * TThemePageControl::GetPage(int Index)
  541. {
  542. return DebugNotNull(dynamic_cast<TThemeTabSheet *>(TPageControl::Pages[Index]));
  543. }
  544. //----------------------------------------------------------------------------------------------------------
  545. TThemeTabSheet * TThemePageControl::GetActivePage()
  546. {
  547. TTabSheet * TabSheet = TPageControl::ActivePage;
  548. TThemeTabSheet * Result = NULL;
  549. if (TabSheet != NULL)
  550. {
  551. Result = DebugNotNull(dynamic_cast<TThemeTabSheet *>(TabSheet));
  552. }
  553. return Result;
  554. }
  555. //----------------------------------------------------------------------------------------------------------
  556. #ifdef _DEBUG
  557. void __fastcall TThemePageControl::RequestAlign()
  558. {
  559. TPageControl::RequestAlign();
  560. }
  561. #endif
  562. //----------------------------------------------------------------------------------------------------------