Share via

Wrong DPI returned

OSVBNET 1,401 Reputation points
2022-04-13T19:10:59.927+00:00

Hi
I always get 96 when using:

Graphics.FromHwnd(Me.Handle).DpiX

in vb.net (.net framework 4.0)

even after changing the scaling in display settings (win10 1909 latest updates)
confusing :(

Developer technologies | VB
0 comments No comments

2 answers

Sort by: Most helpful
  1. Cohn, Robert 21 Reputation points
    2022-08-29T23:50:37.72+00:00

    Hello -

    Thought I'd throw in my two cents. If you are restoring the app to a saved position that is not on the Main display, you need to call GetDpiForWindow after setting that position. Else you always get the dpi for the Main display.

    For example, if I have two displays, the Main display with scaling = 150 and another display at scaling = 100 (which is the display for which the app position was saved), then GetDpiForWindow returns the dpi (144) for the Main display instead of the other display's dpi (96) if I try to get the scaling before setting the app position.

    Perhaps this is obvious, but it took me quite a while to realize it as I had been trying to set the scaling from the MainWindow constructor (after InitializeComponent).

    Otherwise (when you use it correctly), GetDpiForWindow works quite well.

    	private float GetScalingFactor()  
    	{  
    		// Retrieve the window handle (HWND) of the current (XAML) WinUI 3 window.  
    		IntPtr hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);  
    		if (hWnd != IntPtr.Zero)  
    		{  
    			// get display scaling where app window is currently sitting  
    			return GetDpiForWindow(hWnd) / 96.0F;  
    		}  
    		else  
    		{  
    			return 1.0F;  
    		}  
    	}  
    

    The app manifest should support per-monitor dpAware

    235865-image.png

    Was this answer helpful?

    1 person found this answer helpful.
    0 comments No comments

  2. Castorix31 91,871 Reputation points
    2022-04-13T20:01:14.643+00:00

    You need a Manifest with

    	<application xmlns="urn:schemas-microsoft-com:asm.v3">  
    		<windowsSettings>  
    			<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>  
    			<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitor</dpiAwareness>  
    		</windowsSettings>  
    	</application>  
    

    but GetDpiForWindow is better because it does not need the application to be re-started when the DPI changes :

        <DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>  
        Public Shared Function GetDpiForWindow(ByVal hwnd As IntPtr) As UInteger  
        End Function  
    

    Was this answer helpful?

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.