2 {*****************************************************************************}
4 { Tnt Delphi Unicode Controls }
5 { http://www.tntware.com/delphicontrols/unicode/ }
8 { Copyright (c) 2002-2007, Troy Wolbrink (troy.wolbrink@tntware.com) }
10 {*****************************************************************************}
14 {$INCLUDE ..\Source\TntCompilers.inc}
16 {*******************************************************}
17 { Special Thanks to Francisco Leong for getting these }
18 { menu designer enhancements to work w/o MnuBuild. }
19 {*******************************************************}
23 {$IFDEF COMPILER_6} // Delphi 6 and BCB 6 have MnuBuild available
24 {$DEFINE MNUBUILD_AVAILABLE}
27 {$IFDEF COMPILER_7} // Delphi 7 has MnuBuild available
28 {$DEFINE MNUBUILD_AVAILABLE}
32 Windows
, Classes
, Menus
, Messages
,
33 {$IFDEF MNUBUILD_AVAILABLE} MnuBuild
, {$ENDIF}
34 DesignEditors
, DesignIntf
;
37 TTntMenuEditor
= class(TComponentEditor
)
39 procedure ExecuteVerb(Index
: Integer); override;
40 function GetVerb(Index
: Integer): string{TNT-ALLOW string}; override;
41 function GetVerbCount
: Integer; override;
49 {$IFDEF MNUBUILD_AVAILABLE} MnuConst
, {$ELSE} DesignWindows
, {$ENDIF} SysUtils
, Graphics
, ActnList
,
50 Controls
, Forms
, TntDesignEditors_Design
, TntActnList
, TntMenus
;
54 RegisterComponentEditor(TTntMainMenu
, TTntMenuEditor
);
55 RegisterComponentEditor(TTntPopupMenu
, TTntMenuEditor
);
58 function GetMenuBuilder
: TForm
{TNT-ALLOW TForm};
59 {$IFDEF MNUBUILD_AVAILABLE}
67 if Application
<> nil then
69 Comp
:= Application
.FindComponent('MenuBuilder');
70 if Comp
is TForm
{TNT-ALLOW TForm} then
71 Result
:= TForm
{TNT-ALLOW TForm}(Comp
);
76 {$IFDEF DELPHI_9} // verified against Delphi 9
78 THackMenuBuilder
= class(TDesignWindow
)
80 Fields
: array[1..26] of TObject
;
81 FWorkMenu
: TMenuItem
{TNT-ALLOW TMenuItem};
85 {$IFDEF COMPILER_10_UP}
86 {$IFDEF DELPHI_10} // NOT verified against Delphi 10
88 THackMenuBuilder
= class(TDesignWindow
)
90 Fields
: array[1..26] of TObject
;
91 FWorkMenu
: TMenuItem
{TNT-ALLOW TMenuItem};
96 function GetMenuBuilder_WorkMenu(MenuBuilder
: TForm
{TNT-ALLOW TForm}): TMenuItem
{TNT-ALLOW TMenuItem};
98 if MenuBuilder
= nil then
101 {$IFDEF MNUBUILD_AVAILABLE}
102 Result
:= MenuEditor
.WorkMenu
;
104 Result
:= THackMenuBuilder(MenuBuilder
).FWorkMenu
;
105 Assert((Result
= nil) or (Result
is TMenuItem
{TNT-ALLOW TMenuItem}),
106 'TNT Internal Error: THackMenuBuilder has incorrect internal layout.');
111 {$IFDEF DELPHI_9} // verified against Delphi 9
113 THackMenuItemWin
= class(TCustomControl
)
115 FxxxxCaptionExtent
: Integer;
116 FMenuItem
: TMenuItem
{TNT-ALLOW TMenuItem};
120 {$IFDEF DELPHI_10} // beta: NOT verified against Delphi 10
122 THackMenuItemWin
= class(TCustomControl
)
124 FxxxxCaptionExtent
: Integer;
125 FMenuItem
: TMenuItem
{TNT-ALLOW TMenuItem};
129 function GetMenuItem(Control
: TWinControl
; DoVerify
: Boolean = True): TMenuItem
{TNT-ALLOW TMenuItem};
131 {$IFDEF MNUBUILD_AVAILABLE}
132 if Control
is TMenuItemWin
then
133 Result
:= TMenuItemWin(Control
).MenuItem
135 if Control
.ClassName
= 'TMenuItemWin' then begin
136 Result
:= THackMenuItemWin(Control
).FMenuItem
;
137 Assert((Result
= nil) or (Result
is TMenuItem
{TNT-ALLOW TMenuItem}), 'TNT Internal Error: Unexpected TMenuItem field layout.');
140 else if DoVerify
then
141 raise Exception
.Create('TNT Internal Error: Control is not a TMenuItemWin.')
146 procedure SetMenuItem(Control
: TWinControl
; Item
: TMenuItem
{TNT-ALLOW TMenuItem});
148 {$IFDEF MNUBUILD_AVAILABLE}
149 if Control
is TMenuItemWin
then
150 TMenuItemWin(Control
).MenuItem
:= Item
152 if Control
.ClassName
= 'TMenuItemWin' then begin
153 THackMenuItemWin(Control
).FMenuItem
:= Item
;
154 Item
.FreeNotification(Control
);
158 raise Exception
.Create('TNT Internal Error: Control is not a TMenuItemWin.');
161 procedure ReplaceMenuItem(Control
: TWinControl
; ANewItem
: TMenuItem
{TNT-ALLOW TMenuItem});
163 OldItem
: TMenuItem
{TNT-ALLOW TMenuItem};
164 OldName
: string{TNT-ALLOW string};
166 OldItem
:= GetMenuItem(Control
, True);
167 Assert(OldItem
<> nil);
168 OldName
:= OldItem
.Name
;
170 ANewItem
.Name
:= OldName
; { assume old name }
171 SetMenuItem(Control
, ANewItem
);
174 { TTntMenuBuilderChecker }
177 TMenuBuilderChecker
= class(TComponent
)
179 FMenuBuilder
: TForm
{TNT-ALLOW TForm};
180 FCheckMenuAction
: TTntAction
;
181 FLastCaption
: string{TNT-ALLOW string};
182 FLastActiveControl
: TControl
;
183 FLastMenuItem
: TMenuItem
{TNT-ALLOW TMenuItem};
184 procedure CheckMenuItems(Sender
: TObject
);
186 constructor Create(AOwner
: TComponent
); override;
187 destructor Destroy
; override;
190 var MenuBuilderChecker
: TMenuBuilderChecker
= nil;
192 constructor TMenuBuilderChecker
.Create(AOwner
: TComponent
);
195 MenuBuilderChecker
:= Self
;
196 FCheckMenuAction
:= TTntAction
.Create(Self
);
197 FCheckMenuAction
.OnUpdate
:= CheckMenuItems
;
198 FCheckMenuAction
.OnExecute
:= CheckMenuItems
;
199 FMenuBuilder
:= AOwner
as TForm
{TNT-ALLOW TForm};
200 FMenuBuilder
.Action
:= FCheckMenuAction
;
203 destructor TMenuBuilderChecker
.Destroy
;
206 MenuBuilderChecker
:= nil;
210 type TAccessTntMenuItem
= class(TTntMenuItem
);
212 function CreateTntMenuItem(OldItem
: TMenuItem
{TNT-ALLOW TMenuItem}): TTntMenuItem
;
215 OldParent
: TMenuItem
{TNT-ALLOW TMenuItem};
220 // item should be converted.
221 OldItemsList
:= TList
.Create
;
224 Result
:= TTntMenuItem
.Create(OldItem
.Owner
);
225 TAccessTntMenuItem(Result
).FComponentStyle
:= OldItem
.ComponentStyle
; {csTransient hides item from object inspector}
226 Result
.Action
:= OldItem
.Action
;
227 Result
.AutoCheck
:= OldItem
.AutoCheck
;
228 Result
.AutoHotkeys
:= OldItem
.AutoHotkeys
;
229 Result
.AutoLineReduction
:= OldItem
.AutoLineReduction
;
230 Result
.Bitmap
:= OldItem
.Bitmap
;
231 Result
.Break
:= OldItem
.Break
;
232 Result
.Caption
:= OldItem
.Caption
;
233 Result
.Checked
:= OldItem
.Checked
;
234 Result
.Default
:= OldItem
.Default
;
235 Result
.Enabled
:= OldItem
.Enabled
;
236 Result
.GroupIndex
:= OldItem
.GroupIndex
;
237 Result
.HelpContext
:= OldItem
.HelpContext
;
238 Result
.Hint
:= OldItem
.Hint
;
239 Result
.ImageIndex
:= OldItem
.ImageIndex
;
240 Result
.MenuIndex
:= OldItem
.MenuIndex
;
241 Result
.RadioItem
:= OldItem
.RadioItem
;
242 Result
.ShortCut
:= OldItem
.ShortCut
;
243 Result
.SubMenuImages
:= OldItem
.SubMenuImages
;
244 Result
.Visible
:= OldItem
.Visible
;
245 Result
.Tag
:= OldItem
.Tag
;
248 Result
.OnAdvancedDrawItem
:= OldItem
.OnAdvancedDrawItem
;
249 Result
.OnClick
:= OldItem
.OnClick
;
250 Result
.OnDrawItem
:= OldItem
.OnDrawItem
;
251 Result
.OnMeasureItem
:= OldItem
.OnMeasureItem
;
253 // remember name, parent, index, children
254 OldName
:= OldItem
.Name
;
255 OldParent
:= OldItem
.Parent
;
256 OldIndex
:= OldItem
.MenuIndex
;
257 for j
:= OldItem
.Count
- 1 downto 0 do begin
258 OldItemsList
.Insert(0, OldItem
.Items
[j
]);
259 OldItem
.Remove(OldItem
.Items
[j
]);
262 // clone final parts of old item
263 for j
:= 0 to OldItemsList
.Count
- 1 do
264 Result
.Add(TMenuItem
{TNT-ALLOW TMenuItem}(OldItemsList
[j
])); { add children }
265 if OldParent
<> nil then
266 OldParent
.Insert(OldIndex
, Result
); { insert into parent }
272 procedure CheckMenuItemWin(MenuItemWin
: TWinControl
; PartOfATntMenu
: Boolean);
274 OldItem
: TMenuItem
{TNT-ALLOW TMenuItem};
276 OldItem
:= GetMenuItem(MenuItemWin
);
277 if OldItem
= nil then
279 if (OldItem
.ClassType
= TMenuItem
{TNT-ALLOW TMenuItem})
280 and (PartOfATntMenu
or (OldItem
.Parent
is TTntMenuItem
)) then
282 if MenuItemWin
.Focused
then
283 MenuItemWin
.Parent
.SetFocus
; {Lose focus and regain later to ensure object inspector gets updated.}
284 ReplaceMenuItem(MenuItemWin
, CreateTntMenuItem(OldItem
));
285 end else if (OldItem
.ClassType
= TTntMenuItem
)
286 and (OldItem
.Parent
= nil) and (OldItem
.Caption
= '') and (OldItem
.Name
= '')
287 and not (PartOfATntMenu
or (OldItem
.Parent
is TTntMenuItem
)) then begin
288 if MenuItemWin
.Focused
then
289 MenuItemWin
.Parent
.SetFocus
; {Lose focus and regain later to ensure object inspector gets updated.}
290 ReplaceMenuItem(MenuItemWin
, TMenuItem
{TNT-ALLOW TMenuItem}.Create(OldItem
.Owner
));
294 procedure TMenuBuilderChecker
.CheckMenuItems(Sender
: TObject
);
297 MenuWin
: TWinControl
;
298 MenuItemWin
: TWinControl
;
300 PartOfATntMenu
: Boolean;
301 WorkMenu
: TMenuItem
{TNT-ALLOW TMenuItem};
303 if (FMenuBuilder
<> nil)
304 and (FMenuBuilder
.Action
= FCheckMenuAction
) then begin
305 if (FLastCaption
<> FMenuBuilder
.Caption
)
306 or (FLastActiveControl
<> FMenuBuilder
.ActiveControl
)
307 or (FLastMenuItem
<> GetMenuItem(FMenuBuilder
.ActiveControl
, False))
311 with FMenuBuilder
do begin
312 WorkMenu
:= GetMenuBuilder_WorkMenu(FMenuBuilder
);
313 PartOfATntMenu
:= (WorkMenu
<> nil)
314 and ((WorkMenu
.Owner
is TTntMainMenu
) or (WorkMenu
.Owner
is TTntPopupMenu
));
315 SaveFocus
:= Windows
.GetFocus
;
316 for a
:= ComponentCount
- 1 downto 0 do begin
317 {$IFDEF MNUBUILD_AVAILABLE}
318 if Components
[a
] is TMenuWin
then begin
320 if Components
[a
].ClassName
= 'TMenuWin' then begin
322 MenuWin
:= Components
[a
] as TWinControl
;
323 with MenuWin
do begin
324 for i
:= ComponentCount
- 1 downto 0 do begin
325 {$IFDEF MNUBUILD_AVAILABLE}
326 if Components
[i
] is TMenuItemWin
then begin
328 if Components
[i
].ClassName
= 'TMenuItemWin' then begin
330 MenuItemWin
:= Components
[i
] as TWinControl
;
331 CheckMenuItemWin(MenuItemWin
, PartOfATntMenu
);
337 if SaveFocus
<> Windows
.GetFocus
then
338 Windows
.SetFocus(SaveFocus
);
341 on E
: Exception
do begin
342 FMenuBuilder
.Action
:= nil;
346 FLastCaption
:= FMenuBuilder
.Caption
;
347 FLastActiveControl
:= FMenuBuilder
.ActiveControl
;
348 FLastMenuItem
:= GetMenuItem(FMenuBuilder
.ActiveControl
, False);
356 function TTntMenuEditor
.GetVerbCount
: Integer;
361 {$IFNDEF MNUBUILD_AVAILABLE}
363 SMenuDesigner
= 'Menu Designer...';
366 function TTntMenuEditor
.GetVerb(Index
: Integer): string{TNT-ALLOW string};
368 Result
:= SMenuDesigner
;
371 procedure TTntMenuEditor
.ExecuteVerb(Index
: Integer);
373 MenuBuilder
: TForm
{TNT-ALLOW TForm};
375 EditPropertyWithDialog(Component
, 'Items', Designer
);
376 MenuBuilder
:= GetMenuBuilder
;
377 if Assigned(MenuBuilder
) then begin
378 if (MenuBuilderChecker
= nil) or (MenuBuilderChecker
.FMenuBuilder
<> MenuBuilder
) then begin
379 MenuBuilderChecker
.Free
;
380 MenuBuilderChecker
:= TMenuBuilderChecker
.Create(MenuBuilder
);
382 EditPropertyWithDialog(Component
, 'Items', Designer
); // update menu builder caption
389 MenuBuilderChecker
.Free
; // design package might be recompiled