×
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Contact US

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Students Click Here

Get application’s DPI Awareness
2

Get application’s DPI Awareness

Get application’s DPI Awareness

(OP)
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

RE: Get application’s DPI Awareness

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.

RE: Get application’s DPI Awareness

(OP)
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

RE: Get application’s DPI Awareness

Hi,

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

Thanks,
Stanley

RE: Get application’s DPI Awareness

Hi,

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

Quote:

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

RE: Get application’s DPI Awareness

Stanley,

Quote (Stanlyn)

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.

RE: Get application’s DPI Awareness

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

RE: Get application’s DPI Awareness

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.

RE: Get application’s DPI Awareness

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

RE: Get application’s DPI Awareness

Quote (Chriss)

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

RE: Get application’s DPI Awareness

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, ....


RE: Get application’s DPI Awareness

Quote:

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.

Quote:

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.

Quote:

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.

Quote:

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?

Quote:

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

RE: Get application’s DPI Awareness

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: https://github.com/atlopes/DPIAwareManager.

RE: Get application’s DPI Awareness

(OP)
Hi Antonio,

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

Regards, Gerrit

RE: Get application’s DPI Awareness

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...

RE: Get application’s DPI Awareness

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

RE: Get application’s DPI Awareness

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.

RE: Get application’s DPI Awareness

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

RE: Get application’s DPI Awareness

(OP)
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

RE: Get application’s DPI Awareness

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

RE: Get application’s DPI Awareness

(OP)
A small update from my side.

I set the dpi awareness now back to FALSE in my manifest. I have used TRUE for some days. On a full HD screen this looked OK, but on my 4K laptop screen it is dpi aware indeed and all forms are way too small. For normal readability a 200% scaling is requited on a 4K screen. And you cannot use any compatibility setting in the application’s shortcut for this. A full HD form with 1920 x 1080 pixels will still only use 25% of the screen...

I will do some testing soon with Antonio’s code “as is”.

A 4K screen resolution is still presenting a lot of challenges for a lot of commercial programs too, even though they look fine on a full HD screen. I’m still learning how to deal with this and checking all options.

Regards, Gerrit

RE: Get application’s DPI Awareness

Gerrit,

Thank you for testing. There is still a lot of things to test and address, and your input will be precious.

A few things to note:
  1. Some graphic elements are outside the range of action of the DPI manager class: browse windows, the status bar, the Wait window (they will come small), and message boxes (Windows will scale these, making them blurry - I will try with Cesar's Foxydialog and see how a DPI-aware application renders it).
  2. The system menu requires special handling. It can be resized to higher scales, but the menu must be completely rebuilt when the DPI scale changes. I left an example (for just one of the system menu pads) in the test application.
  3. Adding controls at runtime can be done, but to put them under DPI-aware management, the manager must know about them. There is also an example of a DPIAwareOptionGroup subclass in the DPIAwareManager code. It may be used as a template.
  4. Grids scaling needs to be revisited. Some of the grid elements will not scale or not in the same manner (the record mark, the delete mark, panel separators, and the scroll bars). If the overall grid width scales (for instance, 1.5 times), these elements not scaling means extra space for the columns that will not be used. The grid resizing (whether growing or shrinking) must take this into account.
That said, the class is gaining some muscle, and I believe it will become usable eventually.

RE: Get application’s DPI Awareness

Gerrit,

what I suggested was using dpi awareness, and when your forms are okay with HD (1980x1080) or any resolution you know, then start them in that size (instead of fullscreen), afterwards (late, in the first form activate) maximize them and have a traditional resizer, which just enlarges every control width and height and font sizes. The end result then is good. The moment to change to fullscreen can be the first forms activate. That's the easiest way to deal with high resolutions.

Edit: If 200% scaling from Windows are activated, you have to counteract that, because the form design for HD will be best with 100% scaling and that means your fontsize scaling factor should be
actual width/(initial width * windows scaling factor). In case the resolution is double size and the scaling is set to 200%, the effective factor is even just 1, the 200% scaling is then often also recommended by the laptop or (embedded) graphics vendor to not use the high resolution for more text, but simply crisper higher resolution fonts, icons, etc. and when your app is dpi aware Windows will make the fonts double sized (quadruple area) but not change form and control dimensions, that's your only job, then.

Chriss

RE: Get application’s DPI Awareness

Gerrit,

For some reason, I couldn't upload images in the above message as I wanted to illustrate some of the current DPIAwareManager class capabilities.

Meanwhile, I tried running FoxyDialog() in a DPI-aware application to replace MessageBox, and the result is also shown below.



This is a screenshot of an application running @ 150% DPI scale. The points to note:
  • Fonts of menu pads are scaled (this is controlled by a _Screen object that receives information from the DPI manager when a change of scale occurs).
  • The label "hWnd" reacts to the change of scales in a particular fashion. The control displays its caption in orange bold when the DPI scale is not 100%. This demonstrates that controls can incorporate their own processing to complement or replace what is done by the DPI Manager.
  • Images can have an alternate picture to replace the ones targeted at the standard DPI. VFP scales the Image control on the left from a 96x96 image. The one on the right starts with the same image, but the Manager replaces it with a 528x528 image when the scale goes up to 150% and beyond.
Finally, a standard MESSAGEBOX() in a High DPI monitor, scaling to 150% (note the blurriness of the dialog contents, contrasting with the sharpness of the title),



and a FoxyDialog() at the same DPI scale



RE: Get application’s DPI Awareness

Thanks Antonio. Looks like the FoxyDialog is the way to go. This is an important subject and probably the greatest challenge for VFP application development. I hope this thread continues to be updated.

For the sake of this discussion, I will not use the term "DPI Aware" because VFP is not DPI Aware and any effort to make VFP DPI Aware by means of a manifest or SetProcessDPIAware() is useless. It is better to refer to the ability of VFP to properly resize objects, fonts, menus, etc. by means of specialized classes.

We are doing some "best practice" research on this subject: For the last few years, most business OEMs (e.g. Dell, HP, Lenov) have been offering two monitor resolutions for laptops and desktops: 1920x1080 and 3840x2160 (4k). There are also gamer machines with 2560x1440 and 3440x1440 resolutions. These are the important resolutions to be concerned about. To perform effective "resizing", the developer has to start with the lowest common denominator with respect to the development environment: A 1920x1080 (96 dpi) monitor. Any developed application (before resizing) can never exceed a total of 1280x720 pixels - including forms, toolbars and menus. Here is why:

Resolution / Max DPI Scaling = Lowest Dev Resolution
1920x1080 ./ Divide by 150% ... = 1280x720
2560x1440 ./ Divide by 200% ... = 1280x720
3440x1440 ./ Divide by 200% ... = 1720x720
3840x2160 ./ Divide by 200% ... = 1920x1080

The maximum resizing factor (DPI scaling) has to be accounted for to determine the lowest common denominator for the development environment. As shown above, that is 1280x720. This also means that application development for 1920x1080 (96 dpi) monitors is restricted to 1280x720 - yikes, we don't like that!

Of course, this is a broad stroke and does not take into account screen resolutions lower than 1920x1080. However, it may be a good map for the future.

RE: Get application’s DPI Awareness

Vernpace,

An application is DPI-aware as long as it can recognize the state and changes of DPI settings in display devices it is using as output and react accordingly by adjusting to the DPI scale setting of the device. Of course, this meaning allowing and be prepared for its screen and top-level forms to move from one device to another and move from a DPI setting to another.

What Windows expects from a DPI-aware application is laid down here: https://docs.microsoft.com/en-us/windows/win32/hid.... The goal of the DPIAwareManager class is to support "Per-Monitor and Per-Monitor (V2) DPI Awareness". As I pointed out, VFP imposes a few limitations, but those seem marginal and even replaceable.

The class is already honoring the DPI-awareness declaration of the application and, in general, performing as specified. For instance, a form displaying on a device with a DPI scale of 100% can be moved to a monitor with a different scale and automatically resize its objects to support the new settings. The same reaction if the monitor on which it is displaying changes its DPI settings. By using the DPIAwareManager class, or something like it in its place, a VFP9 application can not only be fully DPI-aware but also dynamically DPI-aware.

The manifest is the opposite of being useless. Not only it allows the VFP9 application to take control of the rendering of most of its graphical elements and improve the quality of the process, but it also guarantees that reports using the 90 behavior are properly rendered, without misalignments and printing off-margins.

RE: Get application’s DPI Awareness

Vernpace,

Good reading, thank you. I will check on how GDI scaling affects VFP9 applications, and the output of the report engine in particular (since it's a GDI issue, in the first place).

RE: Get application’s DPI Awareness

Antonio,

One thing to keep in mind is that VFP developers (like us) use GDIPlusX and FoxCharts extensively and not necessarily in reports. Also, the Image control's PictureVal uses GDI+. Not sure what else, but proper GDI+ rendering can be just as important. What is not clear in the docs is whether GDI Scaling can coexist with DPI Scaling

RE: Get application’s DPI Awareness

Antonio,

What you are doing is extremely interesting. Question: Since your DPIAwareManager class will support "Per-Monitor and Per-Monitor (V2) DPI Awareness", will you implement the use of WM_DPICHANGED message structures for HWND notifications?

RE: Get application’s DPI Awareness

Vernpace,

I haven't tried yet with FoxCharts, nor with ActiveX controls. I have access to two different versions of TextControl, for instance, the older one is not DPI-aware, the more recent is. It will be interesting to see how they behave.

The manager reacts to WM_DPICHANGED messages. That's how it senses a change for top-level forms. With the _Screen is a bit different, but this may change in the future.

Anyway, remember that you can accompany (or contribute!) the development of the manager at https://github.com/atlopes/DPIAwareManager, or use its ideas to incorporate into something completely different and that best matches your own framework.

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members! Already a Member? Login


Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close