It is currently Wed May 27, 2020 1:51 pm

All times are UTC + 1 hour




Post new topic Reply to topic  [ 12 posts ] 
Author Message
 Post subject: Important tip: getting the desktop resolution
PostPosted: Sat May 27, 2017 1:48 am 
Offline
Addict
Addict

Joined: Mon Feb 16, 2015 2:49 pm
Posts: 1907
Just discovered this weird issue (bug?) with the GetSystemMetrics_() API on Windows.

My PC's desktop is 1280 x 1024 pixels. I normally use GetSystemMetrics_() to get the width and height of it, and it normally correctly returns 1280 and 1024 accordingly; however today I switched to Large fonts (150%) and noted the results were now incorrect. :( So a tip / heads-up to anyone using GetSystemMetrics_(): drop it!

[Edit] I advocated using ExamineDesktops() instead, but discovered today for myself that it's totally unreliable; so see my new post further below which works reliably instead. For me, anyway. ;)


Last edited by Dude on Wed May 31, 2017 12:14 pm, edited 2 times in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: Important tip: getting the desktop resolution
PostPosted: Mon May 29, 2017 10:56 am 
Offline
PureBasic Expert
PureBasic Expert
User avatar

Joined: Sat May 17, 2003 11:31 am
Posts: 6073
Yup. But even then output isn't always consistent.

http://www.ninelizards.com/purebasic/pu ... 17.htm#top

Once you start messing with DPI settings even DesktopWidth() can give you the wrong number...

_________________
( PB5.xx Win10 x64 Asrock AB350 Pro4 Ryzen 1600X 32GB RAM Evo 840 GTX1060 )
( The path to enlightenment and the PureBasic Survival Guide right here... )


Top
 Profile  
Reply with quote  
 Post subject: Re: Important tip: getting the desktop resolution
PostPosted: Mon May 29, 2017 12:21 pm 
Offline
Addict
Addict

Joined: Mon Feb 16, 2015 2:49 pm
Posts: 1907
blueznl wrote:
Once you start messing with DPI settings even DesktopWidth() can give you the wrong number...

So how can we 100% reliably get the desktop size? Take a screenshot and check the image w/h? That works, but it's damn overkill...


Top
 Profile  
Reply with quote  
 Post subject: Re: Important tip: getting the desktop resolution
PostPosted: Mon May 29, 2017 1:50 pm 
Offline
PureBasic Expert
PureBasic Expert
User avatar

Joined: Sat May 17, 2003 11:31 am
Posts: 6073
Dude wrote:
blueznl wrote:
Once you start messing with DPI settings even DesktopWidth() can give you the wrong number...

So how can we 100% reliably get the desktop size? Take a screenshot and check the image w/h? That works, but it's damn overkill...


Dunno :-)

There's probably a good way to do it, but if there is not one way would be to create an invisible window and make it maximised, then get its size, that would probably work regardless of settings.

You'd still have to accommodate for font size versus DPI issues, I guess. It's a mess, this whole DPI thing on Windows. I haven't worked out the changes in Windows 10 yet, have been very busy with all sorts of (shock!) non-purebasic things :-)

_________________
( PB5.xx Win10 x64 Asrock AB350 Pro4 Ryzen 1600X 32GB RAM Evo 840 GTX1060 )
( The path to enlightenment and the PureBasic Survival Guide right here... )


Top
 Profile  
Reply with quote  
 Post subject: Re: Important tip: getting the desktop resolution
PostPosted: Wed May 31, 2017 12:12 pm 
Offline
Addict
Addict

Joined: Mon Feb 16, 2015 2:49 pm
Posts: 1907
[Deleted as was pointless]


Last edited by Dude on Sun Sep 24, 2017 8:01 am, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: Important tip: getting the desktop resolution
PostPosted: Wed May 31, 2017 1:51 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sat May 05, 2007 5:31 pm
Posts: 731
Location: Linz, Austria
Quote:
I normally use GetSystemMetrics_() to get the width and height of it, and it normally correctly returns 1280 and 1024 accordingly; however today I switched to Large fonts (150%) and noted the results were now incorrect.
The important thing here is, you MUST build your program DPI-Aware! GetSystemMetrics_(), GetDeviceCaps_(), ... return wrong values if you don't.

Just check following sample and comment/uncomment the OpenLibrary part:
Code:
Global txt$

Procedure _IsProcessDPIAware() : EndProcedure
Prototype _IsProcessDPIAware()

Procedure _SetProcessDPIAware() : EndProcedure
Prototype _SetProcessDPIAware()

Define user32 = OpenLibrary(#PB_Any, "user32.dll")
If user32
  Define IsProcessDPIAware__._IsProcessDPIAware = GetFunction(user32, "IsProcessDPIAware")
  If IsProcessDPIAware__ = 0 : IsProcessDPIAware__ = @_IsProcessDPIAware() : EndIf
 
  Define SetProcessDPIAware__._SetProcessDPIAware = GetFunction(user32, "SetProcessDPIAware")
  If SetProcessDPIAware__ = 0 : SetProcessDPIAware__ = @_SetProcessDPIAware() : EndIf
 
  If IsProcessDPIAware__() = #False
    SetProcessDPIAware__()
  EndIf
 
  CloseLibrary(user32)
EndIf


Procedure MonitorEnumProc(hMonitor, hdcMonitor, lprcMonitor, dwData)
 
  ;Protected mi.MONITORINFOEX\cbSize = SizeOf(MONITORINFOEX)
  ;GetMonitorInfo_(hMonitor, mi)
  ;Debug PeekS(@mi\szDevice)   
 
  Protected *monRect.RECT = lprcMonitor
  txt$ +  "hMon: " + Chr(9) + Str(hMonitor) +Chr(10)
  txt$ +  "left: " + Chr(9) + *monRect\left +Chr(10)
  txt$ +  "top: " + Chr(9) + *monRect\top +Chr(10)
  txt$ +  "right: " + Chr(9) + *monRect\right +Chr(10)
  txt$ +  "bottom: " + Chr(9) + *monRect\bottom +Chr(10) +Chr(10)
 
  ProcedureReturn #True
EndProcedure

;Debug MonitorFromWindow_(66560, #MONITOR_DEFAULTTONEAREST)

txt$ + "DPI: " + Str(GetDeviceCaps_(GetDC_(0), #LOGPIXELSX)) +Chr(10) +Chr(10)

txt$ +  "SystemMetrics W: " + Chr(9) + GetSystemMetrics_(0) +Chr(10)
txt$ +  "SystemMetrics H: " + Chr(9) + GetSystemMetrics_(1) +Chr(10) +Chr(10)

ExamineDesktops()
txt$ +  "DesktopWidth: " + Chr(9) + DesktopWidth(0) +Chr(10)
txt$ +  "DesktopHeight: " + Chr(9) + DesktopHeight(0) +Chr(10) +Chr(10)

EnumDisplayMonitors_(#Null, #Null, @MonitorEnumProc(), 0)

MessageRequester("", txt$)


I still don't know why DPI-awareness isn't handled automatically by PB...


Top
 Profile  
Reply with quote  
 Post subject: Re: Important tip: getting the desktop resolution
PostPosted: Tue Jun 13, 2017 1:31 pm 
Offline
Addict
Addict

Joined: Mon Feb 16, 2015 2:49 pm
Posts: 1907
Dude wrote:
The error said something like "ExamineDesktops() must be called before DesktopWidth()" or such... which is weird because I did it already. :shock:

Here's my bug report about this, and screenshot as proof:

viewtopic.php?f=4&t=68632


Top
 Profile  
Reply with quote  
 Post subject: Re: Important tip: getting the desktop resolution
PostPosted: Sun Sep 24, 2017 5:20 am 
Offline
Addict
Addict

Joined: Mon Nov 25, 2013 6:41 am
Posts: 811
Do you have the same behavior in ekzaminedesktop?
Returns the width and height is not correct.
if you uncomment the lines then it starts to return correctly.

Code:
; ; Uncomment ExamineDesktops work very good
; Debug "DPI: " + Str(GetDeviceCaps_(GetDC_(#Null), #LOGPIXELSX)) ; 96
; Procedure _IsProcessDPIAware() : EndProcedure
; Prototype _IsProcessDPIAware()
;
; Procedure _SetProcessDPIAware() : EndProcedure
; Prototype _SetProcessDPIAware()
;
; Define user32 = OpenLibrary(#PB_Any, "user32.dll")
; If user32
;   Define IsProcessDPIAware__._IsProcessDPIAware = GetFunction(user32, "IsProcessDPIAware")
;   If IsProcessDPIAware__ = 0 : IsProcessDPIAware__ = @_IsProcessDPIAware() : EndIf
;   
;   Define SetProcessDPIAware__._SetProcessDPIAware = GetFunction(user32, "SetProcessDPIAware")
;   If SetProcessDPIAware__ = 0 : SetProcessDPIAware__ = @_SetProcessDPIAware() : EndIf
;   
;   If IsProcessDPIAware__() = #False
;     SetProcessDPIAware__()
;   EndIf
;   
;   CloseLibrary(user32)
; EndIf


Debug "DPI: " + Str(GetDeviceCaps_(GetDC_(#Null), #LOGPIXELSX)) ; 96 if uncomment 120
;// Для получения разрешения экрана  напишите следующий код:
hDCScreen =  GetDC_(#Null);
Horres.i = GetDeviceCaps_(hDCScreen,  #HORZRES);
Vertres.i = GetDeviceCaps_(hDCScreen,  #VERTRES);
ReleaseDC_(#Null, hDCScreen);
;// в Horres  содержится разрешение экрана по горизонтали,
;// в Vertres содержится  разрешение экрана по вертикали.

If OpenWindow(0,0,0,500,250,"Window 0")
ButtonGadget(-1, 10,10,80,30,"Button")
   ResizeWindow(0, (Horres-WindowWidth(0, #PB_Window_FrameCoordinate))/2, (Vertres-WindowHeight(0, #PB_Window_FrameCoordinate))/2, #PB_Ignore, #PB_Ignore)
EndIf

Horres.i = GetSystemMetrics_(#SM_CXSCREEN)
Vertres.i = GetSystemMetrics_(#SM_CYSCREEN)
If OpenWindow(20,0,0,500,250,"Window 20")
ButtonGadget(-1, 10,10,80,30,"Button")
   ResizeWindow(20, (Horres-WindowWidth(20, #PB_Window_FrameCoordinate))/2, (Vertres-WindowHeight(20, #PB_Window_FrameCoordinate))/2, #PB_Ignore, #PB_Ignore)
EndIf

ExamineDesktops()
If OpenWindow(10,0,0,500,250,"Window 10")
  ButtonGadget(-1, 10,10,80,30,"Button")
 ResizeWindow(10, (DesktopWidth(0)-WindowWidth(10, #PB_Window_FrameCoordinate))/2, (DesktopHeight(0)-WindowHeight(10, #PB_Window_FrameCoordinate))/2, #PB_Ignore, #PB_Ignore)
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf


Last edited by mestnyi on Sun Sep 24, 2017 6:48 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: Important tip: getting the desktop resolution
PostPosted: Sun Sep 24, 2017 5:49 pm 
Offline
Addict
Addict
User avatar

Joined: Tue Mar 21, 2006 12:31 am
Posts: 1773
Location: Canada
PureBasic language doesn't do 'natively' DPI-aware applications. chi called it!
Really no reason why PB shouldn't now be supporting it natively.

I've personally observed visual issues making applications with PureBasic which aren't DPI-Aware. To quote from Microsoft page.

"Applications that are not DPI–aware but are running on a high-DPI display setting can suffer from many visual artifacts, including incorrect scaling of UI elements, clipped text, and blurry images. By adding support in your application for DPI awareness, you ensure that the presentation of your application's UI is more predictable, making it more visually appealing to users. This gives the user the best possible experience on any display."


GetSystemMetrics_(), GetDeviceCaps_()... is returning logical vs. physical pixels. And there's no bug with PureBasic or Windows APIs. If your desktop resolution is 1280 x 1024 and your DPI is set to 150%, 1280 would now be 853 and 1024 would now be 682 for Not DPI-Aware application. 853 x 682 is roughly your return using GetSystemMetrics?

If you making system info utilities, then getting the physical information would be important. However you trying to make windows and controls then It is easier to work with the logical rather than the physical returns while making not DPI-Aware PB applications. As anyone can clearly see that PureBasic natively included commands such as DesktopWidth() reports physical and using that in Not DPI-Aware code is mind baffling to people. The help file isn't exactly any help to avoid confusion that is repeatedly shown again and again.

Using DesktopWidth() return to make PB Window with maximum desktop width is no help, and no way to calculate properly to my knowledge without also being able to grab the DPI information. I don't believe PB offers such support yet? Therefore OS specific API calls to determine the DPI and do the calculations.

Code:
Procedure CreateWindow(WinID, x, y, iw, ih, backcolor)
  OpenWindow(WinID, x, y, iw, ih, "", #PB_Window_BorderLess)
  SetWindowColor(WinID, backcolor)
EndProcedure

Result = ExamineDesktops()
DesktopWidth = DesktopWidth(0)
DesktopHeight = DesktopHeight(0)
DesktopWidth2 = GetSystemMetrics_(#SM_CXSCREEN)
DesktopHeight2 = GetSystemMetrics_(#SM_CYSCREEN)

Debug "PB_Native: Desktop: "+ Str(DesktopWidth) + "x" + Str(DesktopHeight)
Debug "Win_API: Desktop: "+ Str(DesktopWidth2) + "x" + Str(DesktopHeight2)

; Top left
CreateWindow(0, 0, 0, 30, 30, RGB(255,0,0))
CreateWindow(1, 0, 40, 30, 30, RGB(0, 92, 253))

; Top right
CreateWindow(2, DesktopWidth-30, 0, 30, 30, RGB(255,0,0))
CreateWindow(3, DesktopWidth2-30, 40, 30, 30, RGB(0, 92, 253))

Debug #LF$+"Red blocks to demonstrate using PB Native DesktopWidth() command."
Debug #LF$+"Blue blocks to demonstrate using Windows GetSystemMetrics_()"
Debug #LF$+"... Goal is to have the blocks attached to the top-left & top-right edge of the screen,"+#LF$+
      "With the exception that the blue blocks are lowered by design."

Repeat
  Event = WindowEvent() 
Until Event = #PB_Event_CloseWindow

_________________
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley


Top
 Profile  
Reply with quote  
 Post subject: Re: Important tip: getting the desktop resolution
PostPosted: Sun Sep 24, 2017 6:52 pm 
Offline
Addict
Addict

Joined: Mon Nov 25, 2013 6:41 am
Posts: 811
I do not know what to happen, but I have an api to determine the wines correctly and there is no purebasik. DesktopWidth (0) then at least must have a flag. :cry:


Top
 Profile  
Reply with quote  
 Post subject: Re: Important tip: getting the desktop resolution
PostPosted: Mon Sep 25, 2017 12:34 am 
Offline
Always Here
Always Here

Joined: Fri Oct 23, 2009 2:33 am
Posts: 6176
Location: Wales, UK
Has anyone tried using the Vector Lib for this purpose?

_________________
IdeasVacuum
If it sounds simple, you have not grasped the complexity.


Top
 Profile  
Reply with quote  
 Post subject: Re: Important tip: getting the desktop resolution
PostPosted: Thu Sep 28, 2017 12:09 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Wed Apr 30, 2003 2:04 pm
Posts: 133
Location: Germany (French expat)
For the function GetDeviceCaps_() not all the possible values appear in the documentation.
You can use #DESKTOPHORZRES and #DESKTOPVERTRES (instead of #HORZRES and #VERTRES) to retrieve the width and height of the Screen.
Try this code with scaling >100%

Code:
#DESKTOPVERTRES = $75
#DESKTOPHORZRES = $76
hDCScreen.l = GetDC_(#Null)
 ;Returns the scaled size
Debug GetDeviceCaps_(hDCScreen, #HORZRES) 
Debug GetDeviceCaps_(hDCScreen, #VERTRES)   
;Returns the physical size
Debug GetDeviceCaps_(hDCScreen, #DESKTOPHORZRES) 
Debug GetDeviceCaps_(hDCScreen, #DESKTOPVERTRES)) 
ReleaseDC_(#Null, hDCScreen)

Hope this helps

Tested on Windows 10 x64 only
TeddyLM


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 12 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 11 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye