sobakava Posted April 12, 2015 Share Posted April 12, 2015 Hello, As I have seen, the centered panel topic is being discussed many times in the forum but it is still a confusion, at least for me. Let me place this screenshot to show what I'm talking about first: This is probably the most common Web layout nowadays. A panel at the centers which keeps its central position even if the browser window resizes. How do we do this: - Let's start with the Main Form: This is the MainForm WindowState : wsMaximized BorderStyle : bsNone In the server module, we should have this line: MainFormDisplayMode = mfPage I have placed an UniContainerPanel on the form. There is something we need to do with this panel first. We should clear all Anchors : akTop: false akLeft: false akBottom: false akRight: false And there is a an UniImage in the ContainerPanel with the following properties: Alignment : alClient Autosize : true Center : true Stretch : false (we don't want to distort the image) And as a visual control example, I have placed a button in the ContainerPanel. There is nothing special with its properties. Just place it as you like. This button will show another form: procedure TMainForm.UniBitBtn1Click(Sender: TObject); begin subForm1.showmodal; end; Ok, these are enough to place our image which is going to be the background of our panel at the center of the form. But what happens if the browser window resizes?Well, we need to dynamically adjust the ContainerPanel's position. Luckly Unigui has an event which triggers whenever the browser window resizes. It even reports the last width and height values. We will use this event to move the ContainerPanel to the window center. Calculation is simple. For the left value, just subtract panel's half width from window's half width. Then calculate the top value similarly. procedure TMainForm.UniFormScreenResize(Sender: TObject; AWidth, AHeight: Integer); begin mainform.UniContainerPanel1.Left := (AWidth - mainform.UniContainerPanel1.Width) div 2; mainform.UniContainerPanel1.Top := (AHeight - mainform.UniContainerPanel1.Height) div 2; end; Everything is nice and clean so far. This works as we wish. - Secondary Form: But what if we have more than one Form in our application? The UniFormScreenResize event is being fired for only MainForm. Secondary forms in the application will not receive this event. So even if we do everything explained above exactly the same for the secondary forms, the ContainerPanel won't keep it's central position. There are some other tricks to do for secondary forms as well. First of all, "MainFormDisplayMode = mfPage" this is just for the MainForm. So, if you want your secondary forms to be displayed borderless, you should change following properties and add following code to extEvents to remove border and rounded corners: WindowState : wsMaximized BorderStyle : bsNone //Removes border and round edges extEvents - windows.afterRender: Ext.get(sender.id).el.setStyle("padding", 0); Ext.get(sender.id).el.setStyle("border-width", 0); Ext.get(sender.id).el.setStyle("margin", 0); We will replicate the same procedures for ContainerPanel and UniImage for the second page too. And when we click the button on the MainForm, we'll see the secondary form as we planned to see. This could be a login form, information form, control panel etc. But the ContainerPanel on this form will not stay at the center of the window when we resize the browser window. It is probably because of the intent of the application form's is totally different by philosophy. Well I have tried to implement some tricks to fix this. For instance I thought, even if the secondary form is shown as Modal, the main form should be receiving ScreenResize events and since they are in the same window, I have tried to use main form's event for secondary form too. procedure TMainForm.UniFormScreenResize(Sender: TObject; AWidth, AHeight: Integer); begin mainform.UniContainerPanel1.Left := (AWidth - mainform.UniContainerPanel1.Width) div 2; mainform.UniContainerPanel1.Top := (AHeight - mainform.UniContainerPanel1.Height) div 2; if ( subForm1.visible ) then begin subForm1.UniContainerPanel1.Left := (AWidth - mainform.UniContainerPanel1.Width) div 2; subForm1.UniContainerPanel1.Top := (AHeight - mainform.UniContainerPanel1.Height) div 2; end; end; well, actuall this works. But of course since we try to access subForm1 even before it is being created, it raises exceptions at the startup then it looks like working. I have tried to use an if condition like this: if Assigned( subForm1 ) then begin end; but this Assigned( TUniform) test raises and error: [dcc32 Error] Main.pas(51): E2036 Variable required Anyway, I'll update this post when I learn how to do this correctly. In the attachment you can find the sample project (Unigui 0.99.0 + XE6) I have added TUnimemos to the forms as a reminder of properties to change. centered_forms_.zip Best 1 Link to comment Share on other sites More sharing options...
sobakava Posted April 13, 2015 Author Share Posted April 13, 2015 I have added a boolean variable to keep track of if the subform is already created. As unigui recommends, I have added this variable to mainmodue. In mainmodule.pas : public { Public declarations } subform1_created : boolean; end; Subform's OnCreate and OnClose events update this boolean variable : procedure TsubForm1.UniFormClose(Sender: TObject; var Action: TCloseAction); begin mainmodule.UniMainModule.subform1_created := false; end; procedure TsubForm1.UniFormCreate(Sender: TObject); begin mainmodule.UniMainModule.subform1_created := true; end; And this is how MainForm's OnScreenResize event looks like: procedure TMainForm.UniFormScreenResize(Sender: TObject; AWidth, AHeight: Integer); begin mainform.UniContainerPanel1.Left := (AWidth - mainform.UniContainerPanel1.Width) div 2; mainform.UniContainerPanel1.Top := (AHeight - mainform.UniContainerPanel1.Height) div 2; // Check if we have already created the subform1 if mainmodule.UniMainModule.subform1_created = true then if ( subForm1.visible ) then begin // Update the size of the subform1 with the new window dimensions subForm1.Width := Awidth; subForm1.Height := AHeight; // Adjust containerpanel's position to the center of the window subForm1.UniContainerPanel1.Left := (AWidth - mainform.UniContainerPanel1.Width) div 2; subForm1.UniContainerPanel1.Top := (AHeight - mainform.UniContainerPanel1.Height) div 2; end; end; This is working fine except, when we create subForm with subForm.Showmodal, the ContainerPanel will appear at designated position. Then if we rezise the browser window, it'll be placed at calculated location. So I'm updating subForm's dimensions and ContainerPanel's coordinates using the mainform's dimensions. procedure TsubForm1.UniFormShow(Sender: TObject); begin subForm1.Width := mainform.width; subForm1.Height := mainform.height; subForm1.UniContainerPanel1.Left := (subForm1.Width - mainform.UniContainerPanel1.Width) div 2; subForm1.UniContainerPanel1.Top := (subForm1.Height - mainform.UniContainerPanel1.Height) div 2; end; This is the updated project. Hope it helps someone out there. centered_forms_v2.zip 3 Link to comment Share on other sites More sharing options...
albertovesx Posted April 13, 2015 Share Posted April 13, 2015 Thank you. Link to comment Share on other sites More sharing options...
Recommended Posts
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now