MDI子窗口最大化时,更改主窗口菜单后,子窗口系统图标消失……(100分)

  • 主题发起人 主题发起人 kthy
  • 开始时间 开始时间
K

kthy

Unregistered / Unconfirmed
GUEST, unregistred user!
MDI子窗口最大化时,更改主窗口菜单后,子窗口系统图标消失。
只有当子窗口恢复原来大小,然后再最大化,系统图标才出现。
有没有其他方法避免这种问题?
 
这是delphi的奇大Bug,期待D6;
 
完全转贴:
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 &amp; 4 or the system menu and max/min/close icons to vanish
in Delphi 5. Tested in Delphi Client/Server 3, 4 &amp; 5.


{$IFDEF VER100}
{$DEFINE DELPHI3&amp;4}
{$ENDIF}

{$IFDEF VER120}
{$DEFINE DELPHI3&amp;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&amp;4}
SetWindowLong(Handle, GWL_STYLE, Style or WS_SYSMENU);
{$ELSE}
SendMessage(Handle, WM_SIZE, SIZE_RESTORED, 0);
{$ENDIF}
end;
inherited;
end;


Tip by Sergio Trindade
 
好象有人问过!
 
bbkxjy的第一种方法完美无缺,正好我在网上找到这个答案,分照给。
这种方法一劳永逸,不仅修复了系统图标的问题,同时修改了菜单混乱
的现象。为什么borland没有及时修复这个延续了好几个版本的大大大大
的bug?
 
后退
顶部