急,高分求救。子窗口的最大化、最小化和关闭按纽消失的情况(300分)

  • 主题发起人 主题发起人 wenna
  • 开始时间 开始时间
W

wenna

Unregistered / Unconfirmed
GUEST, unregistred user!
急,高分求救。用C++ Builder编写一MDI程序,内有多种不同类型的子窗口,子窗口之间切换时有时会出现子窗口的最大化、最小化和关闭按纽消失的情况,此时如通过代码(MDIChildren->WindowState=wsMinimized)将其最小化,其后如鼠标在其最小化后的标题栏上点击则程序失去响应。
 
光急没有用啊,看来这里一时没有人回答你,到下面的论坛碰碰运气把
http://www.wapsec.com.cn/delphi/delphibbs/
 
这个好象是MDI的BUG,M$已放弃它了。不过我没碰到过!
 
是个BUG,没办法
 
解决不了,能否避免。
 
不用就可以避免了,呵呵,别打我。
 
呵呵,太逗了。
 
完全转贴:
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;

也是一位富翁的转帖
我就是这么解决的
 
这是一个BUG,我也遇到这个问题。
它出现在最大化的窗口被关闭或最小化,而下层窗口被自动最大化时。
我用了一个凑合的解决办法,
在每个子窗口的OnActive事件处理函数中加入
WindowState=wsNormal;
这样当最大化的窗口被关闭后,下层的窗口不会被最大化,
也就不会出现按钮消失的情况。

另外,如果子窗口的菜单不融入主菜单也不会出现问题。
 
采用pcexplorer的Answer 1,须
取消菜单Project/Options中Packages页中Build with runtime packages复选框才有效果
 
多人接受答案了。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
555
import
I
I
回复
0
查看
599
import
I
后退
顶部