Jump to content

"GuiCtrls_HiDpi" (UDF in progress)


argumentum
 Share

Recommended Posts

Just one suggestion but it's no big deal and can be implemented after the UDF is done. What is you use WH_CBT hook to detect when a window is deleted and if it's already saved in your array then you can make all other stuffs automatically so the final user don't have to call _HiDpi_GUIDelete() for each created GUI.

When the words fail... music speaks.

Link to comment
Share on other sites

6 minutes ago, Andreik said:

but it's no big deal

Yes it is big deal. If you can cook a little sampler or a link to where I can find the code then I'll add it.
Mainly because I have no idea how to do it myself but that's just the main reason :)

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

preliminary results are looking quite good.

As time permits (today), I'm going to attempt to integrate this into a very large existing project I have that currently uses my own implementation of HiDpi.

EDIT - not as easy as I had hoped it would be. One thing I've noticed is that GuiCtrls_HiDpi deals with font, and it should not. When an Application is Dpi Aware, the font is dealt with by the system and does not require user interaction at all. Only the graphical control dimensions and placement, such as the gui itself, labels, checkbox's, splashtext etc. require Dpi adjustment to their " left, top, width, height ", not the font itself.

Example: When a user sets Windows DPI to 225% . . .  left, top, width, height, should each be multiplied bt 2.25 resulting in a perfect gui.

How I currently achieve this (DpiAwareness is set in the manifest)

_GDIPlus_Startup()
Global $iScale = DllCall($__g_hGDIPDll, "int", "GdipGetDpiX", "handle", _GDIPlus_GraphicsCreateFromHWND(0), "float*", 0)[2] / 96 ;Windows scaling
_GDIPlus_Shutdown()
If Not $iScale >= 1 Then $iScale = 1

GUICtrlCreateLabel('Shark007', 185 * $iScale, 60 * $iScale, 145 * $iScale, 18 * $iScale)

 All of the software I create employs this method and all of my software is DpiAware which I distribute globally without complaint.

Edited by Shark007
Link to comment
Share on other sites

8 hours ago, argumentum said:

Yes it is big deal. If you can cook a little sampler or a link to where I can find the code then I'll add it.
Mainly because I have no idea how to do it myself but that's just the main reason :)

Here is what I was talking about. I made the most basic example for a basic understanding but actually to implement it your UDF you just need to put in CBTProc() the logic from _HiDpi_GUIDelete() when you find that a window created by your current process is about to be destroyed. The rest of code is basically what you already do, saving the handles of GUI into an array, etc.

#include <WinAPIProc.au3>
#include <WinAPISys.au3>
#include <Array.au3>

Global Const $WH_CBT = 5
Global $aGUI[2] = [1, 0]

$hCBTProc = DllCallbackRegister('CBTProc', 'long_ptr', 'int;wparam;lparam')
$hHook = _WinAPI_SetWindowsHookEx($WH_CBT, DllCallbackGetPtr($hCBTProc), _WinAPI_GetModuleHandle(0), _WinAPI_GetCurrentThreadId())

$aGUI[1] = GUICreate('Test', 400, 400)
$idButton = GUICtrlCreateButton('Create window', 100, 100, 100, 30)
GUISetState(@SW_SHOW, $aGUI[1])

While True
    $aMsg = GUIGetMsg(1)
    Switch $aMsg[0]
        Case -3 ; GUI_EVENT_CLOSE
            GUIDelete($aMsg[1])
            _ArrayDisplay($aGUI)
            If $aGUI[0] = 0 Then ExitLoop
        Case $idButton
            $aGUI[0] += 1
            ReDim $aGUI[$aGUI[0] + 1]
            $aGUI[$aGUI[0]] = GUICreate('I am a new window', 400, 400, Random(0, @DesktopWidth - 400, 1), Random(0, @DesktopHeight - 400, 1))
            GUISetState(@SW_SHOW, $aGUI[$aGUI[0]])
            _ArrayDisplay($aGUI)
    EndSwitch
WEnd

_WinAPI_UnhookWindowsHookEx($hHook)
DllCallbackFree($hCBTProc)

Func CBTProc($nCode, $wParam, $lParam)
    If $nCode = 4 Then ; HCBT_DESTROYWND
        ; If a window is about to be destroyed
        ; let's check if it's not a GUI created by us
        For $Index = 1 To $aGUI[0]
            If $aGUI[$Index] = $wParam Then ; This is a window created by us
                _ArrayDelete($aGUI, $Index)
                $aGUI[0] -= 1
                ExitLoop
            EndIf
        Next
    EndIf
    Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam)
EndFunc

 

When the words fail... music speaks.

Link to comment
Share on other sites

19 minutes ago, argumentum said:

I was gonna fight you on this,

If you don't change the fonts in your GUI, do set to zero to disable the behavior
If you do change the fonts in any way, the OS will readjust them back to the default set by the user's current theme.

Which should be done/used ?, Had a somewhat heated discussion once and I decided to accommodate both.
If we were back in the days of WinXP I may have said, tweak the OS theme, is not up to me but the OS. Nowadays, meh, using win32 controls, do what you can.

So we will have both, "leave it alone" and "good luck man-handling the controls".

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

..I'll leave the changes of _HiDpi_Default_Do_GUISetFont(1/0) , not posted yet.
But having a main monitor as 100% renders different if, like in my case, the main monitor is 225%.

This patch, will skip any font change, if set to zero. We'll see how that works out. I'll be posting within the hour. 

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

What's new with version  0.2023.8.3(a)

Added "CALLBACK CBTProc()" to aid with the array of controls maintenance in case of UDF misuse, oops, or just plain easier to code with it in.
Added _HiDpi_Default_Do_GUISetFont(1/0)  to optionally skip any and all automatic font change with the UDF.

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

8 hours ago, Shark007 said:

Only the graphical control dimensions and placement, such as the gui itself, labels, checkbox's, splashtext etc. require Dpi adjustment to their " left, top, width, height ", not the font itself.

..looking back, I found that @UEZ used GUICtrlSetResizing(-1, $GUI_DOCKAUTO)  and I used it too. Seeing that it worked without having to adjust anything, kept working on other aspects, like the font.
But I will have to look at it again at a point or another.

Meh, just commenting. Thinking out loud.

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

21 minutes ago, Shark007 said:

I have it working in my quite large project which contains aprox 100 different controls.

Currently tracking down why my app take a full 5 seconds to open whereas it was instant before.

More thinking out loud.

Everything comes with a price. :whistle:

When the words fail... music speaks.

Link to comment
Share on other sites

Still thinking out load, The font looks better using a setting of 1. Using 0, or what I had before, is too bold'ish compared to using 1.

EDIT - Since solving the 5 second delay I was experiencing, I can now tell you that I have completely abondonned my old way of dealing with HiDpi Gui's and have now fully adopted this method.

After dumping the manifest method altogether and using UEZ's August 4th release, I'm a happy camper.

I still need to modify _WinAPI_DPI.au3 with the following though, 

Case @OSBuild > 13999
            $DPIAwareContext = ($DPIAwareContext < -5) ? -5 : ($DPIAwareContext > -1) ? -1 : $DPIAwareContext
            $iMode = ($iMode < 1) ? 1 : ($iMode > 2) ? 2 : $iMode
            Switch $iMode
                Case 1
                    _WinAPI_SetProcessDpiAwarenessContext($DPIAwareContext)
                    If @error Then Return SetError(3, 0, 0)
                Case 2
                    _WinAPI_SetThreadDpiAwarenessContext($DPIAwareContext)
                    If @error Then Return SetError(4, 0, 0)
            EndSwitch

otherwise, my GUI does not show.

 

Edited by Shark007
Link to comment
Share on other sites

...I'm spent. Tried all day and my idea of:
1) I'll catch it before resize, change the GUICtrlSetResizing() to $GUI_DOCKAUTO
2) after the "WM_DPICHANGED" took place, restore whatever resizing was set.

And I did it. But it does not work. It works but no cigar. Going back and forth a few times and unwanted resizing is introduced.

To find the point, just before WM_DPICHANGED and just right after, I put together a script with every entry in the helpfile (WinMsgCodes) and went at it by trial and error.
Was either that, or learn to code. Well I did that. In any case, the file(s) are in a ZIP at the 1st post ( or here ).

I'm out of good ideas. If you think of a functional approach, share it :) 

 

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

On 8/3/2023 at 9:49 PM, Shark007 said:

Still thinking out load, The font looks better using a setting of 1. Using 0, or what I had before, is too bold'ish compared to using 1.

EDIT - Since solving the 5 second delay I was experiencing, I can now tell you that I have completely abondonned my old way of dealing with HiDpi Gui's and have now fully adopted this method.

After dumping the manifest method altogether and using UEZ's August 4th release, I'm a happy camper.

I still need to modify _WinAPI_DPI.au3 with the following though, 

Case @OSBuild > 13999
            $DPIAwareContext = ($DPIAwareContext < -5) ? -5 : ($DPIAwareContext > -1) ? -1 : $DPIAwareContext
            $iMode = ($iMode < 1) ? 1 : ($iMode > 2) ? 2 : $iMode
            Switch $iMode
                Case 1
                    _WinAPI_SetProcessDpiAwarenessContext($DPIAwareContext)
                    If @error Then Return SetError(3, 0, 0)
                Case 2
                    _WinAPI_SetThreadDpiAwarenessContext($DPIAwareContext)
                    If @error Then Return SetError(4, 0, 0)
            EndSwitch

otherwise, my GUI does not show.

 

I was in conversation Shark007 and the issue is not that part of function! The issue is using x64 and #AutoIt3Wrapper_Res_HiDpi=y disables the _WinAPI_SetProcessDpiAwarenessContext() function but an error will not be set.

I updated the UDF and fixed some issue.

 

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 comment
Share on other sites

Since I'm still awake, here's the untouched script of "Resize Testbed":

Spoiler
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>


Opt("GUIResizeMode", $GUI_DOCKAUTO)

Global $idButton1, $idButton2, $idButton3, $idButton4, $idEdit1
Global $hForm, $idLabel1, $idLabel2, $idLabel3, $idLabel4
Global $idInput1, $idInput2, $idInput3, $idInput4, $idInput5, $idInput6


BuildTheForm()
Func BuildTheForm($iW = 600, $iH = 400)

    $hForm = GUICreate("Resize testbed", $iW, $iH, -1, -1, BitOR($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX, $WS_THICKFRAME, $WS_TABSTOP))

    $idButton1 = GUICtrlCreateButton("Button1 - Left Top", 10, 10, 120, 25)
    GUICtrlSetResizing(-1, $GUI_DOCKLEFT + $GUI_DOCKTOP + $GUI_DOCKWIDTH + $GUI_DOCKHEIGHT)
    $idLabel1 = GUICtrlCreateLabel("Label1 - Left Top", 10, 40, 120, 50, BitOR($SS_CENTER, $SS_CENTERIMAGE), $WS_EX_STATICEDGE)
    GUICtrlSetResizing(-1, $GUI_DOCKLEFT + $GUI_DOCKTOP + $GUI_DOCKWIDTH + $GUI_DOCKHEIGHT)

    $idButton2 = GUICtrlCreateButton("Button2 - Right Top", $iW - 130, 10, 120, 25)
    GUICtrlSetResizing(-1, $GUI_DOCKRIGHT + $GUI_DOCKTOP + $GUI_DOCKWIDTH + $GUI_DOCKHEIGHT)
    $idLabel2 = GUICtrlCreateLabel("Label2 - Right Top", $iW - 130, 40, 120, 50, BitOR($SS_CENTER, $SS_CENTERIMAGE), $WS_EX_STATICEDGE)
    GUICtrlSetResizing(-1, $GUI_DOCKRIGHT + $GUI_DOCKTOP + $GUI_DOCKWIDTH + $GUI_DOCKHEIGHT)

    $idButton3 = GUICtrlCreateButton("Button3 - Right Bottom", $iW - 130, $iH - 35, 120, 25)
    GUICtrlSetResizing(-1, $GUI_DOCKRIGHT + $GUI_DOCKBOTTOM + $GUI_DOCKWIDTH + $GUI_DOCKHEIGHT)
    $idLabel3 = GUICtrlCreateLabel("Label3 - Right Bottom", $iW - 130, $iH - 50 - 40, 120, 50, BitOR($SS_CENTER, $SS_CENTERIMAGE), $WS_EX_STATICEDGE)
    GUICtrlSetResizing(-1, $GUI_DOCKRIGHT + $GUI_DOCKBOTTOM + $GUI_DOCKWIDTH + $GUI_DOCKHEIGHT)

    $idButton4 = GUICtrlCreateButton("Button4 - Left Bottom", 10, $iH - 35, 120, 25)
    GUICtrlSetResizing(-1, $GUI_DOCKLEFT + $GUI_DOCKBOTTOM + $GUI_DOCKWIDTH + $GUI_DOCKHEIGHT)
    $idLabel4 = GUICtrlCreateLabel("Label4 - Left Bottom", 10, $iH - 50 - 40, 120, 50, BitOR($SS_CENTER, $SS_CENTERIMAGE), $WS_EX_STATICEDGE)
    GUICtrlSetResizing(-1, $GUI_DOCKLEFT + $GUI_DOCKBOTTOM + $GUI_DOCKWIDTH + $GUI_DOCKHEIGHT)

    For $n = 0 To 2
        Assign("idInput" & $n, GUICtrlCreateInput("Input" & $n + 1, 140, 11 + (28 * $n), $iW - 280, 21, BitOR($GUI_SS_DEFAULT_INPUT, $ES_CENTER, $ES_READONLY)))
        GUICtrlSetResizing(-1, $GUI_DOCKLEFT + $GUI_DOCKRIGHT + $GUI_DOCKTOP + $GUI_DOCKHEIGHT)
    Next

    For $m = 0 To 2
        Assign("idInput" & $m + $n + 1, GUICtrlCreateInput("Input" & $m + $n + 1, 140, $iH - 33 - (28 * $m), $iW - 280, 21, BitOR($GUI_SS_DEFAULT_INPUT, $ES_CENTER, $ES_READONLY)))
        GUICtrlSetResizing(-1, $GUI_DOCKLEFT + $GUI_DOCKRIGHT + $GUI_DOCKBOTTOM + $GUI_DOCKHEIGHT)
    Next

    $idEdit1 = GUICtrlCreateEdit("", 10, 100, $iW - 20, $iH - 200)
    GUICtrlSetData(-1, @CRLF & "  Crowded GUI, ah?." & @CRLF & @CRLF & "  Have fun with the controls." & @CRLF & "  Edit control or whatnot. Maybe a Listview ?.")
    GUICtrlSetResizing(-1, $GUI_DOCKLEFT + $GUI_DOCKRIGHT + $GUI_DOCKTOP + $GUI_DOCKBOTTOM)

    GUISetState(@SW_SHOW)
EndFunc   ;==>BuildForm

RunTheLoop()
Func RunTheLoop()
    Local $nMsg
    While 1
        $nMsg = GUIGetMsg()
        Switch $nMsg
            Case $GUI_EVENT_CLOSE
                GUIDelete()
                Exit

        EndSwitch
    WEnd
EndFunc   ;==>RunLoop

 

 and a picture:
image.png

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

Indeed, GUI / Ctrl resizing is another thing which must be tested...

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 comment
Share on other sites

..testing, I'll test all day.

Maybe writing down every control, wait for the OS to do it's thing and resize each control recalculating, given that changing anchors, kind of "drift pixels", one at the time but after 10 times of going back and forth, the GUI is crap.
It may just need that.

On the other hand, I have to get back to IRL, so to say. This week for me has been this and this alone.

Edited by argumentum

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...