Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Get application’s DPI Awareness 2

Status
Not open for further replies.

Gerrit Broekhuis

Programmer
Aug 16, 2004
316
NL
Hi,

I know it’s best to set an application’s DPI Awareness with a myapp.exe.manifest file (and that is what I do indeed).

Another - less effective - way is to use WIN32API and call SetProcessDPIAware().

I would like to know if there is something like “GetProcessDPiAware()”, to get the DPI awareness from within an application.
This would verify the DPI Awareness is set correctly.

Or is there another logical check for DPI Awareness? I don’t want to rely on visual verification, as most customers don’t notice any difference.

Regards, Gerrit
 
Gerrit,

Don't know if you can use this:

Code:
DECLARE INTEGER GetDC IN user32.dll ;
        INTEGER hwnd
DECLARE INTEGER GetDeviceCaps IN gdi32.dll ;
        INTEGER hdc, INTEGER nIndex
DECLARE INTEGER ReleaseDC IN user32.dll ;
        INTEGER hwnd, INTEGER hdc

#DEFINE LOGPIXELSX 88

hdc = GetDC(0)
ScreenDPI = GetDeviceCaps(hdc, LOGPIXELSX)
ReleaseDC(0, hdc )

ScreenDPI returns the numeric value of the screen DPI. Since VFP is not DPI aware, if ScreenDPI > 96 then you know that DPI awareness may be required. However, I don't know of a way to query if DPI awareness has been applied (e.g. via application manifest) after the fact.
 
Thanks Verne,

I will do some testing with this.

On another VFP Forum Marco Plaze mentioned this:

DECLARE IsProcessDPIAware IN user32.dll
? isProcessDPIAware()

This works fine. I do have a manifest in place and with Microsoft’s MT.EXE I can extract the manifest, to check it’s identical to the manifest file I added to my .EXE.

Regards, Gerrit
 
Hi,

What is DPI awareness and how does it involve our apps?

Thanks,
Stanley
 
Hi,

I found this to help answer my own question, which raises more questions.

What is system DPI awareness mode?
Effectively, System DPI-aware desktop applications only render crisply at a single display scale factor, becoming blurry whenever the DPI changes. It is recommended that desktop applications be updated to use per-monitor DPI awareness mode, allowing them to immediately render correctly whenever the DPI changes.

Does this mean that we should develop for a specific screen resolution or dpi in mind? Or is it a "get the right hardware" for our app? When does this become an issue and how do we identify and know it is a dpi issue?

Thanks, Stanley
 
Stanley,

Stanlyn said:
When does this become an issue and how do we identify and know it is a dpi issue?

For VFP9 applications, it becomes an issue when they are running in monitors that have the resolution scaled by Windows (to 125%, 150%, and so on).

The forms and all graphic objects in these applications are automatically scaled to match the monitor scaling and lose quality in the process (as expected). Furthermore, when the Report Engine Behavior is set to 90, objects in the report form will be misaligned and their sizes mixed up.

An immediate solution is to tell Windows not to touch the graphics (in forms or reports). We declare that our application is "DPI Aware", meaning that the application itself will do any scaling to be done.

The good news is that the graphic objects will be rendered as designed (except for menus and title bars, which Windows always handle in VFP9 applications).

The bad news is that we are not honoring the user's preference. In High DPI monitors, this will mean that our forms will be small compared to others (the contrast will be more significant as scaling gets higher).

The solution is to declare that the application is DPI-aware and make it DPI-aware by scaling all objects in a form (no problems with the reports, since they work in a fixed dimension).

We design once, for 96 DPI (or 100% scaling), and redimension and reposition the objects in a form as the DPI scale changes.

I'm working in a DPIAwareManager class to help VFP9 application with this in the most transparent way possible. I'll make the results public when the class achieves a reasonable state of efficiency.
 
I observe the opposite. Not DPI-aware applications become blurry, because the system cares for these apps and scales up their graphics, which become blurry that way.

Telling your app is dpi aware means you have to do this upscaling yourself. If you don't, your fonts become smaller, but stay crisp.
If using Olecontrols, they can adapt to the system scale factor themselves. To care for the VFP controls you use DeveiceCaps to get the (virtual) dpi and adapt to it.

The terminology isn't very good, as the actual hardware DPI doesn't change. The user decides a scale factor. What complicates things is very high-resolution displays (retina) do report half their real solution, but that's a thing I only ever read about Apple devices.




Chriss
 
We have DPI scaling built into all UI classes of our framework, except for ActiveX controls. However, DPI scaling can be problematic. Consider the following scenario:

The developer designs an application using a 1920x1080 monitor on a 96 DPI (100%) computer. 1920x1080 then becomes the base from which DPI scaling is calculated. Say there is a user with a 1920x1080 monitor with Windows scaling at 150%. The result is that the application is scaled up 50% when it should not have been, unless the scaling algo checks for user's monitor size (using SYSMETRIC(1) and SYSMETRIC(2)) and prevents scaling as part of the process.

There are many scenarios which have to be taken into account when building DPI awareness into VFP applications. We have not accounted for all of them because it requires testing for all monitor resolutions, DPI scaling factors, developer environments, etc.
 
Not doing anything about scaling is just a starting point - the easiest thing to do. You surely need to react to settings of the user. In your example, you'd need to accept the user's choice to want larger text, so perhaps act as if the actual resolution is lower.

You have to determine the scaling factor, not just the screen resolution, and for that GetDEviceCaps is the way to go.

Anyway, fonts always stay crispy when you just set your application as dpi aware, at least in my experience. And what Stanlyn found was stating the opposite.

What you have to deal with is labels getting too large text, for example, so resize controls to have higher headers, less rows, etc. to adjust for that, not scale down the fontsize to compensate for the scaling factor. Another thing is to make your application an exception to the Windows scaling, which can also be decided for single applications.


Chriss
 
Chriss said:
Another thing is to make your application an exception to the Windows scaling, which can also be decided for single applications.
So creating an exception for the app is done where and how. If inside the app, what commands? If outside, then we would be asking the user to change their env, which is not good.

So what is it you're actually doing? In the main startup .prg you detect the env, how? After that, you do what? and to what? Do you change some setting somewhere, or completely resize the forms and controls via code?

Do build your forms at different screen settings until the look good and save all the objects dimensions and at runtime resize them all based on what the env is?

I use and develop at 125% on three 1920 x 1080 monitors and haven't noticed anything unusual, and now I'm wondering what I may be missing?

So, is the best starting point is get back to 100% and just change the resolutions to a comfortable setting?

Stanley

 
Hello,

we set dpiaware on startup.

We use a resizer in form classes which makes fonts bigger/smaller (not the text box for example), for grids users can choose between more columns or bigger font.
And we have buttons in our titlebarclass to make fonts bigger/smaller.

All settings are stored per user and checked if used in other resolutions on another machine.

So it may be not the same scaling as per setting in windows, but User like this with 100%,150%, ... on any resolution
because it allows them to have forms made bigger and forms untouched at the same time on screen to save space.
And they can adopt it to their needs if using multiple monitors, even with different scalings.


Regards
tom

P.S.: There are many resizers, for example mwresize, stretch, ....


 
So creating an exception for the app is done where and how. If inside the app, what commands? If outside, then we would be asking the user to change their env, which is not good.

Look into the compatibility tab of your exe. There's a button for advanced options about DPI settings. So it's neither code nor the env setting of Windows, it's becoming a direct property of your EXE.

So what is it you're actually doing? In the main startup .prg you detect the env, how? After that, you do what? and to what? Do you change some setting somewhere, or completely resize the forms and controls via code?

When you do that, your app does not need to change at all to stay crisp. Well, you have to have your strategy for resizing to the screen size by anchroing or a resizer or your own resize methods, but you're not confronted with a DPI scaling that differs from the hardware DPI, which obviously can't change.

Do build your forms at different screen settings until the look good and save all the objects dimensions and at runtime resize them all based on what the env is?
See above, what you then do with different screen sizes is up to you, anchor or resize, but you don't have to deal with blurried fonts.

I use and develop at 125% on three 1920 x 1080 monitors and haven't noticed anything unusual, and now I'm wondering what I may be missing?
Well, do you have reading glasses which can show you how crisp the display really is? If you scale up to 125% VFPs IDE looks blurried, too, and as I just test it now, the tabs of a project manager window are using a very pixelated font. I can't help you to see it, if you don't. You're not working with an old CRT monitor, do you?

So, is the best starting point is get back to 100% and just change the resolutions to a comfortable setting?
Staying with 100% means the least work to do for adaption to the screen size. Setting the resolution to anything but the native resolution of the screen again only leads to blurried texts. So, no. You then still need a resizer, but it doen't need to handle the dpi awareness aspect anymore.

All that said, obviously you can only really adapt your application to the users wish for larger fonts by making it completely dpi aware, and then the beter option is not to rely on the system enhancing this aspect. Though once you decide your application to be an exception from the general scaling factor you have several choices of handling scaling yourself or use a system default scaling method or set advanced options.

Chriss
 
I've been working in a DPI Aware Manager class to facilitate the creation of real DPI Aware VFP applications.

Its goal is to use in a per-monitor variety scenario, meaning that the VFP Screen and top-level forms can be moved around different monitors with different DPI scales and adjust their dimensional and positional properties accordingly.

Depending on how your framework handles forms, adding the Manager to the application can be easy or even transparent (in our case, besides adding the class to the project, it means adding a line of code - in most cases, forms aren't touched at all).

Nevertheless, it's a work in progress and at its early stages.

But it's already demonstrable, and you can test with your own (self-contained) forms to see the results:
 
Hi Antonio,

Thanks for sharing. I will definitely look into this, it looks very promising.

Regards, Gerrit
 
Atlopes, all the best for your DPI Aware Manager project.

One of the problems we are having with our DPI scaling is with fonts. For example, a 300x22 (300 pixel Width x 22 pixel Height) Textbox can easily be scaled to 450x33 for DPI scaling of 150%. However, a FontSize of 9 cannot be scaled 150% to 13.5, so a FontSize of either 13 or 14 must be used. This produces a Textbox where the text is not vertically aligned properly at runtime. We tried playing with the Margin property, but with limited success. So, when developing DPI aware applications, the delevoper should never use font sizes that are odd numbers.

Another restriction (and a major one) is that the developer can be limited to form Width and Height sizes for DPI aware applications. For example, if a developer using a 96 DPI (100%) 1920x1080 monitor wants his/her applications to be able to scale 150% on 1920x1080 monitors, original form sizes can never exceed 1280x720. While some of you think this is no big deal, it could be depending on customer requirements.

The bottom line is that DPI aware application development is far from clear-cut. Users can have a variety of monitor resolutions and DPI scale factor combinations and you may never know how well your DPI scaling is working because users may never tell you - just like many users never report bugs, they just figure out work-arounds...
 
I agree with vernspace - requirements can differ very much. Like you can decide for using more space for more rows in grids and listboxes as VFPs Anchoring does, or just try to scale up everything.

When the aspect ratio changes from 4:3 to 16:9 and on top of that the physical display size becomes even smaller (like tablets) yet with higher resolution (160 or higher dpi) you may really just want to resize by scaling everything up, but also need to adapt to wider aspect ratios.

I also envy the support of fractional font sizes in other languages. Or alignment based on a fonts baseline instead of top/bottom position of buttons and labels, for example.

Chriss
 
vernpace and Chris, those are good points.

If there are any specific requirements, a container may already disable the DPI awareness process for itself (can even do that during runtime, for some weird effects). Taking into account your much-appreciated remarks, I'm introducing a hook to let containers and controls do their own processing while benefiting from the environment that the manager provides, especially its DPI sensors.
 
Good idea, a dpi aware container base class would be nice to use for sections of a form and also is the usual way to anchor locally to container borders instead of form borders.

Chriss
 
Antonio,

As most of us have developed quite a few applications and forms so far I would like you to keep in mind that it would be nice to be able to add the dpi-awareness “thing” to existing forms. Sort of a “retrofit” solution. I understand this may be difficult, with so many controls, anchors and (re)sizing classes being around.

This could make many existing solutions benefit.

Please keep us informed.

Regards, Gerrit
 
Yes, considering existing applications already have a resizing behavior OK for no scaling (the default 100% setting), one way to keep this would be to start a form with a default size using these already existing mechanisms - whatever they are - in a first stage.

Before that second stage, the form should be okay, just not full screen yet. So the second stage can concentrate on resizing with all anchors raised (set to 0), resizing form and containers and font sizes in a purely zooming/magnifying manner.




Chriss
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top