Mega Code Archive

 
Categories / Delphi / Examples
 

Selective tiling in mdi editors

The Window/Tile menu item is useful if only two files are open. This code implements a more useful "Tile Top 2 of N Windows" that doesn't lose other files that may be open. Selective Tiling in MDI Editors By Gene Fowler acorioso@earthlink.net May 28, 2001 - Change When I added window tracking in a lter article, Tracking Window Numbers in MDI Editors, I found that I had not set Tag values when reopening the files closed before tiling. I have made this change in the TFrameForm.Tile2ofN1Click: // Borrowed guts from Open1Click to replace // ReopenIt in eWriter's complex interweaving with TEditForm.Create(Self) do begin Open(TileTwo[i]); Tag := 3 + i; end; Replaces: // Borrowed guts from Open1Click to replace // ReopenIt in eWriter's complex interweaving with TEditForm.Create(Self) do Open(TileTwo[i]); Some Added Code If you have set up Tile Top 2 of N Windows in TextEdit to look at the code's working, you will want to add this SaveAs1Click routine to MDIEdit.pas. You may have noticed that if you had a new file, saved or not, you got some strange results. Add this and you will not get odd results if you save the file (giving it a pathname). You should not use this menu item if you have an unsaved new file. The loss of Restore sizing is not one of the strange effects. Tiling1 produces that effect and I call it in Tile Top 2 of N Windows. procedure TEditForm.Saveas1Click(Sender: TObject); begin SaveFileDialog.FileName := PathName; if SaveFileDialog.Execute then begin PathName := SaveFileDialog.FileName; Caption := ExtractFileName(PathName); OpenFiles.Insert(Tag, Pathname); // list new Pathname Save1Click(Sender); end; end; Warning: The test-bed for this code is Borland's TextEdit demo that comes with Delphi. If you are compiling in Delphi 5 or 5.01, you will need the modified forms.pas which I direct you to in my earlier article, Programming System/Next (Prev) in MDI editors. When you compile and run Borland's TextEdit (demos/doc/TextEdit) and click the Window menu, you find two file arranging menu items: Tile and Cascade. The Tile command is a design wonder. If you have two files open, they are stacked vertically. This is a very useful work arrangement. But lets go on. If you have three files open, they are still stacked vertically. Now, there isn't much work area in any of them. If you have four files open, they occupy quadrants of the client area. I have not dared try with five files open. I fear pixels popping out of the screen. Tile is most useful if you have just two files open. In the context of a project, however, you might want to have a half dozen close at hand. What you need is a way to set all the files but two aside, with a mouse-click, and, later, bring them back with a mouse-click. You don't want to worry about whether files are tiled or not when making that second click. The code below implements this with a new item on the Window menu below Tile. Click Tile Top 2 of N Windows. All the files other than the top two are closed and the top two are tiled. The menu item is checked. Click it while checked, and the files are re-opened, files are maxed, and the one that was active before the re-opening is on top. On TFrameForm, put a menu item in the Window menu between Tile and Cascade. At the top of the Code section below, I give a Caption (for the user to see) and remind that the Checked property should be False. Everything else can be left as is (since that is what I've done while checking this). The Name property can be shortened as shown. In the Events sheet, Double Click the onClick to get the handler. TFrameForm.Tile2ofN1Click is given here in full. All the declarations (and initializations) are given first. This is not going to compile, yet. I've worked this thread loose from a complex "son of TextEdit," and I've worked up minimal support infrastructure here. In the properties table below, note that TEditForm should have WindowState set to wsMaximized. Under Support Code, I give replacement routines for TEditForm.FormClose and TEditForm.Open. My modifications are necessary for keeping track of what files are open and getting pathnames to re-open. Way down at the bottom is something I should have included in my first article. All the tests of my code involve bringing a gang of files into TextEdit. Opening one at a time is a drag. So I include a replacement TFrameForm.Open1Click to handle gang loading. A note just before the routine tells you how to modify the dialog's properties. Code: Some property settings: In TFrameForm, insert a new menu item between Window/Tile and Window/Cascade. Tile Top &2 of N Windows (Menu item caption) Name can be chopped down to Tile2ofN1 Checked is false TEditForm WindowState: wsmaximized TFrameForm ... var (global) ... TileTwo: TstringList; OpenFiles: TstringList; initialization // TileTwo is for the main code TileTwo := TStringList.Create; TileTwo.Text := ''; // OpenFiles is a juri-rigged system for keeping track of open files OpenFiles := TStringList.Create; OpenFiles.Text := ''; { The main code, a TFrameForm routine } procedure TFrameForm.Tile2ofN1Click(Sender: TObject); var i, j: integer; begin if MDIChildCount < 2 then Exit; if (MDIChildCount = 2) and (Tile2ofN1.Checked = False) then begin Tile1Click(Sender); Exit; end; If (MDIChildCount > 2) and not Tile2ofN1.Checked then begin Tile2ofN1.Checked := True; for i := 2 to MDIChildCount - 1 do begin for j := 0 to OpenFiles.Count - 1 do if pos(MDIChildren[i].Caption, OpenFiles.strings[j]) <> 0 then begin TileTwo.Add(OpenFiles.strings[j]); MDIChildren[i].Close; Break; end; end; Tile2ofN1.Checked := True; messageDlg('In this demo, I need ' + 'an interruption after closing files and before ' + 'calling Tile1Click so Child Count is ' + 'recalculated. Go figure.', mtInformation, [mbOK],0); LockWindowUpdate(Handle); Tile1Click(Sender); LockWindowUpdate(0); end else if Tile2ofN1.Checked and (TileTwo.Text <> '') then begin LockWindowUpdate(Handle); for i := 0 to TileTwo.Count - 1 do // Borrowed guts from Open1Click to replace // ReopenIt in eWriter's complex interweaving with TEditForm.Create(Self) do begin Open(TileTwo[i]); Tag := 3 + i; end; MDIChildren[MDIChildCount - 2].BringToFront; LockWindowUpdate(0); TileTwo.Text := ''; Tile2ofN1.Checked := False; end; end; Support Code: {These two routines in TEDitForm track and handle file opens and closes and replace routines already there} procedure TEditForm.FormClose(Sender: TObject; var Action: TCloseAction); var i: Longint; begin for i := 0 to OpenFiles.Count - 1 do if OpenFiles[i] = Pathname then begin OpenFiles.Delete(i); break; end; Action := caFree; end; procedure TEditForm.Open(const AFileName: string); begin PathName := AFileName; Caption := ExtractFileName(AFileName); // put Pathname into OpenFiles list OpenFiles.Add(Pathname); with Editor do begin Lines.LoadFromFile(PathName); SelStart := 0; Modified := False; end; end; {Taking in multiple files to run tests will be easier if you select TFrameForm's OpenDialog1 and, under options, make multiple selections True. Then, substitute the routine below for Open1Click} procedure TFrameForm.Open1Click(Sender: TObject); var i: integer; begin if OpenFileDialog.Execute then LockWindowUpdate(Handle); For i := 0 to OpenFileDialog.Files.count - 1 do with TEditForm.Create(Self) do Open(OpenFileDialog.Files[i]); LockWindowUpdate(0); end;