Mega Code Archive

 
Categories / Delphi / Forms
 

Another Bug in MDI Applications and two solutions

Title: Another Bug in MDI Applications and two solutions Question: With multiple child windows, if you maximize and close one, the other child windows will have their close ('x') button greyed out, however the button is still active, and will close the window if clicked. Answer: The bug is evident even in imagedit. Start imagedit, and create 3 new bitmaps. Maximize the last bitmap, then close it. The one behind will be maximised (I've thought it to be strange windows behavior, but not delphi's fault), and the X will be greyed out. If you click the X, it will close the window. The same holds for the other windows. Another problem is that in some MDI forms that are programmatically created, they appear without the border icons, a very strange thing! Nevertheless I found two solutions to this situation: The first one is to patch VCLs code, but keep in mind that Borland doesnt give support for modified VCLs code, I preffer this one because I tried to post this solution in Borlands Developer Support but I was very angry because I only found the following: "we will continue to process bug reports from customers currently under contract for Developer Support in the same manner other support requests are made. However, we will not be accepting new bug reports through our public system." How polite hu? Ok you have to modify TCustomForm.MergeMenu code wich is in the Forms.pas file, in Delphi 5 it looks like this procedure TCustomForm.MergeMenu(MergeState: Boolean); var AMergeMenu: TMainMenu; begin if not (fsModal in FFormState) and (Application.MainForm nil) and (Application.MainForm.Menu nil) and (Application.MainForm Self) and ((FormStyle = fsMDIChild) or (Application.MainForm.FormStyle fsMDIForm)) then begin AMergeMenu := nil; if not (csDesigning in ComponentState) and (Menu nil) and (Menu.AutoMerge or (FormStyle = fsMDIChild)) then AMergeMenu := Menu; with Application.MainForm.Menu do if MergeState then Merge(AMergeMenu) else Unmerge(AMergeMenu); end; end; Change the code for this one: procedure TCustomForm.MergeMenu(MergeState: Boolean); var AMergeMenu: TMainMenu; Size: Longint; FixMaximize: boolean; begin if not (fsModal in FFormState) and (Application.MainForm nil) and (Application.MainForm.Menu nil) and (Application.MainForm Self) and ((FormStyle = fsMDIChild) or (Application.MainForm.FormStyle fsMDIForm)) then begin AMergeMenu := nil; if not (csDesigning in ComponentState) and (Menu nil) and (Menu.AutoMerge or (FormStyle = fsMDIChild)) then AMergeMenu := Menu; FixMaximize:= MergeState and (FormStyle = fsMDIChild) and (WindowState = wsMaximized); if FixMaximize then begin { Force MDI to put back the system menu of a maximized child } Size := ClientWidth + (Longint(ClientHeight) shl 16); SendMessage(Handle, WM_SIZE, SIZE_RESTORED, Size); end; try with Application.MainForm.Menu do if MergeState then Merge(AMergeMenu) else Unmerge(AMergeMenu); finally if FixMaximize then SendMessage(Handle, WM_SIZE, SIZE_MAXIMIZED, Size); end; end; end; The second aproach which works in Delphi 3, 4 and 5, in case that you dont have VCLs code is the following: To every MDIChild form you have in your application add the following code. uses .... {$IFDEF VER100} {$DEFINE DELPHI3&4} {$ENDIF} {$IFDEF VER120} {$DEFINE DELPHI3&4} {$ENDIF} type ..... private .... procedure GetDynamicData(const ADynamicToken: String; AProppertGrid: TPropertyGrid); .... procedure TSomeMDIChildForm.WMMDIActivate(var Msg: TWMMDIActivate); 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; Finally some words. I think that a good develoment team has to take bug reports seriously, Borland doesnt accepts bug reports from its public system anymore, I am worried because this means to me a very bad practice, so we have to do something, dont you agree?