Delphi 7: Application scaling - delphi

On my notebook with a screen resolution of 1280x800 I've developed an application. Now I want to use it on a desktop computer with a resolution of 1600x1200.
Of course, it's too small on the desktop computer. I've set the sizes so that I could see the whole form on my notebook. But on the desktop computer, everything should be resized.
But on the large screen, things shouldn't be viewed bigger which means that the same amount of information can be displayed. Things should get a higher height and width value so that more information can be displayed.
In complicated code I mean something like this which should run automatically once when the form is created (OnCreate):
devResolutionX := 1280;
devResolutionY := 800;
useResolutionX := 1600; // how to get / read out this property?
useResolutionY := 1200; // how to get / read out this property?
Form1.Height := Form1.Height+devResolutionY-useResolutionY;
Form1.Height := Form1.Width+devResolutionX-useResolutionX;
// do that with all components which makes this approach complicated
What must I work with to reach that goal?
ScaleBy
alignments
anchors
Thank you very much in advance!

It looks like you just need to set the BorderStyle property of your form to bsSizeable. This will allow the user to resize the form (or maximize it) as he sees fit.
You will also want to make use of anchors here. If you set the akLeft, akTop, akRight, and akBottom anchors for all the components on your form, they will resize with the form.
As soon as you do this, though, you will probably quickly realize that wasn't actually what you wanted to do after all. These growing components are probably going to overlap with each other. So, you are going to need to put some thought into which edges of which components get anchored and which don't.
Sometimes you will need to do some more complicated component moving and sizing than can be handled by anchors alone. In these cases, you will want to handle the Form's OnResize event. This event will get fired whenever the user resizes the form, and it will give you the chance to do some math to recalulate the sizes and positions of certain components.

Just set your anchors correctly and the additional info will show. I wouldn't recommend programmatically forcing an arbitrary height and width. The best thing to do is use the form's OnClose event to save the form's height and width and then set the height and width with OnCreate.

Related

How to calculate the height of a TCategoryButtons at run-time?

In a Delphi 10.4.2 VCL Application in Windows 10, how can I calculate the height of a TCategoryButtons object at run-time, i.e. the sum of all its button heights and its Category items, as this height could vary depending on its font size?
Measuring the pixel heights at run-time, I have noticed that all buttons have the same height and that the buttons have a different height as the Category items.
Also, note that the buttons do not have a published Height property in the Object Inspector.
But shouldn't it be possible to calculate the sum of all its button heights and its Category items with some low-level methods?
This is a control entirely implemented in Pascal, in Vcl.CategoryButtons.pas.
Therefore, you can see exactly how it is implemented. For instance, in TCategoryButtons.Paint you see its complete drawing code. Similarly, you can investigate the hit testing done in MouseMove (or MouseDown or MouseUp).
Consequently, if nothing else, you can create your own modified version of TCategoryButtons using this code. Your version can save the total height when it has been determined (for instance, certainly after painting).
However, after a quick look, it seems like TButtonCategory.Bounds might be interesting. If you are lucky, this returns the on-screen rect of a category. The Bottom of the last category's rect should be the (effectively used) height of the entire control.
It seems to work for me:
Here I draw a red bar of the same height as the control.
procedure TForm5.FormPaint(Sender: TObject);
begin
var y := CategoryButtons1.Categories[
CategoryButtons1.Categories.Count - 1
].Bounds.Bottom;
Canvas.Brush.Color := clRed;
Canvas.FillRect(Rect(0, 0, ClientWidth, y))
end;

SpTBX: can I use Panels' DockedWidth/FloatingWidth

Moving from TBX to SpTBX. I used in the past TTbxDockablePanel which has such props:
DockedWidth
DockedHeight
FloatingWidth
FloatingHeight
I can't find such properties in SpTBX panels, so how should I change my code to use such props? ie. i need to get/set SpTBX panel's docked width/height and floating width/height.
DockedWidth and DockedHeight
A TSpTBXDockablePanel now has a property DefaultDockedSize. A docked panel is docked to either a vertical or horizontal dock, so it only needs one size, which specifies the width (in a vertical dock) or height (in a horizontal dock.) The length of the other axis is a result of either the dock size or the other panels in the same dock. If there are other panels, the size it becomes is the width of the other panels in the dock. If there aren't, it will use either the previous size (if DefaultDockedSize is 0) or try to use DefaultDockedSize.
See TSpTBXCustomDockablePanel.SetParent for the code. You'll be interested in the two branches beginning if ToDock then... and if ToFloating then.... There are some comments there that I've tried to interpret to write the above.
From memory, when I converted from TBX to SpTBX years ago, this was the hardest area to get behaving exactly the same. However, you can get it to behave 'okay', ie with behaviour that makes sense, easily.
FloatingWidth and FloatingHeight
Replaced by FloatingClientWidth and FloatingClientHeight. Note that these are the client sizes not window sizes, but in general they should be direct replacements.
In addition
There is a comment at the top of the SpTBXDkPanels.pas file,
// - To handle the size constraints use GetMinMaxSize when the DP is floating,
// and ConstrainedResize when is Docked (explicitly check if it's docked).
You might find that useful too.
There are a reasonable number of comments scattered through the code. The SpTBX library doesn't have very good documentation, but it does come with high-quality source... Use the source, Luke :)

making a form fit in notebook desktop

I made a form using a laptop which has 15 inches screen laptop but when i transfer the application to a notebook, some button components are invisible especially those below the form which were visible in the laptop.
so is there a possibility of a code that makes the form adjust itself to fit in a notebook screen or how this can be done using properties?
What you're asking for is also called resolution independence which means to design your forms to make them usable on very small and very big screens (screen resolutions).
This is traditionally done using the Anchors and Align properties, so that controls can size and place themselves according to a certain layout.
Newer Delphi versions also have Margins and AlignWithMargins so that automatic alignment can reserve some space between controls.
Another way that is used by many other toolkits is to use an explicit layout concept. That can be done with TGridPanel and TFlowPanel in Delphi, but doesn't work very nice in my experience. There are better layout management systems out there (like DevExpress Layout Control).
You might also consider using TScrollBoxes, TSplitters and docking to allow users to customize their UI experience.
You can also consider putting some functionality in extra dialogs that are called by buttons or hiding some controls on TPageControl tab sheets.
Scaling is also possible (see Steves answer), but it makes forms appear odd and can drastically reduce the user experience, because controls become too small or users have hard time hitting the right control or fonts are too small, etc.
If the effort is to great or if you have totally different devices (like smart phones vs. workstations) it might even be necessary to have completly different forms or different apps that might use a client / server or multi tier architecture to share the same buisiness logic, but that's actually beyond the scope of this question...
You might read the article by Zarko Gajic at http://delphi.about.com/od/standards/a/aa030700a.htm to understand some of the pitfalls in scaling.
Here is a function that might help:
procedure ScaleForm(theF: TForm; ScreenWidth, ScreenHeight: LongInt) ;
begin
theF.Scaled := True;
theF.AutoScroll := False;
if (Screen.Width <> ScreenWidth) then
begin
theF.Height :=LongInt(theF.Height) * LongInt(Screen.Height) div ScreenHeight;
theF.Width := LongInt(theF.Width) * LongInt(Screen.Width) div ScreenWidth;
theF.ScaleBy(Round(Screen.Width,ScreenWidth)) ;
end;
{the following lines work on an Xp PC but seem to have no effect on Win 7
theF.Position := poScreenCenter; //poDefault, poDesigned,poDesktopCenter,poOwnerFromCenter,poMainFormcenter
theF.Font.Name := 'Arial'; //to scale properly, you have to use a scalable font.
}
end;
Call the function in your application's OnCreate handler ScaleForm(Form1,screen.width,screen.height); Form1 is the handle of your form. Place the function call in a MENU item or button on your form to call it manually, if needed.
Also, here is a simple procedure using the ScaleBy function. ScaleBy can be used to adjust the form's size downward (or upward) in increments
until the entire form fits on the Netbook. The example uses 10 percent increments. Depending on the controls you use in your application, this might be all you need. Many controls will scale automatically. There are more elegant and complicated solutions. In XE2 there is a function
called ChangeScale which may be useful however it might not be available in Delphi 7. Remember, not all controls scale gracefully. You may have more work to do.
procedure TPktForm1.ScaleDown1Click(Sender: TObject);
begin
ScaleBy(90,100); //changes this form where ScaleBy(percentage reduction of reduced form, percentage original form);
Form_A.ScaleBy(90,100); //changes other forms in the application
Form_B.ScaleBy(90,100);
Application.ProcessMessages;
end;
or you might add Scaleby(659, Screen.Height ) in the form's OnCreate where '659' is the programmed original form height to fill a screen or Scaleby(Screen.Height, 659); to make the form smaller. Yes, there are limits to what this technique can do as far as down scaling. Going from desktop to Netbook works fine here.
There are plenty of examples on the Web. Are you using a DBGrid? You will have issues, however you can code around them for that control.

TeeChart VCL chart scale issue

I have an issue using Delphi 2007 & TChart 7.0.10.0 or 7.0.11.0 or the latest evaluation 9.0.5.0 on the TChart scaling.
The problem arises as soon I enlarge the window after a certain width and KEEP the Form height!
This is the drawing using a smaller form size.
now if I enlarge to 1200 weight I get this ugly scaling:
If I export in the designer without the aspect ratio set and with 1200 weight you will se this:
How to get ride of this?
Hp
I see you've set top and bottom margins to Chart1 in your project (8 and 20 percent respectively). I guess this has the intention of giving more space (in height) for Chart2 when you resize the form making it bigger.
Chart1's Top and Height properties should be set according to fill this blank space in the Form's OnResize event.
Try this:
procedure TGSSkillgroupStatisticForm.FormResize(Sender: TObject);
begin
Chart1.Draw;
Chart2.Top:=Chart1.ChartRect.Bottom + 25;
Chart2.Height:=Chart1.Height-Chart1.ChartRect.Bottom-40;
end;
Steema Support Central
Keep in mind that I only scale in the x-axis. Your 3-D bar / construct will after a certain width, overlap the scaling numbers! Your given answer do not fix this issue at all. To see the real problem in a better way, I added on the form creation:
Chart2.BottomAxis.Maximum := 20;
Series2.AddBar(12, 'Hallo', clred);
Here the result:

How to find the real size ("logical area") of a TScrollBox

I need to find the entire size (also called "logical area") of a TScrollBox - as opposite to visible area that you get via Width and Height property (or ClientWidth ClientHeight).
I want to create some controls inside that TScrollBox. One of them (called TViewer) needs to be as high as the TScrollBox itself. The thing is that during creation, the TScrollBox is scrolled down to show last created control. So, using Top=1 will not work because my control will have top=1 which is not the top of the logical area.
Delphi 7
Drop a component, like a TLabel, on the TScrollBox.
Set the component's Left and Top properties to 0.
Set the component's Visible property to False.
Now you always have the origin. The "logical height" is now:
myScrollBox.Height + (myOriginControl.Top * -1);
Maybe ScrollBox.HorzScrollBar.Range and ScrollBox.VertScrollBar.Range + the corresponding .Positions are what you need.
Look at Scrollbars:
ScrollBox1.VertScrollBar.Range
ScrollBox1.HorzScrollBar.Range
It can be less than height and width if the scrollbox logical area is not bigger than phisical area (scrollbars not visible in that case)
Or use this to get the max of both:
var
AHeight, AWidth: Integer;
begin
AHeight := Max(ScrollBox1.VertScrollBar.Range, ScrollBox1.Height);
AWidth := Max(ScrollBox1.HorzScrollBar.Range, ScrollBox1.Width);
ShowMessageFmt('%d,%d', [AHeight, AWidth]);
end;
Edit
From #Altar comments, I can add the logical height and/or width is not the problem. If you want to add any control which occupies all the height of the scrollbar, use the AHeight from the above calculation, but set the Top to the negative of VertScrollBar.Position, something like this:
procedure TForm2.Button3Click(Sender: TObject);
var
AHeight, AWidth: Integer;
Btn: TButton;
begin
AHeight := Max(ScrollBox1.VertScrollBar.Range, Height);
AWidth := Max(ScrollBox1.HorzScrollBar.Range, Width);
Btn := TButton.Create(Self);
Btn.Parent := ScrollBox1;
Btn.Left := 15;
Btn.Top := -ScrollBox1.VertScrollBar.Position;
Btn.Height := AHeight;
end;
Im not sure i understand exactly what you want to do, but to get the complete area defined as "scrollable" you would have to write ScrollBox.HorScrollBar.Range + ScrollBox.Clientwidth (and the same thing for the vertical section). The scrollbox always deducts the visible "page" size from the total. So if you define a height of 1000 pixels, with 100 pixels showing - it will have a scrolling range of 900. You have to add the clientheight to get the rest.
Also, to get the correct "top" position you will have to read Canvas.Cliprect.Top, since a scrolling window does not change the top position of sub-controls. Windows handles this for you and only tells you what to re-draw once the scrollbars are initialized.
Since you want to create a control that is just as high as the complete scrollable area, i presume you are creating an editor of sorts?
If so you would probably get better results taking a look at SynEdit and extract the base-class that adds scrollbars to a normal TCustomControl (it's quite easy). That way you can control both the painting and the layout of your controls.
Here is one I wrote for Lazarus and FreePascal a while back. If you add messages to the uses clause and prefix the message handlers with WM rather than TLM it will compile under Delphi.
(code to long, had to use external link): http://delphimax.wordpress.com/2010/09/20/platform-independent-image-component-for-lazarus/
I have tried to do that, and believe me, I was not able to.
If you have the instances of the controls that are inside TScrollBox, you can use them to calculate (not precisely) the area.
Here is a complicated (but complete) solution:
I create my first child control during TScrollBox.Create (when TScrollBox does not have yet a scrollbar)
Set Child.Top:= 1
Create the rest of the child controls (this may force the TScrollBox to show the scrollbar)
Scroll the TScrollBox up
Use one of the above solutions to calculate the height of the TScrollBox

Resources