On transcribing an old Delphi-Program to a Lazarus-program i was in need do have working MDI-functions.
I tried to implement them in customform.inc and they work fine with my program and in my environment.
There are still some problematic spots in the code and i would appreciate comments/solutions for them.
I tried to implement them in customform.inc and they work fine with my program and in my environment.
There are still some problematic spots in the code and i would appreciate comments/solutions for them.
regards
H. Niemeyer
{------------------------------------------------------------------------------ Method: TCustomForm.ActiveMDIChild Params: None Returns: Nothing
Returns currently active MDI child form of self. Valid result is returned only when Self FormStyle = fsMDIForm or fsMDIChild, otherwise Result is nil. ------------------------------------------------------------------------------} function TCustomForm.ActiveMDIChild: TCustomForm; var actMdiChild : TCustomForm; k : integer; begin Result := nil; (* if not (FormStyle in [fsMDIForm, fsMDIChild]) then exit; if HandleAllocated and not (csDesigning in ComponentState) then Result := TWSCustomFormClass(WidgetSetClass).ActiveMDIChild(Self); *) if (csDesigning in ComponentState) or not(FormStyle in [fsMDIForm, fsMDIChild]) then exit; if HandleAllocated then Result := TWSCustomFormClass(WidgetSetClass).ActiveMDIChild(Self); if Result=nil then begin k := 0; while (k<Screen.CustomFormZOrderCount) and (result=nil) do begin actMdiChild:=Screen.CustomFormsZOrdered[k]; if (actMdiChild.Owner=self) and actMdiChild.Visible and (actMdiChild.FormStyle in [fsMDIForm, fsMDIChild]) then result:=actMdiChild else k:=k+1 end; end; end; {------------------------------------------------------------------------------ Method: TCustomForm.MDIChildCount Params: None Returns: Nothing Returns count of MDIChild forms. Result is returned only when Self FormStyle = fsMDIForm or fsMDIChild (can be 0 ... number of mdichild forms). If Result is -1 then caller isn't mdi or handle is not allocated. ------------------------------------------------------------------------------} function TCustomForm.MDIChildCount: Integer; var k : integer; begin Result := -1; (* if not (FormStyle in [fsMDIForm, fsMDIChild]) then exit; if HandleAllocated and not (csDesigning in ComponentState) then Result := TWSCustomFormClass(WidgetSetClass).MDIChildCount(Self); *) if (csDesigning in ComponentState) or not(FormStyle in [fsMDIForm, fsMDIChild]) then exit; if HandleAllocated then Result := TWSCustomFormClass(WidgetSetClass).MDIChildCount(Self) else Result:=0; if Result = 0 then begin for k := 0 to ComponentCount-1 do if (Components[k] is TCustomForm) and (TCustomForm(Components[k]).FormStyle in [fsMDIForm, fsMDIChild]) then result:=result+1; end; end; {------------------------------------------------------------------------------ Method: TCustomForm.GetMDIChildren Params: AIndex: Integer; Returns: TCustomForm with FormStyle = fsMDIChild Returns MDI child (fsMDIChild) of parent mdi form (fsMDIForm) at index AIndex in list of mdi children. Result can be nil if caller isn't an mdi type or handle isn't allocated. ------------------------------------------------------------------------------} function TCustomForm.GetMDIChildren(AIndex: Integer): TCustomForm; var k, index : integer; begin Result := nil; (* if not (FormStyle in [fsMDIForm, fsMDIChild]) then exit; if HandleAllocated and not (csDesigning in ComponentState) then Result := TWSCustomFormClass(WidgetSetClass).GetMDIChildren(Self, AIndex); *) if (csDesigning in ComponentState) or not(FormStyle in [fsMDIForm, fsMDIChild]) then exit; if HandleAllocated then Result := TWSCustomFormClass(WidgetSetClass).GetMDIChildren(Self, AIndex); if Result = nil then begin k := -1; index := -1; While (k<ComponentCount-1) and (index<>AIndex) do begin k := k+1; if (Components[k] is TCustomForm) and (TCustomForm(Components[k]).FormStyle in [fsMDIForm, fsMDIChild]) then index:=index+1; end; if (k<ComponentCount) and (index = AIndex) then result := TCustomForm(Components[k]); end; end; // Boundsrect gives values for inner size. Setting Boundsrect produces a form with bigger size because of frame size. // Is there a function returning those sizes? // Following values are experimental. Don't know if they are correct for other monitors or OSs const defaultFormBorderSize = 8; defaultFormCaptionSize = 22; {------------------------------------------------------------------------------ Method: TForm.Cascade Params: None Returns: Nothing Arranges MDI child forms so they overlap. Use Cascade to arrange MDI child forms so they overlap. Cascade works only if the form is an MDI parent form (FormStyle=fsMDIForm). ------------------------------------------------------------------------------} procedure TForm.Cascade; const offsetY = defaultFormCaptionSize+defaultFormBorderSize; //don't overlap form.caption offsetX = offsetY; //no spezial reason for this var CascadeOk : boolean; r : TRect; w, h, k : integer; comp : TComponent; temp : TCustomForm; visMDIList: TList; begin (* if (FormStyle <> fsMDIForm) then exit; if HandleAllocated and not (csDesigning in ComponentState) then TWSCustomFormClass(WidgetSetClass).Cascade(Self); *) if (FormStyle <> fsMDIForm) or (csDesigning in ComponentState) then exit; if HandleAllocated then CascadeOk:=TWSCustomFormClass(WidgetSetClass).Cascade(Self) else CascadeOk:=false; if CascadeOk then exit; visMDIList := TList.Create; for k := screen.CustomFormZOrderCount-1 downto 0 do // keep old order; activeMDIChild (index=0) in front; begin temp := Screen.CustomFormsZOrdered[k]; if (temp.FormStyle in [fsMDIForm, fsMDIChild]) and (temp.Owner=self) and temp.Visible and (temp.WindowState<>wsMinimized) // don't cascade non-visible or minimized MDIChilds ? then visMdiList.Add(temp); end; if visMdiList.Count>0 then begin temp:=TCustomForm(visMdiList.Items[0]); comp:=temp.Parent; if (comp<>nil) and (comp is TCustomForm) then r := TCustomForm(comp).ClientRect else r := Screen.WorkAreaRect; // screen.DesktopRect; w:=(r.right - r.left)*3 div 4; // no spezial reason for this value h:=(r.bottom - r.top)*3 div 4; if (w>0) and (h>0) then for k:=0 to visMdiList.Count-1 do begin temp:=TCustomForm(visMdiList.Items[k]); temp.SetBounds(r.left + k*offsetX, r.top + k*offsetY, w, h); end; end; visMDIList.Free; end; {------------------------------------------------------------------------------ Method: TForm.Next Params: None Returns: Nothing Activates the next child MDI form (fsMDIChild) in the form sequence. Use Next to change the active child form of an MDI parent. If calling of Next comes to the end of count it restarts and activates first dsMDIChild in sequence. The Next method applies only to forms with FormStyle = fsMDIForm. ------------------------------------------------------------------------------} procedure TForm.Next; var k : integer; success : boolean; Comp : TComponent; nextMDIChild, actMDIChild : TCustomForm; begin (* if (FormStyle <> fsMDIForm) then exit; if HandleAllocated and not (csDesigning in ComponentState) then TWSCustomFormClass(WidgetSetClass).Next(Self); *) if (FormStyle <> fsMDIForm) or (csDesigning in ComponentState) then exit; if HandleAllocated then success:=TWSCustomFormClass(WidgetSetClass).Next(Self) else success:=false; if success then exit; // successful handling by WidgetSetClass actMDIChild := ActiveMDIChild; if actMDIChild=nil then exit; //no active MDIChild k := -1; nextMDIChild := nil; //Don't use Screen.CustomForms as positions in that list are changed, when activating a form While (k<ComponentCount-1) and not success do begin k := k+1; Comp := Components[k]; if (Comp is TCustomForm) and (TCustomForm(Comp).FormStyle in [fsMDIForm, fsMDIChild]) // and TCustomForm(Comp).Visible then begin if nextMDIChild=nil then nextMDIChild := TCustomForm(Comp); // nextMDIChild := GetMDIChildren(0); if TCustomForm(Comp)=actMDIChild then success:=true; end; end; success:=false; While (k<ComponentCount-1) and (not success) do //search for MDIChild after activeMDIChild begin k := k+1; Comp := Components[k]; if (Comp is TCustomForm) and (TCustomForm(Comp).FormStyle in [fsMDIForm, fsMDIChild]) then success:=true; end; if success then nextMDIChild := TCustomForm(Comp); //found MDIChild after activeMDIChild //otherwise take GetMDIChildren(0); nextMDIChild.visible:=true; if nextMDIChild.WindowState=wsMinimized then nextMDIChild.WindowState:=wsNormal; nextMDIChild.BringToFront; nextMDIChild.SetFocus; end; {------------------------------------------------------------------------------ Method: TForm.Previous Params: None Returns: Nothing Activates the previous MDI child form in the form sequence. Behaviour is vice-versa of TForm.Next. The Previous method can be called only for forms with FormStyle = fsMDIForm ------------------------------------------------------------------------------} procedure TForm.Previous; var k : integer; success : boolean; Comp : TComponent; PrevMDIChild, lastMDIChild, actMDIChild : TCustomForm; begin (* if (FormStyle <> fsMDIForm) then exit; if HandleAllocated and not (csDesigning in ComponentState) then TWSCustomFormClass(WidgetSetClass).Previous(Self); *) if (FormStyle <> fsMDIForm) or (csDesigning in ComponentState) then exit; if HandleAllocated then success:=TWSCustomFormClass(WidgetSetClass).Previous(Self) else success:=false; if success then exit; // successful handling by WidgetSetClass actMDIChild := ActiveMDIChild; if actMDIChild=nil then exit; // no active MDIChild k := -1; PrevMDIChild := nil; Comp := nil; lastMDIChild := nil; //Don't use Screen.CustomForms as positions in that list are changed, when activating a form While (k<ComponentCount-1) and not success do begin k := k+1; Comp := Components[k]; if (Comp is TCustomForm) and (TCustomForm(Comp).FormStyle in [fsMDIForm, fsMDIChild]) //and TCustomForm(Comp).Visible then begin PrevMDIChild := lastMDIChild; lastMDIChild := TCustomForm(Comp); if TCustomForm(Comp) = actMDIChild then success:=true; end; end; // if PrevMDIChild=nil then PrevMDIChild := GetMDIChildren(MDIChildCount-1); if PrevMDIChild=nil then // no MDIchild before activeMDIChild begin // get GetMDIChildren(MDIChildCount-1) directly, as we are nearly there PrevMDIChild := lastMDIChild; While (k<ComponentCount-1) do begin k := k+1; Comp := Components[k]; if (Comp is TCustomForm) and (TCustomForm(Comp).FormStyle in [fsMDIForm, fsMDIChild]) then PrevMDIChild := TCustomForm(Comp); end; end; PrevMDIChild.visible:=true; if PrevMDIChild.WindowState=wsMinimized then PrevMDIChild.WindowState:=wsNormal; PrevMDIChild.BringToFront; PrevMDIChild.SetFocus; end; {------------------------------------------------------------------------------ Method: TForm.Tile Params: None Returns: Nothing Arranges MDI child forms so that they are all the same size. Use Tile to arrange MDI child forms so that they are all the same size. Tiled forms completely fill up the client area of the parent form. How the forms arrange themselves depends upon the values of their TileMode properties, and it depends on widgetset. Tile works only if the form FormStyle = fsMDIForm. ------------------------------------------------------------------------------} procedure TForm.Tile; // see comment before procedure TForm.Cascade const xframeoffset = 2*defaultFormBorderSize; yframeoffset = 2*defaultFormBorderSize+defaultFormCaptionSize; var TileOk : boolean; r : TRect; w,h,k,c,z,x,y : integer; comp : TComponent; temp : TCustomForm; visMDIList : TList; begin (* if (FormStyle <> fsMDIForm) then exit; if HandleAllocated and not (csDesigning in ComponentState) then TWSCustomFormClass(WidgetSetClass).Tile(Self); *) if (FormStyle <> fsMDIForm) or (csDesigning in ComponentState) then exit; if HandleAllocated then TileOk:=TWSCustomFormClass(WidgetSetClass).Tile(Self) else TileOk:=false; if TileOk then exit; // Tile was done by WidgetSetClass visMDIList := TList.Create; for k := 0 to screen.CustomFormZOrderCount-1 do // activeMDIChild first - position TopLeft; keep old order begin temp := Screen.CustomFormsZOrdered[k]; if (temp.FormStyle in [fsMDIForm, fsMDIChild]) and (temp.Owner=self) and temp.Visible and (temp.WindowState<>wsMinimized) // don't tile non-visible or minimized MDIChilds ? then visMdiList.Add(temp); end; if visMdiList.Count>0 then begin temp:=TCustomForm(visMdiList.Items[0]); comp:=temp.Parent; if (comp<>nil) and (comp is TCustomForm) then r := TCustomForm(comp).ClientRect else r := screen.WorkAreaRect; (* { tileMode: vertical } z := visMdiList.Count; c := 1; *) (* { tileMode: horizontal } z := 1; c := visMdiList.Count; *) { tileMode: grid-like } z:=Round(Sqrt(visMdiList.Count)); c:=1; while z*c<visMdiList.Count do c:=c+1; w:=(r.right - r.left) div c; h:=(r.bottom - r.top) div z; y:=-1; if (w>0) and (h>defaultFormCaptionSize) then for k:=0 to visMdiList.Count-1 do begin temp:=TCustomForm(visMdiList.Items[k]); (* { tileMode: vertical } // x := 0; // y := k; temp.SetBounds(r.left ,r.top + k*h, w-xframeoffset, h-yframeoffset); *) (* { tileMode: horizontal } // x := k; // y := 0; temp.SetBounds(r.left + k*w, r.top, w-xframeoffset, h-yframeoffset); *) { tileMode: grid-like } x := k mod c; if (x=0) then y:=y+1; temp.SetBounds(r.left + x*w, r.top + y*h, w-xframeoffset, h-yframeoffset); end; end; visMDIList.Free; end;
-- _______________________________________________ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus