WildByDesign Posted Sunday at 01:54 PM Posted Sunday at 01:54 PM (edited) This is a continuation of a script from the SampleControls.au3 in Dark Mode and is a combination of the work of @UEZ and @MattyD. Some of the changes that I have made: Modified the parameters of MsgBoxEx() to match the parameters from the built-in AutoIt MsgBox() function Allows users to simply switch MsgBox() to MsgBoxEx() within their scripts DarkMode_DarkTheme is used for buttons on Win11 24H2/25H2 (builds 26100.6899 and higher) DarkMode_Explorer is used for buttons on Win10 and Win11 (builds 26100.6898 and lower) Added DPI scaling which was needed for some measurements Fixed issue with top background color around border of button(s) MsgBoxEx.au3 MsgBoxEx-Example.au3 Edited 4 hours ago by WildByDesign UEZ, Danyfirex and bladem2003 2 1
WildByDesign Posted Sunday at 01:57 PM Author Posted Sunday at 01:57 PM @MattyD There is one area that I need help with if you have a moment. I really like the idea of adding the timer countdown to the button (as you have done) when a timer has been set. However, I don't necessarily like the idea of adding a custom text to the button in addition to that countdown. My idea would be to grab the original text for whichever button is to receive the countdown timer. I believe that we could use GetDlgItemText to obtain the original text from the button and append the [x] countdown timer to it. Does this sound like an idea that is technically feasible and, if so, would you please be able to help with this part? Thank you.
MattyD Posted Sunday at 10:34 PM Posted Sunday at 10:34 PM Yeah, its pretty straight forward. Func _WinAPI_GetDlgItemText($hDialog, $iDlgItem) Local $aCall = DllCall("user32.dll", "uint", "GetDlgItemTextW", "hwnd", $hDialog, "int", $iDlgItem, "wstr", "", "int", 65536) Return SetError(@error, @extended, @error ? "" : $aCall[3]) EndFunc When using "wstr", I believe autoit creates a buffer size of 65536 characters. This is fine - but its obviously overkill. GetDlgItemText is just a glorified WM_GETTEXT msg, so its also possible to get the required buffer size with WM_GETTEXTLENGTH. Func _WinAPI_GetDlgItemText($hDlg, $iDlgItem) Local $hCtrl, $iBuffLen, $tBuff, $sResult = "" $hCtrl = _WinAPI_GetDlgItem($hDlg, $iDlgItem) If Not @error Then $iBuffLen = _SendMessage($hCtrl, $WM_GETTEXTLENGTH) If Not @error Then $tBuff = DllStructCreate(StringFormat("wchar[%d]", $iBuffLen + 1)) _SendMessage($hCtrl, $WM_GETTEXT, $iBuffLen + 1, DllStructGetPtr($tBuff)) If Not @error Then $sResult = DllStructGetData($tBuff, 1) EndIf Return SetError(@error, @extended, $sResult) EndFunc WildByDesign 1
WildByDesign Posted Sunday at 11:34 PM Author Posted Sunday at 11:34 PM (edited) 1 hour ago, MattyD said: GetDlgItemText is just a glorified WM_GETTEXT msg, so its also possible to get the required buffer size with WM_GETTEXTLENGTH. This works perfectly. Thank you. I just noticed something that differs from your MsgBoxEx and the built-in MsgBox when using the timer. The built-in MsgBox returns $IDTIMEOUT (-1) if the message box timer runs out. Your MsgBoxEx returns 1. Is it possible to modify your MsgBoxEx to return the same? I understand that it would likely be done within the _TimerProc() function. I just don't know the proper way to accomplish it. EDIT: I think that I may have it. In MsgBoxEx() function, I added the $iTimeout variable instead of 0: (default being 0 anyway) Local Const $iReturn = MsgBox($iFlag, $sTitle, $sText, $iTimeout, $hParentHWND) And in _TimerProc() function I removed the following: If $g_Timeout <= 1 Then _WinAPI_PostMessage($hWnd, $WM_COMMAND, $IDOK + 1, 0) This way I still get your fancy countdown for the timer on the button and get the right return. Edited Sunday at 11:51 PM by WildByDesign
MattyD Posted yesterday at 11:16 AM Posted yesterday at 11:16 AM Yeah that should work. I didn't look at the timer very closely to be fair - just gave it a bit of a tidy up. I assume UEZ had it sending IDOK because that's the button that has the text counting down to 0. (doing a bit of mind reading there) Given you can have yes/no boxes etc, setting the countdown exclusively on the OK button might not be the best option? TBH I probably wouldn't have bothered with timer at all, but it wasn't my project. (I can see the appeal though). WildByDesign 1
WildByDesign Posted yesterday at 12:02 PM Author Posted yesterday at 12:02 PM 40 minutes ago, MattyD said: I didn't look at the timer very closely to be fair - just gave it a bit of a tidy up. I assume UEZ had it sending IDOK because that's the button that has the text counting down to 0. (doing a bit of mind reading there) Yes, his only has the OK box since it's intended for his About dialog. So that made it much simpler in that respect. 41 minutes ago, MattyD said: Given you can have yes/no boxes etc, setting the countdown exclusively on the OK button might not be the best option? TBH I probably wouldn't have bothered with timer at all, but it wasn't my project. (I can see the appeal though). Indeed, yes. This is where is got complicated for me. My intention is support all MsgBox button flags but it got really messy. I had to start detecting which buttons were there and figure out which individual button should get the countdown timer value. No matter what, there was not perfect solution in that regard because sometimes it would add the counter to two different buttons at the same time. Either way, I dropped it. It was cool for the single OK button. For now, what I've done basically is added it to the window title with " - [x]" at the end. The countdown works well there. I may or may not drop that as well. There is more that I want to do with it (Mica options, etc. ) and the silly timer is slowing me down. MattyD 1
WildByDesign Posted yesterday at 01:39 PM Author Posted yesterday at 01:39 PM I have updated the scripts in the first post. I've fixed a few things, but the main thing is a new function added to apply Win11 materials such as Mica, Acrylic, etc. The function would need to be run before firing off any message boxes. ; $DWMSBT_AUTO ; Default (Auto) ; $DWMSBT_NONE ; None ; $DWMSBT_MAINWINDOW ; Mica ; $DWMSBT_TRANSIENTWINDOW ; Acrylic ; $DWMSBT_TABBEDWINDOW ; Mica Alt (Tabbed) _MsgBoxExMica($DWMSBT_MAINWINDOW) @Nine @MattyD Sorry to tag you both. But you both have very good knowledge and understanding of using CUSTOMDRAW on buttons. Do you know if it is possible with a MsgBox dialog? I have tried some previous methods from the forum but they did not work since there is not necessarily a GUI here for registering with GUIRegisterMsg() function. Even when attempting to use it with a GUI added to a testing example, it still would not work for me. CUSTOMDRAW is generally the only way that I could have some of the Win11 materials show through the buttons. I am pretty sure that it is the FillRect that does the trick. OWNERDRAW would likely do the job as well.
Nine Posted yesterday at 03:05 PM Posted yesterday at 03:05 PM Could you provide a small Mica example that works so I can see how you would like to apply it to a MsgBox ? “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
WildByDesign Posted yesterday at 03:41 PM Author Posted yesterday at 03:41 PM (edited) 36 minutes ago, Nine said: Could you provide a small Mica example that works so I can see how you would like to apply it to a MsgBox ? For a very simple GUI with Mica applied: expandcollapse popup#include <GUIConstantsEx.au3> #include <APIGdiConstants.au3> #include <WinAPIGdi.au3> #include <WinAPITheme.au3> Global Const $DWMSBT_AUTO = 0 ; Default (Auto) Global Const $DWMSBT_NONE = 1 ; None Global Const $DWMSBT_MAINWINDOW = 2 ; Mica Global Const $DWMSBT_TRANSIENTWINDOW = 3 ; Acrylic Global Const $DWMSBT_TABBEDWINDOW = 4 ; Mica Alt (Tabbed) Global Enum $PAM_Default, $PAM_AllowDark, $PAM_ForceDark, $PAM_ForceLight, $PAM_Max Example() Func Example() ; Create a GUI with various controls. Local $hGUI = GUICreate("Example", 400, 400) GUISetBkColor(0x000000) Local $idBtn_OK = GUICtrlCreateButton("OK", 310, 370, 85, 25) ; Dark Mode button _WinAPI_SetWindowTheme(GUICtrlGetHandle($idBtn_OK), "DarkMode_Explorer") ; Apply Mica _WinAPI_DwmSetWindowAttributeEx($hGUI, $DWMWA_USE_IMMERSIVE_DARK_MODE, True) _WinAPI_DwmSetWindowAttributeEx($hGUI, $DWMWA_SYSTEMBACKDROP_TYPE, $DWMSBT_MAINWINDOW) _WinAPI_DwmExtendFrameIntoClientArea($hGUI, _WinAPI_CreateMargins(-1, -1, -1, -1)) ; Display the GUI. GUISetState(@SW_SHOW, $hGUI) ; Loop until the user exits. While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE, $idBtn_OK ExitLoop EndSwitch WEnd ; Delete the previous GUI and all controls. GUIDelete($hGUI) EndFunc ;==>Example Func _WinAPI_DwmSetWindowAttributeEx($hWnd, $iAttribute, $iData) Switch $iAttribute Case 2, 3, 4, 6, 7, 8, 10, 11, 12, 13, 14, 15, 16, $DWMWA_USE_IMMERSIVE_DARK_MODE, 33, 34, 35, 36, 37, 38, 39, 40 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 + 10, @extended, 0) If $aCall[0] Then Return SetError(10, $aCall[0], 0) Return 1 EndFunc ;==>_WinAPI_DwmSetWindowAttributeEx Essentially, it must come from the titlebar. The material is applied to the titlebar first with DWMWA_SYSTEMBACKDROP_TYPE. After that, you must use DwmExtendFrameIntoClientArea to extend that material down into the rest of the GUI. EDIT: Also, the example in the first post already has a window procedure for the MsgBox window which might be helpful. There is an initial hook for the MsgBox with _CBTHookProc() function that could possibly handle the drawing. Although more likely it would be possible to handle in _MsgBoxProc() function. Edited yesterday at 03:43 PM by WildByDesign
Nine Posted yesterday at 03:47 PM Posted yesterday at 03:47 PM What is it supposed to do ? All I have is a dark mode window. No effect. Since I am not familiar with those API, do I need to set something up ? “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
WildByDesign Posted yesterday at 03:52 PM Author Posted yesterday at 03:52 PM (edited) It requires Win11 build 22621 and higher. But also, it would only display dark window if Transparency effects are disabled on the OS level. Settings app -> Personalization -> Colors -> Transparency effects checkbox must be checked for any Win11 materials to show. Otherwise it will just show a dark window. Also, Mica is very subtle. You could try _WinAPI_DwmSetWindowAttributeEx($hGUI, $DWMWA_SYSTEMBACKDROP_TYPE, $DWMSBT_TRANSIENTWINDOW) instead for Acrylic which is much less subtle. Edited yesterday at 03:53 PM by WildByDesign
Nine Posted yesterday at 03:56 PM Posted yesterday at 03:56 PM Alright thanks. After commenting the 2 lines and comparing the 2 windows, there is effectively a small difference. WildByDesign 1 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
WildByDesign Posted yesterday at 04:04 PM Author Posted yesterday at 04:04 PM 4 minutes ago, Nine said: there is effectively a small difference. I forgot to mention that how subtle or wild the Win11 materials behave depends entirely on the wallpaper. Some wallpapers with lots of colors and big contrast differences within the wallpaper make for more significant appearances with the materials. Those appearances will also change as you drag the window over different areas of your wallpaper. Particularly $DWMSBT_TABBEDWINDOW can have some pretty striking effects. Acrylic ($DWMSBT_TRANSIENTWINDOW) is the one which needs the customdraw buttons the most.
Nine Posted yesterday at 06:00 PM Posted yesterday at 06:00 PM So you want to use CUSTOMDRAW on MsgBox buttons ? If that is the case, I just tested it and it is working as expected. Not exactly sure what is your intentions here. ps. thanks for showing me the mica effect WildByDesign 1 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
WildByDesign Posted yesterday at 06:05 PM Author Posted yesterday at 06:05 PM 2 minutes ago, Nine said: So you want to use CUSTOMDRAW on MsgBox buttons ? If that is the case, I just tested it and it is working as expected. Not exactly sure what is your intentions here. Yes, I would like to do CUSTOMDRAW on the MsgBox buttons. As long as I can do a FillRect on the buttons with a color between 0x000000 and 0x202020, it should be able to show the material effect through the button. I remember with your previous CUSTOMDRAW of buttons, it did work successfully for the material effects. I just don't know how to achieve it with the MsgBox buttons.
Nine Posted yesterday at 06:16 PM Posted yesterday at 06:16 PM (edited) Pretty much the same approach. Your _MsgBoxProc handler should look like this : Switch $iMsg Case $WM_NOTIFY Local $tInfo = DllStructCreate($tagNMCUSTOMDRAWINFO, $lParam) If _WinAPI_GetClassName($tInfo.hWndFrom) = "Button" And $tInfo.Code = $NM_CUSTOMDRAW Then Local $hBrush = _WinAPI_CreateSolidBrush(0xFF) Local $tRECT = DllStructCreate($tagRECT, DllStructGetPtr($tInfo, "left")) _WinAPI_FillRect($tInfo.hDC, $tRECT, $hBrush) _WinAPI_DeleteObject($hBrush) EndIf This paints the buttons in red BTW, the case $WM_CTLCOLORBTN is useless as explained in MSDN : Quote However, only owner-drawn buttons respond to the parent window processing this message. Edited yesterday at 06:17 PM by Nine WildByDesign 1 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
WildByDesign Posted yesterday at 06:54 PM Author Posted yesterday at 06:54 PM 27 minutes ago, Nine said: Pretty much the same approach. Your _MsgBoxProc handler should look like this : This is perfect, thank you. It works well and it blends in the material effects like I was hoping for. I will have to work in the various button states and colors. I have your previous code for that, so it will be easy. 34 minutes ago, Nine said: BTW, the case $WM_CTLCOLORBTN is useless as explained in MSDN : It is interesting that MSDN states that only owner-drawn buttons respond to that because it actually solved a visual issue in this script. Without it, it leaves a blank area of about 2 pixels around the outside part of the button borders. So it was very important and served a purpose. However, the good thing is that with your CUSTOMDRAW for buttons, $WM_CTLCOLORBTN is definitely not needed anymore. Thank you for everything that you do.
WildByDesign Posted yesterday at 09:37 PM Author Posted yesterday at 09:37 PM Current progress on modern MsgBox: I've got the button states working right. I am going to make a function that will make it easy to change the top and bottom colors of the MsgBox. For certain things like Mica, it can be nice to have top and bottom colors matching. Maybe I can expose the button state colors to a function as well. Anyway, good progress so far.
Nine Posted yesterday at 09:47 PM Posted yesterday at 09:47 PM I really like your first MsgBox on previous post. Can you share the code, so I can understand more of those fancy effects. “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
WildByDesign Posted 23 hours ago Author Posted 23 hours ago Absolutely. I just updated the scripts in the first post. Just play around with _MsgBoxExMica($DWMSBT_MAINWINDOW) in Example. I used _WinAPI_ColorAdjustLuma() for the button states which seems good.
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now