1
0

TB2MDI.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  1. unit TB2MDI;
  2. {
  3. Toolbar2000
  4. Copyright (C) 1998-2005 by Jordan Russell
  5. All rights reserved.
  6. The contents of this file are subject to the "Toolbar2000 License"; you may
  7. not use or distribute this file except in compliance with the
  8. "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in
  9. TB2k-LICENSE.txt or at:
  10. http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt
  11. Alternatively, the contents of this file may be used under the terms of the
  12. GNU General Public License (the "GPL"), in which case the provisions of the
  13. GPL are applicable instead of those in the "Toolbar2000 License". A copy of
  14. the GPL may be found in GPL-LICENSE.txt or at:
  15. http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt
  16. If you wish to allow use of your version of this file only under the terms of
  17. the GPL and not to allow others to use your version of this file under the
  18. "Toolbar2000 License", indicate your decision by deleting the provisions
  19. above and replace them with the notice and other provisions required by the
  20. GPL. If you do not delete the provisions above, a recipient may use your
  21. version of this file under either the "Toolbar2000 License" or the GPL.
  22. $jrsoftware: tb2k/Source/TB2MDI.pas,v 1.13 2005/01/06 03:56:50 jr Exp $
  23. }
  24. interface
  25. {$I TB2Ver.inc}
  26. uses
  27. Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  28. Menus, TB2Item, TB2Toolbar;
  29. type
  30. TTBMDIButtonsItem = class;
  31. TTBMDISystemMenuItem = class;
  32. TTBMDIHandler = class(TComponent)
  33. private
  34. FButtonsItem: TTBMDIButtonsItem;
  35. FSystemMenuItem: TTBMDISystemMenuItem;
  36. FToolbar: TTBCustomToolbar;
  37. procedure SetToolbar(Value: TTBCustomToolbar);
  38. protected
  39. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  40. public
  41. constructor Create(AOwner: TComponent); override;
  42. destructor Destroy; override;
  43. published
  44. property Toolbar: TTBCustomToolbar read FToolbar write SetToolbar;
  45. end;
  46. TTBMDIWindowItem = class(TTBCustomItem)
  47. private
  48. FForm: TForm;
  49. FOnUpdate: TNotifyEvent;
  50. FWindowMenu: TMenuItem;
  51. procedure ItemClick(Sender: TObject);
  52. procedure SetForm(AForm: TForm);
  53. protected
  54. procedure EnabledChanged; override;
  55. procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
  56. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  57. public
  58. constructor Create(AOwner: TComponent); override;
  59. procedure InitiateAction; override;
  60. published
  61. property Enabled;
  62. property OnUpdate: TNotifyEvent read FOnUpdate write FOnUpdate;
  63. end;
  64. TTBMDISystemMenuItem = class(TTBCustomItem)
  65. private
  66. FImageList: TImageList;
  67. procedure CommandClick(Sender: TObject);
  68. protected
  69. function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override;
  70. public
  71. constructor Create(AOwner: TComponent); override;
  72. procedure Click; override;
  73. end;
  74. TTBMDISystemMenuItemViewer = class(TTBItemViewer)
  75. protected
  76. procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer);
  77. override;
  78. procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect;
  79. IsSelected, IsPushed, UseDisabledShadow: Boolean); override;
  80. end;
  81. TTBMDIButtonType = (tbmbMinimize, tbmbRestore, tbmbClose);
  82. TTBMDIButtonItem = class(TTBCustomItem)
  83. private
  84. FButtonType: TTBMDIButtonType;
  85. protected
  86. function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override;
  87. public
  88. constructor Create(AOwner: TComponent); override;
  89. end;
  90. TTBMDIButtonItemViewer = class(TTBItemViewer)
  91. protected
  92. procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer);
  93. override;
  94. procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect;
  95. IsSelected, IsPushed, UseDisabledShadow: Boolean); override;
  96. end;
  97. TTBMDISepItem = class(TTBSeparatorItem)
  98. protected
  99. function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override;
  100. end;
  101. TTBMDISepItemViewer = class(TTBSeparatorItemViewer)
  102. protected
  103. procedure CalcSize(const Canvas: TCanvas; var AWidth, AHeight: Integer);
  104. override;
  105. end;
  106. TTBMDIButtonsItem = class(TTBCustomItem)
  107. private
  108. FMinimizeItem: TTBMDIButtonItem;
  109. FRestoreItem: TTBMDIButtonItem;
  110. FCloseItem: TTBMDIButtonItem;
  111. FSep1, FSep2: TTBMDISepItem;
  112. procedure InvalidateSystemMenuItem;
  113. procedure ItemClick(Sender: TObject);
  114. procedure UpdateState(W: HWND; Maximized: Boolean);
  115. public
  116. constructor Create(AOwner: TComponent); override;
  117. destructor Destroy; override;
  118. end;
  119. implementation
  120. uses
  121. TB2Common, TB2Consts, CommCtrl;
  122. type
  123. TTBCustomToolbarAccess = class(TTBCustomToolbar);
  124. { TTBMDIHandler }
  125. constructor TTBMDIHandler.Create(AOwner: TComponent);
  126. begin
  127. inherited;
  128. FSystemMenuItem := TTBMDISystemMenuItem.Create(Self);
  129. FButtonsItem := TTBMDIButtonsItem.Create(Self);
  130. end;
  131. destructor TTBMDIHandler.Destroy;
  132. begin
  133. Toolbar := nil;
  134. inherited;
  135. end;
  136. procedure TTBMDIHandler.Notification(AComponent: TComponent; Operation: TOperation);
  137. begin
  138. inherited;
  139. if (AComponent = FToolbar) and (Operation = opRemove) then
  140. Toolbar := nil;
  141. end;
  142. procedure TTBMDIHandler.SetToolbar(Value: TTBCustomToolbar);
  143. var
  144. Rebuild: Boolean;
  145. begin
  146. if FToolbar <> Value then begin
  147. if Assigned(FToolbar) then begin
  148. Rebuild := False;
  149. if TTBCustomToolbarAccess(FToolbar).FMDIButtonsItem = FButtonsItem then begin
  150. TTBCustomToolbarAccess(FToolbar).FMDIButtonsItem := nil;
  151. Rebuild := True;
  152. end;
  153. if TTBCustomToolbarAccess(FToolbar).FMDISystemMenuItem = FSystemMenuItem then begin
  154. TTBCustomToolbarAccess(FToolbar).FMDISystemMenuItem := nil;
  155. Rebuild := True;
  156. end;
  157. if Rebuild and Assigned(FToolbar.View) then
  158. FToolbar.View.RecreateAllViewers;
  159. end;
  160. FToolbar := Value;
  161. if Assigned(Value) then begin
  162. Value.FreeNotification(Self);
  163. TTBCustomToolbarAccess(Value).FMDIButtonsItem := FButtonsItem;
  164. TTBCustomToolbarAccess(Value).FMDISystemMenuItem := FSystemMenuItem;
  165. Value.View.RecreateAllViewers;
  166. end;
  167. end;
  168. end;
  169. { TTBMDISystemMenuItem }
  170. constructor TTBMDISystemMenuItem.Create(AOwner: TComponent);
  171. begin
  172. inherited;
  173. ItemStyle := ItemStyle + [tbisSubMenu, tbisDontSelectFirst] -
  174. [tbisRedrawOnSelChange, tbisRedrawOnMouseOverChange];
  175. Caption := '&-';
  176. {$R TB2MDI.res}
  177. FImageList := TImageList.Create(Self);
  178. FImageList.Handle := ImageList_LoadBitmap(HInstance, 'TB2SYSMENUIMAGES',
  179. 16, 0, clSilver);
  180. SubMenuImages := FImageList;
  181. end;
  182. function TTBMDISystemMenuItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass;
  183. begin
  184. Result := TTBMDISystemMenuItemViewer;
  185. end;
  186. procedure TTBMDISystemMenuItem.Click;
  187. var
  188. I: Integer;
  189. Form: TForm;
  190. M: HMENU;
  191. State, ID: UINT;
  192. Item: TTBCustomItem;
  193. Buf: array[0..1023] of Char;
  194. begin
  195. inherited;
  196. Clear;
  197. if Application.MainForm = nil then
  198. Exit;
  199. Form := Application.MainForm.ActiveMDIChild;
  200. if Form = nil then
  201. Exit;
  202. M := GetSystemMenu(Form.Handle, False);
  203. for I := 0 to GetMenuItemCount(M)-1 do begin
  204. State := GetMenuState(M, I, MF_BYPOSITION);
  205. if State and MF_SEPARATOR <> 0 then
  206. Add(TTBSeparatorItem.Create(Self))
  207. else begin
  208. Item := TTBCustomItem.Create(Self);
  209. if State and MF_GRAYED <> 0 then
  210. Item.Enabled := False;
  211. if GetMenuString(M, I, Buf, SizeOf(Buf), MF_BYPOSITION) = 0 then
  212. Buf[0] := #0;
  213. Item.Caption := Buf;
  214. ID := GetMenuItemID(M, I);
  215. Item.Tag := ID;
  216. case ID and $FFF0 of
  217. SC_RESTORE: Item.ImageIndex := 3;
  218. SC_MINIMIZE: Item.ImageIndex := 2;
  219. SC_MAXIMIZE: Item.ImageIndex := 1;
  220. SC_CLOSE: begin
  221. Item.ImageIndex := 0;
  222. Item.Options := Item.Options + [tboDefault];
  223. end;
  224. end;
  225. Item.OnClick := CommandClick;
  226. Add(Item);
  227. end;
  228. end;
  229. end;
  230. procedure TTBMDISystemMenuItem.CommandClick(Sender: TObject);
  231. var
  232. Form: TForm;
  233. begin
  234. if Assigned(Application.MainForm) then begin
  235. Form := Application.MainForm.ActiveMDIChild;
  236. if Assigned(Form) then
  237. SendMessage(Form.Handle, WM_SYSCOMMAND, TTBCustomItem(Sender).Tag,
  238. GetMessagePos);
  239. end;
  240. end;
  241. { TTBMDISystemMenuItemViewer }
  242. procedure TTBMDISystemMenuItemViewer.CalcSize(const Canvas: TCanvas;
  243. var AWidth, AHeight: Integer);
  244. begin
  245. AWidth := GetSystemMetrics(SM_CXSMICON) + 2;
  246. AHeight := GetSystemMetrics(SM_CYSMICON) + 2;
  247. end;
  248. procedure TTBMDISystemMenuItemViewer.Paint(const Canvas: TCanvas;
  249. const ClientAreaRect: TRect; IsSelected, IsPushed, UseDisabledShadow: Boolean);
  250. function GetIconHandle: HICON;
  251. var
  252. Form: TForm;
  253. begin
  254. Result := 0;
  255. if Assigned(Application.MainForm) then begin
  256. Form := Application.MainForm.ActiveMDIChild;
  257. if Assigned(Form) then
  258. Result := Form.Icon.Handle;
  259. end;
  260. if Result = 0 then
  261. Result := Application.Icon.Handle;
  262. if Result = 0 then
  263. Result := LoadIcon(0, IDI_APPLICATION);
  264. end;
  265. var
  266. R: TRect;
  267. TempIcon: HICON;
  268. begin
  269. R := ClientAreaRect;
  270. InflateRect(R, -1, -1);
  271. TempIcon := CopyImage(GetIconHandle, IMAGE_ICON, R.Right - R.Left,
  272. R.Bottom - R.Top, LR_COPYFROMRESOURCE);
  273. DrawIconEx(Canvas.Handle, R.Left, R.Top, TempIcon, 0, 0, 0, 0, DI_NORMAL);
  274. DestroyIcon(TempIcon);
  275. end;
  276. { TTBMDIButtonItem }
  277. constructor TTBMDIButtonItem.Create(AOwner: TComponent);
  278. begin
  279. inherited;
  280. ItemStyle := ItemStyle - [tbisSelectable, tbisRedrawOnSelChange] +
  281. [tbisRightAlign];
  282. end;
  283. function TTBMDIButtonItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass;
  284. begin
  285. Result := TTBMDIButtonItemViewer;
  286. end;
  287. { TTBMDIButtonItemViewer }
  288. procedure TTBMDIButtonItemViewer.CalcSize(const Canvas: TCanvas;
  289. var AWidth, AHeight: Integer);
  290. begin
  291. if NewStyleControls then begin
  292. AWidth := GetSystemMetrics(SM_CXMENUSIZE) - 2;
  293. if AWidth < 0 then AWidth := 0;
  294. AHeight := GetSystemMetrics(SM_CYMENUSIZE) - 4;
  295. if AHeight < 0 then AHeight := 0;
  296. end
  297. else begin
  298. AWidth := 16;
  299. AHeight := 14;
  300. end;
  301. end;
  302. procedure TTBMDIButtonItemViewer.Paint(const Canvas: TCanvas;
  303. const ClientAreaRect: TRect; IsSelected, IsPushed, UseDisabledShadow: Boolean);
  304. const
  305. ButtonTypeFlags: array[TTBMDIButtonType] of UINT = (DFCS_CAPTIONMIN,
  306. DFCS_CAPTIONRESTORE, DFCS_CAPTIONCLOSE);
  307. PushedFlags: array[Boolean] of UINT = (0, DFCS_PUSHED);
  308. EnabledFlags: array[Boolean] of UINT = (DFCS_INACTIVE, 0);
  309. begin
  310. DrawFrameControl(Canvas.Handle, ClientAreaRect, DFC_CAPTION,
  311. ButtonTypeFlags[TTBMDIButtonItem(Item).FButtonType] or
  312. PushedFlags[IsPushed] or EnabledFlags[Item.Enabled]);
  313. end;
  314. { TTBMDISepItem }
  315. function TTBMDISepItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass;
  316. begin
  317. Result := TTBMDISepItemViewer;
  318. end;
  319. { TTBMDISepItemViewer }
  320. procedure TTBMDISepItemViewer.CalcSize(const Canvas: TCanvas;
  321. var AWidth, AHeight: Integer);
  322. begin
  323. if View.Orientation <> tbvoVertical then begin
  324. AWidth := 2;
  325. AHeight := 6;
  326. end
  327. else begin
  328. AWidth := 6;
  329. AHeight := 2;
  330. end;
  331. end;
  332. { TTBMDIButtonsItem }
  333. var
  334. CBTHookHandle: HHOOK;
  335. MDIButtonsItems: TList;
  336. function WindowIsMDIChild(W: HWND): Boolean;
  337. var
  338. I: Integer;
  339. MainForm, ChildForm: TForm;
  340. begin
  341. MainForm := Application.MainForm;
  342. if Assigned(MainForm) then
  343. for I := 0 to MainForm.MDIChildCount-1 do begin
  344. ChildForm := MainForm.MDIChildren[I];
  345. if ChildForm.HandleAllocated and (ChildForm.Handle = W) then begin
  346. Result := True;
  347. Exit;
  348. end;
  349. end;
  350. Result := False;
  351. end;
  352. function CBTHook(Code: Integer; WParam: WPARAM; LParam: LPARAM): LRESULT;
  353. stdcall;
  354. var
  355. Maximizing: Boolean;
  356. WindowPlacement: TWindowPlacement;
  357. I: Integer;
  358. begin
  359. case Code of
  360. HCBT_SETFOCUS: begin
  361. if WindowIsMDIChild(HWND(WParam)) and Assigned(MDIButtonsItems) then begin
  362. for I := 0 to MDIButtonsItems.Count-1 do
  363. TTBMDIButtonsItem(MDIButtonsItems[I]).InvalidateSystemMenuItem;
  364. end;
  365. end;
  366. HCBT_MINMAX: begin
  367. if WindowIsMDIChild(HWND(WParam)) and Assigned(MDIButtonsItems) and
  368. (LParam in [SW_SHOWNORMAL, SW_SHOWMAXIMIZED, SW_MINIMIZE, SW_RESTORE]) then begin
  369. Maximizing := (LParam = SW_MAXIMIZE);
  370. if (LParam = SW_RESTORE) and not IsZoomed(HWND(WParam)) then begin
  371. WindowPlacement.length := SizeOf(WindowPlacement);
  372. GetWindowPlacement(HWND(WParam), @WindowPlacement);
  373. Maximizing := (WindowPlacement.flags and WPF_RESTORETOMAXIMIZED <> 0);
  374. end;
  375. for I := 0 to MDIButtonsItems.Count-1 do
  376. TTBMDIButtonsItem(MDIButtonsItems[I]).UpdateState(HWND(WParam),
  377. Maximizing);
  378. end;
  379. end;
  380. HCBT_DESTROYWND: begin
  381. if WindowIsMDIChild(HWND(WParam)) and Assigned(MDIButtonsItems) then begin
  382. for I := 0 to MDIButtonsItems.Count-1 do
  383. TTBMDIButtonsItem(MDIButtonsItems[I]).UpdateState(HWND(WParam),
  384. False);
  385. end;
  386. end;
  387. end;
  388. Result := CallNextHookEx(CBTHookHandle, Code, WParam, LParam);
  389. end;
  390. constructor TTBMDIButtonsItem.Create(AOwner: TComponent);
  391. function CreateItem(const AType: TTBMDIButtonType): TTBMDIButtonItem;
  392. begin
  393. Result := TTBMDIButtonItem.Create(Self);
  394. Result.FButtonType := AType;
  395. Result.OnClick := ItemClick;
  396. end;
  397. begin
  398. inherited;
  399. ItemStyle := ItemStyle + [tbisEmbeddedGroup];
  400. FMinimizeItem := CreateItem(tbmbMinimize);
  401. FRestoreItem := CreateItem(tbmbRestore);
  402. FCloseItem := CreateItem(tbmbClose);
  403. FSep1 := TTBMDISepItem.Create(Self);
  404. FSep1.Blank := True;
  405. FSep1.ItemStyle := FSep1.ItemStyle + [tbisRightAlign, tbisNoLineBreak];
  406. FSep2 := TTBMDISepItem.Create(Self);
  407. FSep2.Blank := True;
  408. FSep2.ItemStyle := FSep2.ItemStyle + [tbisRightAlign, tbisNoLineBreak];
  409. Add(FSep1);
  410. Add(FMinimizeItem);
  411. Add(FRestoreItem);
  412. Add(FSep2);
  413. Add(FCloseItem);
  414. UpdateState(0, False);
  415. AddToList(MDIButtonsItems, Self);
  416. if CBTHookHandle = 0 then
  417. CBTHookHandle := SetWindowsHookEx(WH_CBT, CBTHook, 0, GetCurrentThreadId);
  418. end;
  419. destructor TTBMDIButtonsItem.Destroy;
  420. begin
  421. RemoveFromList(MDIButtonsItems, Self);
  422. if (MDIButtonsItems = nil) and (CBTHookHandle <> 0) then begin
  423. UnhookWindowsHookEx(CBTHookHandle);
  424. CBTHookHandle := 0;
  425. end;
  426. inherited;
  427. end;
  428. procedure TTBMDIButtonsItem.UpdateState(W: HWND; Maximized: Boolean);
  429. var
  430. HasMaxChild, VisibilityChanged: Boolean;
  431. procedure UpdateVisibleEnabled(const Item: TTBCustomItem;
  432. const AEnabled: Boolean);
  433. begin
  434. if (Item.Visible <> HasMaxChild) or (Item.Enabled <> AEnabled) then begin
  435. Item.Visible := HasMaxChild;
  436. Item.Enabled := AEnabled;
  437. VisibilityChanged := True;
  438. end;
  439. end;
  440. var
  441. MainForm, ActiveMDIChild, ChildForm: TForm;
  442. I: Integer;
  443. begin
  444. HasMaxChild := False;
  445. MainForm := Application.MainForm;
  446. ActiveMDIChild := nil;
  447. if Assigned(MainForm) then begin
  448. for I := 0 to MainForm.MDIChildCount-1 do begin
  449. ChildForm := MainForm.MDIChildren[I];
  450. if ChildForm.HandleAllocated and
  451. (((ChildForm.Handle = W) and Maximized) or
  452. ((ChildForm.Handle <> W) and IsZoomed(ChildForm.Handle))) then begin
  453. HasMaxChild := True;
  454. Break;
  455. end;
  456. end;
  457. ActiveMDIChild := MainForm.ActiveMDIChild;
  458. end;
  459. VisibilityChanged := False;
  460. UpdateVisibleEnabled(TTBMDIHandler(Owner).FSystemMenuItem, True);
  461. UpdateVisibleEnabled(FSep1, True);
  462. UpdateVisibleEnabled(FMinimizeItem, (ActiveMDIChild = nil) or
  463. (GetWindowLong(ActiveMDIChild.Handle, GWL_STYLE) and WS_MINIMIZEBOX <> 0));
  464. UpdateVisibleEnabled(FRestoreItem, True);
  465. UpdateVisibleEnabled(FSep2, True);
  466. UpdateVisibleEnabled(FCloseItem, True);
  467. if VisibilityChanged and Assigned((Owner as TTBMDIHandler).FToolbar) then begin
  468. TTBMDIHandler(Owner).FToolbar.View.InvalidatePositions;
  469. TTBMDIHandler(Owner).FToolbar.View.TryValidatePositions;
  470. end;
  471. end;
  472. procedure TTBMDIButtonsItem.ItemClick(Sender: TObject);
  473. var
  474. MainForm, ChildForm: TForm;
  475. Cmd: WPARAM;
  476. begin
  477. MainForm := Application.MainForm;
  478. if Assigned(MainForm) then begin
  479. ChildForm := MainForm.ActiveMDIChild;
  480. if Assigned(ChildForm) then begin
  481. { Send WM_SYSCOMMAND messages so that we get sounds }
  482. if Sender = FRestoreItem then
  483. Cmd := SC_RESTORE
  484. else if Sender = FCloseItem then
  485. Cmd := SC_CLOSE
  486. else
  487. Cmd := SC_MINIMIZE;
  488. SendMessage(ChildForm.Handle, WM_SYSCOMMAND, Cmd, GetMessagePos);
  489. end;
  490. end;
  491. end;
  492. procedure TTBMDIButtonsItem.InvalidateSystemMenuItem;
  493. var
  494. View: TTBView;
  495. begin
  496. if Assigned((Owner as TTBMDIHandler).FToolbar) then begin
  497. View := TTBMDIHandler(Owner).FToolbar.View;
  498. View.Invalidate(View.Find(TTBMDIHandler(Owner).FSystemMenuItem));
  499. end;
  500. end;
  501. { TTBMDIWindowItem }
  502. constructor TTBMDIWindowItem.Create(AOwner: TComponent);
  503. var
  504. Form: TForm;
  505. begin
  506. inherited;
  507. ItemStyle := ItemStyle + [tbisEmbeddedGroup];
  508. Caption := STBMDIWindowItemDefCaption;
  509. FWindowMenu := TMenuItem.Create(Self);
  510. if not(csDesigning in ComponentState) then begin
  511. { Need to set WindowMenu before MDI children are created. Otherwise the
  512. list incorrectly shows the first 9 child windows, even if window 10+ is
  513. active. }
  514. Form := Application.MainForm;
  515. if (Form = nil) and (Screen.FormCount > 0) then
  516. Form := Screen.Forms[0];
  517. SetForm(Form);
  518. end;
  519. end;
  520. procedure TTBMDIWindowItem.GetChildren(Proc: TGetChildProc; Root: TComponent);
  521. begin
  522. end;
  523. procedure TTBMDIWindowItem.Notification(AComponent: TComponent; Operation: TOperation);
  524. begin
  525. inherited;
  526. if (Operation = opRemove) and (AComponent = FForm) then
  527. SetForm(nil);
  528. end;
  529. procedure TTBMDIWindowItem.SetForm(AForm: TForm);
  530. begin
  531. if FForm <> AForm then begin
  532. if Assigned(FForm) and (FForm.WindowMenu = FWindowMenu) then
  533. FForm.WindowMenu := nil;
  534. FForm := AForm;
  535. if Assigned(FForm) then
  536. FForm.FreeNotification(Self);
  537. end;
  538. if Assigned(FForm) then
  539. FForm.WindowMenu := FWindowMenu;
  540. end;
  541. procedure TTBMDIWindowItem.EnabledChanged;
  542. var
  543. I: Integer;
  544. begin
  545. inherited;
  546. for I := 0 to Count-1 do
  547. Items[I].Enabled := Enabled;
  548. end;
  549. procedure TTBMDIWindowItem.InitiateAction;
  550. var
  551. MainForm: TForm;
  552. I: Integer;
  553. M: HMENU;
  554. Item: TTBCustomItem;
  555. ItemCount: Integer;
  556. Buf: array[0..1023] of Char;
  557. begin
  558. inherited;
  559. if csDesigning in ComponentState then
  560. Exit;
  561. MainForm := Application.MainForm;
  562. if Assigned(MainForm) then
  563. SetForm(MainForm);
  564. if FForm = nil then
  565. Exit;
  566. if FForm.ClientHandle <> 0 then
  567. { This is needed, otherwise windows selected on the More Windows dialog
  568. don't move back into the list }
  569. SendMessage(FForm.ClientHandle, WM_MDIREFRESHMENU, 0, 0);
  570. M := FWindowMenu.Handle;
  571. ItemCount := GetMenuItemCount(M) - 1;
  572. if ItemCount < 0 then
  573. ItemCount := 0;
  574. while Count < ItemCount do begin
  575. Item := TTBCustomItem.Create(Self);
  576. Item.Enabled := Enabled;
  577. Item.OnClick := ItemClick;
  578. Add(Item);
  579. end;
  580. while Count > ItemCount do
  581. Items[Count-1].Free;
  582. for I := 0 to ItemCount-1 do begin
  583. Item := Items[I];
  584. Item.Tag := GetMenuItemID(M, I+1);
  585. if GetMenuString(M, I+1, Buf, SizeOf(Buf), MF_BYPOSITION) = 0 then
  586. Buf[0] := #0;
  587. Item.Caption := Buf;
  588. Item.Checked := GetMenuState(M, I+1, MF_BYPOSITION) and MF_CHECKED <> 0;
  589. end;
  590. if Assigned(FOnUpdate) then
  591. FOnUpdate(Self);
  592. end;
  593. procedure TTBMDIWindowItem.ItemClick(Sender: TObject);
  594. var
  595. Form: TForm;
  596. begin
  597. Form := Application.MainForm;
  598. if Assigned(Form) then
  599. PostMessage(Form.Handle, WM_COMMAND, TTBCustomItem(Sender).Tag, 0);
  600. end;
  601. end.