Technical progress is certainly nothing new in the IT world. It is taking place in all areas, not only in a wide variety of hardware, but also in screen resolutions. At the beginning of the 1990s, the most widespread resolution was 640×480 pixels. By the end of the decade, this had risen to 800×600 pixels. Over the years, the resolution increased further from 1024×768 to the current 1366×768 pixels. As a result, there have been an increasing number of inquiries from support in the past about how to implement individual scalability of a frame in conzept 16. In the following article, I would like to introduce you to a procedure that offers an easy way to scale existing frames individually.
The fundamental idea:
Most desktop users work with the usual resolutions of 1024 x 768, 1366 x 768, 1280 x 1024 and 1920 x 1080.
Instead of scaling the underlying dialog at runtime, scaled dialogs are generated for the known resolutions and saved with WinSave()
in the database. If the dialog is then supposed to be displayed in the application, the screen resolution is first determined and then the pre-generated dialog is loaded. This can be achieved with the standard conzept 16 commands WinInfo()
and WinDialog()
. This leaves the task of scaling, which is the subject of this article.
Main-Funktion:
The existing frame that is supposed to be scaled is transferred within this function. The next step is to specify the desired size. It is recommended that the aspect ratio of the scaled frame is identical to the original dialog, as otherwise text objects, including fonts, for example, may not be displayed as desired. Once the desired frame size has been entered, the actual scaling function is called up.
main()
local
{
tDHdl : handle; // Dialog
tSizeWish : point; // Desired dialog size
}
{
// Dialog to be scaled
tDHdl # WinOpen('DragDropEvents', _WinOpenDialog | _WinOpenEventsOff);
if (tDHdl > 0)
{
tDHdl->wpAreaClientRestore # false;
// If the new icons are used, then set
//_App->wpTileTheme # _WinTileThemeEnhanced;
// Desired size of the dialog
tSizeWish # PointMake(1024 , 768);
// Scaling function
ScaleFrame(tDHdl, tSizeWish:x, tSizeWish:y);
tDHdl->WinDialogRun(_WinDialogCenterScreen);
tDHdl->WinClose();
}
}
Scaling function ‘ScaleFrame’:
The output frame, the desired width and height are transferred to this function. First, the current height and width of the frame and that of the client area are determined. The difference in the client area of the scaled dialog is then calculated. In order to scale the frame, the scaling factor must be determined. To do this, it is essential to determine the percentage deviation of the height and width. This is done using function GetDifferencePercent()
. Once the scaling factor has been determined, the current frame is set to the desired size and then all objects and their sub-objects are scaled.
sub ScaleFrame
(
aFrame : handle; // Frame
aWidth : int; // Desired width
aHeight : int; // Desired height
)
local
{
tWidth : int; // Width of the frame
tHeight : int; // Height of the frame
tClientW : int; // Client area width
tClientH : int; // Client area height
tDifW : int; // Width difference (dialog border and client area)
tDifH : int; // Height difference (dialog border and client area)
tScaleClientW : int; // Client area of the scaled frame (Width)
tScaleClientH : int; // Client area of the scaled frame (Height)
tPercentW : float; // Width scaling factor in %
tPercentH : float; // Height scaling factor in %
}
{
// Width and height of the frame
tWidth # aFrame->wpAreaRight - aFrame->wpAreaLeft;
tHeight # aFrame->wpAreaBottom - aFrame->wpAreaTop;
// Client area
tClientW # WinInfo(aFrame, _WinClientWidth);
tClientH # WinInfo(aFrame, _WinClientHeight);
// Difference between frame and client area
tDifH # tHeight - tClientH;
tDifW # tWidth - tClientW;
// Client area of the scaled frame
tScaleClientW # aWidth - tDifW;
tScaleClientH # aHeight - tDifH;
// Percentage deviation (Width)
tPercentW # GetDifferencePercent(tClientW, tScaleClientW);
// Percentage deviation (Height)
tPercentH # GetDifferencePercent(tClientH, tScaleClientH);
// Scaling factor
tPercentW # tPercentW / 100.0;
tPercentH # tPercentH / 100.0;
// Frame size
aFrame->wpAreaLeft # 0;
aFrame->wpAreaTop # 0;
aFrame->wpAreaRight # aWidth;
aFrame->wpAreaBottom # aHeight;
// Scaling objects and sub-objects
aFrame->ScaleObject(tPercentW, tPercentH, tClientW, aWidth, aHeight);
}
Function ‘ScaleObject’:
After transferring the parent object, the scaling factor of the length and width, the client area and the desired width and length, the scaling factor of the font is determined first. The text of the objects is then resized. In the next step, all sub-objects are determined in a loop and checked to ensure that they are not exceptions. The recursive function is now called for each determined sub-object so that the font can also be resized. The final step at the end of the function is to increase the size of each individual object by the previously determined percentage.
// Scale objects
sub ScaleObject
(
aParent : handle; // Parent object
aPercentW : float; // Width scaling factor
aPercentH : float; // Height scaling factor
aWidth : int; // Client area of the old frame
aNewWidth : int; // Desired dialog width
aNewHeight : int; // Desired dialog height
)
local
{
tObj : handle; // Object
tArea : rect; // Size
tGrouping : int; // Grouping property
tHasGrouping : logic; // Grouping set?
tHasFont : logic; // hhas a font?
tFontParent : logic; // FontParent set?
tFont : font; // Font of the object
tFontPercent : float; // FontSize scaling factor
tPoint : float; // FontSize
}
{
// Is grouping set?
if (WinPropGet(aParent, _WinPropGrouping, tGrouping))
tHasGrouping # tGrouping != _WinGroupingNone;
// Scaling factor of the font
tFontPercent # Fnc.CalcPercent(aWidth, aNewWidth, aNewHeight);
// Scaling text in the objects
if (WinPropGet(aParent, _WinPropFontParent, tFontParent)) // Eigenschaft vorhanden?
{
if (!tFontParent) // false
{
tFont # aParent->wpFont;
// FontSize is available in tenths of a point
tPoint # CnvFI(tFont:Size) / 10.0;
// Scale font
tPoint # Fnc.CalcPoint(tPoint, tFontPercent);
tFont:Size # CnvIF(tPoint) * 10;
aParent->wpFont # tFont;
}
}
// Search object
for tObj # WinInfo(aParent, _WinFirst);
loop tObj # WinInfo(tObj, _WinNext);
while (tObj > 0)
{
// Exceptions
if (WinInfo(tObj, _WinType) = _WinTypeListColumn or
WinInfo(tObj, _WinType) = _WinTypeGroupColumn or
WinInfo(tObj, _WinType) = _WinTypeTreeNode or
WinInfo(tObj, _WinType) = _WinTypeToolbarButton or
WinInfo(tObj, _WinType) = _WinTypeStatusbar)
cycle;
// Search for sub-objects
tObj->ScaleObject(aPercentW, aPercentH, aWidth, aNewWidth, aNewHeight);
// Exception
if (WinInfo(tObj, _WinType) = _WinTypeGroupTile)
cycle;
// Exception
if (tHasGrouping)
if (WinPropGet(tObj, _WinPropAlignGrouping, tGrouping) and tGrouping != _WinAlignGroupingNone)
cycle;
// Scaling the objects
tArea # tObj->wpArea;
tArea:Left # CnvIF(CnvFI(tArea:Left) * aPercentW);
tArea:Top # CnvIF(CnvFI(tArea:Top) * aPercentH);
tArea:Right # CnvIF(CnvFI(tArea:Right) * aPercentW);
tArea:Bottom # CnvIF(CnvFI(tArea:Bottom) * aPercentH);
tObj->wpArea # tArea;
}
}
Exceptions
However, there are also objects within concept 16 that cannot be scaled. For example, the Column header of a list object is not adjustable in size. Checkbox, Radio button objects and Scrollbox objects are also not scalable. There are currently other points that should be taken into account before scaling frames in order to achieve a perfect result:
- The property
wpAreaClientRestore
must not be set for the frame.
After the frame has been scaled and saved, the property can be set again. - It must be ensured that the same
wpTileTheme
property is used throughout. - All objects should have a certain distance to the edge of the frame.
- The property
wpShowGrip
forToolbar-Button
should be set
Otherwise it could happen that theToolbar-Button
‘changes’ its previous position. - The text of the
labels
should not go beyond the margin. - The font of the
RtfEdit
object should not be changed procedurally.
The procedure presented in the article is available for download at the end of the article.