Jump to content

making your compiled application DPI Aware


Recommended Posts

What I can say is that DPI awareness is not as simple as just adding a valid manifest and everything will work properly.

A good starting point is https://docs.microsoft.com/en-us/windows/win32/hidpi/high-dpi-desktop-application-development-on-windows

Currently I'm trying to understand how DPI awareness works and how I've to create my GUI incl. child GUIs and what I've to do / call that my code is DPI aware on different operating systems.

In my office I've 3 monitors. 2 of them are external and 1 is from my notebook.

The 2 external are running at 1680x1050 px and the other one at 1600x900 px. Thus the virtual screen size is at 4960x1050 px.

E.g. if I set monitor 1 to 144 DPI, monitor 2 to 168 DPI and monitor 3 to 96 DPI then my test code from above will behave different than setting only one monitor to > 96 DPI. Even only 1 monitor is set to higher DPI it behaves different depending on which monitor will be used.

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to post
Share on other sites
  • Replies 60
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Popular Posts

Since this thread is getting long, I thought I'd copy all the relevant information to the 1st post. Three different types of DPI Aware'ness are made available from Microsoft. 1. System Aware (i

System will not resize GUI and controls according to DPI scaling. You must do this manually. For example ; current value of primary monitor DPI is stored in the registry: ; HKCU\Control

Maybe this will help. As the page is in German, use any translator -> https://autoit.de/index.php?thread/86505-guiscaler-guis-automatisch-zur-dpi-skalieren-lassen-windows-7-und-windows-10-per/

Posted Images

@Shark007 Can you please test this version?

I still used these lines in the manifest

<asmv3:application>
        <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
              <dpiAware>true/pm</dpiAware>
        </asmv3:windowsSettings>
        <asmv3:windowsSettings xmlns="https://schemas.microsoft.com/SMI/2016/WindowsSettings">
              <dpiAwareness>PerMonitorV2, PerMonitor, system</dpiAwareness>
        </asmv3:windowsSettings>
        <asmv3:windowsSettings xmlns="https://schemas.microsoft.com/SMI/2017/WindowsSettings">
              <gdiScaling>true</gdiScaling>
        </asmv3:windowsSettings>
    </asmv3:application>

No _WinAPI_SetDPIAwareness calls, only the DPI awareness from the manifest!

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to post
Share on other sites

The fact that a Manifest written as below works on Windows 10 and 8 in Per Monitor Aware mode
and on Windows 7, (7 only supports System Aware) leads me to assume it is in the best format.

Also know, including gdi scaling (as the 1st line) causes my apps to be Unaware on Windows 8.
This leads me to the conclusion that Windows reads and attempts to connect, from the top down.
Since you manifest has The Windows 8 version before the 10 version (of Per Monitor Aware)
It will use the Windows 8 version on Windows10 systems.

	<asmv3:application>
		<asmv3:windowsSettings>
            	<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
            	<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
		</asmv3:windowsSettings>
	</asmv3:application>

 

They report as Per Monitor Aware on 8 and 10 

Windows 8

Windows8.jpg

Windows 10

Windows10.jpg

Edited by Shark007
Link to post
Share on other sites

Thanks for testing.

I've modified the manifest to following lines:

<asmv3:application>
        <asmv3:windowsSettings xmlns="https://schemas.microsoft.com/SMI/2016/WindowsSettings">
              <dpiAwareness>PerMonitorV2, PerMonitor, system</dpiAwareness>
        </asmv3:windowsSettings>
        <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
              <dpiAware>true/pm</dpiAware>
        </asmv3:windowsSettings>
    </asmv3:application>

I tested it using 3 monitors, 175%, 125%, 150% and the main GUI looked ok. The child GUI has no interaction yet, only main GUI where the font size will be reset when GUI is moved to another screen.

I'm wondering why your screenshot on Win10 looks so different...

 

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to post
Share on other sites

To inform, 

I tested this code as standalone (without other entries)

<asmv3:windowsSettings xmlns="https://schemas.microsoft.com/SMI/2016/WindowsSettings">
              <dpiAwareness>PerMonitorV2, PerMonitor, system</dpiAwareness>
        </asmv3:windowsSettings>

and it does not fallback at all. It works on Windows 10 in Per Monitor Aware mode, but on 8 and 7, the apps are unaware

Edited by Shark007
Link to post
Share on other sites

I changed the manifest to

<asmv3:application>
        <asmv3:windowsSettings xmlns="https://schemas.microsoft.com/SMI/2016/WindowsSettings">
              <dpiAwareness>PerMonitorV2</dpiAwareness>
        </asmv3:windowsSettings>
        <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
              <dpiAware>true/pm</dpiAware>
        </asmv3:windowsSettings>
    </asmv3:application>

 

How it looks on my Win10 notebook on different monitors with different DPI settings:

 

150%:150.png
125%:125.png
175%:175.png

 

100%: 100.png
 

 

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to post
Share on other sites

@UEZ In my travels, some information you may find interesting.

To enable support for Mixed-Mode High DPI scaling, you can set the following AppContext switch in the manifest.

<runtime>
   <AppContextSwitchOverrides value = "Switch.System.Windows.DoNotScaleForDpiChanges=false; Switch.System.Windows.DoNotUsePresentationDpiCapabilityTier2OrGreater=false"/>
</runtime>

Documentation

Edited by Shark007
Link to post
Share on other sites
10 hours ago, Shark007 said:

@UEZ In my travels, some information you may find interesting.

To enable support for Mixed-Mode High DPI scaling, you can set the following AppContext switch in the manifest.


<runtime>
   <AppContextSwitchOverrides value = "Switch.System.Windows.DoNotScaleForDpiChanges=false; Switch.System.Windows.DoNotUsePresentationDpiCapabilityTier2OrGreater=false"/>
</runtime>

Documentation

When I add these lines than the exe cannot be started!

Error message:

The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log or use the command-line sxstrace.exe tool for more detail.

 

I was able to reproduce your screens when I changed by main screen to 175%.

 

Can you test the executables in the 7-Zip archive please?

 

 

 

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to post
Share on other sites
2 minutes ago, Deye said:

UEZ

when you start one at 175% then change the settings to 100% and start another they are not the same sizes

also the text with the one that started on 175% becomes too small to read ..

If you mean the child GUI with the bitmap then you are right as the 2nd (child) GUI has no awareness code.

When the result is as expected than I will release the code.

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to post
Share on other sites
	<configuration>
		<windows>
			<runtime>
   				<AppContextSwitchOverrides value = "Switch.System.Windows.DoNotScaleForDpiChanges=false; Switch.System.Windows.DoNotUsePresentationDpiCapabilityTier2OrGreater=false"/>
			</runtime>
		</windows>
	</configuration>

	<asmv3:application>
		<asmv3:windowsSettings>
			<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
			<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
		</asmv3:windowsSettings>
	</asmv3:application>

@UEZ OK, I got this working. i'm laughing at myself at this point. But this works and is reproducible

Edited by Shark007
Link to post
Share on other sites

@Shark007 For me it is still not working - getting the same error message!

Regarding Win8 -> the function _WinAPI_GetDpiForWindow() requires Win10 v1607+. I've added another GDI+ function to get the DPI which should work, too.

Can you test please?

 

Here the code:

;Coded by UEZ build 2019-08-08 beta

#AutoIt3Wrapper_Res_HiDpi=Y

#include <GUIConstantsEx.au3>
#include <GDIPlus.au3>
#include <WinAPIGdiDC.au3>
#include <WinAPISysWin.au3>
#include <WindowsConstants.au3>

; enum _PROCESS_DPI_AWARENESS -> https://msdn.microsoft.com/en-us/library/windows/desktop/dn280512(v=vs.85).aspx
Global Enum $DPI_AWARENESS_INVALID = -1, $PROCESS_DPI_UNAWARE = 0, $PROCESS_SYSTEM_DPI_AWARE, $PROCESS_PER_MONITOR_DPI_AWARE

Global Enum $Context_UnawareGdiScaled = -5, $Context_PerMonitorAwareV2, $Context_PerMonitorAware, $Context_SystemAware, $Context_Unaware

Global Const $WM_DPICHANGED = 0x02E0, $WM_GETDPISCALEDSIZE = 0x02E4

Global $dpiScaledX, $dpiScaledY, $aCtrlFS[5][2], $hGUI, $hGUI_child, $g_iDPI_ratio2

Example1()


Func Example1() ;thanks to alpines for the main GUI layout

    _WinAPI_SetDPIAwareness()

    Local $iDPI
    If @OSBuild < 14393 Then
        $iDPI = _GDIPlus_GraphicsGetDPIRatio()
    Else
        Local $hGUI_dummy = GUICreate("", 1, 1)
        $iDPI = _WinAPI_GetDpiForWindow($hGUI_dummy)
        GUIDelete($hGUI_dummy)
    EndIf
    Local $iDPI_ratio = $iDPI / 96
    $g_iDPI_ratio2 = 96 / $iDPI

    $hGUI = GUICreate("Example 1", 314 * $iDPI_ratio, 130 * $iDPI_ratio, -1, 10)
    GUISetFont(12 * $iDPI_ratio, 400, 0, "Times New Roman")

    $aCtrlFS[0][0] = GUICtrlCreateLabel("Label1", 16 * $iDPI_ratio, 16 * $iDPI_ratio, 40 * $iDPI_ratio, 21 * $iDPI_ratio)
    $aCtrlFS[0][1] = 10
    GUICtrlSetBkColor(-1, 0x3399FF)
    GUICtrlSetResizing(-1, $GUI_DOCKAUTO)

    $aCtrlFS[1][0] = GUICtrlCreateLabel("Label2", 64 * $iDPI_ratio, 16 * $iDPI_ratio, 40 * $iDPI_ratio, 21 * $iDPI_ratio)
    $aCtrlFS[1][1] = 10
    GUICtrlSetBkColor(-1, 0x3399FF)
    GUICtrlSetResizing(-1, $GUI_DOCKAUTO)

    $aCtrlFS[2][0] = GUICtrlCreateLabel("Label3", 112 * $iDPI_ratio, 16 * $iDPI_ratio, 40 * $iDPI_ratio, 21 * $iDPI_ratio)
    $aCtrlFS[2][1] = 10
    GUICtrlSetBkColor(-1, 0x3399FF)
    GUICtrlSetResizing(-1, $GUI_DOCKAUTO)

    $aCtrlFS[3][0] = GUICtrlCreateInput("Input1", 160 * $iDPI_ratio, 16 * $iDPI_ratio, 137 * $iDPI_ratio, 22 * $iDPI_ratio)
    $aCtrlFS[3][1] = 10
    GUICtrlSetResizing(-1, $GUI_DOCKAUTO)

    $aCtrlFS[4][0] = GUICtrlCreateButton("Close", 16 * $iDPI_ratio, 48 * $iDPI_ratio, 283 * $iDPI_ratio, 65 * $iDPI_ratio)
    $aCtrlFS[4][1] = 16
    GUICtrlSetResizing(-1, $GUI_DOCKAUTO)

    $hGUI_child = GUICreate("Child", 320 * $iDPI_ratio, 260 * $iDPI_ratio, -1, -1, -1, -1, $hGUI)
    GUISetBkColor(0xFFFFFF)
    Local $iLable_child = GUICtrlCreateLabel("Label1", 16, 16, 288 * $iDPI_ratio, 168 * $iDPI_ratio)
    GUICtrlSetFont(-1, 65, 400, 0, "Times New Roman", 5)
    Local $iPic_child = GUICtrlCreatePic("c:\Program Files (x86)\AutoIt3\Examples\GUI\Merlin.gif", 0, 160, 68, 71)

    ResizeFont($hGUI)

    GUISetState(@SW_SHOW, $hGUI)
    GUISetState(@SW_SHOW, $hGUI_child)

    GUIRegisterMsg($WM_DPICHANGED, "WM_DPICHANGED") ;requires Win 8.1+ / Server 2012 R2+ os
;~  GUIRegisterMsg($WM_GETDPISCALEDSIZE, "WM_GETDPISCALEDSIZE")

    While True
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE, $aCtrlFS[4][0]
                GUIDelete($hGUI)
                ExitLoop
        EndSwitch
    WEnd
EndFunc   ;==>Example1

Func ResizeFont($hWnd)
    If $hWnd = $hGUI Then
        Local $iDPI = _WinAPI_GetDpiForWindow($hWnd)
        Local $i, $dpi_ratio = $iDPI / 96
        For $i = 0 To UBound($aCtrlFS) - 1
            GUICtrlSetFont($aCtrlFS[$i][0], $aCtrlFS[$i][1] * $dpi_ratio * $g_iDPI_ratio2, 400, 0, "Times New Roman", 5)
        Next
    EndIf
EndFunc

Func _WinAPI_FindWindowEx($hWndParent, $hWndChildAfter = 0, $sClassName = "", $sWindowName = "")
    Local $aResult = DllCall("user32.dll", "hwnd", "FindWindowEx", "hwnd", $hWndParent, "hwnd", $hWndChildAfter, "wstr", $sClassName, "wstr", $sWindowName)
    If @error Then Return SetError(@error, @extended, 0)
    Return $aResult[0]
EndFunc

Func _WinAPI_GetDpiForWindow($hWnd)
    Local $aResult = DllCall("user32.dll", "uint", "GetDpiForWindow", "hwnd", $hWnd) ;requires Win10 v1607+ / no server support
    If @error Then Return SetError(@error, @extended, 0)
    Return $aResult[0]
EndFunc

Func _GDIPlus_GraphicsGetDPIRatio($iDPIDef = 96)
    _GDIPlus_Startup()
    Local $hGfx = _GDIPlus_GraphicsCreateFromHWND(0)
    If @error Then Return SetError(1, @extended, 0)
    Local $aResult = DllCall($__g_hGDIPDll, "int", "GdipGetDpiX", "handle", $hGfx, "float*", 0)
    If @error Then Return SetError(2, @extended, 0)
    _GDIPlus_GraphicsDispose($hGfx)
    _GDIPlus_Shutdown()
    Return $aResult[2]
EndFunc   ;==>_GDIPlus_GraphicsGetDPIRatio

Func WM_GETDPISCALEDSIZE($hWnd, $iMsg, $wParam, $lParam)
    Local $tSize = DllStructCreate($tagSIZE, $lParam)
    Return True
EndFunc

Func WM_DPICHANGED($hWnd, $iMsg, $wParam, $lParam)
    Local $tRECT = DllStructCreate($tagRECT, $lParam)
    Local $iX = $tRECT.left, $iY = $tRECT.top, $iW = $tRECT.right - $iX, $iH = $tRECT.bottom - $iY
    _WinAPI_SetWindowPos($hWnd, 0, $iX, $iY, $iW, $iH, BitOR($SWP_NOZORDER, $SWP_NOACTIVATE))
    ResizeFont($hWnd)
    $tRECT = 0
    Return 1
EndFunc   ;==>WM_DPICHANGED


Func _WinAPI_SetDPIAwareness($hGUI = 0)
    Switch @OSBuild
        Case 6000 To 9199
            If Not DllCall("user32.dll", "bool", "SetProcessDPIAware") Then Return SetError(1, 0, 0) ;requires Vista+ / Server 2008+
            Return 1
        Case 9200 To 13999
            _WinAPI_SetProcessDpiAwareness($PROCESS_PER_MONITOR_DPI_AWARE)
            If @error Then Return SetError(2, 0, 0)
            Return 1
        Case @OSBuild > 13999
            #cs
                Context_Unaware = ((DPI_AWARENESS_CONTEXT)(-1)),
                Context_SystemAware = ((DPI_AWARENESS_CONTEXT)(-2)),
                Context_PerMonitorAware = ((DPI_AWARENESS_CONTEXT)(-3)),
                Context_PerMonitorAwareV2 = ((DPI_AWARENESS_CONTEXT)(-4)),
                Context_UnawareGdiScaled = ((DPI_AWARENESS_CONTEXT)(-5))
            #ce
            _WinAPI_SetProcessDpiAwarenessContext($Context_PerMonitorAwareV2, $hGUI, 1)
            If @error Then Return SetError(3, @error, 0)
            Return 1
    EndSwitch
    Return -1
EndFunc   ;==>_WinAPI_SetDPIAwareness


Func _WinAPI_SetProcessDpiAwareness($DPIAware) ;https://docs.microsoft.com/en-us/windows/desktop/api/shellscalingapi/nf-shellscalingapi-setprocessdpiawareness
    Local $aResult = DllCall("Shcore.dll", "long", "SetProcessDpiAwareness", "int", $DPIAware) ;requires Win 8.1+ / Server 2012 R2+ os
    If @error Then Return SetError(1, 0, 0)
    Return 1
EndFunc   ;==>_WinAPI_SetProcessDpiAwareness

Func _WinAPI_SetProcessDpiAwarenessContext($DPIAwareContext = $Context_PerMonitorAware, $hGUI = 0, $iMode = 1)
    $DPIAwareContext = ($DPIAwareContext < -5) ? -5 : ($DPIAwareContext > -1) ? -1 : $DPIAwareContext
    $iMode = ($iMode < 1) ? 1 : ($iMode > 3) ? 3 : $iMode
    Switch $iMode
        Case 1
            Local $hDC = _WinAPI_GetDC($hGUI)
            Local $aResult1 = DllCall("user32.dll", "int", "GetDpiFromDpiAwarenessContext", "ptr", $hDC) ;requires Win10 v1803+ / Server 2016+
            If @error Or Not IsArray($aResult1) Then Return SetError(11, 0, 0)
            _WinAPI_ReleaseDC(0, $hDC)
            ;https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setprocessdpiawarenesscontext
            Local $aResult = DllCall("user32.dll", "Bool", "SetProcessDpiAwarenessContext", "int", $aResult1[0] + $DPIAwareContext) ;requires Win10 v1703+ / Server 2016+
            If @error Or Not IsArray($aResult) Then Return SetError(12, 0, 0)
        Case 2
;~          If Not $hGUI Then $hGUI = WinGetHandle(AutoItWinGetTitle())
            Local $aResult2 = DllCall("user32.dll", "int", "GetWindowDpiAwarenessContext", "ptr", $hGUI) ;requires Win10 v1607+ / no server support
            If @error Or Not IsArray($aResult2) Then Return SetError(21, 0, 0)
            Local $aResult = DllCall("user32.dll", "Bool", "SetProcessDpiAwarenessContext", "int", $aResult2[0] + $DPIAwareContext) ;requires Win10 v1703+ / Server 2016+
            If @error Or Not IsArray($aResult) Then Return SetError(22, 0, 0)
        Case 3
            Local $aResult31 = DllCall("user32.dll", "ptr", "GetThreadDpiAwarenessContext") ;requires Win10 v1607+ / no server support
            If @error Or Not IsArray($aResult31) Then Return SetError(31, 0, 0)
            Local $aResult32 = DllCall("user32.dll", "int", "GetAwarenessFromDpiAwarenessContext", "ptr", $aResult31[0]) ;requires Win10 v1607+ / no server support
            If @error Or Not IsArray($aResult32) Then Return SetError(32, 0, 0)
            Local $aResult = DllCall("user32.dll", "Bool", "SetThreadDpiAwarenessContext", "int", $aResult32[0] + $DPIAwareContext) ;requires Win10 v1607+ / no server support
            If @error Or Not IsArray($aResult) Then Return SetError(33, 0, 0)
    EndSwitch

    Return 1
EndFunc   ;==>_WinAPI_SetProcessDpiAwarenessContext

 

_WinAPI_SetDPIAwareness.zip

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to post
Share on other sites

Working with Windows... more aaarrrggg  because I can no longer reproduce good results with the manifest editing.

Moving on... Windows 10, screen shots are the same... Windows 8...

8.jpg

I see an awesome UDF coming out soon'ish.  Good work UEZ!

Edited by Shark007
Link to post
Share on other sites
8 hours ago, Deye said:

UEZ

when you start one at 175% then change the settings to 100% and start another they are not the same sizes

also the text with the one that started on 175% becomes too small to read ..

@Deye This is the reason why there is a warning when you change resolutions that some apps may not appear correctly until you log off and back in again. I'm pretty sure this statement is addressing DPI Aware applications specifically.

Edited by Shark007
Link to post
Share on other sites
35 minutes ago, Shark007 said:

@UEZ To inform, I had other testing to do in Win7 and before I left, I tested your latest iteration there too .It is set to 125% and and all was well!

Cool, thanks for testing. :)

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Jowy
      Hello dears,
      I'm trying to write a script in AutoIT but, I have issue in DPI. I'm basically a Lead Software Developer and I use AutoIT from time to time. I have an ERP Launcher that should work on all machines starting by Windows 7, Windows 8.x , Windows 10, Windows Server 2003/2008/2012.
      When I was searching in AutoIT forum, I could see previously this " Writing DPI Awareness App - workaround" in the signature of Mr. @mLipok,, but clicking on the link, => page not found.
      Do you have any new link or something that you can share with me ? I'm using macbook pro with retina display and VMware machines: Windows 10 and Server 2012 as development machines, but both of them they have 200% scaling and they have AutoIT installed. In this case, when I use Koda (blurry font for sure), I have the controls as I want, and application is working fine, but also blurry font, until it is used on 96 DPI machine.
      Now, in windows 10, with DPI System Enhanced feature in the compatibility tab, the application running on 200% scaling is excellent visual like it's running on 96 DPI without touching my code and without doing anything, but no all clients they have windows 10. It seems Microsoft worked a lot on the new feature. But for other machines like windows 7/8/2012, the font is blurry if the clients have scaling above 100% (more than 96 DPI). I know how to enable hidpi stuff in the wrapper and I know how to write the code to use a scaling factor that can be multiplied by every coordinate, but this way is cumbersome and I have to change all coordinates of all X, Y, Width, Height after getting the code from Koda. Is there a fast way ? 
      So, what do you recommend me guys ?
      Thanks,
      Jowy
    • By LegitStack
      Been struggling with this one for a while. 
      when I do a _screencapture_capture call on a high resolution monitor (like my surface book) it gives me an image that has 2 problems:
      1. its in the wrong location on the screen
      and
      2. it gives me a picture that is larger than the area of the screen I selected, though it only has the content of what I selected. 
      ---------------------------
      I was able to easily fix problem #1 by manually adjusting the x y coordinates to compensate for the amount of DPI scale I have.
      for instance if I'm 200% zoomed in the code looks like this:
      Local $bmp = _ScreenCapture_Capture("", $iX1*2, $iY1*2, $iX2*2, $iY2*2, false)  it's problem #2 that is the big problem. I'd like to attach a screen shot of what I'm talking about (see capture.png)

      ---------------------------
      Now I basically understand why this is happening. ScreenCapture grabs each pixel of the screen. This screen, being a high resolution, when its zoomed in adds up several pixels to make one on the screen. 
      This is a problem for me because I'm taking images of the screen and later looking for those exact images on the screen. if everything is blown up by an indeterminate amount (in my case 2x) then those images can't be found later on. 
      Does anyone know what I can do? 
      I tried resizing the images back down to no avail. 
      _GDIPlus_ImageResize and _GDIPlus_ImageScale don't work because they don't compress the pixels correctly. quality is lost. and the exact image isn't preserved, so I can't search for it later. (see capture1.png)

       
      Anyway, I'm about to give up, been on this problem for too long! does anyone know what I can do? Seems to me that the ideal solution would be to eventually have autoit add an argument to _screencapture_capture that lets you specify a DPI scale amount or something.  that can be pulled from the registry at HKEY_CURRENT_USER\control panel\desktop\windowmetrics\appliedDPI.
      But in the meantime, does anyone have any suggestions for how I can make my program compatible with 4k resolution monitors? I either need to take the screen capture like normal, then scale it down appropriately without losing quality, or I need to capture the screen in the first place like the human sees it. But I don't know how to do that either. 
      I'll post my relevant code here: (in my project I call ScreenCapture_DPI_Aware)
      #include <Security.au3> Func _GetAppliedDPI()   Local $aArrayOfData = _Security__LookupAccountName(@UserName)   If IsArray($aArrayOfData) Then   ;msgbox(64, "SID String = ", $aArrayOfData[0] & @CRLF)   ;msgbox(64, "Domain name = ", $aArrayOfData[1] & @CRLF)   ;msgbox(64, "SID type = ", _Security__SidTypeStr($aArrayOfData[2]) & @CRLF)     ;Local $AppliedDPI = RegRead("HKEY_USERS\" & $aArrayOfData[0] & "\Control Panel\Desktop\WindowMetrics", "AppliedDPI") Local $AppliedDPI = RegRead("HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics", "AppliedDPI")     return $AppliedDPI   EndIf EndFunc Func GetScale()   $applied = _GetAppliedDPI()   if $applied == "" then     return 1   else     return $applied / 96   EndIf EndFunc Func ScreenCapture_Capture_DPI_Aware($sBMP_Path, $iX1, $iY1, $iX2, $iY2, $bool)   $R = GetScale() ;Raito   Local $bmp = _ScreenCapture_Capture($sBMP_Path, $iX1*$R, $iY1*$R, $iX2*$R, $iY2*$R, $bool) ;Scaling didn't work: ;_ScaleImage($bmp, $sBMP_Path, abs($iX2 - $iX1), abs($iY2 - $iY1), $R)   ;return _ScreenCapture_Capture($sBMP_Path, $iX1*$R, $iY1*$R, $iX2*$R, $iY2*$R, $bool) EndFunc ;Func _ScaleImage($bmp, $outimage, $w, $h, $scale) ; _GDIPlus_Startup() ;Get the encoder of to save the resized image in the format you want. ; Local $Ext = StringUpper(StringMid($outimage, StringInStr($outimage, ".", 0, -1) + 1)) ; $CLSID = _GDIPlus_EncodersGetCLSID($Ext) ; code found here : https://www.autoitscript.com/autoit3/docs/libfunctions/_GDIPlus_ImageSaveToStream.htm ; Local $sImgCLSID = _GDIPlus_EncodersGetCLSID("png") ;create CLSID for a JPG image file type ; Local $tGUID = _WinAPI_GUIDFromString($sImgCLSID) ;convert CLSID GUID to binary form and returns $tagGUID structure ; Local $tParams = _GDIPlus_ParamInit(1) ;initialize an encoder parameter list and return $tagGDIPENCODERPARAMS structure ; Local $tData = DllStructCreate("int Quality") ;create struct to set JPG quality setting ; DllStructSetData($tData, "Quality", 100) ;quality 0-100 (0: lowest, 100: highest) ; Local $pData = DllStructGetPtr($tData) ;get pointer from quality struct ; _GDIPlus_ParamAdd($tParams, $GDIP_EPGQUALITY, 1, $GDIP_EPTLONG, $pData) ;add a value to an encoder parameter list ; Local $gbmp = _GDIPlus_BitmapCreateFromHBITMAP($bmp) ; _WinAPI_DeleteObject($bmp) ; Local $gsbmp = _GDIPlus_ImageResize($gbmp, $w * $scale, $h * $scale) ;Local $ext = _GDIPlus_EncodersGetCLSID("PNG") ; _GDIPlus_ImageSaveToFileEx($gsbmp, $outimage, $sImgCLSID) ; _GDIPlus_BitmapDispose($gbmp) ; _GDIPlus_BitmapDispose($gsbmp) ; _GDIPlus_Shutdown() ;EndFunc
      Thanks for any help you can give me!!!
×
×
  • Create New...