Modify

Opened 3 months ago

Closed 3 months ago

#3992 closed Bug (Fixed)

_WinAPI_DwmSetWindowAttribute() remove child proofing

Reported by: argumentum <argumentum@…> Owned by: Jpm
Milestone: 3.3.17.0 Component: AutoIt
Version: 3.3.16.1 Severity: None
Keywords: DwmSetWindowAttribute Cc:

Description

_WinAPI_DwmSetWindowAttribute() does not come with an example so is not used much. Looking at it, it would not work nowadays, because only functional enumerators of the time of coding are permitted.

Func _WinAPI_DwmSetWindowAttribute($hWnd, $iAttribute, $iData)
	;Switch $iAttribute ; https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute
	;	Case 2, 3, 4, 6, 7, 8, 10, 11, 12
	;	Case Else
	;		Return SetError(1, 0, 0)
	;EndSwitch
	Local $aCall = DllCall('dwmapi.dll', 'long', 'DwmSetWindowAttribute', 'hwnd', $hWnd, 'dword', $iAttribute, _
			'dword*', $iData, 'dword', 4)
	If @error Then Return SetError(@error, @extended, 0)
	If $aCall[0] Then Return SetError(10, $aCall[0], 0)
	Return 1
EndFunc   ;==>_WinAPI_DwmSetWindowAttribute

I ask to remove the $iAttribute filter.

In https://www.autoitscript.com/forum/topic/211196-gui-title-bar-dark-theme-an-elegant-solution-using-dwmapi/?do=findComment&comment=1527581 , if _WinAPI_DwmSetWindowAttribute() was to be used, it'd fail, due to this filter.

Attachments (0)

Change History (11)

comment:1 Changed 3 months ago by argumentum <argumentum@…>

_WinAPI_DwmSetWindowAttribute() does not come with an example

Ok, here is a simple one:

#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
#include <WinAPIGdi.au3>

Example()

Func Example()
	; Create a GUI with various controls.
	Local $hGUI = GUICreate("Example", 300, 200)

	; Create a checkbox control.
	Local $idCheckbox = GUICtrlCreateCheckbox("Disable GUI animation", 10, 10, 185, 25)
	Local $idButton_Close = GUICtrlCreateButton("Close", 210, 170, 85, 25)

	; Display the GUI.
	GUISetState(@SW_SHOW, $hGUI)

	; Loop until the user exits.
	While 1
		Switch GUIGetMsg()
			Case $GUI_EVENT_CLOSE, $idButton_Close
				ExitLoop

			Case $idCheckbox
				If _IsChecked($idCheckbox) Then
					_WinAPI_DwmSetWindowAttribute($hGUI, $DWMWA_TRANSITIONS_FORCEDISABLED, True) ; disable window animation
				Else
					_WinAPI_DwmSetWindowAttribute($hGUI, $DWMWA_TRANSITIONS_FORCEDISABLED, False) ; enable window animation
				EndIf

		EndSwitch
	WEnd

	; Delete the previous GUI and all controls.
	GUIDelete($hGUI)
EndFunc   ;==>Example

comment:2 Changed 3 months ago by argumentum <argumentum@…>

Ok, here is a simple one:

"#include <MsgBoxConstants.au3>" is not used and should be removed.

comment:3 Changed 3 months ago by Jpm

What is the effect of such attribute change?
it is better that something change after clicking the checkbox

comment:4 Changed 3 months ago by argumentum <argumentum@…>

it is better that something change after clicking the checkbox

Ok, this will show the difference between on setting and another.

#include <GUIConstantsEx.au3>
#include <WinAPIGdi.au3>
#include <EditConstants.au3>

Global $hGUI

Example()
Func Example()
	; Create a GUI with various controls.
	$hGUI = GUICreate("Example", 300, 200)

	; Create a checkbox control.
	Local $idCheckbox = GUICtrlCreateCheckbox("Disable GUI animation", 10, 10, 185, 25)
	Local $idButton_Close = GUICtrlCreateButton("Close", 210, 170, 85, 25)
	GUICtrlCreateEdit(@CRLF & "Clicking the checkbox will change the transition" & _
				@CRLF & " effect shown while Minimize/Restore/Maximize", 10, 50, 280, _
				70, BitOR($ES_CENTER,$ES_AUTOVSCROLL,$ES_AUTOHSCROLL,$ES_READONLY,$ES_WANTRETURN))

	; Display the GUI.
	GUISetState(@SW_SHOW, $hGUI)

	; Loop until the user exits.
	While 1
		Switch GUIGetMsg()
			Case $GUI_EVENT_CLOSE, $idButton_Close
				ExitLoop

			Case $idCheckbox
				If _IsChecked($idCheckbox) Then

					_WinAPI_DwmSetWindowAttribute($hGUI, $DWMWA_TRANSITIONS_FORCEDISABLED, True) ; disable window animation
					LetsSeeTheDifference()
				Else
					_WinAPI_DwmSetWindowAttribute($hGUI, $DWMWA_TRANSITIONS_FORCEDISABLED, False) ; enable window animation
					LetsSeeTheDifference()
				EndIf

		EndSwitch
	WEnd

	; Delete the previous GUI and all controls.
	GUIDelete($hGUI)
EndFunc   ;==>Example

Func LetsSeeTheDifference()
	Sleep(200)
	WinSetState($hGUI, "", @SW_MINIMIZE)
	Sleep(500)
	WinSetState($hGUI, "", @SW_RESTORE)
EndFunc

Func _IsChecked($idControlID)
	Return BitAND(GUICtrlRead($idControlID), $GUI_CHECKED) = $GUI_CHECKED
EndFunc   ;==>_IsChecked

comment:5 Changed 3 months ago by argumentum <argumentum@…>

..I find this to be a nicer looking GUI and code:

#include <GUIConstantsEx.au3>
#include <WinAPIGdi.au3>
#include <EditConstants.au3>

Global $hGUI

Example()
Func Example()
	; Create a GUI with various controls.
	$hGUI = GUICreate("Example", 300, 200)

	; Create a checkbox control.
	Local $idCheckbox = GUICtrlCreateCheckbox("Disable GUI animation", 10, 10, 185, 25)
	Local $idButton_Close = GUICtrlCreateButton("Close", 210, 170, 85, 25)
	GUICtrlCreateEdit(@CRLF & "Clicking the checkbox will change the transition" & _
			@CRLF & " effect shown while Minimize/Restore/Maximize.", 10, 60, 280, 70, _
			BitOR($ES_CENTER, $ES_AUTOVSCROLL, $ES_AUTOHSCROLL, $ES_READONLY))

	; Display the GUI.
	GUISetState(@SW_SHOW, $hGUI)

	; Loop until the user exits.
	While 1
		Switch GUIGetMsg()
			Case $GUI_EVENT_CLOSE, $idButton_Close
				ExitLoop

			Case $idCheckbox
				If _IsChecked($idCheckbox) Then ; disable window animation
					_WinAPI_DwmSetWindowAttribute($hGUI, $DWMWA_TRANSITIONS_FORCEDISABLED, True)
					LetsSeeTheDifference()
				Else                            ;  enable window animation
					_WinAPI_DwmSetWindowAttribute($hGUI, $DWMWA_TRANSITIONS_FORCEDISABLED, False)
					LetsSeeTheDifference()
				EndIf

		EndSwitch
	WEnd

	; Delete the previous GUI and all controls.
	GUIDelete($hGUI)
EndFunc   ;==>Example

Func LetsSeeTheDifference()
	Sleep(200)
	WinSetState($hGUI, "", @SW_MINIMIZE)
	Sleep(500)
	WinSetState($hGUI, "", @SW_RESTORE)
EndFunc   ;==>LetsSeeTheDifference

Func _IsChecked($idControlID)
	Return BitAND(GUICtrlRead($idControlID), $GUI_CHECKED) = $GUI_CHECKED
EndFunc   ;==>_IsChecked

comment:6 Changed 3 months ago by argumentum <argumentum@…>

This 2nd example will work once the $iAttribute filter is removed from the function.

#include <GUIConstantsEx.au3>
#include <WinAPIGdi.au3>
#include <EditConstants.au3>

Example() ; Win 10 onwards
Func Example()
	; Create a GUI with various controls.
	Local $hGUI = GUICreate("Example", 300, 200)
	Local Const $DWMWA_USE_IMMERSIVE_DARK_MODE = (@osbuild <= 18985) ? 19 : 20

	; Create a checkbox control.
	Local $idCheckbox = GUICtrlCreateCheckbox("Use Dark mode frame", 10, 10, 185, 25)
	Local $idButton_Close = GUICtrlCreateButton("Close", 210, 170, 85, 25)
	GUICtrlCreateEdit(@CRLF & "Clicking the checkbox allows the window frame " & _
			@CRLF & " for this window to be drawn in dark mode colors" & _
			@CRLF & " when the dark mode system setting is enabled.", 10, 60, 280, 75, _
			BitOR($ES_CENTER, $ES_AUTOVSCROLL, $ES_AUTOHSCROLL, $ES_READONLY))

	; Display the GUI.
	GUISetState(@SW_SHOW, $hGUI)

	; Loop until the user exits.
	While 1
		Switch GUIGetMsg()
			Case $GUI_EVENT_CLOSE, $idButton_Close
				ExitLoop

			Case $idCheckbox
				If _IsChecked($idCheckbox) Then ;  enable window frame dark mode
					_WinAPI_DwmSetWindowAttribute($hGUI, $DWMWA_USE_IMMERSIVE_DARK_MODE, True)
					WinActivate("[CLASS:Progman;]")
					WinActivate($hGUI)
				Else                            ;  disable window frame dark mode
					_WinAPI_DwmSetWindowAttribute($hGUI, $DWMWA_USE_IMMERSIVE_DARK_MODE, False)
					WinActivate("[CLASS:Progman;]")
					WinActivate($hGUI) ; To refresh the frame
				EndIf

		EndSwitch
	WEnd

	; Delete the previous GUI and all controls.
	GUIDelete($hGUI)
EndFunc   ;==>Example

Func _IsChecked($idControlID)
	Return BitAND(GUICtrlRead($idControlID), $GUI_CHECKED) = $GUI_CHECKED
EndFunc   ;==>_IsChecked

comment:7 Changed 3 months ago by Jpm

Is it normal that the Windows title get dark and after back the same in my case Blue?

comment:8 Changed 3 months ago by argumentum <argumentum@…>

In the focus window, the accent color would be applied for "light mode".
I use more than one non-standard theme https://www.autoitscript.com/forum/index.php?showtopic=211400&view=findpost&p=1529608 on my PC.
I'd have to test in other PCs to have a global assessment of what does actually happen on each version and setting.

A highly requested feature in the forum in regards to Dark mode, is to make the caption title look, in our win32 GUI, black as in those in the rest of the OS. This example shows how.
The call is not meant to go back and forth, but a declaration in the GUI setting to True before @SW_SHOW, otherwise don't use it for light mode as light mode is the default anyway.
In this case, the example showcases the back and forth for a "wow" factor. It will not brake anything. It only affects the current GUI. Nonetheless the change in behavior when changing back to "light mode" is something to be noted, all through MSDN is unlikely to go into specifics. They do say that is for Win11 22000 onwards. Yet the example is noteworthy.

This code below is better. More information too.

#include <GUIConstantsEx.au3>
#include <WinAPIGdi.au3>
#include <EditConstants.au3>

Global $hGUI

Example() ; Win 10 onwards
Func Example()
	; Create a GUI with various controls.
	$hGUI = GUICreate("Example", 300, 200)

	Local Const $DWMWA_USE_IMMERSIVE_DARK_MODE = (@osbuild <= 18985) ? 19 : 20
; 		DWMWA_USE_IMMERSIVE_DARK_MODE ; https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute
; 		Use with DwmSetWindowAttribute. Allows the window frame for this window to be drawn in dark mode colors when the dark mode system setting is enabled.
; 		For compatibility reasons, all windows default to light mode regardless of the system setting.
; 		The pvAttribute parameter points to a value of type BOOL. TRUE to honor dark mode for the window, FALSE to always use light mode.
; 		This value is supported starting with Windows 11 Build 22000.

	; Create a checkbox control.
	Local $idCheckbox = GUICtrlCreateCheckbox("Use Dark mode frame", 10, 10, 185, 25)
	Local $idButton_Close = GUICtrlCreateButton("Close", 210, 170, 85, 25)
	GUICtrlCreateEdit(@CRLF & "Clicking the checkbox allows the window frame " & _
			@CRLF & " for this window to be drawn in dark mode colors" & _
			@CRLF & " when the dark mode system setting is enabled.", 10, 60, 280, 75, _
			BitOR($ES_CENTER, $ES_AUTOVSCROLL, $ES_AUTOHSCROLL, $ES_READONLY))

	; Display the GUI.
	GUISetState(@SW_SHOW, $hGUI)

	; Loop until the user exits.
	While 1
		Switch GUIGetMsg()
			Case $GUI_EVENT_CLOSE, $idButton_Close
				ExitLoop

			Case $idCheckbox
				If _IsChecked($idCheckbox) Then ;  enable window frame dark mode
					_WinAPI_DwmSetWindowAttribute_($hGUI, $DWMWA_USE_IMMERSIVE_DARK_MODE, True)
					LetsSeeTheDifference()
				Else                            ;  disable window frame dark mode
					_WinAPI_DwmSetWindowAttribute_($hGUI, $DWMWA_USE_IMMERSIVE_DARK_MODE, False)
					LetsSeeTheDifference()
				EndIf

		EndSwitch
	WEnd

	; Delete the previous GUI and all controls.
	GUIDelete($hGUI)
EndFunc   ;==>Example

Func _IsChecked($idControlID)
	Return BitAND(GUICtrlRead($idControlID), $GUI_CHECKED) = $GUI_CHECKED
EndFunc   ;==>_IsChecked

Func LetsSeeTheDifference()
	WinActivate("[CLASS:Progman;]") ; To refresh the frame.
	WinActivate($hGUI) ;              Only needed for the constant back and forth in this demo.
EndFunc

comment:9 Changed 3 months ago by argumentum <argumentum@…>

Is it normal that the Windows title get dark

Yes, is in dark mode

and after back the same in my case Blue?

Yes, it should look the same as before.

I looked around in other PCs, and the behavior is in my short testing, without unexpected artifacts.

If you find an odd behavior, PM me the 3 pics of the cycle. Loaded, swap to "Dark Mode", swap back to "Light Mode".

comment:10 Changed 3 months ago by Jpm

I pm you the pictures

comment:11 Changed 3 months ago by Jpm

  • Milestone set to 3.3.17.0
  • Owner set to Jpm
  • Resolution set to Fixed
  • Status changed from new to closed

Fixed by revision [13037] in version: 3.3.17.0

Guidelines for posting comments:

  • You cannot re-open a ticket but you may still leave a comment if you have additional information to add.
  • In-depth discussions should take place on the forum.

For more information see the full version of the ticket guidelines here.

Add Comment

Modify Ticket

Action
as closed The owner will remain Jpm.
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.