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 [email protected] http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
