Jump to content

Recommended Posts

Posted

Thank you as always!

2 hours ago, WildByDesign said:

What happens in the case of version mismatches between the bootstrapper DLL and the Windows App SDK that a user has on their machine?

I think it should be OK. It'll just try to load a requested runtime version - and it'll either succeed or fail. 

A few posts back, we found MddBootstrapInitialize2 reported success when the installed runtime differed from what we requested,  but the runtime didn't actually initialize.  So in response to that,  _WinUI3_Startup() now attempts to retrieve a version number to verify all is OK before returning success.

By memory, loading the "2.0 experimental3" version worked fine with our current bootstrapper, so I don't think its critical to keep this dll up to date.  But it might be worth double checking I guess. Either way I'll keep the dll up to date in the WinRT releases.

Also - the default runtime version that _WinUI3_Startup() targets is static, and that will change depending on the WinRT release.  This is because all our WinUI3 libraries are generated from one WinAPPSDK version, and so _WinUI3_Startup is setup to target that.  I'll pop an announcement up whenever the default version changes (I'll probably release whenever a new stable SDK drops), but there's certainly no plans to support parallel versions of the SDK!!!

3 hours ago, WildByDesign said:

. I've never fully understood where (or when) end users get updates to the Windows App SDK platform.

yeah generally end users don't. It's our responsibility as developers to distribute the runtime along with our software. (Multiple versions can co-exist).

This is probably worth a read around distribution, if we ever make it that far!
https://learn.microsoft.com/en-us/windows/apps/windows-app-sdk/deploy-unpackaged-apps

3 hours ago, WildByDesign said:

I feel like it's kind of unfortunate that MS doesn't store that bootstrapper DLL anywhere on a user's machine

yeah, a decision was made obviously made at some point to decouple the WinUI stuff from the OS. So lucky us I guess!

Posted (edited)

Hi guys, just FYI. 

Here's how the "override-able interfaces" stuff is currently looking for the next WinRT release.

In WinRT.au3...

  •  _WinRT_CreateOverridesObj($pFactory, $ahFunctions, $sOverriddenIID)
    • $pFactory must be a pointer to a "composable" interface.
    • The $ahFunctions param must be an array of handles returned from DllCallbackRegister().
    • The order is important - it must match the v-table of the interface that we're overriding.  (do not include IUnknown and IInspectable methods, these are handled internally)
  • _WinRT_DestroyOverridesObj($pOverrides, $bFreeCalbacks = True)

    • ATM the $pOverrides must be the same pointer as that returned by _WinRT_CreateOverridesObj. So be careful when using _WinRT_SwitchInterface() - it'll change your object pointer as you're flicking between interfaces!

    • By default DestroyOverridesObj frees the callbacks that were provided on creation of the object.  If we're using one function for multiple objects for eg., you may need to suppress this behavior by setting  $bFreeCalbacks to False.  (I may yet reverse the default setting for the param... I'll probably need to play with other objects with a few more override-able methods before deciding!)

    • The IUnknown/IInspectable funcs again are managed internally, and are not affected by the $bFreeCalbacks param.

And in WinRT_WinUI3.au3 there's a special func for OnLaunched().

  • _WinUI3_StartApp($sOnLaunchedFunc)
    • $sOnLaunchedFunc is the user function to be executed on Launch
    • The user func must have 2 params to receive the 2 objects..
      • Microsoft.UI.Xaml.Application
      • Microsoft.UI.Xaml.LaunchActivatedEventArgs pEventArgs
    • _WinUI3_StartApp will also call IApplicationStatics_Start() to kick off the dispatch loop. (for now anyway!)
      • I might take this part out if its necessary to do more stuff on the statics interface before launching!

ATM it looks kinda like this...

#include "..\Include\WinRT.au3"
#include "..\Include\WinRT_WinUI3.au3"
#include "..\Include\Classes\Microsoft.UI.Xaml.Application.au3"
#include "..\Include\Classes\Microsoft.UI.Xaml.LaunchActivatedEventArgs.au3"
#include "..\Include\Classes\Microsoft.UI.Xaml.Window.au3"

_WinRT_Startup()
_WinUI3_Startup()
_WinUI3_StartApp("OnLaunched")
_WinUI3_Shutdown()
_WinRT_Shutdown()

Func OnLaunched($pApplication, $pEventArgs)
    Local $pWindow = _WinRT_ActivateInstance("Microsoft.UI.Xaml.Window")
    _WinRT_SwitchInterface($pWindow, $sIID_IWindow)
    IWindow_Activate($pWindow)
EndFunc
Edited by MattyD
  • 4 months later...
Posted

@WildByDesign, this one's for you mate,

Mica in a normal win32 window without the extended frame business ;)

#include <GUIConstants.au3>
#include <WindowsConstants.au3>
#include "..\Include\WinRT.au3"
#include "..\Include\WinRT_WinUI3.au3"
#include "..\Include\Classes\Microsoft.UI.Composition.SystemBackdrops.MicaController.au3"
#include "..\Include\Classes\Microsoft.UI.Composition.SystemBackdrops.DesktopAcrylicController.au3"
#include "..\Include\Classes\Windows.UI.Composition.Desktop.DesktopWindowTarget.au3"
#include "..\Include\Classes\Windows.System.DispatcherQueueController.au3"
#include "..\Include\Classes\Windows.UI.Composition.Compositor.au3"
#include "..\Include\Classes\Windows.UI.Composition.Visual.au3"

Global Const $sIID_ICompositorDesktopInterop = "{29E691FA-4567-4DCA-B319-D0F207EB6807}"
$__g_mIIDs[$sIID_ICompositorDesktopInterop] = "ICompositorDesktopInterop"

Global Const $tagDispatcherQueueOptions  = "struct;dword dwSize;dword threadType;dword apartmentType;endstruct"
Global Const $DQTYPE_THREAD_DEDICATED = 1
Global Const $DQTYPE_THREAD_CURRENT = 2
Global Const $DQTAT_COM_NONE = 0
Global Const $DQTAT_COM_ASTA = 1
Global Const $DQTAT_COM_STA = 2

_Init()
_Main()
_Cleanup()

Func _Init()
    _WinRT_Startup()
    _WinUI3_Startup()
EndFunc

Func _Main()
    Local $hGUI = GUICreate("Mica", 400, 200, -1, -1, $WS_OVERLAPPEDWINDOW, $WS_EX_COMPOSITED)
    Local $pDispatcher = _WinRT_CreateDispatcherQueueController()
    Local $pCompositor = _WinRT_ActivateInstance("Windows.UI.Composition.Compositor")

    _WinRT_SwitchInterface($pCompositor, $sIID_ICompositorDesktopInterop)
    Local $pTarget = ICompositorDesktopInterop_CreateDesktopWindowTarget($pCompositor, $hGUI, False)


    _WinRT_SwitchInterface($pCompositor, $sIID_ICompositor)
    Local $pRoot = ICompositor_CreateContainerVisual($pCompositor)

    _WinRT_SwitchInterface($pTarget, $sIID_ICompositionTarget)
    ICompositionTarget_SetRoot($pTarget, $pRoot)
    _WinRT_DisplayError()

    Local $pMicaController = _WinRT_ActivateInstance("Microsoft.UI.Composition.SystemBackdrops.MicaController")
    _WinRT_SwitchInterface($pMicaController, $sIID_IMicaController2)
    IMicaController2_SetKind($pMicaController, $mMicaKind["Base"]) ; OR $mMicaKind["BaseAlt"]

    _WinRT_SwitchInterface($pMicaController, $sIID_ISystemBackdropController)
    _WinRT_SwitchInterface($pTarget, $sIID_IDesktopWindowTarget)
    ISystemBackdropController_SetTarget($pMicaController, _WinUI3_GetWindowIdFromWindow($hGUI), $pTarget)

    GUISetState()
    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE

    _WinRT_SwitchInterface($pMicaController, $sIID_IClosable)
    IClosable_Close($pMicaController)

    _WinRT_SwitchInterface($pRoot, $sIID_IClosable)
    IClosable_Close($pRoot)

    _WinRT_SwitchInterface($pTarget, $sIID_IClosable)
    IClosable_Close($pTarget)

    _WinRT_SwitchInterface($pCompositor, $sIID_IClosable)
    IClosable_Close($pCompositor)

    IUnknown_Release($pDispatcher)
EndFunc

Func _Cleanup()

    _WinRT_Shutdown()
    _WinUI3_Shutdown()
EndFunc

Func _WinRT_CreateDispatcherQueueController()

    Local $tOptions = DllStructCreate($tagDispatcherQueueOptions)
    $tOptions.dwSize = DllStructGetSize($tOptions)
    $tOptions.threadType = $DQTYPE_THREAD_CURRENT
    $tOptions.apartmentType = $DQTAT_COM_NONE

    Local $aCall = DllCall("CoreMessaging.dll", "long", "CreateDispatcherQueueController", "struct*", $tOptions, "ptr*", 0)
    Return SetError($aCall[0], 0, $aCall[2])
EndFunc

Func ICompositorDesktopInterop_CreateDesktopWindowTarget($pThis, $hTarget, $bIsTopmost)
    Local $vFailVal = False
    Local $pFunc = __WinRT_GetFuncAddress($pThis, 4)
    If @error Then Return SetError(@error, @extended, $vFailVal)
    If $hTarget And Not IsHWnd($hTarget) Then Return SetError($ERROR_INVALID_PARAMETER, 0, $vFailVal)

    Local $aCall = DllCallAddress("ulong", $pFunc, "ptr", $pThis, "hwnd", $hTarget, "bool", ($bIsTopmost = True), "ptr*", 0)
    If @error Then Return SetError(__WinRT_GetDllError(), 0, $vFailVal)
    Return SetError($aCall[0], 0, $aCall[4])

EndFunc   ;==>ICompositorDesktopInterop_CreateDesktopWindowTarget
Posted (edited)
1 hour ago, MattyD said:

this one's for you mate,

Mica in a normal win32 window without the extended frame business ;)

You just made my day, Matty! 😁

I am incredibly thankful. I certainly never would have been able to do it myself because the WinRT stuff still boggles my mind. Thank you.

EDIT: By the way, if you have a moment, could you please share an example with Acrylic?

I'm reading up on the controllers and such right now but I am not anywhere near understanding it yet. Regardless, I am going to spend the next hour or so trying to learn more because this is really neat. You've got the whole Mica effect which is great.

EDIT2: I like how the Mica effect can switch between dark mode and light mode.

Edited by WildByDesign
Posted (edited)

No problems. I found we also need $WS_CLIPCHILDREN in order to see controls too.

Still need to confirm what the most "correct" way is to remove a backdrop.  I'm just closing the backdrop controller atm, but not sure if we should be de-targeting a window's visual container first...  Anyway - there's no crashy crashy when we tear down windows, so we can't be doing anything too bad!

Edit: Added title bar effect.

#include <GUIConstants.au3>
#include <WindowsConstants.au3>
#include "..\Include\WinRT.au3"
#include "..\Include\WinRT_WinUI3.au3"
#include "..\Include\Classes\Microsoft.UI.Composition.SystemBackdrops.MicaController.au3"
#include "..\Include\Classes\Microsoft.UI.Composition.SystemBackdrops.DesktopAcrylicController.au3"
#include "..\Include\Classes\Windows.UI.Composition.Desktop.DesktopWindowTarget.au3"
#include "..\Include\Classes\Windows.System.DispatcherQueueController.au3"
#include "..\Include\Classes\Windows.UI.Composition.Compositor.au3"
#include "..\Include\Classes\Windows.UI.Composition.Visual.au3"

Global Const $sIID_ICompositorDesktopInterop = "{29E691FA-4567-4DCA-B319-D0F207EB6807}"
$__g_mIIDs[$sIID_ICompositorDesktopInterop] = "ICompositorDesktopInterop"

Global Const $tagDispatcherQueueOptions  = "struct;dword dwSize;dword threadType;dword apartmentType;endstruct"
Global Const $DQTYPE_THREAD_DEDICATED = 1
Global Const $DQTYPE_THREAD_CURRENT = 2
Global Const $DQTAT_COM_NONE = 0
Global Const $DQTAT_COM_ASTA = 1
Global Const $DQTAT_COM_STA = 2

Global Const $DWMSBT_AUTO = 0
Global Const $DWMSBT_NONE = 1
Global Const $DWMSBT_MAINWINDOW = 2
Global Const $DWMSBT_TRANSIENTWINDOW = 3
Global Const $DWMSBT_TABBEDWINDOW = 4

Global $pDispatcher, $pCompositor
Global $aObjects[0][4]

_Init()
_Main()
_Cleanup()


Func _Init()
    _WinRT_Startup()
    _WinUI3_Startup()
    $pDispatcher = _WinRT_CreateDispatcherQueueController()
    $pCompositor = _WinRT_ActivateInstance("Windows.UI.Composition.Compositor")
EndFunc

Func _Main()

    Local $iWindowCount = 1
    Local $hGUI = GUICreate("System Backdrops", 240, 100, -1, -1, BitOR($WS_OVERLAPPED, $WS_CAPTION, $WS_SYSMENU))
    Local $idCreateMica = GUICtrlCreateButton("Mica", 20, 20, 60, 60)
    Local $idCreateMicaAlt = GUICtrlCreateButton("Mica Alt", 90, 20, 60, 60)
    Local $idCreateAcrylic = GUICtrlCreateButton("Acrylic", 160, 20, 60, 60)

    GUISetState()
    Local $aMsg
    While 1
        $aMsg = GUIGetMsg($GUI_EVENT_ARRAY)
        Switch $aMsg[0]
            Case $GUI_EVENT_CLOSE
                DeleteWin($aMsg[1])
                $iWindowCount -= 1

            Case $idCreateMica
                _MicaWindow(200, 100)
                $iWindowCount += 1

            Case $idCreateMicaAlt
                _MicaWindow(200, 100, True)
                $iWindowCount += 1

            Case $idCreateAcrylic
                _AcrylicWindow(200, 100)
                $iWindowCount += 1

        EndSwitch
        If Not $iWindowCount Then ExitLoop
    WEnd
EndFunc


Func _MicaWindow($iWidth, $iHeight, $bAlternate = False)
    ReDim $aObjects[UBound($aObjects) + 1][4]
    Local $iIdx = UBound($aObjects) - 1

    Local $hGUI = GUICreate($bAlternate ? "MicaAlt" : "Mica", $iWidth, $iHeight, -1, -1, BitOR($WS_OVERLAPPED, $WS_CAPTION, $WS_SYSMENU, $WS_CLIPCHILDREN), $WS_EX_COMPOSITED)
    _SetNCBackdropType($hGUI, $bAlternate ? $DWMSBT_TABBEDWINDOW : $DWMSBT_MAINWINDOW)
    _CreateCloseButton($hGUI, $iWidth - 90, $iHeight - 35, 80, 25)

    _WinRT_SwitchInterface($pCompositor, $sIID_ICompositorDesktopInterop)
    Local $pTarget = ICompositorDesktopInterop_CreateDesktopWindowTarget($pCompositor, $hGUI, False)

    _WinRT_SwitchInterface($pCompositor, $sIID_ICompositor)
    Local $pRoot = ICompositor_CreateContainerVisual($pCompositor)

    _WinRT_SwitchInterface($pTarget, $sIID_ICompositionTarget)
    ICompositionTarget_SetRoot($pTarget, $pRoot)

    Local $pSysBkdropController = _WinRT_ActivateInstance("Microsoft.UI.Composition.SystemBackdrops.MicaController")
    _WinRT_SwitchInterface($pSysBkdropController, $sIID_IMicaController2)
    IMicaController2_SetKind($pSysBkdropController, $bAlternate ? $mMicaKind["BaseAlt"] : $mMicaKind["Base"])

    _WinRT_SwitchInterface($pSysBkdropController, $sIID_ISystemBackdropController)
    _WinRT_SwitchInterface($pTarget, $sIID_IDesktopWindowTarget)
    ISystemBackdropController_SetTarget($pSysBkdropController, _WinUI3_GetWindowIdFromWindow($hGUI), $pTarget)

    GUISetState(@SW_SHOW, $hGUI)

    $aObjects[$iIdx][0] = $hGUI
    $aObjects[$iIdx][1] = $pSysBkdropController
    $aObjects[$iIdx][2] = $pRoot
    $aObjects[$iIdx][3] = $pTarget
EndFunc

Func _AcrylicWindow($iWidth, $iHeight)
    ReDim $aObjects[UBound($aObjects) + 1][4]
    Local $iIdx = UBound($aObjects) - 1

    Local $hGUI = GUICreate("Acrylic", $iWidth, $iHeight, -1, -1, BitOR($WS_OVERLAPPED, $WS_CAPTION, $WS_SYSMENU, $WS_CLIPCHILDREN), $WS_EX_COMPOSITED)
    _SetNCBackdropType($hGUI, $DWMSBT_TRANSIENTWINDOW)
    _CreateCloseButton($hGUI, $iWidth - 90, $iHeight - 35, 80, 25)

    _WinRT_SwitchInterface($pCompositor, $sIID_ICompositorDesktopInterop)
    Local $pTarget = ICompositorDesktopInterop_CreateDesktopWindowTarget($pCompositor, $hGUI, False)

    _WinRT_SwitchInterface($pCompositor, $sIID_ICompositor)
    Local $pRoot = ICompositor_CreateContainerVisual($pCompositor)

    _WinRT_SwitchInterface($pTarget, $sIID_ICompositionTarget)
    ICompositionTarget_SetRoot($pTarget, $pRoot)

    Local $pSysBkdropController = _WinRT_ActivateInstance("Microsoft.UI.Composition.SystemBackdrops.DesktopAcrylicController")
    _WinRT_SwitchInterface($pSysBkdropController, $sIID_ISystemBackdropController)
    _WinRT_SwitchInterface($pTarget, $sIID_IDesktopWindowTarget)

    ISystemBackdropController_SetTarget($pSysBkdropController, _WinUI3_GetWindowIdFromWindow($hGUI), $pTarget)

    $aObjects[$iIdx][0] = $hGUI
    $aObjects[$iIdx][1] = $pSysBkdropController
    $aObjects[$iIdx][2] = $pRoot
    $aObjects[$iIdx][3] = $pTarget

    GUISetState(@SW_SHOW, $hGUI)
EndFunc

Func DeleteWin($hWnd)
    For $i = 0 To UBound($aObjects) - 1
        If $hWnd = $aObjects[$i][0] Then
            For $j = 1 To UBound($aObjects, 2) - 1
                _WinRT_SwitchInterface($aObjects[$i][$j], $sIID_IClosable)
                IClosable_Close($aObjects[$i][$j])
            Next
            $aObjects[$i][0] = 0
        EndIf
    Next
    GUIDelete($hWnd)
EndFunc

Func _Cleanup()
    _WinRT_SwitchInterface($pCompositor, $sIID_IClosable)
    IClosable_Close($pCompositor)
    IUnknown_Release($pDispatcher)
    _WinRT_Shutdown()
    _WinUI3_Shutdown()
EndFunc

Func _WinRT_CreateDispatcherQueueController()
    Local $tOptions = DllStructCreate($tagDispatcherQueueOptions)
    $tOptions.dwSize = DllStructGetSize($tOptions)
    $tOptions.threadType = $DQTYPE_THREAD_CURRENT
    $tOptions.apartmentType = $DQTAT_COM_NONE

    Local $aCall = DllCall("CoreMessaging.dll", "long", "CreateDispatcherQueueController", "struct*", $tOptions, "ptr*", 0)
    Return SetError($aCall[0], 0, $aCall[2])
EndFunc

Func ICompositorDesktopInterop_CreateDesktopWindowTarget($pThis, $hTarget, $bIsTopmost)
    Local $vFailVal = False
    Local $pFunc = __WinRT_GetFuncAddress($pThis, 4)
    If @error Then Return SetError(@error, @extended, $vFailVal)
    If $hTarget And Not IsHWnd($hTarget) Then Return SetError($ERROR_INVALID_PARAMETER, 0, $vFailVal)

    Local $aCall = DllCallAddress("ulong", $pFunc, "ptr", $pThis, "hwnd", $hTarget, "bool", ($bIsTopmost = True), "ptr*", 0)
    If @error Then Return SetError(__WinRT_GetDllError(), 0, $vFailVal)
    Return SetError($aCall[0], 0, $aCall[4])
EndFunc   ;==>ICompositorDesktopInterop_CreateDesktopWindowTarget

Func _CreateCloseButton($hWnd, $iX, $iY, $iWidth, $iHeight, $iStyle = -1, $iExStyle = -1)
    If $iStyle = -1 Then $iStyle = BitOR($WS_VISIBLE, $WS_CHILD)
    If $iExStyle = -1 Then $iExStyle = 0
    $hButton = _WinAPI_CreateWindowEx($iExStyle, $WC_BUTTON, "Close", $iStyle, $iX, $iY, $iWidth, $iHeight, $hWnd, $IDCANCEL, _WinAPI_GetModuleHandle(0), 0)
    $hButton = _SendMessage($hButton, $WM_SETFONT, _WinAPI_GetStockObject($DEFAULT_GUI_FONT), True)
    Return $hButton
EndFunc

Func _SetNCBackdropType($hWnd, $iBackdropType)
    Local $aCall = DllCall("Dwmapi.dll", "long", "DwmSetWindowAttribute", "hwnd", $hWnd, "dword", $DWMWA_SYSTEMBACKDROP_TYPE, "dword*", $iBackdropType, "dword", 4)
    Return SetError($aCall[0], 0, $aCall[0] = $S_OK)
EndFunc
Edited by MattyD
Posted
4 hours ago, MattyD said:

No problems. I found we also need $WS_CLIPCHILDREN in order to see controls too.

Thanks. This example is a really nice example for showcasing the Win11 materials. I like how you've done a separate button to test each one. Excellent example.

The only concern that I have is the WS_EX_COMPOSITED extended style. I know that Microsoft has that in all of their examples for Win11 materials on Win32 GUI, so clearly there is a reason for it. I personally like WS_EX_COMPOSITED, but it is a double-edged sword in AutoIt due to the way in which AutoIt creates their GUI windows:

Extended Window Styles (Microsoft):

Quote

This cannot be used if the window has a class style of CS_OWNDC, CS_CLASSDC, or CS_PARENTDC.

I also tested your examples at one point removing the WS_EX_COMPOSITED extended style. I didn't notice any issues specific to having or not having WS_EX_COMPOSITED. The background (right side and bottom edge of frame) seems to have a white flicker when resizing the GUI no matter what. I'm not sure exactly why.

Do you foresee any issues without WS_EX_COMPOSITED?

Posted

Yeah you're right, the AutoIt GUI class does have CS_OWNDC.

13 hours ago, WildByDesign said:

Do you foresee any issues without WS_EX_COMPOSITED?

I'm still sussing things out -  WS_EX_COMPOSITED was in the Microsoft example that I was trying to emulate, but it seems to work ok without it... Not sure if we need this to blend our Win32 buttons properly if clipping isn't the answer.

If it turns out that WS_EX_COMPOSITED is required,  we can strip the CS_OWNDC style from our GUI class before creating windows.

Local $sAu3GUIClass = "AutoIt v3 GUI"
Local $tInfo = _WinAPI_GetClassInfoEx($sAu3GUIClass, _WinAPI_GetModuleHandle(0))
$tInfo.Size = DllStructGetSize($tInfo)
$tInfo.Style = 0x0B
Local $tClassName = DllStructCreate("wchar name[257]")
$tClassName.name = $sAu3GUIClass
$tInfo.ClassName = DllStructGetPtr($tClassName)
_WinAPI_UnregisterClass($sAu3GUIClass, _WinAPI_GetModuleHandle(0))
_WinAPI_RegisterClassEx($tInfo)

RE clipping. - everything is clipped as a square, so our buttons with rounded corners are a bit ugly.  If we can't get the 2 worlds working together nicely I've had some success using layered windows to get the buttons floating nicely on top.  I doubt its the most efficient way of approaching things - but hey.  I'll post an example of that in a little bit.

I can't find much in the way of doco/examples around any of this, so its all very much "suck it and see" ATM

Posted
7 hours ago, MattyD said:

If it turns out that WS_EX_COMPOSITED is required,  we can strip the CS_OWNDC style from our GUI class before creating windows.

Local $sAu3GUIClass = "AutoIt v3 GUI"
Local $tInfo = _WinAPI_GetClassInfoEx($sAu3GUIClass, _WinAPI_GetModuleHandle(0))
$tInfo.Size = DllStructGetSize($tInfo)
$tInfo.Style = 0x0B
Local $tClassName = DllStructCreate("wchar name[257]")
$tClassName.name = $sAu3GUIClass
$tInfo.ClassName = DllStructGetPtr($tClassName)
_WinAPI_UnregisterClass($sAu3GUIClass, _WinAPI_GetModuleHandle(0))
_WinAPI_RegisterClassEx($tInfo)

If this type of magic could be done (safely), you could potentially save decades of flickering ListView headers that are affected when WS_EX_COMPOSITED is used on an AutoIt GUI with WS_EX_COMPOSITED extended style applied.

7 hours ago, MattyD said:

RE clipping. - everything is clipped as a square, so our buttons with rounded corners are a bit ugly. 

I didn't have much luck. Some, but not much. I tried handling the brush returned from WM_CTLCOLORBTN which was slightly better, but still left some artifacts.

7 hours ago, MattyD said:

If we can't get the 2 worlds working together nicely I've had some success using layered windows to get the buttons floating nicely on top.  I doubt its the most efficient way of approaching things - but hey.  I'll post an example of that in a little bit.

For sure, even if it does not end up being a solution to this specific issue, I would definitely like to see this layered windows method with the buttons.

7 hours ago, MattyD said:

I can't find much in the way of doco/examples around any of this, so its all very much "suck it and see" ATM

You're right, there isn't much docs for Mica and Win32 specifically. I'm guessing we are lucky that they even extended some of it to Win32.

By the way, do they allow using the Mica/Acrylic created brushes in Win32?

My guess is no, but I figure you would know better. They have details about creating these types of brushes but I have a feeling that they don't extend those to Win32.

Posted
7 hours ago, MattyD said:

we can strip the CS_OWNDC style from our GUI class before creating windows.

How would you strip it before the window is created?

Or would that mean avoiding the use of GUICreate and using CreateWindowEx API instead?

It just boggles my mind on how to catch it early enough.

Posted

 

2 minutes ago, WildByDesign said:
7 hours ago, MattyD said:

If we can't get the 2 worlds working together nicely I've had some success using layered windows to get the buttons floating nicely on top.  I doubt its the most efficient way of approaching things - but hey.  I'll post an example of that in a little bit.

For sure, even if it does not end up being a solution to this specific issue, I would definitely like to see this layered windows method with the buttons.

 Gonna have to backtrack on that sorry! - I was doing something dumb🤦‍♂️

My current theory is that the WinRT compositor just paints last - after a widow's traditional paint cycle. If this is always True,  neither WS_EX_COMPOSITED or WS_EX_LAYERED will be able to save us. The compositor will ultimately just paint its visual tree over the top. But I could be totally wrong about this too.

Clipping children works because the parent is not allowed to paint into a child's region at all.. So we can't paint over a button - but we also can't paint a mica background behind it. 

It looks like you can do some very cool things with the compositor.  But perhaps its not best suited to being a backdrop for win32 controls!

10 minutes ago, WildByDesign said:
7 hours ago, MattyD said:

we can strip the CS_OWNDC style from our GUI class before creating windows.

How would you strip it before the window is created?

Or would that mean avoiding the use of GUICreate and using CreateWindowEx API instead?

It just boggles my mind on how to catch it early enough.

Its just a sequence thing, not a race ;).  AutoIt registers a window Class on startup named "AutoIt v3 GUI", and we get a window of this class by calling GUICreate(). 

We can happily query, modify, and re-register that class - but only while there's no AutoIt GUIs  around.

42 minutes ago, WildByDesign said:

If this type of magic could be done (safely)...

I haven't tested anything, but If you're just doing stock windows things I'd imagine it should be pretty safe.  If its going to break it'll likely be around autoit-specific funcs that customize the look - so things like GuiSetBkColor etc.

Posted

Alright, I managed to get the layered window working in the end, but we run into the same trouble. The button background is part of the button - so we still get a square surrounding it.  We can make the button background transparent and _SetNCBackdropType() will fill in the gaps with a material... but your mouse will simply click through that bit of the window.

Comping together the 2 UI frameworks is confirmed a no-go.  There's event a name for it:

Quote

When two different UI technologies are used together, such as WPF and the Visual Layer, they are each responsible for drawing their own pixels on the screen, and they can't share pixels. As a result, Visual Layer content is always rendered on top of other UI content. (This is known as the airspace issue.)

We can restrict where the button can paint by setting a region though. This looks great, but it won't help with things like labels - good luck with cutting holes around text!

Func _CreateCloseButton($hWnd, $iX, $iY, $iWidth, $iHeight, $iStyle = -1, $iExStyle = -1)
    If $iStyle = -1 Then $iStyle = BitOR($WS_VISIBLE, $WS_CHILD)
    If $iExStyle = -1 Then $iExStyle = 0
    $hButton = _WinAPI_CreateWindowEx($iExStyle, $WC_BUTTON, "Close", $iStyle, $iX, $iY, $iWidth, $iHeight, $hWnd, $IDCANCEL, _WinAPI_GetModuleHandle(0), 0)
   _SendMessage($hButton, $WM_SETFONT, _WinAPI_GetStockObject($DEFAULT_GUI_FONT), True)
    Local $hRgn = _WinAPI_CreateRoundRectRgn(1, 1, $iWidth, $iHeight, 4, 4)
    _WinAPI_SetWindowRgn($hButton, $hRgn, False)
    Return $hButton
EndFunc

 

Posted
19 hours ago, MattyD said:

Comping together the 2 UI frameworks is confirmed a no-go.

Yeah it definitely seems like we are going against the grain on this one. More cons than pros unfortunately.

I see that you've added the backdrops in your updated WinRT 1.7 release which is nice. It definitely makes sense to keep WinUI3 with WinUI3 but not mix with Win32 as we've just learned.

I appreciate you digging into this. Even though it wasn't entirely successful in the end, it was fun and I still learned a few things.

Posted

Access to the compositor still has value, so the exercise was worth while. It looks like you can do all sorts of fancy animations in there and such.

At some point I'll dig into that a bit more, time permitting..

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
×
×
  • Create New...