完全转贴:
How to fix the MDI close button and window menu glitches
---------------------------------------------------------
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 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.
procedure TMenuItem.RebuildHandle;
const
; cFAF = $04;
var
; I: Integer;
; LRepopulate: Boolean;
begin
; if csDestroying in ComponentState then
; ; Exit;
; if csReading in ComponentState then
; ; FStreamedRebuild := True
; else
; begin
; ; if FMergedWith <> nil then
; ; ; FMergedWith.RebuildHandle
; ; else
; ; begin
; ; ; I := GetMenuItemCount(Handle);
; ; ; LRepopulate := I = 0;
; ; ; while I > 0 do
; ; ; begin
; ; ; ; if (WordRec(LongRec(GetMenuState(Handle, I - 1,
MF_BYPOSITION)).Lo).Lo and cFAF) = 0 then
; ; ; ; begin
; ; ; ; ; RemoveMenu(Handle, I - 1, MF_BYPOSITION);
; ; ; ; ; LRepopulate := True;
; ; ; ; end;
; ; ; ; Dec(I);
; ; ; end;
; ; ; if LRepopulate then
; ; ; begin
; ; ; ; if (FParent = nil) and (FMenu is TMainMenu) and
(GetMenuItemCount(Handle) = 0) then
; ; ; ; begin
; ; ; ; ; DestroyMenu(FHandle);
; ; ; ; ; FHandle := 0;
; ; ; ; end
; ; ; ; else
; ; ; ; ; PopulateMenu;
; ; ; ; MenuChanged(False);
; ; ; end;
; ; end;
; end;
end;
function TMenu.DispatchPopup(AHandle: HMENU): Boolean;
; function IsMDIWindowMenu(AItem: TMenuItem): Boolean;
; begin
; ; Result := Assigned(Application.MainForm) and
(Application.MainForm.FormStyle = fsMDIForm)
; ; ; ; ; ; ; ; ; ; ;and (Application.MainForm.WindowMenu = AItem);
; end;
var
; Item: TMenuItem;
; LRebuild: Boolean;
begin
; Result := False;
; Item := FindItem(AHandle, fkHandle);
; if Item <> nil then
; begin
; ; if not (csDesigning in Item.ComponentState) then Item.InitiateActions;
; ; Item.Click;
; ; LRebuild := Item.InternalRethinkHotkeys(False);
; ; LRebuild := Item.InternalRethinkLines(False) or LRebuild;
; ; if LRebuild then
; ; ; Item.RebuildHandle;
; ; if IsMDIWindowMenu(Item) then
; ; ; if SendMessage(Application.MainForm.ClientHandle, WM_MDIREFRESHMENU,
0, 0) <> 0 then
; ; ; ; DrawMenuBar(Application.MainForm.Handle);
; ; Result := True;
; end
; else if not (csDesigning in ComponentState) and (Self is TPopupMenu)
then
; ; Items.InitiateActions;
end;
Tip by Max (max@nomail.com)
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.
Tip by Peter Below
Answer 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.
{$IFDEF VER100}
; {$DEFINE DELPHI3&4}
{$ENDIF}
{$IFDEF VER120}
; {$DEFINE DELPHI3&4}
{$ENDIF}
type
; TMDIChild = class(TForm)
; { ... }
; private
; ; procedure WMMDIActivate(var Msg: TWMMDIActivate); message
WM_MDIACTIVATE;
; ; { ... }
; end;
procedure TMDIChild.WMMDIActivate;
var
; Style: Longint;
begin
; if (Msg.ActiveWnd = Handle) and (biSystemMenu in BorderIcons) then
; begin
; ; Style := GetWindowLong(Handle, GWL_STYLE);
; ; if (Style and WS_MAXIMIZE <> 0) and (Style and WS_SYSMENU = 0) then
{$IFDEF DELPHI3&4}
; ; ; SetWindowLong(Handle, GWL_STYLE, Style or WS_SYSMENU);
{$ELSE}
; ; ; SendMessage(Handle, WM_SIZE, SIZE_RESTORED, 0);
{$ENDIF}
; end;
; inherited;
end;
也是一位富翁的转帖
我就是这么解决的