[Solved] DPI issue when app can't use DPI awareness

Just starting out? Need help? Post your questions and find answers here.
BarryG
Addict
Addict
Posts: 4118
Joined: Thu Apr 18, 2019 8:17 am

[Solved] DPI issue when app can't use DPI awareness

Post by BarryG »

[Edit] Solved - See new post below (https://www.purebasic.fr/english/viewto ... 22#p639722).

Hi all. I am using the following code to copy an image of my 1920x1080 desktop and show it in a window over my real desktop, and it works great at 100% DPI:

Code: Select all

Global w,h

Procedure ScreenshotDesktop()
  ExamineDesktops()
  w=DesktopWidth(0)
  h=DesktopHeight(0)
  hImage=CreateImage(#PB_Any,w,h)
  If hImage
    hDC=StartDrawing(ImageOutput(hImage))
    If hDC
      dt=GetDesktopWindow_()
      dc=GetDC_(dt)
      If dc
        If BitBlt_(hDC,0,0,w,h,dc,0,0,#SRCCOPY)
          ssdesktop=hImage
        EndIf
        ReleaseDC_(dt,dc)
      EndIf
      StopDrawing()
    EndIf
  EndIf
  ProcedureReturn ssdesktop
EndProcedure

ss=ScreenshotDesktop()
StartDrawing(ImageOutput(ss))
DrawText(5,5," This is the captured image ("+Str(ImageWidth(ss))+"x"+Str(ImageHeight(ss))+" / Esc to close) ",#Yellow)
StopDrawing()

OpenWindow(0,0,0,w,h,"",#PB_Window_BorderLess)
ImageGadget(0,0,0,w,h,ImageID(ss))
Repeat : WaitWindowEvent() : Until GetAsyncKeyState_(#VK_ESCAPE)
Now, the problem is when my 1920x1080 desktop is set to 125% DPI or higher. The window that gets overlayed on my desktop doesn't show the full captured image, because the right and bottom sides get cropped. This is despite the image and window being 1920x1080 like my desktop. Here's an example image of it at 125% DPI:

Image

See how the desktop's Start button, taskbar, and system tray items (clock, etc) aren't visible? I know I can turn on DPI-awareness to fix this, but let's pretend that I can't for any given reason. Is there a way to make this image scale properly and not be cropped when DPI awareness is off? As I said, the image is the correct desktop size, but just isn't showing all of itself. :(
Last edited by BarryG on Thu Apr 24, 2025 12:08 pm, edited 2 times in total.
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: DPI issue when app can't use DPI awareness

Post by Michael Vogel »

If you are using Windows, it's not very difficult. Examples are seen in some of my codes here, like this (have a look at ScaleUp and ScaleDown).
BarryG
Addict
Addict
Posts: 4118
Joined: Thu Apr 18, 2019 8:17 am

Re: DPI issue when app can't use DPI awareness

Post by BarryG »

Thanks, Michael. I'm too dumb to understand what you did, but I found a hacky "fix" by simply resizing the image (below). Not the best method but it'll be okay for now. I really have to convert my app to be DPI-aware but it's going to take so much work. :(

Code: Select all

Global w,h

Procedure ScreenshotDesktop()
  ExamineDesktops()
  w=DesktopWidth(0)
  h=DesktopHeight(0)
  hImage=CreateImage(#PB_Any,w,h)
  If hImage
    hDC=StartDrawing(ImageOutput(hImage))
    If hDC
      dt=GetDesktopWindow_()
      dc=GetDC_(dt)
      If dc
        If BitBlt_(hDC,0,0,w,h,dc,0,0,#SRCCOPY)
          ssdesktop=hImage
        EndIf
        ReleaseDC_(dt,dc)
      EndIf
      StopDrawing()
    EndIf
  EndIf
  ResizeImage(ssdesktop,GetSystemMetrics_(#SM_CXSCREEN),GetSystemMetrics_(#SM_CYSCREEN)) ; The hacky "fix".
  ProcedureReturn ssdesktop
EndProcedure

ss=ScreenshotDesktop()
StartDrawing(ImageOutput(ss))
DrawText(5,5," This is the captured image ("+Str(ImageWidth(ss))+"x"+Str(ImageHeight(ss))+" / Esc to close) ",#Yellow)
StopDrawing()

OpenWindow(0,0,0,w,h,"",#PB_Window_BorderLess)
ImageGadget(0,0,0,w,h,ImageID(ss))
Repeat : WaitWindowEvent() : Until GetAsyncKeyState_(#VK_ESCAPE)
Fred
Administrator
Administrator
Posts: 18150
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: [Solved] DPI issue when app can't use DPI awareness

Post by Fred »

I don't think it's that much work, we did the IDE very quickly.
BarryG
Addict
Addict
Posts: 4118
Joined: Thu Apr 18, 2019 8:17 am

Re: [Solved] DPI issue when app can't use DPI awareness

Post by BarryG »

Literally 99% of my app's display and functions get broken when I turn DPI on. :( Gadgets appear too small or large, images aren't the right size, opening a window to the edge of the desktop never works (they go off the edge similar to my first post above), etc. It's a massive re-write to fix it, which is why I haven't done it, and at this stage probably never will.

I started this app years ago before DPI was a thing, which is why it's all broken and incompatible now if I turn DPI on. There's over 65,000 lines of code to go through. :( To anyone writing a new app: turn DPI on and code with it on, so you don't suffer my fate.
fluent
User
User
Posts: 72
Joined: Sun Jan 24, 2021 10:57 am

Re: [Solved] DPI issue when app can't use DPI awareness

Post by fluent »

BarryG wrote: Mon Apr 21, 2025 9:49 am Literally 99% of my app's display and functions get broken when I turn DPI on. :( Gadgets appear too small or large, images aren't the right size, opening a window to the edge of the desktop never works (they go off the edge similar to my first post above), etc. It's a massive re-write to fix it, which is why I haven't done it, and at this stage probably never will.

I started this app years ago before DPI was a thing, which is why it's all broken and incompatible now if I turn DPI on. There's over 65,000 lines of code to go through. :( To anyone writing a new app: turn DPI on and code with it on, so you don't suffer my fate.
Is there an easy tutorial available to adapt an old program to DPI?
Or maybe ChatGPT can help? (just asking.)
PBJim
Enthusiast
Enthusiast
Posts: 293
Joined: Fri Jan 19, 2024 11:56 pm

Re: [Solved] DPI issue when app can't use DPI awareness

Post by PBJim »

BarryG wrote: Mon Apr 21, 2025 9:49 am To anyone writing a new app: turn DPI on and code with it on, so you don't suffer my fate.
I can sympathise with the work involved. As far as I'm aware though, isn't it enabled by default? Or are you referring to changing the Windows scaling factor?

In my experience, PB automatically handles the majority of gadgets when scaling is increased and it still works — for our systems at least — even when the DPI setting in Compiler Options is disabled. The PB manual offers a little on this, although limited background :
Enable DPI Aware Executable (Windows only)
This option enable DPI awareness when creating an executable. That means than [that a] GUI created in
PureBasic will scale automatically if the DPI of the screen is above 100%. Most of the process is
seemless, but some case needs to be worked out, like pixel based gadgets
(ImageGadget, CanvasGadget etc.).
One can take from this, there are some gadgets for which scaling is not performed automatically, but for those exceptions we have the functions DesktopResolutionX() and DesktopResolutionY(), therefore a question of compensating for their size.
BarryG
Addict
Addict
Posts: 4118
Joined: Thu Apr 18, 2019 8:17 am

Re: [Solved] DPI issue when app can't use DPI awareness

Post by BarryG »

PBJim wrote: Tue Apr 22, 2025 9:04 amisn't it enabled by default?
No. And turning it on means you need to change screen coordinates for a lot of stuff. Take the example below. Run it as a compiled exe on a 100% DPI desktop, and the mouse correctly goes over the window's icon. Now turn DPI on for the exe and recompile, and then change your desktop to 125% DPI and run it. The mouse is now way off the window and not where it should be. This is what I mean by turning DPI on breaks my app in major ways. :(

Code: Select all

x=300
y=300
OpenWindow(0,x,y,320,120,"test",#PB_Window_SystemMenu)
SetCursorPos_(x+10,y+10) ; Put the mouse over the window icon.
Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
Yes, this can be "fixed" by using DesktopScaledX() and DesktopScaledY() like below, but that's a hell of a lot of additional coding and typing just to make it work with API commands. PureBasic is requiring us to scale everything with wrappers like this? This is not good.

Code: Select all

x=300
y=300
OpenWindow(0,x,y,320,120,"test",#PB_Window_SystemMenu)
SetCursorPos_(DesktopScaledX(x+10),DesktopScaledY(y+10)) ; To make it work on all DPI scales. :(
Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
I know what you're probably going to say: just use the official PureBasic commands. That's not possible for me because using API calls are a big part of my app for commands that don't exist in PureBasic, such as creating window thumbnails at X/Y/W/H positions, or custom balloon tips at specific X/Y positions. These break with DPI turned on unless I wrap them like above. :(
Fred
Administrator
Administrator
Posts: 18150
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: [Solved] DPI issue when app can't use DPI awareness

Post by Fred »

It's not PureBasic which requires that, but Windows. For example on MacOS you have almost nothing to do for HiDPI screen as the OS takes care of all that. So yes If you use API here and here you need to adjust the coordinates with the desktop commands and your app will work with and without the DPI flags. It's some work but it shouldn't be that big IMHO.
PBJim
Enthusiast
Enthusiast
Posts: 293
Joined: Fri Jan 19, 2024 11:56 pm

Re: [Solved] DPI issue when app can't use DPI awareness

Post by PBJim »

No, I accept what you say, with regard to external APIs. I don't think there's any easy way Barry mate, with a sizable application that's been developed over a long period, there's sometimes going to be tasks like this, as part of its lifecycle. I'm sure it's a task that becomes easier as you work through it.

I suspect that on my system, the graphics card is doing the scaling, because the mouse position is spot-on at the icon every time, as marked with the arrow below. This would account for everything being consistently upscaled to 125% — regardless of the compiler option "DPI aware".

Image
BarryG
Addict
Addict
Posts: 4118
Joined: Thu Apr 18, 2019 8:17 am

Re: [Solved] DPI issue when app can't use DPI awareness

Post by BarryG »

Fred wrote: Tue Apr 22, 2025 1:55 pmIf you use API here and here you need to adjust the coordinates with the desktop commands and your app will work with and without the DPI flags. It's some work but it shouldn't be that big IMHO.
You underestimate how many API commands that use screen coords that my app has. :lol:

@PBJim: You're lucky. Every PC that I try it on, gives the wrong coords when DPI is on for the built exe.
User avatar
kenmo
Addict
Addict
Posts: 2032
Joined: Tue Dec 23, 2003 3:54 am

Re: [Solved] DPI issue when app can't use DPI awareness

Post by kenmo »

Rather than change hundreds of lines of your code, you can use Macro wrappers to scale each API function "once"...

Example...

Code: Select all

CompilerIf (#PB_Compiler_DPIAware)

Procedure SetCursorPos_DPI_(X, Y)
  SetCursorPos_(DesktopScaledX(X), DesktopScaledY(Y))
EndProcedure
Macro SetCursorPos_(X, Y)
  SetCursorPos_DPI_((X), (Y))
EndMacro

CompilerEndIf


SetCursorPos_(100, 100)
BarryG
Addict
Addict
Posts: 4118
Joined: Thu Apr 18, 2019 8:17 am

Re: [Solved] DPI issue when app can't use DPI awareness

Post by BarryG »

Thanks, Kenmo. I totally forgot about wrapping with macros. That should definitely make things a LOT easier! 8)
BarryG
Addict
Addict
Posts: 4118
Joined: Thu Apr 18, 2019 8:17 am

Re: [Solved] DPI issue when app can't use DPI awareness

Post by BarryG »

DPI TRULY SOLVED!

I just found out I can write a Registry setting to make my non-DPI exe work perfectly scaled on any DPI system setting! :D

I just added a string entry to my exe's location like this, with the data value shown:

Image

Here's the Registry section for easy copying:

Code: Select all

Computer\HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers
So I just made my app check on start if that entry exists, and if not, it writes it and then restarts itself. Works perfect! Now there's no need for me to change anything in my app to make everything scale and look good on any DPI setting! It also solves all issues with SetCursorPos_() and so on, and I don't need to wrap macros with DesktopScaledX() and such. So happy. :) Sometimes Microsoft does do things right!

How it works: What this Registry setting does is simply changes the DPI setting of the exe to the below. The user could do this manually by right-clicking the exe and going into the Compatibility properties page, but making the exe do it is more user-friendly. Hope this info helps someone in future. :)

Image
PBJim
Enthusiast
Enthusiast
Posts: 293
Joined: Fri Jan 19, 2024 11:56 pm

Re: [Solved] DPI issue when app can't use DPI awareness

Post by PBJim »

What you've actually shown there, Barry, is a newish DPI function in Windows. On all our systems, we have the below Compatibility tab — which is different from your example.

Image

If I select the disable option, it creates the same registry value and data as you've shown — ~ HIGHDPIAWARE — but it doesn't behave the same way as yours, if that option isn't ticked. Our Windows systems, which are a mix of Server and Windows 10, scale everything regardless even when PureBasic's DPI compiler option isn't chosen, whereas you've found your application was broken by the setting in the compiler, combined with scaling at 125%.

The appearance is not satisfactory though, as shown below left, with original on right. It affects drawing clarity and I would think that coding it properly is better, because you're then retaining the fine resolution of the GUI drawing, without distorting it, but you adjust the size of certain graphical objects to compensate for variation in monitor size.

Image
Post Reply