MDI Forms
Ian Foster wrote: > > Can anyone help me with a way to hide MDIChild forms in an MDI application. Ideally I would not like to have a minimised form on the parent form as the default, but perhaps have an icon displayed on the parent form.
This is a feature of Win 95. It's how minimized MDI childs are supposed to look.
But, try to override WM_PAINT (or maybe you need WM_NCPAINT), check IsIconized, and draw your icon as you please.
> Currently if I just try to hide the child, I get an error that tells me that it's an invalid method on a child form.
Try ShowWindow(MdiChild1.Handle, SW_HIDE), and see what happens.
From: billb@imed.omen.org (Bill Brown)
If you want to limit an MDI application to only one child window open at any given time, look at the MDIChildCount property of the MDI parent form. If it is greater than 0, don't create the new child.
If you want to allow multiple MDI children forms but no duplicates of any particular type of form (ie: only one invoice form, only one sales rep form, etc.), you will could loop through the MDI children to see if the one about to be created already exists. Again, the key to this is in the MDI parent form. Example code:
ChildIndex := 0 while (ChildIndex < frmMDIParent.ChildCount) and (frmMDIParent.MDIChildren[ChildIndex].Name <> frmNewChild.Name) do Inc(ChildIndex); if ChildIndex = frmMDIParent.ChildCount then {create new child here} begin Create it... if no exception occurred, then show it... end else {child form already exists so just bring it to the top} frmMDIParent.MDIChildren[ChildIndex].BringToFront;
From: "Carl Clark" <cclark@IAfrica.com>
How about,
if Form1 <> nil then begin Form1 := TForm1.Create(Application); Form1.Show; end;
Then in Form1's OnClose:
Action := caFree; Form1 := nil;
CF>How do I make an MDI Form appear 'more' 3D (like M$ progs)?This is from the Tips & Tricks section in The Delphi Magazine.
constructor TMainForm.Create(AOwner: TComponent); begin Inherited Create(AOwner); SetWindowLong(ClientHandle, GWL_EXSTYLE, GetWindowLong(ClientHandle, GWL_EXSTYLE) or WS_EX_CLIENTEDGE); SetWindowPos(ClientHandle, 0, 0, 0, 0, 0, swp_DrawFrame or swp_NoMove or swp_NoSize or swp_NoZOrder); end;
Michael Ax <ax@HREF.COM>
>Hello to All! > >Does somebody know how to put an image in a MDI form and make >Tile with her?yes. that's the easy part..
procedure TForm.OnPaint(Sender: TObject); procedure Tile(c:TCanvas;b:TBitMap); var x,y,h,w,i,j:integer; begin with b do begin h:=b.height; w:=b.width; end; y:=0; with c.Cliprect do begin i:=bottom-top-1; //height j:=right-left-1; //width end; while y<i do begin x:=0; while x<j do begin c.draw(x,y,b); inc(x,w); end; inc(y,h); end; end; begin if Sender is TForm then Tile(TForm(Sender).Canvas,fTileWith); end;
From: tnomad@digital.net
We were able to kill the title bar of an MDI child by doing the following:
type TForm2 = class(TForm) { other stuff above } procedure CreateParams(var Params: TCreateParams); override; { other stuff below } end; procedure TForm2.CreateParams(var Params: TCreateParams); begin inherited CreateParams(Params); Params.Style := Params.Style and not WS_OVERLAPPEDWINDOW or WS_BORDER end;
From: amcfarl@ndlc.occ.uky.edu (Andy McFarland)
For an MDI child form, setting the BorderStyle to bsNone does NOT remove the title bar. (This is mentioned in the help). This does it:
Procedure tMdiChildForm.CreateParams( var Params : tCreateParams ) ; Begin Inherited CreateParams( Params ) ; Params.Style := Params.Style and (not WS_CAPTION) ; End ;
From: johan@lindgren.pp.se
You can set a number to indicate the position of the menu in the new menu bar that is compiled from the menues in the MDI form and the menues in the child form.
So for example if your MDI menu has:
File View About (with the group index values of 1 5 10) (It does not matter exactly what numbers you chose, they are only used for
sorting.)
And your child menu has:
File Edit (and they have the values 1 and 3)
When you open a child window the child File menu item will replace the MDI form menu item. The Edit menu item will be inserted before View and About from the MDI form.
This is quite useful since you can have lesser choices on the File menu of the MDI form compared to what should be there when
you have a child window open.
You do not need Save or Close on the MDI form File menu but you need Open and New for example.
But you have to enter all menu lines on the File menu in the child menu control since that will replace the File menu from the MDI
parent.
You can still use the code from the parent in the child.
So if you have a procedure "parent.open1click"
You can call that from the child file menu open event.
From: jennings@meltech.com (Roy H. Jennings, Jr.)
Don't attempt to destroy the form from within itself. Setting action to caFree in the form close event will cause the parent window to destroy the form.You probably need to implement the closequery event to prevent the form from closing when table1 is in edit mode or at least all the user the option of abandoning changes.
The MDIparent window should have a menu option that closes the currently active mdi child window. If not you can add one and execute the following from the click method:
ActiveMDIChild.Close;
procedure TFrmServers.FormClose(Sender:TObject; var Action:TCloseAction); begin Action := caFree; end; procedure TFrmServers.FormDestroy begin Table1.Close; end; procedure TFrmServers.FormCloseQuery begin if table1.state in [dsEdit,dsInsert] then begin // warn user that changes will be lost and // ask if ok to close if not UserSaysOk then CanClose := False; end; end;
Here's some code that may prove useful. It is for either a normal form or an MDI form and tiles a bitmap or produces gradients. The only tricky part is establishing the window message handler for the ClientHandle of the window that actually manages the child forms. That's where the bitmaps and graphics actually appear in an MDI form. Just load a bitmap into imgTile at design time and you're ready to go.
unit UMain; interface uses Windows, Messages, Classes, SysUtils, Graphics, Controls, Forms, Dialogs, ExtCtrls, Menus; type TfrmMain = class(TForm) mnuMain: TMainMenu; mnuFile: TMenuItem; mnuExit: TMenuItem; imgTile: TImage; mnuOptions: TMenuItem; mnuBitmap: TMenuItem; mnuGradient: TMenuItem; procedure mnuExitClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure mnuBitmapClick(Sender: TObject); procedure mnuGradientClick(Sender: TObject); procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); procedure FormResize(Sender: TObject); procedure FormPaint(Sender: TObject); private { Private declarations } MDIDefProc:pointer; MDIInstance:TFarProc; procedure MDIWndProc(var prmMsg:TMessage); procedure CreateWnd;override; procedure ShowBitmap(prmDC:hDC); procedure ShowGradient(prmDC:hDC;prmRed,prmGreen,prmBlue:byte); public { Public declarations } end; var frmMain: TfrmMain; glbImgWidth:integer; glbImgHeight:integer; implementation {$R *.DFM} procedure TfrmMain.FormCreate(Sender: TObject); begin glbImgHeight:=imgTile.Picture.Height; glbImgWidth:=imgTile.Picture.Width; end; procedure TfrmMain.FormResize(Sender: TObject); begin FormPaint(Sender); end; procedure TfrmMain.MDIWndProc(var prmMsg:TMessage); begin with prmMsg do begin if Msg=WM_ERASEBKGND then begin if mnuBitmap.Checked then ShowBitmap(wParam) else ShowGradient(wParam,255,0,0); Result:=1; end else Result:=CallWindowProc(MDIDefProc,ClientHandle,Msg,wParam,lParam); end; end; procedure TfrmMain.CreateWnd; begin inherited CreateWnd; MDIInstance:=MakeObjectInstance(MDIWndProc); { create wrapper } MDIDefProc:=pointer(SetWindowLong(ClientHandle,GWL_WNDPROC, longint(MDIInstance)) ); end; procedure TfrmMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin { restore default window proc } SetWindowLong(ClientHandle,GWL_WNDPROC,longint(MDIDefProc)); { dispose of instance } FreeObjectInstance(MDIInstance); end; procedure TfrmMain.mnuExitClick(Sender: TObject); begin close; end; procedure TfrmMain.mnuBitmapClick(Sender: TObject); var wrkDC:hDC; begin wrkDC:=GetDC(ClientHandle); ShowBitmap(wrkDC); ReleaseDC(ClientHandle,wrkDC); mnuBitmap.Checked:=true; mnuGradient.Checked:=false; end; procedure TfrmMain.mnuGradientClick(Sender: TObject); var wrkDC:hDC; begin wrkDC:=GetDC(ClientHandle); ShowGradient(wrkDC,0,0,255); ReleaseDC(ClientHandle,wrkDC); mnuGradient.Checked:=true; mnuBitMap.Checked:=false; end; procedure TfrmMain.ShowBitmap(prmDC:hDC); var wrkSource:TRect; wrkTarget:TRect; wrkX:integer; wrkY:integer; begin {tile bitmap } if FormStyle=fsNormal then begin wrkY:=0; while wrkY < ClientHeight do { go from top to bottom.. } begin wrkX:=0; while wrkX < ClientWidth do { ..and left to right. } begin Canvas.Draw(wrkX,wrkY,imgTile.Picture.Bitmap); Inc(wrkX,glbImgWidth); end; Inc(wrkY,glbImgHeight); end; end else if FormStyle=fsMDIForm then begin Windows.GetClientRect(ClientHandle,wrkTarget); wrkY:=0; while wrkY < wrkTarget.Bottom do begin wrkX:=0; while wrkX < wrkTarget.Right do begin BitBlt(longint(prmDC),wrkX,wrkY,imgTile.Width,imgTile.Height, imgTile.Canvas.Handle,0,0,SRCCOPY); Inc(wrkX,glbImgWidth); end; Inc(wrkY,glbImgHeight); end; end; end; procedure TfrmMain.ShowGradient(prmDC:hDC;prmRed,prmGreen,prmBlue:byte); var wrkBrushNew:hBrush; wrkBrushOld:hBrush; wrkColor:TColor; wrkCount:integer; wrkDelta:integer; wrkRect:TRect; wrkSize:integer; wrkY:integer; begin { gradient routine } wrkDelta:=255 div (1+ClientHeight); { number of shades desired } if wrkDelta=0 then wrkDelta:=1; { yes, usually 1 } wrkSize:=ClientHeight div 240; { size of blended bars } if wrkSize=0 then wrkSize:=1; for wrkY:=0 to 1+(ClientHeight div wrkSize) do begin wrkColor:=RGB(prmRed,prmGreen,prmBlue); wrkRect:=Rect(0,wrkY*wrkSize,ClientWidth,(wrkY+1)*wrkSize); if FormStyle=fsNormal then begin Canvas.Brush.Color:=wrkColor; Canvas.FillRect(wrkRect); end else if FormStyle=fsMDIForm then begin wrkBrushNew:=CreateSolidBrush(wrkColor); wrkBrushOld:=SelectObject(prmDC,wrkBrushNew); FillRect(prmDC,wrkRect,wrkBrushNew); SelectObject(prmDC,wrkBrushOld); DeleteObject(wrkBrushNew); end; if prmRed >wrkDelta then Dec(prmRed,wrkDelta); if prmGreen > wrkDelta then Dec(prmGreen,wrkDelta); if prmBlue > wrkDelta then Dec(prmBlue,wrkDelta); end; end; procedure TfrmMain.FormPaint(Sender: TObject); begin if FormStyle=fsNormal then if mnuBitMap.Checked then mnuBitMapClick(Sender) else mnuGradientClick(Sender); end; end.