Proper DPI Awarness

Windows specific forum
User avatar
❤x1
User
User
Posts: 49
Joined: Thu Jan 10, 2019 5:56 pm

Proper DPI Awarness

Post by ❤x1 »

I figured it out :

Code: Select all

#WM_DPICHANGED = $2E0 ;https://learn.microsoft.com/en-us/windows/win32/hidpi/wm-dpichanged

Procedure EnableDPIAwarness()
	Protected ver.OSVERSIONINFOEX, hDLL.i, Result
	
	ver\dwOSVersionInfoSize = SizeOf(ver)
	
	hDLL = OpenLibrary(#PB_Any, "ntdll.dll")     
	If hDLL   
		CallFunction(hDLL, "RtlGetVersion", @ver)
		CloseLibrary(hDLL)       
	EndIf
	
	If ver\dwMajorVersion > 6 Or (ver\dwMajorVersion = 6 And ver\dwMinorVersion = 3)
		hDLL = OpenLibrary(#PB_Any, "SHCore.dll")
		If hDLL
			; SetProcessDpiAwareness(Value) : https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setthreaddpiawarenesscontext
			; 2 = DPI_AWARENESS_PER_MONITOR_AWARE as defined here : https://learn.microsoft.com/en-us/windows/win32/api/shellscalingapi/ne-shellscalingapi-process_dpi_awareness
			Result = CallFunction(hDLL, "SetProcessDpiAwareness", 2)
			CloseLibrary(hDLL)
			
			If Result = #S_OK
				Result = #True
			Else
				Result = #False
				CompilerIf #PB_Compiler_Debugger
					MessageRequester("EnableDPIAwareness", "Couldn't set DPI awareness. Please make sure that `DPI awereness executable` is DISABLED in the compiler options.")
				CompilerEndIf
			EndIf
		EndIf
	EndIf
	
	ProcedureReturn Result
EndProcedure

; Example :
ImportC "user32.lib"
	GetDpiForWindow(WindowID.i)
EndImport

EnableDPIAwarness()

OpenWindow(0, 200, 200, 400, 400, "DPI Test", #PB_Window_SystemMenu)

Procedure Callback(WindowID, Message, WParam, LParam)
	If Message = #WM_DPICHANGED
		Debug GetDpiForWindow(WindowID(0))
	EndIf
	ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

SetWindowCallback(@Callback(), 0)

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EnableDPIAwarness() will enable per monitor DPI awareness on Windows 8.1 and above. You'll have to handle the #WM_DPICHANGED message.

Tested on up-to-date Windows 11 enterprise, I'd appreciate if you could try it on other version.

Before edit :
Hi!
I'm trying to achieve proper DPI awareness on Windows 11, and I'm failing miserably. So I came to ask if someone could show me the way.

A few pages of interest :
Message that should be sent to my windows if the DPI change if the thread was DPI Aware
The SetThreadDpiAwarenessContext function, which always returns zero, so I'm doing something wrong.
My biggest issue is DPI_AWARENESS_CONTEXT. What is it supposed to be? I know it's not a constant and that's why my attempt at setting the thread DPI awareness fails. Here is the doc : https://learn.microsoft.com/fr-fr/windo ... s-context
Would you have any clue?
Last edited by ❤x1 on Thu Apr 13, 2023 1:09 pm, edited 2 times in total.
User avatar
Caronte3D
Addict
Addict
Posts: 1361
Joined: Fri Jan 22, 2016 5:33 pm
Location: Some Universe

Re: Proper DPI Awarness

Post by Caronte3D »

Why that complexity? :?
What are you trying to do?
You have't enough with the PB functions related to DPI?

DesktopResolutionX()
DesktopResolutionY()
DesktopScaledX(Value)
DesktopScaledY(Value)
DesktopUnScaledX(Value)
DesktopUnScaledY(Value)
Fred
Administrator
Administrator
Posts: 18199
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Proper DPI Awarness

Post by Fred »

This is useful to know when a window is moved on different DPI screen, so you need to adjust the DPI. PB doesn't (for now) support per monitor automatic DPI switch.
Rinzwind
Enthusiast
Enthusiast
Posts: 690
Joined: Wed Mar 11, 2009 4:06 pm
Location: NL

Re: Proper DPI Awarness

Post by Rinzwind »

Yes, now you receive a DPI changed message and then what? Manually change all controls? PB does not do it for you. Ps you should also not set DPI awareness im the PB properties when trying to handle it all yourself.
Post Reply