Author: Jonas Bilinkevicius
I am trying to write a MDI application. I use a main form with a MainMenu. Every
child form merges its main menu in the main form's main menu. If one of the child
forms gets maximized, the close button (x button in the upper right corner) is
grayed out but still works. If I merge the child form's main menu manually, the
close button behaves in the same way.
Answer:
Solve 1:
I have tried the following patch to Menus.pas and it works wonders for me. The
button no longer disappears or disable and the window menu functions after changes
are made to it. I would like to know how well this works for them. Neither of these
two fixes are 'hacks' into that they don't cause extra flashing or refreshing. They
just fix the 'problematic' code in Menus.pas. The below snippits of code are based
on D5.
1 procedure TMenuItem.RebuildHandle;
2 const
3 cFAF = $04;
4 var
5 I: Integer;
6 LRepopulate: Boolean;
7 begin
8 if csDestroying in ComponentState then
9 Exit;
10 if csReading in ComponentState then
11 FStreamedRebuild := True
12 else
13 begin
14 if FMergedWith <> nil then
15 FMergedWith.RebuildHandle
16 else
17 begin
18 I := GetMenuItemCount(Handle);
19 LRepopulate := I = 0;
20 while I > 0 do
21 begin
22 if (WordRec(LongRec(GetMenuState(Handle, I - 1, MF_BYPOSITION)).Lo).Lo and
23 cFAF) = 0 then
24 begin
25 RemoveMenu(Handle, I - 1, MF_BYPOSITION);
26 LRepopulate := True;
27 end;
28 Dec(I);
29 end;
30 if LRepopulate then
31 begin
32 if (FParent = nil) and (FMenu is TMainMenu) and (GetMenuItemCount(Handle) =
33 0)
34 then
35 begin
36 DestroyMenu(FHandle);
37 FHandle := 0;
38 end
39 else
40 PopulateMenu;
41 MenuChanged(False);
42 end;
43 end;
44 end;
45 end;
46
47 function TMenu.DispatchPopup(AHandle: HMENU): Boolean;
48
49 function IsMDIWindowMenu(AItem: TMenuItem): Boolean;
50 begin
51 Result := Assigned(Application.MainForm) and (Application.MainForm.FormStyle =
52 fsMDIForm)
53 and (Application.MainForm.WindowMenu = AItem);
54 end;
55
56 var
57 Item: TMenuItem;
58 LRebuild: Boolean;
59 begin
60 Result := False;
61 Item := FindItem(AHandle, fkHandle);
62 if Item <> nil then
63 begin
64 if not (csDesigning in Item.ComponentState) then
65 Item.InitiateActions;
66 Item.Click;
67 LRebuild := Item.InternalRethinkHotkeys(False);
68 LRebuild := Item.InternalRethinkLines(False) or LRebuild;
69 if LRebuild then
70 Item.RebuildHandle;
71 if IsMDIWindowMenu(Item) then
72 if SendMessage(Application.MainForm.ClientHandle, WM_MDIREFRESHMENU, 0, 0) <>
73 0
74 then
75 DrawMenuBar(Application.MainForm.Handle);
76 Result := True;
77 end
78 else if not (csDesigning in ComponentState) and (Self is TPopupMenu) then
79 Items.InitiateActions;
80 end;
You cannot recompile the standard packages, your license does not allow it and
there are some units missing anyway. Copy the menus unit to your project directory,
modify the copy, and compile it as part of your project. You can copy the produced
DCU back into the LIB directory for other projects to use. This will work as long
as you don't build with packages and don't change anything in the units interface.
Solve 2:
This piece of code fixes a bug present in all versions of Delphi, that occurs when
switching between maximized MDI child windows, causing the close icon to be grayed
in Delphi 3 & 4 or the system menu and max/min/close icons to vanish in Delphi 5.
Tested in Delphi Client/Server 3, 4 & 5.
81
82 {$IFDEF VER100}
83 {$DEFINE DELPHI3&4}
84 {$ENDIF}
85
86 {$IFDEF VER120}
87 {$DEFINE DELPHI3&4}
88 {$ENDIF}
89
90 type
91 TMDIChild = class(TForm)
92 { ... }
93 private
94 procedure WMMDIActivate(var Msg: TWMMDIActivate); message WM_MDIACTIVATE;
95 { ... }
96 end;
97
98 procedure TMDIChild.WMMDIActivate;
99 var
100 Style: Longint;
101 begin
102 if (Msg.ActiveWnd = Handle) and (biSystemMenu in BorderIcons) then
103 begin
104 Style := GetWindowLong(Handle, GWL_STYLE);
105 if (Style and WS_MAXIMIZE <> 0) and (Style and WS_SYSMENU = 0) then
106
107 {$IFDEF DELPHI3&4}
108 SetWindowLong(Handle, GWL_STYLE, Style or WS_SYSMENU);
109 {$ELSE}
110 SendMessage(Handle, WM_SIZE, SIZE_RESTORED, 0);
111 {$ENDIF}
112 end;
113 inherited;
114 end;
|