Leaderboard
Popular Content
Showing content with the highest reputation since 10/06/2025 in Posts
-
V1.0.0 released! 🎊 Event on toast interaction now works! 🎉6 points
-
Guiscape -- A new GUI builder project!
Marc and 4 others reacted to jaberwacky for a topic
Hello! I'm working on a new GUI builder that I have been making great progress on! A helpful forum member ioa747 answered a question I had which started me on my journey, and now I'd like to present to you an alpha version of the software. As of now only Form and Button works in a rudimentary fashion. To run this, open Guiscape.au3 and go from there! I'd love to hear your feedback and suggestions. 🙂 Latest versions will be on Github from now on. https://github.com/matthewrg/Guiscape Guiscape.zip Downloads: 355 points -
Added File path validation to prevent path traversal attacks Parameter safety warnings for autoit.consoleParams to detect potentially dangerous shell metacharacters Workspace symbol performance optimizations with batch processing to prevent UI freezing on large projects Configuration options autoit.workspaceSymbolMaxFiles (default: 500) and autoit.workspaceSymbolBatchSize (default: 10) Configuration option autoit.symbolMaxLines (default: 50000) to control maximum lines processed for symbol information Warning message when files exceed symbol processing limit with actionable instructions Comprehensive unit tests for completion provider with 8 test cases Comprehensive README documentation improvements with installation guide, quick start section, platform support matrix, troubleshooting guide, and reorganized configuration Distribution scripts for packaging the extension to multiple marketplaces: package-all.js for simultaneous packaging to VS Code Marketplace and OpenVSX package-openvsx.js for OpenVSX-specific packaging with publisher name handling Fixed Command injection risk in registry update functionality by replacing exec with execFile for safer argument handling Multiple global output panels opening for AutoIt on startup Memory leak in completion provider where include cache grew indefinitely across document switches Incorrect array comparison logic in completion cache invalidation Cross-document contamination of completion items from include files Changed Simplified ESLint configuration by using globals package and removing redundant rules Workspace symbol cache now uses incremental updates instead of full invalidation on file changes Completion provider now uses per-document Map-based caching with LRU eviction (50 document limit) Include cache automatically cleans up when documents are closed Symbol processing limit increased from hardcoded 10,000 to configurable 50,000 lines by default Removed The unused autoit.YAML-tmLanguage file Rate and View on VS Code Marketplace Star & Submit Issues on GitHub5 points
-
AutoIt Live Wallpaper
SOLVE-SMART and 3 others reacted to WildByDesign for a topic
This example script is a desktop live wallpaper program. It is a combination of MediaPlayerElement - WinRT Xaml Island by @MattyD and Move window behind desktop icons by @Parsix. It basically creates a GUI layer under the desktop icons but above the wallpaper (eg. in a WorkerW window within Program Manager). Features: Configuration file (LiveWallpaper.ini) Plays .mp4 videos and likely many more formats Light on CPU (uses GPU for video processing) Play/Pause video by double-click (can change to single-click in config) Option to Loop video Transparency level (to blend video with your real wallpaper) Start button trigger to play media Important Note: To run this, the XAML Islands require the following value in the AutoIt binary manifest: <maxversiontested Id="10.0.18362.1"/> There are two options. The first is ExternalManifest.au3 which essentially drops an external manifest file that includes that value beside your existing AutoIt binaries (eg. AutoIt3.exe.manifest and AutoIt3_x64.exe.manifest). This will allow you to run LiveWallpaper.au3 in your file manager by double-clicking on the script. However, the downside to this method is that it will not work through VSCode or SciTE and therefore you cannot get any ConsoleWrite info if you need it. The second option is Update Manifest.au3 which patches your actual AutoIt binary to include the required maxversiontested value. It makes a backup of your original AutoIt binary and you have to copy the modified one over your original. This is the better method if you want to extend the LiveWallpaper code, run through VSCode or SciTE and add/get console output. If you intend to compile as a binary, that compiled binary needs the maxversiontested value. You need to set the "win10" compatibility flag with AutoIt3Wrapper (already at top of LiveWallpaper.au3) and you need to be using the absolute latest beta version of AutoIt3Wrapper.au3 because the maxversiontested value has been added to it. To Do (possibilities): Option for volume level Option for playback rate Hotkeys Start on trigger (when logging in, when clicking Start menu, etc.) etc. Live Wallpaper Videos: I have only tested a bunch of .mp4 videos with this, including 4K. I have included bloom.mp4 which is rather low quality, but I wanted something that people can test with and it's small enough for attachment space. But there are many, many live wallpaper web sites out there. Some videos look good on loop (like a fireplace), while others don't. I'm sure lots of other video formats work. But I have only tested .mp4 and that is the format that most video wallpaper sites use. LiveWallpaper.7z4 points -
I've done enough editing of image files to know a few things. If you are going to have % of transparency you should have a small input section from 0 - 255 as exacting levels of transparency. Most people cannot tell the difference of 1% to about 5% level of transparency, but some might want the option to have exacting levels for better control. Don't presume that about me. I don't like to lie as much as stretching the truth so far that is snaps back on me like a rubber band that has broke from the stress.4 points
-
Just a little program I whipped up today. If like me, you connect to the web via LAN, but don't always like your PC to be connected all the time, especially at boot up, then you might find my script handy. Basically I use it to turn my Ethernet connection off. A fairly simple affair, and the state persists after shutdown. BIG THANKS to jguinch for the Network configuration UDF. My script uses and requires the Network.au3 include file from the first post of that topic. My script runs with Admin Rights, as per the first line of the script. Show Adapters.au3 (40 previous downloads) NOTE - On my system, some adapters have a CRLF in the middle of the returned entry. My script changes that, within program, to a backward slash (\) for ease of use etc. As can be noted in the screenshot, the second portion, after the backslash, is the actual adapter name used for ENABLE and DISABLE and getting INFO. To work with the same adapter by default, you can SAVE a selected entry as the one, which can appear selected at startup after first being checked. Enjoy!4 points
-
After giving it some thoughts, I went with a callback function to modify any aspect of the GIF frame by frame. You need to provide a valid callback function receiving a GDI+ image handle (originating from the GIF) and returning a modified GDI+ handle to fit the size of the GIF control creation. A few tests showed me that the callback function seems to be the fastest approach. Added a basic example showing how to use the callback. New version available4 points
-
Hi @genius257 Your input data reader works great! I added several inputs and buttons for a quick, rough test, and the values entered into the "toast" are returned to the callback and parsed correctly by your function. It appears that a notification toast doesn't allow more than 5 inputs; each selector input can't contain more than 5 options, and buttons can't exceed 5. Text inputs allow about 2,000 characters. But these limitations are due to the inherent features of Microsoft notification toasts, not your code. ... these toasts are funny... Bye and thanks again! cheers #include "./src/toast.au3" #include <GuiRichEdit.au3> #include <GUIConstantsEx.au3> #include <InetConstants.au3> #include <WinApiReg.au3> #include <WinApiIcons.au3> #include <GDIPlus.au3> #include <WinAPIConv.au3> If Not FileExists(@TempDir & "\e25dbe211ddfb027fcb8271d833159fc.png") Then _GDIPlus_Startup() $thIcons = DllStructCreate("HWND") $x = _WinAPI_ExtractIconEx(@AutoItExe, 0, 0, $thIcons, 1) ConsoleWrite($x & @CRLF) $hBitmap = _GDIPlus_BitmapCreateFromHICON(DllStructGetData($thIcons, 1)) _GDIPlus_ImageSaveToFileEx($hBitmap, @TempDir & "\e25dbe211ddfb027fcb8271d833159fc.png", _GDIPlus_EncodersGetCLSID("PNG")) _GDIPlus_BitmapDispose($hBitmap) ConsoleWrite(@error & @CRLF) _GDIPlus_Shutdown() _WinAPI_DestroyIcon(DllStructGetData($thIcons, 1)) EndIf Global Const $sAppName = @ScriptName Global $tCLSID = _Toast_CoCreateGuid() Global $sGUID = _WinAPI_StringFromGUID($tCLSID) ConsoleWrite("app CLSID: " & $sGUID & @CRLF) _Toast_Initialize($sAppName, $tCLSID, OnToastActivation, "AutoIt Toast Example", @TempDir & "\e25dbe211ddfb027fcb8271d833159fc.png") Opt("GuiOnEventMode", 1) Global $hWnd = GUICreate("Toast example", 700, 320) GUISetOnEvent($GUI_EVENT_CLOSE, "GUI_CLOSE") Global $hButton01 = GUICtrlCreateButton("From template", 10, 10, 200, 120) GUICtrlSetOnEvent(-1, "ToastFromTemplateExample") Global $hButton02 = GUICtrlCreateButton("From XML string", 10, 140, 200, 120) GUICtrlSetOnEvent(-1, "ToastFromXmlString") Global $hRich = _GUICtrlRichEdit_Create($hWnd, "", 220, 10, 470, 300) GUISetState() While 1 Sleep(10) WEnd Func ToastFromTemplateExample() Local $oXml = _Toast_CreateToastTemplateXmlDocument() Local $pToast = _Toast_CreateToastNotificationFromXmlObject($oXml) _Toast_Show($pToast) EndFunc ;==>ToastFromTemplateExample Func DownloadImage() If FileExists(@TempDir & "\e21cd29c9fb51c3a5b82f009ec33fc997d2edd1ece931e8568f37e205c445778.jpeg") Then Return _GUICtrlRichEdit_AppendText($hRich, "Trying to download avatar image from gravatar..." & @CRLF) Local $iBytes = InetGet("https://gravatar.com/avatar/e21cd29c9fb51c3a5b82f009ec33fc997d2edd1ece931e8568f37e205c445778", @TempDir & "\e21cd29c9fb51c3a5b82f009ec33fc997d2edd1ece931e8568f37e205c445778.jpeg", $INET_FORCEBYPASS) Local $error = @error If @error <> 0 Then _GUICtrlRichEdit_AppendText($hRich, "Failed to download image" & @CRLF) Return EndIf _GUICtrlRichEdit_AppendText($hRich, "Done! " & $iBytes & " bytes downloaded" & @CRLF) EndFunc ;==>DownloadImage Func ToastFromXmlString() DownloadImage() ; https://learn.microsoft.com/en-us/windows/apps/design/shell/tiles-and-notifications/adaptive-interactive-toasts?tabs=xml Local $sToast = "" $sToast &= "<toast activationType=""foreground"" launch=""action=viewAlarm&alarmId=3"" scenario=""alarm"">" ; action=mainContent;alarmId=3 $sToast &= "" $sToast &= " <visual>" $sToast &= " <binding template=""ToastGeneric"">" $sToast &= " <text>Time to wake up!</text>" $sToast &= " <text>To prove you're awake, select which of the following fruits is yellow...</text>" $sToast &= ' <image placement="appLogoOverride" src="file://' & @TempDir & '\e21cd29c9fb51c3a5b82f009ec33fc997d2edd1ece931e8568f37e205c445778.jpeg" hint-crop="circle"/>' $sToast &= " </binding>" $sToast &= " </visual>" $sToast &= "" $sToast &= " <actions>" $sToast &= "<!-- #1 First input-->" $sToast &= " <input id=""Options"" type=""selection"" defaultInput=""Selection1"">" $sToast &= " <selection id=""Selection1"" content=""Option 1/5""/>" $sToast &= " <selection id=""Selection2"" content=""Option 2/5""/>" $sToast &= " <selection id=""Selection3"" content=""Option 3/5""/>" $sToast &= " <selection id=""Selection4"" content=""Option 4/5""/>" $sToast &= " <selection id=""Selection5"" content=""Option 5/5""/>" ; $sToast &= " <selection id=""Selection6"" content=""Option 6/6""/>" ; No more than 5 options allowed $sToast &= " </input>" $sToast &= "<!-- #2 Second input-->" $sToast &= " <input id=""Poem"" type=""text"" placeHolderContent=""Please write a poem"" />" $sToast &= "<!-- #3 Third input-->" $sToast &= " <input id=""Season"" type=""selection"" defaultInput=""Autumn"">" $sToast &= " <selection id=""Spring"" content=""Spring""/>" $sToast &= " <selection id=""Summer"" content=""Summer""/>" $sToast &= " <selection id=""Autumn"" content=""Autumn""/>" $sToast &= " <selection id=""Winter"" content=""Winter""/>" $sToast &= " </input>" $sToast &= "<!-- #4 Fourth input-->" $sToast &= " <input id=""Mood"" type=""selection"" defaultInput=""Love"">" $sToast &= " <selection id=""Happy"" content=""I'm Happy 😀""/>" $sToast &= " <selection id=""Sad"" content=""I'm Sad 😢""/>" $sToast &= " <selection id=""Love"" content=""I'm in love ❤️""/>" $sToast &= " <selection id=""Angry"" content=""I'm mad at the whole world 🖕""/>" $sToast &= " </input>" $sToast &= "<!-- #5 Fifth input-->" $sToast &= " <input id=""Gender"" type=""selection"" defaultInput=""Female"">" $sToast &= " <selection id=""Male"" content=""I'm a man""/>" $sToast &= " <selection id=""Female"" content=""I'm a woman""/>" $sToast &= " </input>" #cs ; --- No more than 5 inputs allowed and no more than 5 entry --- $sToast &= "<!-- #6 Sixth input-->" $sToast &= " <input id=""WeekDay"" type=""selection"" defaultInput=""Wednesday"">" $sToast &= " <selection id=""Monday"" content=""Monday""/>" $sToast &= " <selection id=""Tuesday"" content=""5 Sincronizza contatti""/>" $sToast &= " <selection id=""Wednesday"" content=""Wednesday""/>" $sToast &= " <selection id=""Thursday"" content=""Thursday""/>" $sToast &= " <selection id=""Friday"" content=""Friday""/>" $sToast &= " <selection id=""Saturday"" content=""Saturday""/>" $sToast &= " <selection id=""Sunday"" content=""Sunday""/>" $sToast &= " </input>" #ce ; --- No more than 5 inputs allowed and no more than 5 entry --- $sToast &= "" $sToast &= " <!-- Button 1 -->" $sToast &= " <action content=""Yes, I agree""" $sToast &= " arguments=""action=Agree""" $sToast &= " activationType=""background""/>" $sToast &= " <!-- Button 2 -->" $sToast &= " <action content=""No, I disagree""" $sToast &= " arguments=""action=Disagree""" $sToast &= " activationType=""background""/>" $sToast &= " <!-- Button 3 -->" $sToast &= " <action content=""Save data""" $sToast &= " arguments=""action=Save""" $sToast &= " activationType=""background""/>" $sToast &= " <!-- Button 4 -->" $sToast &= " <action content=""Open settings""" $sToast &= " arguments=""action=Open""" $sToast &= " activationType=""background""/>" $sToast &= " <!-- Button 5 -->" $sToast &= " <action content=""Dismiss""" $sToast &= " arguments=""action=Dismiss""" $sToast &= " activationType=""background""/>" #cs ; --- No more than 5 buttons allowed --- $sToast &= " <!-- Button 6 -->" $sToast &= " <action content=""Snooze""" $sToast &= " arguments=""action=Snooze""" $sToast &= " activationType=""background""/>" #ce ; --- No more than 5 buttons allowed --- $sToast &= " </actions>" $sToast &= ' <audio src=''ms-winsoundevent:Notification.Looping.Alarm'' loop=''false''/>' $sToast &= "</toast>" ;#ce Local $pToast = _Toast_CreateToastNotificationFromXmlString($sToast) If @error <> 0 Then _GUICtrlRichEdit_AppendText($hRich, _WinAPI_GetErrorMessage(@error)) Return EndIf _Toast_Show($pToast) _GUICtrlRichEdit_AppendText($hRich, $pToast & @TAB & "VarGetType: " & VarGetType($pToast) & @CRLF) EndFunc ;==>ToastFromXmlString ; https://learn.microsoft.com/en-us/windows/win32/api/notificationactivationcallback/nf-notificationactivationcallback-inotificationactivationcallback-activate Func OnToastActivation($pSelf, $appUserModelId, $invokedArgs, $data, $count) _GUICtrlRichEdit_AppendText($hRich, _ "Toast activated!" & @CRLF _ & " " & "appUserModelId: " & $appUserModelId & @TAB & "VarGetType: " & VarGetType($appUserModelId) & @CRLF _ & " " & "invokedArgs: " & $invokedArgs & @TAB & "VarGetType: " & VarGetType($invokedArgs) & @CRLF _ & " " & "$data: " & $data & @TAB & "VarGetType: " & VarGetType($data) & @TAB & DllStructGetData($data, 1) & @CRLF _ ; ??? also _WinAPI_GetString ... no good as well & " " & "$count: " & $count & @TAB & "VarGetType: " & VarGetType($count) & @CRLF _ ) _GUICtrlRichEdit_AppendText($hRich, @CRLF & "-----------------------------" & @CRLF) Local $pData = $data For $i = 1 To $count $tData = DllStructCreate('PTR Key;PTR Value;', $pData) $key = _WinAPI_GetString($tData.Key) $value = _WinAPI_GetString($tData.Value) ; ConsoleWrite(StringFormat('"%s"="%s"\n', $key, $value)) _GUICtrlRichEdit_AppendText($hRich, StringFormat('"%s"="%s"\n', $key, $value)) $pData += DllStructGetSize($tData) Next Return $_Toast_S_OK EndFunc ;==>OnToastActivation Func GUI_CLOSE() Exit EndFunc ;==>GUI_CLOSE4 points
-
Hi @Gianni, Thanks you, glad to see the interest in the code Yes, the $data variable contains a pointer to a array of NOTIFICATION_USER_INPUT_DATA elements. The length of the array is given via the $count variable. Something like this should do it: $pData = $data For $i = 1 To $count $tData = DllStructCreate('PTR Key;PTR Value;', $pData) $key = _WinAPI_GetString($tData.Key) $value = _WinAPI_GetString($tData.Value) ConsoleWrite(StringFormat('"%s"="%s"\n', $key, $value)) $pData += DllStructGetSize($tData) Next I think I'll update the example with inputs to demonstrate later, and I'll also add a helper function to convert the data array into a Map4 points
-
Peace Equalizer shows power of AutoIt
ModemJunki and 2 others reacted to PeterVerbeek for a topic
Released Peace version 1.6.8.11. It now support VST plugins by controlling and using Equalizer APO's Configuration Editor. The Peace AutoEQ interface now includes OPRA by Roon (collaborators such as Oratory1990). A new import interface has been created for better import. And a theme can be installed directly from within Peace through a new theme installation interface.3 points -
[Solved] Complex UDF simplification?
argumentum and 2 others reacted to water for a topic
So you are a real language ✨Universalist ✨3 points -
Converting Transparency Level 0-255 To Percentage
SOLVE-SMART and 2 others reacted to UEZ for a topic
A generic map function: ;Coded by UEZ build 2025-10-29 Func Map($val, $source_start, $source_stop, $dest_start, $dest_stop) Return (($val - $source_start) * ($dest_stop - $dest_start) / ($source_stop - $source_start) + $dest_start) EndFunc $iCol = Int(Map(87, 0, 100, 0, 255)) ConsoleWrite($iCol & " - 0x" & Hex($iCol, 2) & @CRLF) ;87% from color value (0 - 255) $iCol = 1 + Int(Map($iCol, 0, 255, 0, 100)) ;and back again ConsoleWrite($iCol & " - 0x" & Hex($iCol, 2) & @CRLF)3 points -
Updated v25.205.1420.14 available in Beta.3 points
-
Trying to make a form that is constrained inside of another form.
ioa747 and 2 others reacted to jaberwacky for a topic
Progress! ... Click the form button beside of the cursor button (more than once if you want to). Now the windows are clipped to the left too! #include-once Opt("WinTitleMatchMode", 4) ; advanced Opt("MouseCoordMode" , 2) #include <WindowsStylesConstants.au3> #include <ButtonConstants.au3> #include <GuiConstantsEx.au3> Global $formList[], $formCount = 0 Global Const $main_width = 815 Global Const $main_height = 860 Global Const $main_left = (@DesktopWidth / 2) - ($main_width / 2) Global Const $main_top = (@DesktopHeight / 2) - ($main_height / 2) Global Const $guiCanvas = GuiCreate("GUI Canvas", $main_width, $main_height, $main_left, $main_top) Global Const $canvas = GuiCreate('', ($main_width - 105), ($main_height - 35), 95, 5, $WS_CHILD, $WS_EX_OVERLAPPEDWINDOW, $guiCanvas) GUISetFont(10, -1, -1, "Segoe UI", $guiCanvas) #region ; menu items Global Const $menu_file = GUICtrlCreateMenu ("File") Global Const $menu_save_definition = GUICtrlCreateMenuitem("Save", $menu_file) ; Roy add-on Global Const $menu_load_definition = GUICtrlCreateMenuitem("Load", $menu_file) ; Roy add-on GUICtrlCreateMenuitem('' , $menu_file) ; Roy add-on Global Const $menu_exit = GUICtrlCreateMenuitem("Exit", $menu_file) Global Const $menu_edit = GUICtrlCreateMenu ("Edit") Global Const $menu_vals = GUICtrlCreateMenuitem("Vals" , $menu_edit) ; added by: TheSaint Global Const $menu_wipe = GUICtrlCreateMenuitem("Clear all controls", $menu_edit) Global Const $menu_about = GUICtrlCreateMenuitem("About" , $menu_edit) ; added by: TheSaint GUICtrlSetState($menu_wipe, $GUI_DISABLE) Global Const $menu_settings = GUICtrlCreateMenu ("Settings") Global Const $menu_show_grid = GUICtrlCreateMenuItem("Show grid" , $menu_settings) Global Const $menu_grid_snap = GUICtrlCreateMenuItem("Snap to grid" , $menu_settings) Global Const $menu_paste_pos = GUICtrlCreateMenuItem("Paste at mouse position" , $menu_settings) Global Const $menu_show_ctrl = GUICtrlCreateMenuItem("Show control when moving", $menu_settings) Global Const $menu_show_hidden = GUICtrlCreateMenuItem("Show hidden controls" , $menu_settings) GUICtrlSetState($menu_show_grid , $GUI_CHECKED ) GUICtrlSetState($menu_grid_snap , $GUI_CHECKED ) GUICtrlSetState($menu_paste_pos , $GUI_CHECKED ) GUICtrlSetState($menu_show_ctrl , $GUI_CHECKED ) GUICtrlSetState($menu_show_hidden, $GUI_UNCHECKED) #endregion ; menu items #region ; toolbar Global Const $default_cursor = CreateToolButton("Cursor" , 5, 5) Global Const $toolForm = CreateToolButton("Form" , 45, 5) Global Const $toolGroup = CreateToolButton("Group" , 5, 45) Global Const $toolButton = CreateToolButton("Button" , 45, 45) Global Const $toolCheckbox = CreateToolButton("Checkbox" , 5, 85) Global Const $toolRadio = CreateToolButton("Radio" , 45, 85) Global Const $toolEdit = CreateToolButton("Edit" , 5, 125) Global Const $toolInput = CreateToolButton("Input" , 45, 125) Global Const $toolLabel = CreateToolButton("Label" , 5, 165) Global Const $toolUpDown = CreateToolButton("UpDown" , 45, 165) Global Const $toolList = CreateToolButton("List" , 5, 205) Global Const $toolCombo = CreateToolButton("Combo" , 45, 205) Global Const $toolDate = CreateToolButton("Date" , 5, 245) Global Const $toolTreeview = CreateToolButton("Treeview" , 45, 245) Global Const $toolProgress = CreateToolButton("Progress" , 5, 285) Global Const $toolAvi = CreateToolButton("Avi" , 45, 285) Global Const $toolIcon = CreateToolButton("Icon" , 5, 325) Global Const $toolPic = CreateToolButton("Pic" , 45, 325) Global Const $toolSlider = CreateToolButton("Slider" , 5, 365) Global Const $toolMenu = CreateToolButton("Menu" , 45, 365) Global Const $toolContextMenu = CreateToolButton("Context Menu", 5, 405) Global Const $toolTab = CreateToolButton("Tab" , 45, 405) #endregion ; toolbar main() Func main() GUISetState(@SW_SHOWNORMAL, $guiCanvas) GUISetState(@SW_SHOWNORMAL, $canvas) Local $msg Do $msg = GUIGetMsg($GUI_EVENT_ARRAY) Switch $msg[1] Case $guiCanvas Switch $msg[0] Case $toolForm CreateForm() Case $GUI_EVENT_CLOSE Exit EndSwitch EndSwitch Until False EndFunc Func CreateForm() GUISwitch($canvas) $formCount += 1 Local Const $form = GuiCreate("Form " & $formCount, 400, 600, 5, 5, BitOR($WS_CHILD, $WS_OVERLAPPEDWINDOW), -1, $canvas) $formList["Form" & $formCount] = $form GUISetState(@SW_SHOWNORMAL, $form) GUISwitch($guiCanvas) Return $form EndFunc Func CreateToolButton(Const $name, Const $left, Const $top) Local Const $tool = GUICtrlCreateRadio($name, $left, $top, 40, 40, BitOR($BS_PUSHLIKE, $BS_ICON)) GUICtrlSetImage($tool, @ScriptDir & "\resources\Icons\" & $name & ".ico") GUICtrlSetTip($tool, $name) Return $tool EndFunc3 points -
Need help removing line from dark mode menubar
UEZ and 2 others reacted to WildByDesign for a topic
I just wanted to take a moment to thank everyone again who helped with this issue. I've completed the part of the project that relates to the menubar. I actually ended up coloring that line in such a way that it gives the GUI some depth and also made the statusbar sizing and style to match it. When I started learning AutoIt a little over a year ago, I never thought that such beautiful GUIs could be made. I was able to make that line semi-transparent along with the rest of the GUI so that it does the blur behind well and also the Windows 11 materials (Mica, Acrylic, etc.) Cheers everyone! 🍷3 points -
I am sure he's happy after 5 years!!! 😉3 points
-
Move window behind desktop icons
Parsix and 2 others reacted to WildByDesign for a topic
That's a very good point. I shouldn't have used a hardcoded path like that. I like the creative way that you used the @AutoItExe macro to get the AutoIt install directory. Thanks for sharing. This was a really fun example. Thanks for sharing. I didn't expect that a child GUI would work in this type of situation, so that was a neat surprise.3 points -
to test different patterns simultaneously ; https://www.autoitscript.com/forum/topic/212981-move-window-behind-desktop-icons/page/2/#findComment-1544444 #include <WinAPI.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> Opt("MustDeclareVars", True) Example() Func Example() Local $hWorkerW = _GetDesktopWorkerW() If @error Then Exit MsgBox(16, @ScriptName, "! Error - Couldn't find WorkerW under Progman", 30) ConsoleWrite("WorkerW = " & $hWorkerW & @CRLF) ; Overlay GUICreate Local $hGUI = GUICreate("Overlay", @DesktopWidth, @DesktopHeight, -1, -1, $WS_POPUP, $WS_EX_TOOLWINDOW) Local $BkColor = 0x000000 GUISetBkColor($BkColor, $hGUI) GUISetFont(12) _WinAPI_SetParent($hGUI, $hWorkerW) _WinAPI_SetWindowLong($hGUI, $GWL_EXSTYLE, BitOR(_WinAPI_GetWindowLong($hGUI, $GWL_EXSTYLE), $WS_EX_LAYERED)) _WinAPI_SetLayeredWindowAttributes($hGUI, 0, 150, $LWA_ALPHA) GUISetState(@SW_SHOWNOACTIVATE) Local $aChildGui[10] = [9], $aLbl[10] = [9] Local $iW = @DesktopWidth * 0.33, $iH = @DesktopHeight * 0.33, $iX = 0, $iY = 20, $iCnt = 0 For $i = 1 To 3 For $j = 1 To 3 $iCnt += 1 $aChildGui[$iCnt] = GUICreate("Child_" & $iCnt, $iW, $iH, $iX, $iY, $WS_CHILD, $WS_EX_TOOLWINDOW, $hGUI) $BkColor = "0x" & Hex(Random(0, 255, 1), 2) & Hex(Random(0, 255, 1), 2) & Hex(Random(0, 255, 1), 2) ConsoleWrite("$BkColor=" & $BkColor & @CRLF) GUISetBkColor($BkColor, $aChildGui[$iCnt]) $aLbl[$iCnt] = GUICtrlCreateLabel("Child_" & $iCnt & ", BkColor:" & $BkColor, 0, 0, $iW, 25) GUICtrlSetFont(-1, 18) GUISetState(@SW_SHOWNOACTIVATE) $iX += $iW Next $iX = 0 $iY += $iH Next $iCnt = 0 While GUIGetMsg() <> $GUI_EVENT_CLOSE Sleep(50) $iCnt += 1 If $iCnt > 40 Then $iCnt = 0 For $i = 1 To $aChildGui[0] $BkColor = "0x" & Hex(Random(0, 255, 1), 2) & Hex(Random(0, 255, 1), 2) & Hex(Random(0, 255, 1), 2) GUISetBkColor($BkColor, $aChildGui[$i]) GUICtrlSetData($aLbl[$i], "Child_" & $i & ", BkColor:" & $BkColor) Next EndIf WEnd EndFunc ;==>Example Func _GetDesktopWorkerW() Local $hWorkerW = 0, $hProgman = _WinAPI_GetShellWindow() _WinAPI_SendMessageTimeout($hProgman, 0x052C, 0, 0, 3000, $SMTO_NORMAL) ; same as _SendMessage() Local $aEnumWindows = WinList("[CLASS:WorkerW]") For $n = 1 To $aEnumWindows[0][0] Local $hWnd = $aEnumWindows[$n][1] If _WinAPI_GetParent($hWnd) = $hProgman Then Return SetError(0, $hProgman, $hWnd) Next Return SetError(1, $hProgman, 0) EndFunc ;==>_GetDesktopWorkerW3 points
-
Move window behind desktop icons
Parsix and 2 others reacted to WildByDesign for a topic
I was so grouchy at the thought of blasting away my Windows partition to reinstall Windows but thankfully I figured it out before I got that far. In Advanced System Properties (SystemPropertiesAdvanced.exe) in the Performance settings dialog - Visual Effects tab, there is a checkbox labelled "Animate controls and element inside windows". Apparently that simple little checkbox controls whether or not a WorkerW window is even allowed to be created under Progman. I have always disabled any and all animation effects in Windows for years. And this was one of them. After checking this box, WorkerW is able to be created under Progman and all is good now. All examples work on my machine now. I would have reinstalled Windows and it still would have failed because disabling animation effects is one of the first things that I do after a clean install. 😄3 points -
No need to click for see it, just put your mouse on the left side of your screen Why on the left? Because the taskbar is already crowded, on the right side we scroll, and at the top when we use our browser tab by tab, it's not convenient to have a GUI in the way. You can add Shortcut, InternetShortcut, Files, and Folder by drag and drop on any button (special folders not supported) Right click menu on it for delete item See tray menu for options To exit, click on the InfoBar at the bottom of the GUI or by tray menu SlidingToolbar.7z3 points
-
I don't know if something like this has already been posted. DarkMode API Calls (undocumented): ;Coded by UEZ build 2025-10-10 ;IMMERSIVE_HC_CACHE_MODE Enum $IHCM_USE_CACHED_VALUE, $IHCM_REFRESH Enum $Default, $AllowDark, $ForceDark, $ForceLight, $Max ;$iPreferredAppMode ;~ Enum $DWMWA_USE_IMMERSIVE_DARK_MODE = (@OSBuild <= 18985) ? 19 : 20 Func _WinAPI_ShouldAppsUseDarkMode() Local $aResult = DllCall("UxTheme.dll", "bool", 132) If @error Then Return SetError(1, 0, False) Return ($aResult[0] <> 0) EndFunc ;==>_WinAPI_ShouldAppsUseDarkMode Func _WinAPI_AllowDarkModeForWindow($hWND, $bAllow = True) Local $aResult = DllCall("UxTheme.dll", "bool", 133, "hwnd", $hWND, "bool", $bAllow) If @error Then Return SetError(1, 0, False) Return ($aResult[0] <> 0) EndFunc ;==>_WinAPI_AllowDarkModeForWindow Func _WinAPI_AllowDarkModeForApp($bAllow = True) ;Windows 10 Build 17763 Return _WinAPI_SetPreferredAppMode($bAllow ? 1 : 0) ; 1 = AllowDark, 0 = Default EndFunc ;==>_WinAPI_AllowDarkModeForApp Func _WinAPI_SetPreferredAppMode($iPreferredAppMode) ;Windows 10 Build 18362+ Local $aResult = DllCall("UxTheme.dll", "long", 135, "long", $iPreferredAppMode) If @error Then Return SetError(1, 0, False) Return $aResult[0] EndFunc ;==>_WinAPI_SetPreferredAppMode Func _WinAPI_FlushMenuThemes() Local $aResult = DllCall("UxTheme.dll", "none", 136) If @error Then Return SetError(1, 0, False) Return True EndFunc ;==>_WinAPI_FlushMenuThemes Func _WinAPI_RefreshImmersiveColorPolicyState() Local $aResult = DllCall("UxTheme.dll", "none", 104) If @error Then Return SetError(1, 0, False) Return True EndFunc ;==>_WinAPI_RefreshImmersiveColorPolicyState Func _WinAPI_IsDarkModeAllowedForWindow($hWND) Local $aResult = DllCall("UxTheme.dll", "bool", 137, "hwnd", $hWND) If @error Then Return SetError(1, 0, False) Return ($aResult[0] <> 0) EndFunc ;==>_WinAPI_IsDarkModeAllowedForWindow Func _WinAPI_GetIsImmersiveColorUsingHighContrast($iIMMERSIVE_HC_CACHE_MODE) Local $aResult = DllCall("UxTheme.dll", "bool", 106, "long", $iIMMERSIVE_HC_CACHE_MODE) If @error Then Return SetError(1, 0, False) Return ($aResult[0] <> 0) EndFunc ;==>_WinAPI_GetIsImmersiveColorUsingHighContrast Func _WinAPI_OpenNcThemeData($hWND, $tClassList) Local $aResult = DllCall("UxTheme.dll", "hwnd", 49, "hwnd", $hWND, "struct*", $tClassList) If @error Then Return SetError(1, 0, False) Return $aResult[0] EndFunc ;==>_WinAPI_OpenNcThemeData Func _WinAPI_ShouldSystemUseDarkMode() Local $aResult = DllCall("UxTheme.dll", "bool", 138) If @error Then Return SetError(1, 0, False) Return ($aResult[0] <> 0) EndFunc ;==>_WinAPI_ShouldSystemUseDarkMode Func _WinAPI_IsDarkModeAllowedForApp() Local $aResult = DllCall("UxTheme.dll", "bool", 139) If @error Then Return SetError(1, 0, False) Return ($aResult[0] <> 0) EndFunc ;==>_WinAPI_IsDarkModeAllowedForApp Requires OSBuild > 17762! API may change in next Windows updates! PS: I've reinvented the wheel ->3 points
-
read and write xlsx files without Excel
ermar and 2 others reacted to AspirinJunkie for a topic
Several adjustments were made within the UDF. 1. Writing Excel function cells _xlsx_WriteFromArray() can now write Excel functions. For this, the element value in the input array must be a string that starts with `=`. The string itself is then interpreted as an Excel function. Example: =IF(F2>E2,"yes","no") Note: For Excel to interpret this correctly, only the English notation is permitted. If you need to write a string that starts with `=` but should not be interpreted as a function, escape the first `=` by doubling it (`==`). 2. Smallest possible .xlsx output files The .xlsx file generated with _xlsx_WriteFromArray() has been consistently optimized for minimal size. Files produced this way are close to the minimum possible for the format given the data. Sample dataset: [[1,2,3],[4,5,6]] Excel: 8.45 KB _xlsx_WriteFromArray(): 1.23 KB 3. Formatting of date and time If an element value in the input array for _xlsx_WriteFromArray() contains a date or time, the cell in the .xlsx file is formatted accordingly as date, time, or date/time style. The string format for these cells must be as follows: Date: YYYY-MM-DD Time: HH:MM[:SS[.mmmmmm]] Date + Time: YYYY-MM-DD[T ]HH:MM[:SS[.mmmmmm]] Note: Date and Date+Time remain as string values. A pure time, however, is encoded as a number (Excel notation where 24h = 1.0). Bug fixes and style _xlsx_2Array() can now also handle files whose sharedstrings.xml elements have a prefix (= higher compatibility). _xlsx_2Array() now also reads files that skip empty rows (= higher compatibility). Au3Check no longer emits (partly incorrect) warnings when using the UDF.3 points -
here is a simple powershell command I use to set an ignore exclusion in Defender for a specific folder Run(@ComSpec & ' /c powershell -Command Add-MpPreference -ExclusionPath ' & '"' & @ScriptDir & '"' & ' -Force', @ScriptDir, @SW_HIDE) Use this command where ever your compiled script is to be created. By changing the word Add to Remove, it will remove the set exclusion. This script will require Administrative rights to be able to perform its function(s).3 points
-
UEZ's solution is better - but I did the work so... Technically it'll be in the ttf/otf itself in the name table #include <AutoitConstants.au3> #include <FileConstants.au3> Local $hFontFile = FileOpen("C:\Windows\Fonts\wingding.ttf", $FO_BINARY) Local $tagTTCHeader = "align 4; uint sfntVersion; ushort numTables; ushort searchRange; ushort entrySelector; ushort rangeShift" Local $tTTCHeader = DllStructCreate($tagTTCHeader) Local $iTTCHeaderLen = DllStructGetSize($tTTCHeader) Local $tTTCHeaderBuff = DllStructCreate(StringFormat("byte data[%d]", $iTTCHeaderLen), DllStructGetPtr($tTTCHeader)) $tTTCHeaderBuff.Data = FileRead($hFontFile, $iTTCHeaderLen) Local $iNumTables = _ByteSwap($tTTCHeader.numTables, 16) Local $tagTableRecord = "align 4; char tag[4]; uint checksum; uint offset; uint length" Local $tTableRecord = DllStructCreate($tagTableRecord) Local $iTableRecordLen = DllStructGetSize($tTableRecord) Local $tTableRecordBuff = DllStructCreate(StringFormat("byte data[%d]", $iTableRecordLen), DllStructGetPtr($tTableRecord)) Local $iNameTabOffset, $iNameTabTotalLen For $i = 1 To $iNumTables $tTableRecordBuff.Data = FileRead($hFontFile, $iTableRecordLen) ConsoleWrite(StringFormat("table: %s Offset: %08x Length: %08x\r\n", _ $tTableRecord.tag, _ByteSwap($tTableRecord.Offset), _ByteSwap($tTableRecord.Length))) If $tTableRecord.tag = "name" Then $iNameTabOffset = _ByteSwap($tTableRecord.Offset) $iNameTabLen = _ByteSwap($tTableRecord.Length) ExitLoop EndIf Next FileSetPos($hFontFile, $iNameTabOffset, $FILE_BEGIN) Local $tagNameTable = "align 4; ushort version; ushort count; ushort storageOffset" Local $tNameTable = DllStructCreate($tagNameTable) Local $iNameTabLen = DllStructGetSize($tNameTable) Local $tNameTableBuff = DllStructCreate(StringFormat("byte data[%d]", $iNameTabLen), DllStructGetPtr($tNameTable)) $tNameTableBuff.data = FileRead($hFontFile, $iNameTabLen) Local $iNameRecordCount = _ByteSwap($tNameTable.count, 16) Local $iNameStorageOffset = _ByteSwap($tNameTable.storageOffset, 16) Local $tagNameRecord = "align 4; ushort platformID; ushort encodingID; ushort languageID; ushort nameID; ushort length; ushort stringOffset;" Local $tNameRecord = DllStructCreate($tagNameRecord) Local $iNameRecordLen = DllStructGetSize($tNameRecord) Local $tNameRecordBuff = DllStructCreate(StringFormat("byte data[%d]", $iNameRecordLen), DllStructGetPtr($tNameRecord)) Local $iFontFamilyNameOffset, $iFontFamilyNameLen For $i = 1 To $iNameRecordCount $tNameRecordBuff.data = FileRead($hFontFile, $iNameRecordLen) ConsoleWrite(StringFormat("NameRecord: nameID: %04x length %04x offset %04x", _ _ByteSwap($tNameRecord.nameID, 16), _ByteSwap($tNameRecord.length, 16), _ByteSwap($tNameRecord.stringOffset, 16)) & @CRLF) If _ByteSwap($tNameRecord.nameID, 16) = 1 Then ; Font Family name. $iFontFamilyNameLen = _ByteSwap($tNameRecord.length, 16) $iFontFamilyNameOffset = _ByteSwap($tNameRecord.stringOffset, 16) ExitLoop EndIf Next FileSetPos($hFontFile, $iNameTabOffset + $iNameStorageOffset + $iFontFamilyNameOffset, $FILE_BEGIN) Local $tFontFamilyName = DllStructCreate(StringFormat("char Name[%d]", $iFontFamilyNameLen)) Local $tFontFamilyNameBuff = DllStructCreate(StringFormat("byte data[%d]", $iFontFamilyNameLen), DllStructGetPtr($tFontFamilyName)) $tFontFamilyNameBuff.Data = FileRead($hFontFile, $iFontFamilyNameLen) MsgBox(0, "Font Family Name", $tFontFamilyName.Name) FileClose($hFontFile) Func _ByteSwap($iInt, $iSize = 32) Switch $iSize Case 16 Return BitAND(0xFFFF, BitOR(BitAND(0xFF00, BitShift($iInt, -8)), BitShift($iInt, 8))) Case 32 Local $tBuff = DllStructCreate("byte[4]") For $i = 1 To 4 DllStructSetData($tBuff, 1, BitAND($iInt, 0xFF), 5-$i) $iInt = BitShift($iInt, 8) Next Local $tInt = DllStructCreate("int", DllStructGetPtr($tBuff)) Return DllStructGetData($tInt, 1) EndSwitch EndFunc3 points
-
Free style DateTimeFormat
argumentum and 2 others reacted to ioa747 for a topic
_DTFormat Formats a given date/time string according to the specified format. _DTFormat($sDate, $sFormat [, $iLcid = $LOCALE_USER_DEFAULT]) $sDate - The date string to be formatted "[YYYY/MM/DD][ HH:MM:SS [ tt]]" $sFormat - A string containing the desired format for the date and time. Supported tokens are: Date and/or Time Date: d, dd = day; ddd, dddd = day of week; M= month; y = year Time: h= hour m= minute s = second (long time only) tt= AM. or P.M. h/H = 12/24 hour hh, mm, ss = display leading zero h, m, s = do not display leading zero Tokens can be separated by '|' to specify different formats for date and time. $iLcid - [optional] The locale identifier. Defaults to the user's default locale (default is $LOCALE_USER_DEFAULT). ; https://www.autoitscript.com/forum/topic/213249-free-style-datetimeformat/ ;---------------------------------------------------------------------------------------- ; Title...........: _DTFormat.au3 ; Description.....: Formats a given date/time string according to the specified format. ; AutoIt Version..: 3.3.16.1 Author: ioa747 Script Version: 0.1 ; Note............: Testet in Win10 22H2 Date:07/10/2025 ;---------------------------------------------------------------------------------------- #AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #include <Date.au3> Example() ; Function to demonstrate the use of _DTFormat Func Example() ; https://help.tradestation.com/10_00/eng/tsdevhelp/elobject/class_el/lcid_values.htm ; Example using specific LCID (German=1031, English=1033, Spain=1034, France=1036) ConsoleWrite("- German : " & _DTFormat("2025/09/01 08:30:00 PM", "dddd, d MMMM yyyy|, HH:mm", 1031) & @CRLF) ConsoleWrite("- English : " & _DTFormat("2025/09/01 08:30:00 PM", "dddd, d MMMM yyyy|, HH:mm", 1033) & @CRLF) ConsoleWrite("- Spain : " & _DTFormat("2025/09/01 08:30:00 PM", "dddd, d MMMM yyyy|, HH:mm", 1034) & @CRLF) ConsoleWrite("- France : " & _DTFormat("2025/09/01 08:30:00 PM", "dddd, d MMMM yyyy|, HH:mm", 1036) & @CRLF) ConsoleWrite("-" & @CRLF) ; Example using the default User Locale LCID ConsoleWrite("- User Locale : " & _DTFormat("2025/09/01 20:30:00", "dddd, d MMMM yyyy|, hh:mm tt") & @CRLF) ConsoleWrite("- MMMM yyyy : " & _DTFormat("2025/09/01", "MMMM yyyy") & @CRLF) ConsoleWrite("- Date & Time : " & _DTFormat("2025/09/01 20:30:00", "'Date:' dddd d|, 'Time:' HH:mm") & @CRLF) ConsoleWrite("-" & @CRLF) ; More Example ConsoleWrite("- only Time : " & _DTFormat("08:30:00 PM", "HH:mm:ss") & @CRLF) ConsoleWrite("- only Date : " & _DTFormat("2025/09/01", "dddd, d MMMM yyyy") & @CRLF) ConsoleWrite("-" & @CRLF) ConsoleWrite("- _NowCalc() : " & _NowCalc() & @CRLF) ConsoleWrite("- only Time : " & _DTFormat(_NowCalc(), "|HH:mm:ss") & @CRLF) ConsoleWrite("- only Date : " & _DTFormat(_NowCalc(), "dddd, d MMMM yyyy|") & @CRLF) ConsoleWrite("-" & @CRLF) ConsoleWrite("- ! HH with tt: " & _DTFormat("08:30:00 PM", "HH:mm tt") & @CRLF) ConsoleWrite("- Now Stamp : " & _DTFormat(_NowCalc(), "yyyy_MM_dd|_HH_mm_ss_" & @MSEC) & @CRLF) ConsoleWrite("-" & @CRLF) EndFunc ;==>Example ; #FUNCTION# ==================================================================================================================== ; Name...........: _DTFormat ; Description....: Formats a given date/time string according to the specified format. ; Syntax.........: _DTFormat($sDate, $sFormat [, $iLcid = $LOCALE_USER_DEFAULT]) ; Parameters.....: $sDate - The date string to be formatted "[YYYY/MM/DD][ HH:MM:SS [ tt]]". ; $sFormat - A string containing the desired format for the date and time. ; Supported tokens are: Date and/or Time ; Date: ; d, dd = day; ddd, dddd = day of week; M= month; y = year ; Time: ; h= hour m= minute ; s = second (long time only) ; tt= AM. or P.M. ; h/H = 12/24 hour ; hh, mm, ss = display leading zero ; h, m, s = do not display leading zero ; Tokens can be separated by '|' to specify different formats for date and time. ; $iLcid - [optional] The locale identifier. Defaults to the user's default locale (default is $LOCALE_USER_DEFAULT). ; Return values .: Success: Returns the formatted date string. ; Failure: Returns an empty string and set the @error flag to non-zero. ; @error: ; 1 - Error date is not valid. ; 2 - Error in splitting the date string ; 3 - Error in encoding SystemTime ; 4 - Error in time formatting ; 5 - Error in date formatting ; Author ........: ioa747 ; Modified ......: ; Remarks .......: This function uses the Windows API to format date and time according to the specified locale. ; Related .......: _Date_Time_EncodeSystemTime, _WinAPI_GetDateFormat, _WinAPI_GetTimeFormat, _WinAPI_GetLocaleInfo ; Link ..........: https://learn.microsoft.com/en-us/windows/win32/intl/day--month--year--and-era-format-pictures ; Example .......: MsgBox(0, "Formatted Date", _DTFormat("2023/10/05 14:30:00", "MM/DD/YYYY|, HH:MM:SS")) ; =============================================================================================================================== Func _DTFormat($sDate, $sFormat, $iLcid = $LOCALE_USER_DEFAULT) Local $asDatePart[4], $asTimePart[4] Local $sTempDate = "", $sTempTime = "" Local $sAM, $sPM, $sTempString = "" Local $bDate = True ; If there is no date, add a dummy one (2000/01/01) If StringInStr($sDate, "/") = 0 And Not @error Then $bDate = False $sDate = "2000/01/01 " & $sDate Else ; Verify If InputDate is valid If Not _DateIsValid($sDate) Then Return SetError(1, 0, "") ; Error date is not valid. EndIf ; Split the date and time into arrays _DateTimeSplit($sDate, $asDatePart, $asTimePart) If @error Then Return SetError(2, @error, "") ; Error in splitting the date string Local $aPart = StringSplit($sFormat, "|") If $bDate Then $sTempDate = $aPart[1] $sTempTime = "" If $aPart[0] = 2 Then $sTempTime = $aPart[2] Else $sTempTime = $aPart[1] EndIf ; If time parts exist, check for AM/PM and convert to 24-hour format If $asTimePart[0] > 1 Then ; Get locale's AM designator, or AM $sTempString = _WinAPI_GetLocaleInfo($iLcid, $LOCALE_S1159) ; AM designator. If Not @error And Not ($sTempString = '') Then $sAM = $sTempString Else $sAM = "AM" EndIf ; Get locale's PM designator, or PM $sTempString = _WinAPI_GetLocaleInfo($iLcid, $LOCALE_S2359) ; PM designator. If Not @error And Not ($sTempString = '') Then $sPM = $sTempString Else $sPM = "PM" EndIf ; Convert 12-hour clock (with PM) to 24-hour clock If (StringInStr($sDate, 'pm') > 0) Or (StringInStr($sDate, $sPM) > 0) Then If $asTimePart[1] < 12 Then $asTimePart[1] += 12 ; Convert 12-hour clock (with AM) to 24-hour clock (handle 12 AM midnight case) ElseIf (StringInStr($sDate, 'am') > 0) Or (StringInStr($sDate, $sAM) > 0) Then If $asTimePart[1] = 12 Then $asTimePart[1] = 0 EndIf EndIf ; Remove ' tt' if hour is in format H/24 hour If StringInStr($sTempTime, "H", 1) > 0 Then $sTempTime = StringReplace($sTempTime, " tt", "") ; Encode a system time structure (required by WinAPI date/time functions) Local $tSystem = _Date_Time_EncodeSystemTime($asDatePart[2], $asDatePart[3], $asDatePart[1], $asTimePart[1], $asTimePart[2], $asTimePart[3]) If @error Then Return SetError(3, @error, "") ; Error in encoding SystemTime Local $sfinalTime = _WinAPI_GetTimeFormat($iLcid, $tSystem, 0, $sTempTime) If @error Then Return SetError(4, @error, "") ; Error in time formatting ; Force AM/PM if the format string contains 'tt' but regional settings didn't include it If StringInStr($sTempTime, "tt") Then If (StringInStr($sfinalTime, 'pm') = 0) And (StringInStr($sfinalTime, $sPM) = 0) And _ (StringInStr($sfinalTime, 'am') = 0) And (StringInStr($sfinalTime, $sAM) = 0) Then If $asTimePart[1] < 12 Then $sfinalTime &= " " & $sAM Else $sfinalTime &= " " & $sPM EndIf EndIf EndIf Local $sResult = "" If $sTempDate <> "" Then $sResult &= _WinAPI_GetDateFormat($iLcid, $tSystem, 0, $sTempDate) If @error Then Return SetError(5, @error, "") ; Error in date formatting If $sTempTime <> "" Then $sResult &= $sfinalTime Return $sResult EndFunc ;==>_DTFormat Please, every comment is appreciated! leave your comments and experiences here! Thank you very much3 points -
Guiscape -- A new GUI builder project!
SOLVE-SMART and one other reacted to argumentum for a topic
...developing GUI stuff is a pain. Mostly because you'd need at least 2 monitors and at least on with scaling as otherwise, you can't clearly see what it looks like. On the other hand, that would be a pain to code without an stablished UDF for it. Therefore, since we don't have a stablish UDF ( that I know of ) forget the HiDPI stuff and make the GUI editor without that into consideration. If "GuiCtrls_HiDpi" (UDF in progress) or another UDF comes along or, "New and improved: AutoIt v3.4.0.0. Now with HiDPI" comes into existence, then patching the editor shouldn't be a big deal. Santa Claus/Saint Nicholas/Saint Nick/Father Christmas/Kris Kringle/bearded dude: I wish for a "dark/light mode, DPI aware" all in one UDF 😇 TIA2 points -
Because working with multiple monitors was required during the development of ImageSearchUDF , this UDF was created UDF: #include-once #include <WinAPIGdi.au3> #include <WinAPISysWin.au3> #include <WindowsConstants.au3> ; =============================================================================================================================== ; Title .........: Monitor UDF ; Description ...: Provides advanced monitor management and multi-monitor utilities. ; Author ........: Dao Van Trong - TRONG.PRO ; Version .......: 2.1 ; Modified ......: Fixed bugs, added features, improved error handling, Windows XP compatibility ; Compatibility .: Windows XP SP2 and later (most functions) ; Windows 8.1+ required for GetDpiForMonitor API (automatic fallback on older systems) ; =============================================================================================================================== ; FUNCTIONS SUMMARY ; =============================================================================================================================== ; _Monitor_GetList() - Enumerate connected monitors and fill global info. ; _Monitor_GetCount() - Return total number of monitors. ; _Monitor_GetPrimary() - Get index of the primary monitor. ; _Monitor_GetInfo($iMonitor) - Get detailed info about a monitor. ; _Monitor_GetBounds($iMonitor, ...) - Get full monitor rectangle (including taskbar). ; _Monitor_GetWorkArea($iMonitor, ...) - Get working area of a monitor (excluding taskbar). ; _Monitor_GetDisplaySettings($iMonitor) - Get current display mode. ; _Monitor_GetResolution($iMonitor) - Get monitor resolution. ; _Monitor_GetFromPoint([$x, $y]) - Get monitor from screen point or mouse. ; _Monitor_GetFromWindow($hWnd) - Get monitor containing a specific window. ; _Monitor_GetFromRect(...) - Get monitor overlapping a given rectangle. ; _Monitor_GetVirtualBounds() - Get bounding rectangle of the entire virtual screen. ; _Monitor_ToVirtual($iMonitor, $x, $y) - Convert local monitor coordinates to virtual coordinates. ; _Monitor_FromVirtual($iMonitor, $x, $y)- Convert from virtual to local monitor coordinates. ; _Monitor_IsVisibleWindow($hWnd) - Check if a window is top-level visible. ; _Monitor_MoveWindowToScreen(...) - Move a window to specific monitor (center if unspecified). ; _Monitor_MoveWindowToAll(...) - Move a visible window across all monitors. ; _Monitor_EnumAllDisplayModes($iMonitor)- Enumerate all available display modes. ; _Monitor_ShowInfo([$bShowMsgBox = 1, $iTimeout = 10]) - Show all monitor information. ; _Monitor_Refresh() - Refresh monitor list (reload from system). ; _Monitor_IsConnected($iMonitor) - Check if monitor is still connected. ; _Monitor_GetDPI($iMonitor) - Get DPI scaling for a monitor. ; _Monitor_GetOrientation($iMonitor) - Get display orientation (0, 90, 180, 270 degrees). ; _Monitor_GetLayout() - Get current display layout configuration. ; _Monitor_SaveLayout($sFilePath) - Save current layout to file. ; _Monitor_LoadLayout($sFilePath) - Load layout from file. ; _Monitor_GetLayoutDescription() - Get text description of current layout. ; _Monitor_ApplyLayoutHorizontal() - Arrange monitors horizontally (side by side). ; _Monitor_ApplyLayoutVertical() - Arrange monitors vertically (stacked). ; _Monitor_ApplyLayoutGrid([$iCols = 2[, $iRows = 2]]) - Arrange monitors in grid layout. ; =============================================================================================================================== ;~ ; Constants for SystemMetrics (define if not available, compatible with Windows XP) ;~ If Not IsDeclared("SM_CMONITORS") Then Global $SM_CMONITORS = 80 ;~ If Not IsDeclared("SM_XVIRTUALSCREEN") Then Global $SM_XVIRTUALSCREEN = 76 ;~ If Not IsDeclared("SM_YVIRTUALSCREEN") Then Global $SM_YVIRTUALSCREEN = 77 ;~ If Not IsDeclared("SM_CXVIRTUALSCREEN") Then Global $SM_CXVIRTUALSCREEN = 78 ;~ If Not IsDeclared("SM_CYVIRTUALSCREEN") Then Global $SM_CYVIRTUALSCREEN = 79 ;~ ; Monitor flags (define if not available) ;~ If Not IsDeclared("MONITOR_DEFAULTTONULL") Then Global $MONITOR_DEFAULTTONULL = 0 ;~ If Not IsDeclared("MONITOR_DEFAULTTOPRIMARY") Then Global $MONITOR_DEFAULTTOPRIMARY = 1 ;~ If Not IsDeclared("MONITOR_DEFAULTTONEAREST") Then Global $MONITOR_DEFAULTTONEAREST = 2 ;~ ; EnumDisplaySettings mode (define if not available) ;~ If Not IsDeclared("ENUM_CURRENT_SETTINGS") Then Global $ENUM_CURRENT_SETTINGS = -1 ;~ If Not IsDeclared("ENUM_REGISTRY_SETTINGS") Then Global $ENUM_REGISTRY_SETTINGS = -2 ;~ ; Window constants (define if not available, compatible with Windows XP) ;~ If Not IsDeclared("GWL_STYLE") Then Global $GWL_STYLE = -16 ;~ If Not IsDeclared("GWL_EXSTYLE") Then Global $GWL_EXSTYLE = -20 ;~ If Not IsDeclared("WS_VISIBLE") Then Global $WS_VISIBLE = 0x10000000 ;~ If Not IsDeclared("WS_CHILD") Then Global $WS_CHILD = 0x40000000 ;~ If Not IsDeclared("WS_EX_TOOLWINDOW") Then Global $WS_EX_TOOLWINDOW = 0x00000080 #Region --- Global Variables --- ; =============================================================================================================================== ; Global Monitor Information Array ; =============================================================================================================================== ; $__g_aMonitorList[][] structure: ; ; [0][0] = Number of monitors detected ; [0][1] = Virtual desktop Left coordinate (combined area) ; [0][2] = Virtual desktop Top coordinate ; [0][3] = Virtual desktop Right coordinate ; [0][4] = Virtual desktop Bottom coordinate ; [0][5] = Virtual desktop Width ; [0][6] = Virtual desktop Height ; ; For each monitor index i (1..$__g_aMonitorList[0][0]): ; [i][0] = Monitor handle (HMONITOR) ; [i][1] = Left coordinate of monitor ; [i][2] = Top coordinate of monitor ; [i][3] = Right coordinate of monitor ; [i][4] = Bottom coordinate of monitor ; [i][5] = IsPrimary (1 if primary, 0 otherwise) - FIXED: Now stores actual flag ; [i][6] = Device name string (e.g. "\\.\DISPLAY1") ; ; =============================================================================================================================== Global $__g_aMonitorList[1][7] = [[0, 0, 0, 0, 0, 0, ""]] #EndRegion --- Global Variables --- #Region --- OS Compatibility Functions --- ; #FUNCTION# ==================================================================================================================== ; Name...........: __Monitor_IsWindowsVersionOrGreater ; Description....: Check if running on Windows version or greater (internal function) ; Syntax.........: __Monitor_IsWindowsVersionOrGreater($iMajor, $iMinor = 0) ; Parameters.....: $iMajor - Major version number (e.g., 6 for Vista, 10 for Windows 10) ; $iMinor - [optional] Minor version number. Default is 0 ; Return values..: True if OS version is equal or greater, False otherwise ; Author.........: Dao Van Trong - TRONG.PRO ; Remarks........: Internal function for OS compatibility checking. Uses GetVersionEx API directly for accurate ; version detection, works on all AutoIt versions (even old ones where @OSVersion may be inaccurate). ; Windows XP = 5.1, Vista = 6.0, Win7 = 6.1, Win8 = 6.2, Win8.1 = 6.3, Win10 = 10.0 ; ================================================================================================================================ Func __Monitor_IsWindowsVersionOrGreater($iMajor, $iMinor = 0) ; Use GetVersionEx API directly (works on all Windows versions and all AutoIt versions) ; This is more reliable than @OSVersion which may not be accurate on old AutoIt versions ; Define OSVERSIONINFOEX structure ; dwOSVersionInfoSize, dwMajorVersion, dwMinorVersion, dwBuildNumber, dwPlatformId, ; szCSDVersion[128], wServicePackMajor, wServicePackMinor, wSuiteMask, wProductType, wReserved Local $tOSVI = DllStructCreate("dword;dword;dword;dword;dword;wchar[128];ushort;ushort;ushort;byte;byte") If @error Then Return False ; Set structure size (first field) DllStructSetData($tOSVI, 1, DllStructGetSize($tOSVI)) ; Call GetVersionExW (Unicode version, available from Windows 2000+) Local $aRet = DllCall("kernel32.dll", "bool", "GetVersionExW", "struct*", $tOSVI) If @error Or Not IsArray($aRet) Or Not $aRet[0] Then ; Fallback: Try ANSI version GetVersionExA (available from Windows 95+) ; Note: ANSI version uses char[128] instead of wchar[128] Local $tOSVIA = DllStructCreate("dword;dword;dword;dword;dword;char[128];ushort;ushort;ushort;byte;byte") If Not @error Then DllStructSetData($tOSVIA, 1, DllStructGetSize($tOSVIA)) $aRet = DllCall("kernel32.dll", "bool", "GetVersionExA", "struct*", $tOSVIA) If @error Or Not IsArray($aRet) Or Not $aRet[0] Then ; Last resort: Use @OSVersion as fallback (but this may be inaccurate) Return __Monitor_FallbackOSVersionCheck($iMajor, $iMinor) EndIf ; Use ANSI version data Local $iOSMajor = DllStructGetData($tOSVIA, 2) Local $iOSMinor = DllStructGetData($tOSVIA, 3) ; Compare versions If $iOSMajor > $iMajor Then Return True If $iOSMajor = $iMajor And $iOSMinor >= $iMinor Then Return True Return False Else ; Last resort: Use @OSVersion as fallback Return __Monitor_FallbackOSVersionCheck($iMajor, $iMinor) EndIf EndIf ; Get version from structure (Unicode version) Local $iOSMajor = DllStructGetData($tOSVI, 2) Local $iOSMinor = DllStructGetData($tOSVI, 3) ; Handle Windows 10/11: GetVersionEx may return 6.3 for compatibility ; Check build number to distinguish Windows 10/11 from 8.1 Local $iBuildNumber = DllStructGetData($tOSVI, 4) If $iOSMajor = 6 And $iOSMinor = 3 And $iBuildNumber >= 10000 Then ; Windows 10/11 (build number >= 10000) $iOSMajor = 10 $iOSMinor = 0 EndIf ; Compare versions If $iOSMajor > $iMajor Then Return True If $iOSMajor = $iMajor And $iOSMinor >= $iMinor Then Return True Return False EndFunc ;==>__Monitor_IsWindowsVersionOrGreater ; #FUNCTION# ==================================================================================================================== ; Name...........: __Monitor_FallbackOSVersionCheck ; Description....: Fallback OS version check using @OSVersion macro (internal function) ; Syntax.........: __Monitor_FallbackOSVersionCheck($iMajor, $iMinor) ; Parameters.....: $iMajor - Major version number ; $iMinor - Minor version number ; Return values..: True if OS version is equal or greater, False otherwise ; Author.........: Dao Van Trong - TRONG.PRO ; Remarks........: Used only when GetVersionEx API fails. Less reliable than API call. ; ================================================================================================================================ Func __Monitor_FallbackOSVersionCheck($iMajor, $iMinor) ; Fallback to @OSVersion (may be inaccurate on old AutoIt versions, but better than nothing) Local $sOSVersion = @OSVersion Local $iOSMajor = 5, $iOSMinor = 1 ; Default to XP If StringInStr($sOSVersion, "WIN_11") Then $iOSMajor = 10 $iOSMinor = 0 ElseIf StringInStr($sOSVersion, "WIN_10") Then $iOSMajor = 10 $iOSMinor = 0 ElseIf StringInStr($sOSVersion, "WIN_8") Then ; Use @OSBuild to distinguish 8.0 vs 8.1 (8.1 has build >= 9600) If @OSBuild >= 9600 Then $iOSMajor = 6 $iOSMinor = 3 ; Windows 8.1 Else $iOSMajor = 6 $iOSMinor = 2 ; Windows 8 EndIf ElseIf StringInStr($sOSVersion, "WIN_7") Then $iOSMajor = 6 $iOSMinor = 1 ElseIf StringInStr($sOSVersion, "WIN_VISTA") Then $iOSMajor = 6 $iOSMinor = 0 ElseIf StringInStr($sOSVersion, "WIN_XP") Then $iOSMajor = 5 $iOSMinor = 1 ElseIf StringInStr($sOSVersion, "WIN_2003") Then $iOSMajor = 5 $iOSMinor = 2 EndIf ; Compare versions If $iOSMajor > $iMajor Then Return True If $iOSMajor = $iMajor And $iOSMinor >= $iMinor Then Return True Return False EndFunc ;==>__Monitor_FallbackOSVersionCheck ; #FUNCTION# ==================================================================================================================== ; Name...........: __Monitor_IsWindows8_1OrGreater ; Description....: Check if running on Windows 8.1 or greater (internal function) ; Syntax.........: __Monitor_IsWindows8_1OrGreater() ; Parameters.....: None ; Return values..: True if Windows 8.1 or greater, False otherwise ; Author.........: Dao Van Trong - TRONG.PRO ; Remarks........: Internal function for checking if GetDpiForMonitor API is available ; ================================================================================================================================ Func __Monitor_IsWindows8_1OrGreater() ; Windows 8.1 = version 6.3, but GetVersionEx may return 6.3 for Windows 10/11 too ; We need to check build number: Windows 8.1 = build 9600-9999, Windows 10+ = build >= 10000 ; Use GetVersionEx API directly Local $tOSVI = DllStructCreate("dword;dword;dword;dword;dword;wchar[128];ushort;ushort;ushort;byte;byte") If Not @error Then DllStructSetData($tOSVI, 1, DllStructGetSize($tOSVI)) Local $aRet = DllCall("kernel32.dll", "bool", "GetVersionExW", "struct*", $tOSVI) If Not @error And IsArray($aRet) And $aRet[0] Then Local $iOSMajor = DllStructGetData($tOSVI, 2) Local $iOSMinor = DllStructGetData($tOSVI, 3) Local $iBuildNumber = DllStructGetData($tOSVI, 4) ; Windows 8.1 = 6.3 with build 9600-9999 ; Windows 10+ = 6.3 (or 10.0) with build >= 10000 If $iOSMajor = 6 And $iOSMinor = 3 Then ; Check build number If $iBuildNumber >= 10000 Then Return True ; Windows 10 or later (>= 8.1) ElseIf $iBuildNumber >= 9600 Then Return True ; Windows 8.1 EndIf ElseIf $iOSMajor >= 10 Or ($iOSMajor = 6 And $iOSMinor >= 3) Then Return True ; Windows 8.1 or later EndIf EndIf EndIf ; Fallback to version check Return __Monitor_IsWindowsVersionOrGreater(6, 3) EndFunc ;==>__Monitor_IsWindows8_1OrGreater #EndRegion --- OS Compatibility Functions --- ; #FUNCTION# ==================================================================================================================== ; Name...........: _Monitor_GetFromPoint ; Description....: Get the monitor index from a screen coordinate or current mouse position ; Syntax.........: _Monitor_GetFromPoint([$iX = -1 [, $iY = -1]]) ; Parameters.....: $iX - [optional] X coordinate in virtual screen coordinates. Default is -1 (use mouse position) ; $iY - [optional] Y coordinate in virtual screen coordinates. Default is -1 (use mouse position) ; Return values..: Success - Monitor index (1..N) ; Failure - 0, sets @error to non-zero: ; |@error = 1 - Invalid parameters or MouseGetPos failed ; |@error = 2 - Monitor not found at specified coordinates ; Author.........: Dao Van Trong - TRONG.PRO ; Remarks........: If both $iX and $iY are -1 (default), function uses current mouse position. ; Function automatically calls _Monitor_GetList() if monitor list is not initialized. ; Related........: _Monitor_GetList, _Monitor_GetFromWindow, _Monitor_GetFromRect ; ================================================================================================================================ Func _Monitor_GetFromPoint($iX = -1, $iY = -1) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() ; Use WinAPI function if available If $iX = -1 Or $iY = -1 Then Local $aMouse = MouseGetPos() If @error Then Return SetError(1, 0, 0) $iX = $aMouse[0] $iY = $aMouse[1] EndIf Local $tPoint = DllStructCreate($tagPOINT) If @error Then Return SetError(1, 0, 0) DllStructSetData($tPoint, "X", $iX) DllStructSetData($tPoint, "Y", $iY) ; _WinAPI_MonitorFromPoint is available from Windows 2000+ (compatible with XP) Local $hMonitor = _WinAPI_MonitorFromPoint($tPoint, $MONITOR_DEFAULTTONEAREST) If @error Then ; Fallback to coordinate checking if WinAPI call fails $hMonitor = 0 EndIf ; Find index in our list For $i = 1 To $__g_aMonitorList[0][0] If $__g_aMonitorList[$i][0] = $hMonitor Then Return $i Next ; Fallback to coordinate checking For $i = 1 To $__g_aMonitorList[0][0] If $iX >= $__g_aMonitorList[$i][1] _ And $iX < $__g_aMonitorList[$i][3] _ And $iY >= $__g_aMonitorList[$i][2] _ And $iY < $__g_aMonitorList[$i][4] Then Return $i EndIf Next Return SetError(2, 0, 0) EndFunc ;==>_Monitor_GetFromPoint ; #FUNCTION# ==================================================================================================================== ; Name...........: _Monitor_GetFromWindow ; Description....: Get the monitor index that contains the specified window ; Syntax.........: _Monitor_GetFromWindow($hWnd [, $iFlag = $MONITOR_DEFAULTTONEAREST]) ; Parameters.....: $hWnd - Window handle or title string. Can be HWND or window title ; $iFlag - [optional] Monitor flag. Default is $MONITOR_DEFAULTTONEAREST ; Can be: $MONITOR_DEFAULTTONULL, $MONITOR_DEFAULTTOPRIMARY, $MONITOR_DEFAULTTONEAREST ; Return values..: Success - Monitor index (1..N) ; Failure - 0, sets @error to non-zero: ; |@error = 1 - Invalid window handle or window not found ; |@error = 2 - WinAPI MonitorFromWindow call failed ; |@error = 3 - Monitor handle not found in internal list ; Author.........: Dao Van Trong - TRONG.PRO ; Remarks........: Function accepts both window handles and window titles. Automatically converts title to handle. ; Function automatically calls _Monitor_GetList() if monitor list is not initialized. ; Related........: _Monitor_GetList, _Monitor_GetFromPoint, _Monitor_GetFromRect ; ================================================================================================================================ Func _Monitor_GetFromWindow($hWnd, $iFlag = $MONITOR_DEFAULTTONEAREST) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() If Not IsHWnd($hWnd) Then $hWnd = WinGetHandle($hWnd) If Not $hWnd Then Return SetError(1, 0, 0) ; _WinAPI_MonitorFromWindow is available from Windows 2000+ (compatible with XP) Local $hMonitor = _WinAPI_MonitorFromWindow($hWnd, $iFlag) If @error Or Not $hMonitor Then Return SetError(2, 0, 0) For $i = 1 To $__g_aMonitorList[0][0] If $__g_aMonitorList[$i][0] = $hMonitor Then Return $i Next Return SetError(3, 0, 0) EndFunc ;==>_Monitor_GetFromWindow ; #FUNCTION# ==================================================================================================================== ; Name...........: _Monitor_GetFromRect ; Description....: Get the monitor index that has the largest intersection with the specified rectangle ; Syntax.........: _Monitor_GetFromRect($iLeft, $iTop, $iRight, $iBottom [, $iFlag = $MONITOR_DEFAULTTONEAREST]) ; Parameters.....: $iLeft - Left coordinate of the rectangle in virtual screen coordinates ; $iTop - Top coordinate of the rectangle in virtual screen coordinates ; $iRight - Right coordinate of the rectangle in virtual screen coordinates ; $iBottom - Bottom coordinate of the rectangle in virtual screen coordinates ; $iFlag - [optional] Monitor flag. Default is $MONITOR_DEFAULTTONEAREST ; Can be: $MONITOR_DEFAULTTONULL, $MONITOR_DEFAULTTOPRIMARY, $MONITOR_DEFAULTTONEAREST ; Return values..: Success - Monitor index (1..N) ; Failure - 0, sets @error to non-zero: ; |@error = 1 - DllStructCreate failed or WinAPI MonitorFromRect call failed ; |@error = 2 - Monitor not found in internal list ; Author.........: Dao Van Trong - TRONG.PRO ; Remarks........: Coordinates should be in virtual screen coordinate system (can span multiple monitors). ; Function automatically calls _Monitor_GetList() if monitor list is not initialized. ; Related........: _Monitor_GetList, _Monitor_GetFromPoint, _Monitor_GetFromWindow ; ================================================================================================================================ Func _Monitor_GetFromRect($iLeft, $iTop, $iRight, $iBottom, $iFlag = $MONITOR_DEFAULTTONEAREST) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() Local $tRect = DllStructCreate($tagRECT) If @error Then Return SetError(1, 0, 0) DllStructSetData($tRect, "Left", $iLeft) DllStructSetData($tRect, "Top", $iTop) DllStructSetData($tRect, "Right", $iRight) DllStructSetData($tRect, "Bottom", $iBottom) ; _WinAPI_MonitorFromRect is available from Windows 2000+ (compatible with XP) Local $hMonitor = _WinAPI_MonitorFromRect($tRect, $iFlag) If @error Or Not $hMonitor Then Return SetError(1, 0, 0) For $i = 1 To $__g_aMonitorList[0][0] If $__g_aMonitorList[$i][0] = $hMonitor Then Return $i Next Return SetError(2, 0, 0) EndFunc ;==>_Monitor_GetFromRect ; #FUNCTION# ==================================================================================================================== ; Name...........: _Monitor_GetWorkArea ; Description....: Get working area of a specific monitor (excluding taskbar and system bars) ; Syntax.........: _Monitor_GetWorkArea($iMonitor, ByRef $left, ByRef $top, ByRef $right, ByRef $bottom) ; Parameters.....: $iMonitor - Monitor index (1..N) ; $left - [out] Left coordinate of work area (virtual screen coordinates) ; $top - [out] Top coordinate of work area (virtual screen coordinates) ; $right - [out] Right coordinate of work area (virtual screen coordinates) ; $bottom - [out] Bottom coordinate of work area (virtual screen coordinates) ; Return values..: Success - 1 ; Failure - 0, sets @error to non-zero: ; |@error = 1 - Invalid monitor index ; |@error = 2 - WinAPI GetMonitorInfo call failed ; Author.........: Dao Van Trong - TRONG.PRO ; Remarks........: Work area excludes taskbar and other system bars. Use _Monitor_GetBounds() for full monitor area. ; All coordinates are in virtual screen coordinate system. ; Function automatically calls _Monitor_GetList() if monitor list is not initialized. ; Related........: _Monitor_GetBounds, _Monitor_GetInfo, _Monitor_GetList ; ================================================================================================================================ Func _Monitor_GetWorkArea($iMonitor, ByRef $left, ByRef $top, ByRef $right, ByRef $bottom) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() If $iMonitor < 1 Or $iMonitor > $__g_aMonitorList[0][0] Then Return SetError(1, 0, 0) Local $hMonitor = $__g_aMonitorList[$iMonitor][0] ; _WinAPI_GetMonitorInfo is available from Windows 2000+ (compatible with XP) Local $aInfo = _WinAPI_GetMonitorInfo($hMonitor) If @error Or Not IsArray($aInfo) Then Return SetError(2, 0, 0) Local $tWorkArea = $aInfo[1] If Not IsDllStruct($tWorkArea) Then Return SetError(2, 0, 0) $left = DllStructGetData($tWorkArea, "Left") $top = DllStructGetData($tWorkArea, "Top") $right = DllStructGetData($tWorkArea, "Right") $bottom = DllStructGetData($tWorkArea, "Bottom") Return 1 EndFunc ;==>_Monitor_GetWorkArea ; #FUNCTION# ==================================================================================================================== ; Name...........: _Monitor_GetBounds ; Description....: Get full bounds of a specific monitor (including taskbar and all system areas) ; Syntax.........: _Monitor_GetBounds($iMonitor, ByRef $left, ByRef $top, ByRef $right, ByRef $bottom) ; Parameters.....: $iMonitor - Monitor index (1..N) ; $left - [out] Left coordinate of monitor (virtual screen coordinates) ; $top - [out] Top coordinate of monitor (virtual screen coordinates) ; $right - [out] Right coordinate of monitor (virtual screen coordinates) ; $bottom - [out] Bottom coordinate of monitor (virtual screen coordinates) ; Return values..: Success - 1 ; Failure - 0, sets @error = 1 (Invalid monitor index) ; Author.........: Dao Van Trong - TRONG.PRO ; Remarks........: Returns the full physical bounds of the monitor including all system bars (taskbar, etc.). ; All coordinates are in virtual screen coordinate system. ; Function automatically calls _Monitor_GetList() if monitor list is not initialized. ; For usable area excluding taskbar, use _Monitor_GetWorkArea() instead. ; Related........: _Monitor_GetWorkArea, _Monitor_GetInfo, _Monitor_GetList ; ================================================================================================================================ Func _Monitor_GetBounds($iMonitor, ByRef $left, ByRef $top, ByRef $right, ByRef $bottom) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() If $iMonitor < 1 Or $iMonitor > $__g_aMonitorList[0][0] Then Return SetError(1, 0, 0) $left = $__g_aMonitorList[$iMonitor][1] $top = $__g_aMonitorList[$iMonitor][2] $right = $__g_aMonitorList[$iMonitor][3] $bottom = $__g_aMonitorList[$iMonitor][4] Return 1 EndFunc ;==>_Monitor_GetBounds ; #FUNCTION# ==================================================================================================================== ; Name...........: _Monitor_GetInfo ; Description....: Get detailed information about a monitor ; Syntax.........: _Monitor_GetInfo($iMonitor) ; Parameters.....: $iMonitor - Monitor index (1..N) ; Return values..: Success - Array with 11 elements: ; |[0] - Monitor handle (HMONITOR) ; |[1] - Left coordinate of monitor bounds (virtual screen coordinates) ; |[2] - Top coordinate of monitor bounds (virtual screen coordinates) ; |[3] - Right coordinate of monitor bounds (virtual screen coordinates) ; |[4] - Bottom coordinate of monitor bounds (virtual screen coordinates) ; |[5] - Left coordinate of work area (virtual screen coordinates) ; |[6] - Top coordinate of work area (virtual screen coordinates) ; |[7] - Right coordinate of work area (virtual screen coordinates) ; |[8] - Bottom coordinate of work area (virtual screen coordinates) ; |[9] - IsPrimary flag (1 = Primary, 0 = Secondary) ; |[10] - Device name string (e.g., "\\.\DISPLAY1") ; Failure - 0, sets @error to non-zero: ; |@error = 1 - Invalid monitor index ; |@error = 2 - WinAPI GetMonitorInfo call failed ; Author.........: Dao Van Trong - TRONG.PRO ; Remarks........: This is the most comprehensive function to get all monitor information at once. ; Function automatically calls _Monitor_GetList() if monitor list is not initialized. ; Related........: _Monitor_GetList, _Monitor_GetBounds, _Monitor_GetWorkArea, _Monitor_GetPrimary ; ================================================================================================================================ Func _Monitor_GetInfo($iMonitor) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() If $iMonitor < 1 Or $iMonitor > $__g_aMonitorList[0][0] Then Return SetError(1, 0, 0) Local $hMonitor = $__g_aMonitorList[$iMonitor][0] ; _WinAPI_GetMonitorInfo is available from Windows 2000+ (compatible with XP) Local $aInfo = _WinAPI_GetMonitorInfo($hMonitor) If @error Or Not IsArray($aInfo) Then Return SetError(2, 0, 0) Local $tMonitorRect = $aInfo[0] Local $tWorkRect = $aInfo[1] If Not IsDllStruct($tMonitorRect) Or Not IsDllStruct($tWorkRect) Then Return SetError(2, 0, 0) Local $aResult[11] $aResult[0] = $hMonitor $aResult[1] = DllStructGetData($tMonitorRect, "Left") $aResult[2] = DllStructGetData($tMonitorRect, "Top") $aResult[3] = DllStructGetData($tMonitorRect, "Right") $aResult[4] = DllStructGetData($tMonitorRect, "Bottom") $aResult[5] = DllStructGetData($tWorkRect, "Left") $aResult[6] = DllStructGetData($tWorkRect, "Top") $aResult[7] = DllStructGetData($tWorkRect, "Right") $aResult[8] = DllStructGetData($tWorkRect, "Bottom") $aResult[9] = ($aInfo[2] <> 0) ; IsPrimary $aResult[10] = $aInfo[3] ; DeviceName Return $aResult EndFunc ;==>_Monitor_GetInfo ; #FUNCTION# ==================================================================================================================== ; Name...........: _Monitor_GetDisplaySettings ; Description....: Get display settings for a monitor (resolution, color depth, refresh rate, etc.) ; Syntax.........: _Monitor_GetDisplaySettings($iMonitor [, $iMode = $ENUM_CURRENT_SETTINGS]) ; Parameters.....: $iMonitor - Monitor index (1..N) ; $iMode - [optional] Display mode index. Default is $ENUM_CURRENT_SETTINGS ; Use $ENUM_CURRENT_SETTINGS to get current active settings ; Use index number (0..N) to enumerate available modes ; Return values..: Success - Array with 5 elements: ; |[0] - Width (pixels) ; |[1] - Height (pixels) ; |[2] - Bits per pixel (color depth) ; |[3] - Refresh rate (Hz) ; |[4] - Display mode flags ; Failure - 0, sets @error to non-zero: ; |@error = 1 - Invalid monitor index ; |@error = 2 - GetInfo failed (could not get device name) ; |@error = 3 - WinAPI EnumDisplaySettings call failed ; Author.........: Dao Van Trong - TRONG.PRO ; Remarks........: Use $ENUM_CURRENT_SETTINGS to get the currently active display mode. ; Use _Monitor_EnumAllDisplayModes() to get all available display modes. ; Function automatically calls _Monitor_GetList() if monitor list is not initialized. ; Related........: _Monitor_GetResolution, _Monitor_EnumAllDisplayModes, _Monitor_GetList ; ================================================================================================================================ Func _Monitor_GetDisplaySettings($iMonitor, $iMode = $ENUM_CURRENT_SETTINGS) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() If $iMonitor < 1 Or $iMonitor > $__g_aMonitorList[0][0] Then Return SetError(1, 0, 0) Local $sDevice = $__g_aMonitorList[$iMonitor][6] If $sDevice = "" Then Local $aInfo = _Monitor_GetInfo($iMonitor) If @error Then Return SetError(2, 0, 0) $sDevice = $aInfo[10] EndIf ; _WinAPI_EnumDisplaySettings is available from Windows 95+ (fully compatible with XP) Local $aSettings = _WinAPI_EnumDisplaySettings($sDevice, $iMode) If @error Or Not IsArray($aSettings) Then Return SetError(3, 0, 0) Return $aSettings EndFunc ;==>_Monitor_GetDisplaySettings ; #FUNCTION# ==================================================================================================================== ; Name...........: _Monitor_GetResolution ; Description....: Get the current resolution (width and height) of a monitor ; Syntax.........: _Monitor_GetResolution($iMonitor) ; Parameters.....: $iMonitor - Monitor index (1..N) ; Return values..: Success - Array with 2 elements: ; |[0] - Width in pixels ; |[1] - Height in pixels ; Failure - 0, sets @error to non-zero: ; |@error = 1 - Invalid monitor index ; |@error = 2 - GetDisplaySettings failed ; Author.........: Dao Van Trong - TRONG.PRO ; Remarks........: This is a convenience function that returns only width and height from display settings. ; For full display settings (color depth, refresh rate, etc.), use _Monitor_GetDisplaySettings(). ; Function automatically calls _Monitor_GetList() if monitor list is not initialized. ; Related........: _Monitor_GetDisplaySettings, _Monitor_GetInfo, _Monitor_GetList ; ================================================================================================================================ Func _Monitor_GetResolution($iMonitor) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() If $iMonitor < 1 Or $iMonitor > $__g_aMonitorList[0][0] Then Return SetError(1, 0, 0) Local $aSettings = _Monitor_GetDisplaySettings($iMonitor) If @error Then Return SetError(2, @error, 0) Local $aResult[2] = [$aSettings[0], $aSettings[1]] Return $aResult EndFunc ;==>_Monitor_GetResolution ; #FUNCTION# ==================================================================================================================== ; Name...........: _Monitor_GetPrimary ; Description....: Get the index of the primary monitor ; Syntax.........: _Monitor_GetPrimary() ; Parameters.....: None ; Return values..: Success - Monitor index (1..N) of the primary monitor ; Failure - 0, sets @error = 1 (No primary monitor found) ; Author.........: Dao Van Trong - TRONG.PRO ; Remarks........: Primary monitor is the monitor that contains the taskbar by default in Windows. ; Function first checks cached IsPrimary flags, then falls back to querying system if needed. ; Function automatically calls _Monitor_GetList() if monitor list is not initialized. ; Related........: _Monitor_GetList, _Monitor_GetInfo, _Monitor_GetCount ; ================================================================================================================================ Func _Monitor_GetPrimary() If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() ; Use cached IsPrimary flag if available For $i = 1 To $__g_aMonitorList[0][0] If $__g_aMonitorList[$i][5] = 1 Then Return $i Next ; Fallback: query from system For $i = 1 To $__g_aMonitorList[0][0] Local $aInfo = _Monitor_GetInfo($i) If Not @error And $aInfo[9] = 1 Then Return $i Next Return SetError(1, 0, 0) EndFunc ;==>_Monitor_GetPrimary ; #FUNCTION# ==================================================================================================================== ; Name...........: _Monitor_GetCount ; Description....: Returns the total number of connected monitors ; Syntax.........: _Monitor_GetCount() ; Parameters.....: None ; Return values..: Success - Number of monitors (>= 1) ; Failure - 0, sets @error = 1 (Enumeration failed) ; Author.........: Dao Van Trong - TRONG.PRO ; Remarks........: Function first tries GetSystemMetrics API for fastest response. ; Falls back to cached monitor list if API call fails. ; Automatically validates and refreshes monitor list if count mismatch detected. ; Related........: _Monitor_GetList, _Monitor_Refresh, _Monitor_GetPrimary ; ================================================================================================================================ Func _Monitor_GetCount() ; Try GetSystemMetrics first (compatible with Windows XP and later) ; Note: SM_CMONITORS is available from Windows 2000+ Local $aRet = DllCall("user32.dll", "int", "GetSystemMetrics", "int", $SM_CMONITORS) If @error Or Not IsArray($aRet) Or $aRet[0] < 1 Then ; Fallback to our cached list If $__g_aMonitorList[0][0] = 0 Then If _Monitor_GetList() = -1 Then Return SetError(1, 0, 0) EndIf Return $__g_aMonitorList[0][0] Else ; Validate count matches our list (refresh if needed) If $__g_aMonitorList[0][0] <> $aRet[0] Then _Monitor_GetList() EndIf Return $aRet[0] EndIf EndFunc ;==>_Monitor_GetCount ; #FUNCTION# ==================================================================================================================== ; Name...........: _Monitor_GetVirtualBounds ; Description....: Get bounding rectangle of all monitors combined (the "virtual screen") ; Syntax.........: _Monitor_GetVirtualBounds() ; Parameters.....: None ; Return values..: Success - Array with 4 elements: ; |[0] - Left coordinate of virtual screen ; |[1] - Top coordinate of virtual screen ; |[2] - Width of virtual screen in pixels ; |[3] - Height of virtual screen in pixels ; Failure - 0, sets @error = 1 (DllCall failed) ; Author.........: Dao Van Trong - TRONG.PRO ; Remarks........: Virtual screen is the bounding rectangle that encompasses all connected monitors. ; Function uses GetSystemMetrics API. Falls back to cached virtual bounds if API fails. ; Function automatically calls _Monitor_GetList() if monitor list is not initialized. ; Related........: _Monitor_GetList, _Monitor_GetBounds, _Monitor_GetCount ; ================================================================================================================================ Func _Monitor_GetVirtualBounds() ; GetSystemMetrics for virtual screen is available from Windows 2000+ ; All SM_*VIRTUALSCREEN constants are supported on Windows XP and later Local $aL = DllCall("user32.dll", "int", "GetSystemMetrics", "int", $SM_XVIRTUALSCREEN) Local $aT = DllCall("user32.dll", "int", "GetSystemMetrics", "int", $SM_YVIRTUALSCREEN) Local $aW = DllCall("user32.dll", "int", "GetSystemMetrics", "int", $SM_CXVIRTUALSCREEN) Local $aH = DllCall("user32.dll", "int", "GetSystemMetrics", "int", $SM_CYVIRTUALSCREEN) ; Validate all calls succeeded (comprehensive error checking for XP compatibility) Local $bError = False If @error Then $bError = True If Not IsArray($aL) Or Not IsArray($aT) Or Not IsArray($aW) Or Not IsArray($aH) Then $bError = True If $bError Then ; Fallback to cached virtual bounds If $__g_aMonitorList[0][0] = 0 Then If _Monitor_GetList() = -1 Then Return SetError(1, 0, 0) EndIf Local $aRet[4] = [$__g_aMonitorList[0][1], $__g_aMonitorList[0][2], $__g_aMonitorList[0][5], $__g_aMonitorList[0][6]] Return $aRet EndIf ; Validate returned values are reasonable If $aL[0] < -32768 Or $aT[0] < -32768 Or $aW[0] < 1 Or $aH[0] < 1 Then ; Invalid values, use fallback If $__g_aMonitorList[0][0] = 0 Then If _Monitor_GetList() = -1 Then Return SetError(1, 0, 0) EndIf Local $aRet[4] = [$__g_aMonitorList[0][1], $__g_aMonitorList[0][2], $__g_aMonitorList[0][5], $__g_aMonitorList[0][6]] Return $aRet EndIf Local $a[4] = [$aL[0], $aT[0], $aW[0], $aH[0]] Return $a EndFunc ;==>_Monitor_GetVirtualBounds ; #FUNCTION# ==================================================================================================================== ; Name...........: _Monitor_ToVirtual ; Description....: Convert local monitor coordinates to virtual screen coordinates ; Syntax.........: _Monitor_ToVirtual($iMonitor, $x, $y) ; Parameters.....: $iMonitor - Monitor index (1..N) ; $x - X coordinate in local monitor coordinates (0-based from monitor's left edge) ; $y - Y coordinate in local monitor coordinates (0-based from monitor's top edge) ; Return values..: Success - Array with 2 elements [X, Y] in virtual screen coordinates ; Failure - 0, sets @error = 1 (Invalid monitor index) ; Author.........: Dao Van Trong - TRONG.PRO ; Remarks........: Local coordinates are relative to the monitor (0,0 is top-left of that monitor). ; Virtual coordinates are absolute in the virtual screen coordinate system. ; Coordinate validation is optional (currently commented out for flexibility). ; Function automatically calls _Monitor_GetList() if monitor list is not initialized. ; Related........: _Monitor_FromVirtual, _Monitor_GetBounds, _Monitor_GetList ; ================================================================================================================================ Func _Monitor_ToVirtual($iMonitor, $x, $y) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() If $iMonitor < 1 Or $iMonitor > $__g_aMonitorList[0][0] Then Return SetError(1, 0, 0) ; Optional: Validate coordinates are within monitor bounds Local $iWidth = $__g_aMonitorList[$iMonitor][3] - $__g_aMonitorList[$iMonitor][1] Local $iHeight = $__g_aMonitorList[$iMonitor][4] - $__g_aMonitorList[$iMonitor][2] If $x < 0 Or $y < 0 Or $x > $iWidth Or $y > $iHeight Then ; Return SetError(2, 0, 0) ; Uncomment if strict validation needed EndIf Local $aRet[2] = [$__g_aMonitorList[$iMonitor][1] + $x, $__g_aMonitorList[$iMonitor][2] + $y] Return $aRet EndFunc ;==>_Monitor_ToVirtual ; #FUNCTION# ==================================================================================================================== ; Name...........: _Monitor_FromVirtual ; Description....: Convert virtual screen coordinates back to local monitor coordinates ; Syntax.........: _Monitor_FromVirtual($iMonitor, $x, $y) ; Parameters.....: $iMonitor - Monitor index (1..N) ; $x - X coordinate in virtual screen coordinates ; $y - Y coordinate in virtual screen coordinates ; Return values..: Success - Array with 2 elements [X, Y] in local monitor coordinates (0-based) ; Failure - 0, sets @error to non-zero: ; |@error = 1 - Invalid monitor index ; |@error = 2 - Coordinates are not within the specified monitor's bounds ; Author.........: Dao Van Trong - TRONG.PRO ; Remarks........: Local coordinates are relative to the monitor (0,0 is top-left of that monitor). ; Virtual coordinates are absolute in the virtual screen coordinate system. ; Function validates that coordinates are actually on the specified monitor. ; Function automatically calls _Monitor_GetList() if monitor list is not initialized. ; Related........: _Monitor_ToVirtual, _Monitor_GetBounds, _Monitor_GetList ; ================================================================================================================================ Func _Monitor_FromVirtual($iMonitor, $x, $y) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() If $iMonitor < 1 Or $iMonitor > $__g_aMonitorList[0][0] Then Return SetError(1, 0, 0) ; Validate coordinates are on this monitor If $x < $__g_aMonitorList[$iMonitor][1] Or $x >= $__g_aMonitorList[$iMonitor][3] _ Or $y < $__g_aMonitorList[$iMonitor][2] Or $y >= $__g_aMonitorList[$iMonitor][4] Then Return SetError(2, 0, 0) EndIf Local $aRet[2] = [$x - $__g_aMonitorList[$iMonitor][1], $y - $__g_aMonitorList[$iMonitor][2]] Return $aRet EndFunc ;==>_Monitor_FromVirtual ; #FUNCTION# ==================================================================================================================== ; Name...........: _Monitor_IsVisibleWindow ; Description....: Check if a window is visible and is a top-level window (not a child window or tool window) ; Syntax.........: _Monitor_IsVisibleWindow($hWnd) ; Parameters.....: $hWnd - Window handle or title string. Can be HWND or window title ; Return values..: Success - True if window is visible and top-level, False otherwise ; Failure - False, sets @error = 1 (Invalid window handle) ; Author.........: Dao Van Trong - TRONG.PRO ; Remarks........: Function checks for: WS_VISIBLE flag, not WS_CHILD, and not WS_EX_TOOLWINDOW. ; Accepts both window handles and window titles. Automatically converts title to handle. ; This is useful for filtering which windows should be moved between monitors. ; Related........: _Monitor_MoveWindowToScreen, _Monitor_GetFromWindow ; ================================================================================================================================ Func _Monitor_IsVisibleWindow($hWnd) If Not IsHWnd($hWnd) Then $hWnd = WinGetHandle($hWnd) If Not $hWnd Or Not WinExists($hWnd) Then Return SetError(1, 0, False) ; _WinAPI_GetWindowLong is available from Windows 95+ (fully compatible with XP) Local $style = _WinAPI_GetWindowLong($hWnd, $GWL_STYLE) If @error Then Return SetError(1, 0, False) If BitAND($style, $WS_VISIBLE) = 0 Then Return False If BitAND($style, $WS_CHILD) <> 0 Then Return False Local $ex = _WinAPI_GetWindowLong($hWnd, $GWL_EXSTYLE) If @error Then Return False If BitAND($ex, $WS_EX_TOOLWINDOW) <> 0 Then Return False Return True EndFunc ;==>_Monitor_IsVisibleWindow ; #FUNCTION# ==================================================================================================================== ; Name...........: _Monitor_MoveWindowToScreen ; Description....: Move a visible window to a specific monitor (centered if coordinates not specified) ; Syntax.........: _Monitor_MoveWindowToScreen($vTitle [, $sText = "" [, $iMonitor = -1 [, $x = -1 [, $y = -1 [, $bUseWorkArea = True]]]]]) ; Parameters.....: $vTitle - Window title or handle. Can be HWND, title string, or class string ; $sText - [optional] Window text (for matching with title). Default is "" ; $iMonitor - [optional] Target monitor index (1..N). Default is -1 (uses monitor 1) ; $x - [optional] X position on monitor. Default is -1 (centers horizontally) ; $y - [optional] Y position on monitor. Default is -1 (centers vertically) ; $bUseWorkArea - [optional] Use work area instead of full bounds. Default is True ; Return values..: Success - 1 ; Failure - 0, sets @error to non-zero: ; |@error = 1 - Window not visible or not top-level ; |@error = 2 - Invalid monitor index or GetWorkArea/GetBounds failed ; |@error = 3 - WinGetPos failed (could not get window position/size) ; |@error = 4 - Window too large to fit on monitor ; |@error = 5 - WinMove failed ; Author.........: Dao Van Trong - TRONG.PRO ; Remarks........: If both $x and $y are -1, window is centered on the monitor. ; If $bUseWorkArea is True, positioning is relative to work area (excludes taskbar). ; Function ensures window stays within monitor bounds (adjusts if necessary). ; Function automatically calls _Monitor_GetList() if monitor list is not initialized. ; Related........: _Monitor_MoveWindowToAll, _Monitor_IsVisibleWindow, _Monitor_GetWorkArea, _Monitor_GetBounds ; ================================================================================================================================ Func _Monitor_MoveWindowToScreen($vTitle, $sText = "", $iMonitor = -1, $x = -1, $y = -1, $bUseWorkArea = True) Local $hWnd = IsHWnd($vTitle) ? $vTitle : WinGetHandle($vTitle, $sText) If Not _Monitor_IsVisibleWindow($hWnd) Then Return SetError(1, 0, 0) If $iMonitor = -1 Then $iMonitor = 1 If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() If $iMonitor < 1 Or $iMonitor > $__g_aMonitorList[0][0] Then Return SetError(2, 0, 0) Local $aWinPos = WinGetPos($hWnd) If @error Or Not IsArray($aWinPos) Then Return SetError(3, 0, 0) Local $iLeft, $iTop, $iRight, $iBottom If $bUseWorkArea Then If Not _Monitor_GetWorkArea($iMonitor, $iLeft, $iTop, $iRight, $iBottom) Then Return SetError(2, @error, 0) Else If Not _Monitor_GetBounds($iMonitor, $iLeft, $iTop, $iRight, $iBottom) Then Return SetError(2, @error, 0) EndIf Local $iWidth = $iRight - $iLeft Local $iHeight = $iBottom - $iTop ; Check if window fits on monitor If $aWinPos[2] > $iWidth Or $aWinPos[3] > $iHeight Then Return SetError(4, 0, 0) EndIf If $x = -1 Or $y = -1 Then $x = $iLeft + ($iWidth - $aWinPos[2]) / 2 $y = $iTop + ($iHeight - $aWinPos[3]) / 2 Else $x += $iLeft $y += $iTop ; Ensure window stays within bounds If $x + $aWinPos[2] > $iRight Then $x = $iRight - $aWinPos[2] If $y + $aWinPos[3] > $iBottom Then $y = $iBottom - $aWinPos[3] If $x < $iLeft Then $x = $iLeft If $y < $iTop Then $y = $iTop EndIf WinMove($hWnd, "", $x, $y) If @error Then Return SetError(5, 0, 0) Return 1 EndFunc ;==>_Monitor_MoveWindowToScreen ; #FUNCTION# ==================================================================================================================== ; Name...........: _Monitor_MoveWindowToAll ; Description....: Move a visible window sequentially across all monitors with a delay between moves ; Syntax.........: _Monitor_MoveWindowToAll($vTitle [, $sText = "" [, $bCenter = True [, $iDelay = 1000]]]) ; Parameters.....: $vTitle - Window title or handle. Can be HWND, title string, or class string ; $sText - [optional] Window text (for matching with title). Default is "" ; $bCenter - [optional] Center window on each monitor. Default is True ; If False, window is positioned at (50, 50) on each monitor ; $iDelay - [optional] Delay in milliseconds between moves. Default is 1000 ; Return values..: Success - 1 ; Failure - 0, sets @error = 1 (Window not visible or not top-level) ; Author.........: Dao Van Trong - TRONG.PRO ; Remarks........: This is a demonstration function that moves a window to each monitor in sequence. ; Function automatically calls _Monitor_GetList() if monitor list is not initialized. ; Useful for testing multi-monitor setups or demonstrating window movement. ; Related........: _Monitor_MoveWindowToScreen, _Monitor_IsVisibleWindow, _Monitor_GetCount ; ================================================================================================================================ Func _Monitor_MoveWindowToAll($vTitle, $sText = "", $bCenter = True, $iDelay = 1000) Local $hWnd = IsHWnd($vTitle) ? $vTitle : WinGetHandle($vTitle, $sText) If Not _Monitor_IsVisibleWindow($hWnd) Then Return SetError(1, 0, 0) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() For $i = 1 To $__g_aMonitorList[0][0] If $bCenter Then _Monitor_MoveWindowToScreen($hWnd, "", $i) Else _Monitor_MoveWindowToScreen($hWnd, "", $i, 50, 50) EndIf Sleep($iDelay) Next Return 1 EndFunc ;==>_Monitor_MoveWindowToAll ; #FUNCTION# ==================================================================================================================== ; Name...........: _Monitor_EnumAllDisplayModes ; Description....: Enumerate all available display modes for a monitor ; Syntax.........: _Monitor_EnumAllDisplayModes($iMonitor) ; Parameters.....: $iMonitor - Monitor index (1..N) ; Return values..: Success - 2D array with display modes: ; |[0][0] - Number of modes found ; |[n][0] - Width in pixels for mode n ; |[n][1] - Height in pixels for mode n ; |[n][2] - Bits per pixel (color depth) for mode n ; |[n][3] - Refresh rate in Hz for mode n ; |[n][4] - Display mode flags for mode n ; Failure - 0, sets @error to non-zero: ; |@error = 1 - Invalid monitor index ; |@error = 2 - GetInfo failed (could not get device name) ; |@error = 3 - No display modes found ; Author.........: Dao Van Trong - TRONG.PRO ; Remarks........: Returns all supported display modes for the specified monitor. ; Use _Monitor_GetDisplaySettings() to get only the current active mode. ; Function automatically calls _Monitor_GetList() if monitor list is not initialized. ; Related........: _Monitor_GetDisplaySettings, _Monitor_GetResolution, _Monitor_GetList ; ================================================================================================================================ Func _Monitor_EnumAllDisplayModes($iMonitor) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() If $iMonitor < 1 Or $iMonitor > $__g_aMonitorList[0][0] Then Return SetError(1, 0, 0) Local $aInfo = _Monitor_GetInfo($iMonitor) If @error Then Return SetError(2, 0, 0) Local $sDevice = $aInfo[10] Local $aModes[1][5] $aModes[0][0] = 0 Local $iIndex = 0 While True Local $aMode = _WinAPI_EnumDisplaySettings($sDevice, $iIndex) If @error Then ExitLoop ReDim $aModes[$aModes[0][0] + 2][5] $aModes[0][0] += 1 $aModes[$aModes[0][0]][0] = $aMode[0] $aModes[$aModes[0][0]][1] = $aMode[1] $aModes[$aModes[0][0]][2] = $aMode[2] $aModes[$aModes[0][0]][3] = $aMode[3] $aModes[$aModes[0][0]][4] = $aMode[4] $iIndex += 1 WEnd If $aModes[0][0] = 0 Then Return SetError(3, 0, 0) Return $aModes EndFunc ;==>_Monitor_EnumAllDisplayModes ; #FUNCTION# ==================================================================================================================== ; Name...........: _Monitor_GetList ; Description....: Enumerate all connected monitors and fill the global monitor list with their information ; Syntax.........: _Monitor_GetList() ; Parameters.....: None ; Return values..: Success - Number of monitors detected (>= 1) ; Failure - -1, sets @error = 1 (WinAPI EnumDisplayMonitors call failed) ; Author.........: Dao Van Trong - TRONG.PRO ; Remarks........: This is the core function that initializes the monitor list. Most other functions call this ; automatically if the list is not initialized (when $__g_aMonitorList[0][0] = 0). ; Populates the global array $__g_aMonitorList with monitor handles, coordinates, and device names. ; Also stores virtual desktop bounds and IsPrimary flags for each monitor. ; Related........: _Monitor_Refresh, _Monitor_GetCount, _Monitor_GetInfo ; ================================================================================================================================ Func _Monitor_GetList() ; _WinAPI_EnumDisplayMonitors is available from Windows 2000+ (compatible with XP) Local $aMonitors = _WinAPI_EnumDisplayMonitors() If @error Or Not IsArray($aMonitors) Or $aMonitors[0][0] = 0 Then Return SetError(1, 0, -1) EndIf ReDim $__g_aMonitorList[$aMonitors[0][0] + 1][7] $__g_aMonitorList[0][0] = $aMonitors[0][0] Local $l_aVirtual = _Monitor_GetVirtualBounds() Local $l_vRight = $l_aVirtual[0] + $l_aVirtual[2] Local $l_vBottom = $l_aVirtual[1] + $l_aVirtual[3] $__g_aMonitorList[0][1] = $l_aVirtual[0] $__g_aMonitorList[0][2] = $l_aVirtual[1] $__g_aMonitorList[0][3] = $l_vRight $__g_aMonitorList[0][4] = $l_vBottom $__g_aMonitorList[0][5] = $l_aVirtual[2] $__g_aMonitorList[0][6] = $l_aVirtual[3] For $i = 1 To $aMonitors[0][0] Local $hMonitor = $aMonitors[$i][0] Local $tRect = $aMonitors[$i][1] $__g_aMonitorList[$i][0] = $hMonitor $__g_aMonitorList[$i][1] = DllStructGetData($tRect, "Left") $__g_aMonitorList[$i][2] = DllStructGetData($tRect, "Top") $__g_aMonitorList[$i][3] = DllStructGetData($tRect, "Right") $__g_aMonitorList[$i][4] = DllStructGetData($tRect, "Bottom") ; Get additional info - FIXED: Store IsPrimary flag correctly ; _WinAPI_GetMonitorInfo is available from Windows 2000+ (compatible with XP) Local $aInfo = _WinAPI_GetMonitorInfo($hMonitor) If Not @error And IsArray($aInfo) Then ; FIXED: Store IsPrimary flag (0 or 1) instead of pointer $__g_aMonitorList[$i][5] = ($aInfo[2] <> 0) ? 1 : 0 ; IsPrimary flag $__g_aMonitorList[$i][6] = $aInfo[3] ; Device name Else ; Safe fallback if GetMonitorInfo fails (shouldn't happen on XP, but safe anyway) $__g_aMonitorList[$i][5] = 0 $__g_aMonitorList[$i][6] = "" EndIf Next Return $__g_aMonitorList[0][0] EndFunc ;==>_Monitor_GetList ; #FUNCTION# ==================================================================================================================== ; Name...........: _Monitor_ShowInfo ; Description....: Display monitor coordinates and detailed information in a message box and console ; Syntax.........: _Monitor_ShowInfo([$bShowMsgBox = 1 [, $iTimeout = 10]]) ; Parameters.....: $bShowMsgBox - [optional] Show message box. Default is 1 (True) ; $iTimeout - [optional] Message box timeout in seconds. Default is 10 ; Return values..: Success - String containing formatted monitor information ; Failure - Empty string "", sets @error = 1 (Enumeration failed) ; Author.........: Dao Van Trong - TRONG.PRO ; Remarks........: Displays comprehensive information about all monitors including bounds, work areas, ; resolutions, refresh rates, and device names. Information is written to console and ; optionally shown in a message box. ; Function automatically calls _Monitor_GetList() if monitor list is not initialized. ; Useful for debugging and displaying system monitor configuration. ; Related........: _Monitor_GetList, _Monitor_GetInfo, _Monitor_GetDisplaySettings ; ================================================================================================================================ Func _Monitor_ShowInfo($bShowMsgBox = 1, $iTimeout = 10) If $__g_aMonitorList[0][0] = 0 Then If _Monitor_GetList() = -1 Then Return SetError(1, 0, "") EndIf Local $sMsg = "> Total Monitors: " & $__g_aMonitorList[0][0] & @CRLF & @CRLF $sMsg &= StringFormat("+ Virtual Desktop: " & @CRLF & "Left=%d, Top=%d, Right=%d, Bottom=%d, Width=%d, Height=%d", $__g_aMonitorList[0][1], $__g_aMonitorList[0][2], $__g_aMonitorList[0][3], $__g_aMonitorList[0][4], $__g_aMonitorList[0][5], $__g_aMonitorList[0][6]) & @CRLF & @CRLF For $i = 1 To $__g_aMonitorList[0][0] Local $aInfo = _Monitor_GetInfo($i) If @error Then ContinueLoop Local $aSettings = _Monitor_GetDisplaySettings($i) Local $sResolution = @error ? "N/A" : $aSettings[0] & "x" & $aSettings[1] & " @" & $aSettings[3] & "Hz" $sMsg &= StringFormat("+ Monitor %d: %s%s\n", $i, $aInfo[9] ? "(Primary) " : "", $aInfo[10]) $sMsg &= StringFormat(" Bounds: L=%d, T=%d, R=%d, B=%d (%dx%d)\n", _ $aInfo[1], $aInfo[2], $aInfo[3], $aInfo[4], _ $aInfo[3] - $aInfo[1], $aInfo[4] - $aInfo[2]) $sMsg &= StringFormat(" Work Area: L=%d, T=%d, R=%d, B=%d (%dx%d)\n", _ $aInfo[5], $aInfo[6], $aInfo[7], $aInfo[8], _ $aInfo[7] - $aInfo[5], $aInfo[8] - $aInfo[6]) $sMsg &= " Resolution: " & $sResolution & @CRLF & @CRLF Next ConsoleWrite($sMsg) If $bShowMsgBox Then MsgBox(64 + 262144, "Monitor Information", $sMsg, $iTimeout) Return $sMsg EndFunc ;==>_Monitor_ShowInfo ; #FUNCTION# ==================================================================================================================== ; Name...........: _Monitor_Refresh ; Description....: Refresh the monitor list by reloading information from the system ; Syntax.........: _Monitor_Refresh() ; Parameters.....: None ; Return values..: Success - Number of monitors detected (>= 1) ; Failure - -1, sets @error = 1 (Refresh failed, _Monitor_GetList failed) ; Author.........: Dao Van Trong - TRONG.PRO ; Remarks........: Resets the monitor list and re-enumerates all monitors from the system. ; Useful when monitors are hot-plugged or display configuration changes. ; This forces a complete refresh of all monitor information. ; Related........: _Monitor_GetList, _Monitor_GetCount, _Monitor_IsConnected ; ================================================================================================================================ Func _Monitor_Refresh() ; Reset the list $__g_aMonitorList[0][0] = 0 Local $iResult = _Monitor_GetList() If $iResult = -1 Then Return SetError(1, 0, -1) Return $iResult EndFunc ;==>_Monitor_Refresh ; #FUNCTION# ==================================================================================================================== ; Name...........: _Monitor_IsConnected ; Description....: Check if a monitor is still connected and its handle is still valid ; Syntax.........: _Monitor_IsConnected($iMonitor) ; Parameters.....: $iMonitor - Monitor index (1..N) ; Return values..: Success - True if monitor is connected and valid, False if disconnected ; Failure - False, sets @error = 1 (Invalid monitor index) ; Author.........: Dao Van Trong - TRONG.PRO ; Remarks........: Verifies that the monitor handle is still valid by querying GetMonitorInfo. ; Useful for detecting when a monitor has been unplugged or disconnected. ; Function automatically calls _Monitor_GetList() if monitor list is not initialized. ; Related........: _Monitor_Refresh, _Monitor_GetList, _Monitor_GetCount ; ================================================================================================================================ Func _Monitor_IsConnected($iMonitor) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() If $iMonitor < 1 Or $iMonitor > $__g_aMonitorList[0][0] Then Return SetError(1, 0, False) ; Check if monitor handle is still valid Local $hMonitor = $__g_aMonitorList[$iMonitor][0] ; _WinAPI_GetMonitorInfo is available from Windows 2000+ (compatible with XP) Local $aInfo = _WinAPI_GetMonitorInfo($hMonitor) Return (Not @error And IsArray($aInfo)) EndFunc ;==>_Monitor_IsConnected ; #FUNCTION# ==================================================================================================================== ; Name...........: _Monitor_GetDPI ; Description....: Get DPI (Dots Per Inch) scaling information for a monitor ; Syntax.........: _Monitor_GetDPI($iMonitor) ; Parameters.....: $iMonitor - Monitor index (1..N) ; Return values..: Success - Array with 3 elements: ; |[0] - X DPI value ; |[1] - Y DPI value ; |[2] - Scaling percentage (typically 100, 125, 150, 175, 200, etc.) ; Failure - 0, sets @error to non-zero: ; |@error = 1 - Invalid monitor index ; |@error = 2 - DPI query failed (fallback uses default 96 DPI) ; Author.........: Dao Van Trong - TRONG.PRO ; Remarks........: Tries to use GetDpiForMonitor API (Windows 8.1+) for accurate DPI values. ; Falls back to GetDeviceCaps (Windows XP compatible) if GetDpiForMonitor is not available. ; On Windows XP/Vista/7/8, function uses GetDeviceCaps which works reliably. ; Scaling percentage is calculated as (DPI / 96) * 100. ; Function automatically calls _Monitor_GetList() if monitor list is not initialized. ; Compatible with Windows XP SP2 and later. ; Related........: _Monitor_GetInfo, _Monitor_GetDisplaySettings, _Monitor_GetList ; ================================================================================================================================ Func _Monitor_GetDPI($iMonitor) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() If $iMonitor < 1 Or $iMonitor > $__g_aMonitorList[0][0] Then Return SetError(1, 0, 0) Local $hMonitor = $__g_aMonitorList[$iMonitor][0] Local $iDPI_X = 96, $iDPI_Y = 96 ; Try to get DPI using GetDpiForMonitor (Windows 8.1+ only) ; Check OS version first to avoid loading shcore.dll on older systems If __Monitor_IsWindows8_1OrGreater() Then ; Check if shcore.dll exists before calling (Windows 8.1+) Local $hShCore = DllOpen("shcore.dll") If $hShCore <> -1 Then DllClose($hShCore) Local $aRet = DllCall("shcore.dll", "long", "GetDpiForMonitor", "handle", $hMonitor, "int", 0, "uint*", 0, "uint*", 0) If Not @error And IsArray($aRet) And $aRet[0] = 0 Then $iDPI_X = $aRet[3] $iDPI_Y = $aRet[4] Local $iScaling = Round(($iDPI_X / 96) * 100) Local $aResult[3] = [$iDPI_X, $iDPI_Y, $iScaling] Return $aResult EndIf EndIf EndIf ; Fallback: Use GetDeviceCaps (compatible with Windows XP and later) Local $hDC2 = DllCall("user32.dll", "handle", "GetDC", "hwnd", 0) If Not @error And IsArray($hDC2) And $hDC2[0] Then Local $aDPI_X = DllCall("gdi32.dll", "int", "GetDeviceCaps", "handle", $hDC2[0], "int", 88) ; LOGPIXELSX Local $aDPI_Y = DllCall("gdi32.dll", "int", "GetDeviceCaps", "handle", $hDC2[0], "int", 90) ; LOGPIXELSY If Not @error And IsArray($aDPI_X) And IsArray($aDPI_Y) And $aDPI_X[0] > 0 And $aDPI_Y[0] > 0 Then $iDPI_X = $aDPI_X[0] $iDPI_Y = $aDPI_Y[0] EndIf DllCall("user32.dll", "bool", "ReleaseDC", "hwnd", 0, "handle", $hDC2[0]) EndIf Local $iScaling = Round(($iDPI_X / 96) * 100) Local $aResult[3] = [$iDPI_X, $iDPI_Y, $iScaling] Return $aResult EndFunc ;==>_Monitor_GetDPI ; #FUNCTION# ==================================================================================================================== ; Name...........: _Monitor_GetOrientation ; Description....: Get the display orientation (rotation angle) for a monitor ; Syntax.........: _Monitor_GetOrientation($iMonitor) ; Parameters.....: $iMonitor - Monitor index (1..N) ; Return values..: Success - Orientation angle in degrees: ; |0 - Landscape (normal) ; |90 - Portrait (rotated 90° clockwise) ; |180 - Landscape flipped (rotated 180°) ; |270 - Portrait flipped (rotated 270° clockwise / 90° counter-clockwise) ; Failure - -1, sets @error to non-zero: ; |@error = 1 - Invalid monitor index ; |@error = 2 - GetDisplaySettings failed (could not query display mode) ; Author.........: Dao Van Trong - TRONG.PRO ; Remarks........: Orientation is extracted from display mode flags. ; Most monitors typically return 0 (landscape) unless rotated in Windows display settings. ; Function automatically calls _Monitor_GetList() if monitor list is not initialized. ; Related........: _Monitor_GetDisplaySettings, _Monitor_GetInfo, _Monitor_GetList ; ================================================================================================================================ Func _Monitor_GetOrientation($iMonitor) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() If $iMonitor < 1 Or $iMonitor > $__g_aMonitorList[0][0] Then Return SetError(1, 0, -1) Local $aSettings = _Monitor_GetDisplaySettings($iMonitor) If @error Then Return SetError(2, 0, -1) ; DisplayMode field contains orientation information ; DM_DISPLAYORIENTATION values: 0=0°, 1=90°, 2=180°, 3=270° Local $iOrientation = 0 If IsArray($aSettings) And UBound($aSettings) > 4 Then ; Check display mode flags for orientation Local $iDisplayMode = $aSettings[4] ; Orientation is stored in bits 8-9 of display mode $iOrientation = BitAND(BitShift($iDisplayMode, 8), 3) * 90 EndIf Return $iOrientation EndFunc ;==>_Monitor_GetOrientation EG: ; ================================================================================================== ; MonitorUDF_Examples.au3 ; Interactive example tester for MonitorUDF.au3 UDF ; Fixed: Array index bug in FuncTest_10, improved error handling ; ================================================================================================== #include <GUIConstantsEx.au3> #include <ButtonConstants.au3> #include <WindowsConstants.au3> #include <GuiListBox.au3> #include <GuiEdit.au3> #include <Array.au3> #include "Monitor_UDF.au3" ; Updated include name ; ================================================================================================== ; Create GUI ; ================================================================================================== Global $GUI_W = 860, $GUI_H = 600 Global $hGUI = GUICreate("MonitorUDF - Examples (by TRONG.PRO)", $GUI_W, $GUI_H, -1, -1) GUISetBkColor(0xF5F5F5, $hGUI) ; Title GUICtrlCreateLabel("MonitorUDF Example Launcher", 12, 10, 400, 24) GUICtrlSetFont(-1, 12, 800, 0, 'Segoe UI', 5) ; Buttons column 1 - 6 buttons (1-6) Local $x1 = 12, $y1 = 48, $bw = 260, $bh = 36, $gap = 8 Global $iBtn1 = GUICtrlCreateButton("1. Enumerate monitors", $x1, $y1 + ($bh + $gap) * 0, $bw, $bh) Global $iBtn2 = GUICtrlCreateButton("2. Move Notepad -> Monitor #2 (center)", $x1, $y1 + ($bh + $gap) * 1, $bw, $bh) Global $iBtn3 = GUICtrlCreateButton("3. Move Notepad -> Monitor #2 @ (100,100)", $x1, $y1 + ($bh + $gap) * 2, $bw, $bh) Global $iBtn4 = GUICtrlCreateButton("4. Which monitor is mouse on?", $x1, $y1 + ($bh + $gap) * 3, $bw, $bh) Global $iBtn5 = GUICtrlCreateButton("5. Show virtual desktop bounds", $x1, $y1 + ($bh + $gap) * 4, $bw, $bh) Global $iBtn6 = GUICtrlCreateButton("6. Convert coords (local <-> virtual)", $x1, $y1 + ($bh + $gap) * 5, $bw, $bh) ; Buttons column 2 - 6 buttons (7-12) Local $x2 = $x1 + $bw + 12 Global $iBtn7 = GUICtrlCreateButton("7. Show monitor info (MsgBox)", $x2, $y1 + ($bh + $gap) * 0, $bw, $bh) Global $iBtn8 = GUICtrlCreateButton("8. Check if Notepad is visible", $x2, $y1 + ($bh + $gap) * 1, $bw, $bh) Global $iBtn9 = GUICtrlCreateButton("9. Create small GUI on each monitor", $x2, $y1 + ($bh + $gap) * 2, $bw, $bh) Global $iBtn10 = GUICtrlCreateButton("10. Move all visible windows -> primary", $x2, $y1 + ($bh + $gap) * 3, $bw, $bh) Global $iBtn11 = GUICtrlCreateButton("11. Refresh monitor list", $x2, $y1 + ($bh + $gap) * 4, $bw, $bh) Global $iBtn12 = GUICtrlCreateButton("12. Check monitor connected", $x2, $y1 + ($bh + $gap) * 5, $bw, $bh) ; Buttons column 3 - 6 buttons (13-17, but layout for 6) Local $x3 = $x2 + $bw + 12 Global $iBtn13 = GUICtrlCreateButton("13. Get DPI scaling", $x3, $y1 + ($bh + $gap) * 0, $bw, $bh) Global $iBtn14 = GUICtrlCreateButton("14. Get display orientation", $x3, $y1 + ($bh + $gap) * 1, $bw, $bh) Global $iBtn15 = GUICtrlCreateButton("15. Enumerate display modes", $x3, $y1 + ($bh + $gap) * 2, $bw, $bh) Global $iBtn16 = GUICtrlCreateButton("16. Get monitor from rect", $x3, $y1 + ($bh + $gap) * 3, $bw, $bh) Global $iBtn17 = GUICtrlCreateButton("17. Get monitor from window", $x3, $y1 + ($bh + $gap) * 4, $bw, $bh) ; Controls: log edit, clear, auto-demo, close Local $logX = 12, $logY = $y1 + ($bh + $gap) * 6 Local $logW = $GUI_W - 24, $logH = 180 Global $idLog = GUICtrlCreateEdit("", $logX, $logY, $logW, $logH, BitOR($ES_READONLY, $WS_HSCROLL, $WS_VSCROLL, $ES_MULTILINE)) GUICtrlSetFont($idLog, 9) Global $idFuncTest__ClearLog = GUICtrlCreateButton("Clear Log", 12, $logY + $logH + 10, 120, 28) Global $idFuncTest__RunAllDemo = GUICtrlCreateButton("Auto Demo (Run 1..17)", 150, $logY + $logH + 10, 220, 28) Global $idFuncTest__Close = GUICtrlCreateButton("Close", $GUI_W - 120, $logY + $logH + 10, 100, 28) Global $pidNotepad = 0 GUISetState(@SW_SHOW) ; Keep a list of created GUIs for Example 10 so we can close them later Global $Msg, $g_createdGUIs[0] ; FIXED: Initialize as empty array Global $g_bAutoMode = False ; Track if running in auto demo mode Global $g_hNotepadWindows[0] ; Track all notepad windows created ; ================================================================================================== ; Main loop ; ================================================================================================== While 1 $Msg = GUIGetMsg() Switch $Msg Case $GUI_EVENT_CLOSE, $idFuncTest__Close ; close any GUIs created in example 10 For $i = 0 To UBound($g_createdGUIs) - 1 If IsHWnd($g_createdGUIs[$i]) Then GUIDelete($g_createdGUIs[$i]) Next ExitLoop Case $idFuncTest__ClearLog GUICtrlSetData($idLog, '', '') Case $idFuncTest__RunAllDemo $g_bAutoMode = True ReDim $g_hNotepadWindows[0] FuncTest_1() Sleep(1000) FuncTest_2() Sleep(2000) FuncTest_3() Sleep(2000) FuncTest_4() Sleep(1500) FuncTest_5() Sleep(1000) FuncTest_6() Sleep(1000) FuncTest_7() Sleep(1000) FuncTest_8() Sleep(2000) FuncTest_9() Sleep(1000) FuncTest_10() Sleep(1000) FuncTest_11() Sleep(1000) FuncTest_12() Sleep(1000) FuncTest_13() Sleep(1000) FuncTest_14() Sleep(1000) FuncTest_15() Sleep(1000) FuncTest_16() Sleep(1000) FuncTest_17() Sleep(2000) ; Cleanup all created windows _CleanupAllWindows() $g_bAutoMode = False Case $iBtn1 FuncTest_1() Case $iBtn2 FuncTest_2() Case $iBtn3 FuncTest_3() Case $iBtn4 FuncTest_4() Case $iBtn5 FuncTest_5() Case $iBtn6 FuncTest_6() Case $iBtn7 FuncTest_7() Case $iBtn8 FuncTest_8() Case $iBtn9 FuncTest_9() Case $iBtn10 FuncTest_10() Case $iBtn11 FuncTest_11() Case $iBtn12 FuncTest_12() Case $iBtn13 FuncTest_13() Case $iBtn14 FuncTest_14() Case $iBtn15 FuncTest_15() Case $iBtn16 FuncTest_16() Case $iBtn17 FuncTest_17() EndSwitch Sleep(5) WEnd GUIDelete() Exit 0 ; ================================================================================================== ; Helper: append to log (with timestamp) ; ================================================================================================== Func _Log($s) ConsoleWrite($s & @CRLF) ; Format: DD/MM/YYYY HH:MM:SS Local $sDate = StringFormat("%02d/%02d/%04d", @MDAY, @MON, @YEAR) Local $sTime = StringFormat("%02d:%02d:%02d", @HOUR, @MIN, @SEC) Local $t = $sDate & " " & $sTime Local $cur = GUICtrlRead($idLog) If $cur = "" Then GUICtrlSetData($idLog, "[" & $t & "] " & $s) Else GUICtrlSetData($idLog, $cur & @CRLF & "[" & $t & "] " & $s) EndIf ; move caret to end _GUICtrlEdit_LineScroll($idLog, 0, _GUICtrlEdit_GetLineCount($idLog)) EndFunc ;==>_Log ; ================================================================================================== ; Helper: Cleanup all created windows (Notepad and GUIs) ; ================================================================================================== Func _CleanupAllWindows() ; Close all Notepad windows Local $aList = WinList("[CLASS:Notepad]") For $i = 1 To $aList[0][0] If $aList[$i][0] <> "" Then Local $hWnd = WinGetHandle($aList[$i][0]) If $hWnd Then WinClose($hWnd) EndIf Next Sleep(300) ; Force close any remaining Notepad processes While ProcessExists("notepad.exe") ProcessClose("notepad.exe") Sleep(100) WEnd ; Close all created GUIs For $i = 0 To UBound($g_createdGUIs) - 1 If IsHWnd($g_createdGUIs[$i]) Then GUIDelete($g_createdGUIs[$i]) Next ReDim $g_createdGUIs[0] ReDim $g_hNotepadWindows[0] EndFunc ;==>_CleanupAllWindows ; ================================================================================================== ; Helper: Track Notepad window ; ================================================================================================== Func _TrackNotepadWindow($hWnd) If $hWnd Then Local $n = UBound($g_hNotepadWindows) ReDim $g_hNotepadWindows[$n + 1] $g_hNotepadWindows[$n] = $hWnd EndIf EndFunc ;==>_TrackNotepadWindow Func FuncTest_1() _Log('+ TEST 1: Enumerate monitors -----------------------\') ; Enumerate monitors _Monitor_GetList() Local $cnt = _Monitor_GetCount() If @error Then Local $sMsg = "TEST 1: FAILED" & @CRLF & "ERROR - Failed to enumerate monitors" & @CRLF & "@error=" & @error _Log("---> Example 1: ERROR - Failed to enumerate monitors") If Not $g_bAutoMode Then MsgBox(48, "Example 1", $sMsg, 3) Return EndIf _Log("---> Example 1: Monitors detected: " & $cnt) Local $sResults = "Total Monitors: " & $cnt & @CRLF & @CRLF For $i = 1 To $cnt Local $a = _Monitor_GetInfo($i) If @error Then _Log(" Monitor " & $i & ": ERROR getting info") $sResults &= "Monitor #" & $i & ": ERROR" & @CRLF Else Local $sPrimary = $a[9] ? " [PRIMARY]" : "" _Log(" Monitor " & $i & ": Device=" & $a[10] & " Bounds=(" & $a[1] & "," & $a[2] & ")-(" & $a[3] & "," & $a[4] & ") Work=(" & $a[5] & "," & $a[6] & ")-(" & $a[7] & "," & $a[8] & ") Primary=" & $a[9]) $sResults &= "Monitor #" & $i & $sPrimary & ": " & $a[10] & @CRLF & _ " Bounds: " & $a[1] & "," & $a[2] & " to " & $a[3] & "," & $a[4] & @CRLF & _ " Work Area: " & $a[5] & "," & $a[6] & " to " & $a[7] & "," & $a[8] & @CRLF EndIf Next Local $sMsg = "TEST 1: SUCCESS" & @CRLF & @CRLF & $sResults If Not $g_bAutoMode Then MsgBox(64, "Example 1", $sMsg, 8) _Log('- End ------------------------------------------------/') EndFunc ;==>FuncTest_1 Func FuncTest_2() _Log('+ TEST 2: Move Notepad to monitor #2 centered ------\') ; Move Notepad to monitor #2 centered $pidNotepad = Run("notepad.exe") If Not WinWaitActive("[CLASS:Notepad]", "", 5) Then _Log("---> Example 2: Notepad did not start / focus") Local $sMsg = "TEST 2: FAILED" & @CRLF & "Notepad did not start / focus" If Not $g_bAutoMode Then MsgBox(48, "Example 2", $sMsg, 3) Else Sleep(1000) Local $hWnd = WinGetHandle("[CLASS:Notepad]") _TrackNotepadWindow($hWnd) _Monitor_GetList() Local $cnt = _Monitor_GetCount() If $cnt < 2 Then Local $sMsg = "TEST 2: SKIPPED" & @CRLF & "Need at least 2 monitors" & @CRLF & "Current: " & $cnt & " monitor(s)" _Log("---> Example 2: Need at least 2 monitors") If Not $g_bAutoMode Then MsgBox(64, "Example 2", $sMsg, 3) Else Local $iResult = _Monitor_MoveWindowToScreen("[CLASS:Notepad]", "", 2, -1, -1, True) If @error Then Local $sMsg = "TEST 2: FAILED" & @CRLF & "ERROR moving window" & @CRLF & "@error=" & @error _Log("---> Example 2: ERROR moving window: @error=" & @error) If Not $g_bAutoMode Then MsgBox(48, "Example 2", $sMsg, 3) Else Local $sMsg = "TEST 2: SUCCESS" & @CRLF & "Notepad moved to Monitor #2" & @CRLF & "Position: Centered" _Log("---> Example 2: Notepad moved to monitor #2 (centered)") If Not $g_bAutoMode Then MsgBox(64, "Example 2", $sMsg, 3) EndIf EndIf EndIf _Log('- End ------------------------------------------------/') EndFunc ;==>FuncTest_2 Func FuncTest_3() _Log('+ TEST 3: Move Notepad to monitor #2 at (100,100 ----\)') ; Move Notepad to monitor #2 at (100,100) $pidNotepad = Run("notepad.exe") If Not WinWaitActive("[CLASS:Notepad]", "", 5) Then Local $sMsg = "TEST 3: FAILED" & @CRLF & "Notepad did not start / focus" _Log("---> Example 3: Notepad did not start / focus") If Not $g_bAutoMode Then MsgBox(48, "Example 3", $sMsg, 3) Else Sleep(1000) Local $hWnd = WinGetHandle("[CLASS:Notepad]") _TrackNotepadWindow($hWnd) _Monitor_GetList() Local $cnt = _Monitor_GetCount() If $cnt < 2 Then Local $sMsg = "TEST 3: SKIPPED" & @CRLF & "Need at least 2 monitors" & @CRLF & "Current: " & $cnt & " monitor(s)" _Log("---> Example 3: Need at least 2 monitors") If Not $g_bAutoMode Then MsgBox(64, "Example 3", $sMsg, 3) Else Local $iResult = _Monitor_MoveWindowToScreen("[CLASS:Notepad]", "", 2, 100, 100, True) If @error Then Local $sMsg = "TEST 3: FAILED" & @CRLF & "ERROR moving window" & @CRLF & "@error=" & @error _Log("---> Example 3: ERROR moving window: @error=" & @error) If Not $g_bAutoMode Then MsgBox(48, "Example 3", $sMsg, 3) Else Local $sMsg = "TEST 3: SUCCESS" & @CRLF & "Notepad moved to Monitor #2" & @CRLF & "Position: (100, 100)" _Log("---> Example 3: Notepad moved to monitor #2 at (100,100)") If Not $g_bAutoMode Then MsgBox(64, "Example 3", $sMsg, 3) EndIf EndIf EndIf _Log('- End ------------------------------------------------/') EndFunc ;==>FuncTest_3 Func FuncTest_4() _Log('+ TEST 4: Which monitor is mouse on ------------------\') ; Automatically move mouse to each monitor and test _Monitor_GetList() Local $cnt = _Monitor_GetCount() If $cnt < 1 Then Local $sMsg = "TEST 4: SKIPPED" & @CRLF & "No monitors detected" _Log("---> Example 4: No monitors detected") If Not $g_bAutoMode Then MsgBox(64, "Example 4", $sMsg, 3) Else Local $aResults = "" Local $sCurrentPos = MouseGetPos() Local $iOrigX = $sCurrentPos[0], $iOrigY = $sCurrentPos[1] _Log("---> Example 4: Testing " & $cnt & " monitor(s)") For $i = 1 To $cnt ; Get monitor center Local $iLeft, $iTop, $iRight, $iBottom _Monitor_GetBounds($i, $iLeft, $iTop, $iRight, $iBottom) Local $iCenterX = $iLeft + ($iRight - $iLeft) / 2 Local $iCenterY = $iTop + ($iBottom - $iTop) / 2 ; Move mouse to center of monitor MouseMove($iCenterX, $iCenterY, 0) Sleep(200) ; Check which monitor mouse is on Local $m = _Monitor_GetFromPoint() If @error Then _Log(" Monitor " & $i & ": ERROR - @error=" & @error) $aResults &= "Monitor " & $i & ": ERROR" & @CRLF Else Local $aInfo = _Monitor_GetInfo($i) Local $sDevice = @error ? "N/A" : $aInfo[10] Local $sStatus = ($m = $i) ? "CORRECT" : "WRONG (detected #" & $m & ")" _Log(" Monitor " & $i & " (" & $sDevice & "): Mouse detected on #" & $m & " - " & $sStatus) $aResults &= "Monitor #" & $i & " (" & $sDevice & "): #" & $m & " - " & $sStatus & @CRLF EndIf Sleep(300) Next ; Restore original mouse position MouseMove($iOrigX, $iOrigY, 0) Local $sMsg = "TEST 4: COMPLETE" & @CRLF & @CRLF & "Mouse Position Test Results:" & @CRLF & $aResults _Log("---> Example 4: Test complete, mouse restored to original position") If Not $g_bAutoMode Then MsgBox(64, "Example 4", $sMsg, 5) EndIf _Log('- End ------------------------------------------------/') EndFunc ;==>FuncTest_4 Func FuncTest_5() _Log('+ TEST 5: Virtual desktop bounds -----------------------\') ; Virtual desktop bounds Local $aV = _Monitor_GetVirtualBounds() If @error Then Local $sMsg = "TEST 5: FAILED" & @CRLF & "ERROR getting virtual bounds" & @CRLF & "@error=" & @error _Log("---> Example 5: ERROR getting virtual bounds: @error=" & @error) If Not $g_bAutoMode Then MsgBox(48, "Example 5", $sMsg, 3) Else Local $sMsg = "TEST 5: SUCCESS" & @CRLF & @CRLF & "Virtual Desktop Bounds:" & @CRLF & _ "Left: " & $aV[0] & @CRLF & _ "Top: " & $aV[1] & @CRLF & _ "Width: " & $aV[2] & @CRLF & _ "Height: " & $aV[3] & @CRLF & @CRLF & _ "Right: " & ($aV[0] + $aV[2]) & @CRLF & _ "Bottom: " & ($aV[1] + $aV[3]) _Log("---> Example 5: Virtual bounds L=" & $aV[0] & " T=" & $aV[1] & " W=" & $aV[2] & " H=" & $aV[3]) If Not $g_bAutoMode Then MsgBox(64, "Example 5", $sMsg, 5) EndIf _Log('- End ------------------------------------------------/') EndFunc ;==>FuncTest_5 Func FuncTest_6() _Log('+ TEST 6: Convert coords example (local -> virtual -> back) --\') ; Convert coords example (local -> virtual -> back) _Monitor_GetList() Local $mon = _Monitor_GetCount() If $mon < 1 Then Local $sMsg = "TEST 6: SKIPPED" & @CRLF & "No monitors detected" _Log("---> Example 6: No monitors detected") If Not $g_bAutoMode Then MsgBox(64, "Example 6", $sMsg, 3) Else Local $sResults = "" For $i = 1 To $mon Local $xLocal = 50, $yLocal = 100 Local $aV = _Monitor_ToVirtual($i, $xLocal, $yLocal) If @error Then _Log("---> Example 6: Monitor " & $i & " ERROR converting to virtual: @error=" & @error) $sResults &= "Monitor #" & $i & ": ERROR (to virtual)" & @CRLF Else Local $aBack = _Monitor_FromVirtual($i, $aV[0], $aV[1]) If @error Then _Log("---> Example 6: Monitor " & $i & " ERROR converting from virtual: @error=" & @error) $sResults &= "Monitor #" & $i & ": ERROR (from virtual)" & @CRLF Else Local $bMatch = (Abs($aBack[0] - $xLocal) < 1) And (Abs($aBack[1] - $yLocal) < 1) _Log("---> Example 6: Mon " & $i & " local(" & $xLocal & "," & $yLocal & ") -> virtual(" & $aV[0] & "," & $aV[1] & ") -> back(" & $aBack[0] & "," & $aBack[1] & ")") $sResults &= "Monitor #" & $i & ": (" & $xLocal & "," & $yLocal & ") -> (" & $aV[0] & "," & $aV[1] & ") -> (" & $aBack[0] & "," & $aBack[1] & ")" & _ ($bMatch ? " ✓" : " ✗") & @CRLF EndIf EndIf Next Local $sMsg = "TEST 6: COMPLETE" & @CRLF & @CRLF & "Coordinate Conversion Test:" & @CRLF & $sResults If Not $g_bAutoMode Then MsgBox(64, "Example 6", $sMsg, 5) EndIf _Log('- End --------------------------------------------------------/') EndFunc ;==>FuncTest_6 Func FuncTest_7() _Log('+ TEST 7: Show detailed info via MsgBox (calls UDF) ------\') ; Show detailed info via MsgBox (calls UDF) _Monitor_GetList() Local $sResult = _Monitor_ShowInfo(1, 8) If @error Then Local $sMsg = "TEST 7: FAILED" & @CRLF & "ERROR showing info" & @CRLF & "@error=" & @error _Log("---> Example 7: ERROR showing info: @error=" & @error) If Not $g_bAutoMode Then MsgBox(48, "Example 7", $sMsg, 3) Else Local $sMsg = "TEST 7: SUCCESS" & @CRLF & @CRLF & "Detailed monitor information displayed above." _Log("---> Example 7: _Monitor_ShowInfo() called successfully") If Not $g_bAutoMode Then MsgBox(64, "Example 7", $sMsg, 3) EndIf _Log('- End ------------------------------------------------/') EndFunc ;==>FuncTest_7 Func FuncTest_8() _Log('+ TEST 8: Start notepad, check visible ---------------\') ; Start notepad, check visible $pidNotepad = Run("notepad.exe") If Not WinWaitActive("[CLASS:Notepad]", "", 5) Then Local $sMsg = "TEST 8: FAILED" & @CRLF & "Notepad did not start/focus" _Log("---> Example 8: Notepad did not start/focus") If Not $g_bAutoMode Then MsgBox(48, "Example 8", $sMsg, 3) Else Sleep(1000) Local $h = WinGetHandle("[CLASS:Notepad]") _TrackNotepadWindow($h) Local $b = _Monitor_IsVisibleWindow($h) If @error Then Local $sMsg = "TEST 8: FAILED" & @CRLF & "ERROR checking visibility" & @CRLF & "@error=" & @error _Log("---> Example 8: ERROR checking visibility: @error=" & @error) If Not $g_bAutoMode Then MsgBox(48, "Example 8", $sMsg, 3) Else Local $sTitle = WinGetTitle($h) Local $sMsg = "TEST 8: SUCCESS" & @CRLF & @CRLF & "Window: " & ($sTitle = "" ? "[No Title]" : $sTitle) & @CRLF & _ "Handle: " & $h & @CRLF & _ "Visible: " & ($b ? "YES ✓" : "NO ✗") _Log("---> Example 8: Notepad handle " & $h & " visible? " & ($b ? "Yes" : "No")) If Not $g_bAutoMode Then MsgBox(64, "Example 8", $sMsg, 3) EndIf EndIf _Log('- End ------------------------------------------------/') EndFunc ;==>FuncTest_8 Func FuncTest_9() _Log('+ TEST 9: Create small GUI on each monitor -------------\') ; Create small GUI on each monitor _Monitor_GetList() ; close previously created For $i = 0 To UBound($g_createdGUIs) - 1 If IsHWnd($g_createdGUIs[$i]) Then GUIDelete($g_createdGUIs[$i]) Next ReDim $g_createdGUIs[0] ; reset Local $created = 0 For $i = 1 To _Monitor_GetCount() Local $a = _Monitor_GetInfo($i) If @error Then _Log(" Monitor " & $i & ": ERROR getting info") ContinueLoop EndIf Local $h = GUICreate("Monitor #" & $i & " - " & $a[10], 260, 120, $a[1] + 40, $a[2] + 40) GUICtrlCreateLabel("Monitor " & $i & ($a[9] ? " (Primary)" : ""), 10, 12, 240, 20) GUISetState(@SW_SHOW, $h) ; store to close later __ArrayAdd($g_createdGUIs, $h) $created += 1 Next Local $sMsg = "TEST 9: SUCCESS" & @CRLF & @CRLF & "Created " & $created & " GUI window(s)" & @CRLF & @CRLF If $created > 0 Then $sMsg &= "One GUI created on each monitor:" & @CRLF For $i = 1 To _Monitor_GetCount() Local $a = _Monitor_GetInfo($i) If Not @error Then Local $sPrimary = $a[9] ? " [PRIMARY]" : "" $sMsg &= " Monitor #" & $i & $sPrimary & ": " & $a[10] & @CRLF EndIf Next $sMsg &= @CRLF & "Windows will be closed when you close the launcher." Else $sMsg &= "No GUIs were created." EndIf _Log("---> Example 9: Created " & $created & " GUI(s) on monitors. Use Close to exit (they will be closed).") If Not $g_bAutoMode Then MsgBox(64, "Example 9", $sMsg, 5) _Log('- End ------------------------------------------------/') EndFunc ;==>FuncTest_9 Func FuncTest_10() _Log('+ TEST 10: Move all visible windows to primary ----------\') ; Move all visible windows to primary _Monitor_GetList() Local $prim = _Monitor_GetPrimary() If $prim = 0 Or @error Then Local $sMsg = "TEST 10: FAILED" & @CRLF & "Primary monitor not found or error" & @CRLF & "@error=" & @error _Log("---> Example 10: Primary monitor not found or error") If Not $g_bAutoMode Then MsgBox(48, "Example 10", $sMsg, 3) Else Local $aList = WinList() Local $moved = 0 Local $aInfo = _Monitor_GetInfo($prim) Local $sDevice = @error ? "N/A" : $aInfo[10] For $i = 1 To $aList[0][0] If $aList[$i][0] <> "" Then ; FIXED: Use correct array index - WinList()[i][0] is title, need to get handle from title Local $h = WinGetHandle($aList[$i][0]) ; FIXED: Changed from [1] to [0] If Not @error And $h Then If _Monitor_IsVisibleWindow($h) Then Local $iResult = _Monitor_MoveWindowToScreen($h, "", $prim) If Not @error Then $moved += 1 EndIf EndIf EndIf Next Local $sMsg = "TEST 10: SUCCESS" & @CRLF & @CRLF & _ "Moved " & $moved & " visible window(s)" & @CRLF & _ "to Primary Monitor #" & $prim & @CRLF & _ "Device: " & $sDevice _Log("---> Example 10: Moved " & $moved & " visible windows to primary monitor #" & $prim) If Not $g_bAutoMode Then MsgBox(64, "Example 10", $sMsg, 4) EndIf _Log('- End ------------------------------------------------/') EndFunc ;==>FuncTest_10 Func FuncTest_11() _Log('+ TEST 11: Refresh monitor list ----------------------\') ; Refresh monitor list Local $cntBefore = _Monitor_GetCount() _Log("---> Example 11: Monitors before refresh: " & $cntBefore) Local $cntAfter = _Monitor_Refresh() If @error Then Local $sMsg = "TEST 11: FAILED" & @CRLF & "ERROR refreshing monitor list" & @CRLF & "@error=" & @error _Log("---> Example 11: ERROR refreshing: @error=" & @error) If Not $g_bAutoMode Then MsgBox(48, "Example 11", $sMsg, 3) Else Local $sChangeInfo = "" If $cntBefore <> $cntAfter Then _Log(" --> Monitor count changed! (was " & $cntBefore & ", now " & $cntAfter & ")") $sChangeInfo = @CRLF & "⚠ CHANGE DETECTED! ⚠" & @CRLF & "Before: " & $cntBefore & " monitor(s)" & @CRLF & "After: " & $cntAfter & " monitor(s)" Else _Log(" --> Monitor count unchanged") $sChangeInfo = @CRLF & "Count unchanged: " & $cntAfter & " monitor(s)" EndIf Local $sMsg = "TEST 11: SUCCESS" & @CRLF & @CRLF & "Monitor list refreshed" & $sChangeInfo _Log("---> Example 11: Monitors after refresh: " & $cntAfter) If Not $g_bAutoMode Then MsgBox(64, "Example 11", $sMsg, 4) EndIf _Log('- End ------------------------------------------------/') EndFunc ;==>FuncTest_11 Func FuncTest_12() _Log('+ TEST 12: Check if monitors are connected -----------\') ; Check if monitors are still connected _Monitor_GetList() Local $cnt = _Monitor_GetCount() If $cnt < 1 Then Local $sMsg = "TEST 12: SKIPPED" & @CRLF & "No monitors detected" _Log("---> Example 12: No monitors detected") If Not $g_bAutoMode Then MsgBox(64, "Example 12", $sMsg, 3) Else _Log("---> Example 12: Checking connection status for " & $cnt & " monitor(s):") Local $sResults = "" Local $iConnected = 0, $iDisconnected = 0 For $i = 1 To $cnt Local $bConnected = _Monitor_IsConnected($i) If @error Then _Log(" Monitor " & $i & ": ERROR checking connection: @error=" & @error) $sResults &= "Monitor #" & $i & ": ERROR" & @CRLF Else Local $sStatus = $bConnected ? "CONNECTED ✓" : "DISCONNECTED ✗" Local $aInfo = _Monitor_GetInfo($i) Local $sDevice = @error ? "N/A" : $aInfo[10] _Log(" Monitor " & $i & " (" & $sDevice & "): " & ($bConnected ? "CONNECTED" : "DISCONNECTED")) $sResults &= "Monitor #" & $i & " (" & $sDevice & "): " & $sStatus & @CRLF If $bConnected Then $iConnected += 1 Else $iDisconnected += 1 EndIf EndIf Next Local $sMsg = "TEST 12: COMPLETE" & @CRLF & @CRLF & "Connection Status:" & @CRLF & _ "Connected: " & $iConnected & @CRLF & _ "Disconnected: " & $iDisconnected & @CRLF & @CRLF & _ $sResults If Not $g_bAutoMode Then MsgBox(64, "Example 12", $sMsg, 5) EndIf _Log('- End ------------------------------------------------/') EndFunc ;==>FuncTest_12 Func FuncTest_13() _Log('+ TEST 13: Get DPI scaling for monitors -------------\') ; Get DPI scaling for each monitor _Monitor_GetList() Local $cnt = _Monitor_GetCount() If $cnt < 1 Then Local $sMsg = "TEST 13: SKIPPED" & @CRLF & "No monitors detected" _Log("---> Example 13: No monitors detected") If Not $g_bAutoMode Then MsgBox(64, "Example 13", $sMsg, 3) Else _Log("---> Example 13: DPI information for " & $cnt & " monitor(s):") Local $sResults = "" For $i = 1 To $cnt Local $aDPI = _Monitor_GetDPI($i) If @error Then _Log(" Monitor " & $i & ": ERROR getting DPI: @error=" & @error) $sResults &= "Monitor #" & $i & ": ERROR" & @CRLF Else Local $aInfo = _Monitor_GetInfo($i) Local $sDevice = @error ? "N/A" : $aInfo[10] _Log(" Monitor " & $i & " (" & $sDevice & "):") _Log(" DPI X: " & $aDPI[0] & ", DPI Y: " & $aDPI[1]) _Log(" Scaling: " & $aDPI[2] & "%") $sResults &= "Monitor #" & $i & " (" & $sDevice & "):" & @CRLF & _ " DPI X: " & $aDPI[0] & ", DPI Y: " & $aDPI[1] & @CRLF & _ " Scaling: " & $aDPI[2] & "%" & @CRLF EndIf Next Local $sMsg = "TEST 13: COMPLETE" & @CRLF & @CRLF & "DPI Information:" & @CRLF & $sResults If Not $g_bAutoMode Then MsgBox(64, "Example 13", $sMsg, 6) EndIf _Log('- End ------------------------------------------------/') EndFunc ;==>FuncTest_13 Func FuncTest_14() _Log('+ TEST 14: Get display orientation -------------------\') ; Get display orientation for each monitor _Monitor_GetList() Local $cnt = _Monitor_GetCount() If $cnt < 1 Then Local $sMsg = "TEST 14: SKIPPED" & @CRLF & "No monitors detected" _Log("---> Example 14: No monitors detected") If Not $g_bAutoMode Then MsgBox(64, "Example 14", $sMsg, 3) Else _Log("---> Example 14: Display orientation for " & $cnt & " monitor(s):") Local $sOrientationNames[4] = ["Landscape (0°)", "Portrait (90°)", "Landscape Flipped (180°)", "Portrait Flipped (270°)"] Local $sResults = "" For $i = 1 To $cnt Local $iOrientation = _Monitor_GetOrientation($i) If @error Then _Log(" Monitor " & $i & ": ERROR getting orientation: @error=" & @error) $sResults &= "Monitor #" & $i & ": ERROR" & @CRLF Else Local $aInfo = _Monitor_GetInfo($i) Local $sDevice = @error ? "N/A" : $aInfo[10] Local $sOrientationName = "Unknown" If $iOrientation >= 0 And $iOrientation <= 270 Then Local $iIndex = Int($iOrientation / 90) If $iIndex >= 0 And $iIndex < 4 Then $sOrientationName = $sOrientationNames[$iIndex] EndIf _Log(" Monitor " & $i & " (" & $sDevice & "): " & $iOrientation & "° (" & $sOrientationName & ")") $sResults &= "Monitor #" & $i & " (" & $sDevice & "): " & $iOrientation & "°" & @CRLF & _ " " & $sOrientationName & @CRLF EndIf Next Local $sMsg = "TEST 14: COMPLETE" & @CRLF & @CRLF & "Display Orientation:" & @CRLF & $sResults If Not $g_bAutoMode Then MsgBox(64, "Example 14", $sMsg, 5) EndIf _Log('- End ------------------------------------------------/') EndFunc ;==>FuncTest_14 Func FuncTest_15() _Log('+ TEST 15: Enumerate all display modes ---------------\') ; Enumerate all display modes for all monitors (auto mode) or selected monitor _Monitor_GetList() Local $cnt = _Monitor_GetCount() If $cnt < 1 Then Local $sMsg = "TEST 15: SKIPPED" & @CRLF & "No monitors detected" _Log("---> Example 15: No monitors detected") If Not $g_bAutoMode Then MsgBox(64, "Example 15", $sMsg, 3) Else Local $sAllResults = "" Local $iTotalModes = 0 ; In auto mode, test all monitors. Otherwise, ask user Local $bTestAll = $g_bAutoMode Local $aTestMonitors[1] = [1] ; Default to monitor 1 If Not $bTestAll And $cnt > 1 Then Local $sInput = InputBox("Example 15", "Select monitor to test (1-" & $cnt & ") or 0 for all:", "0", "", 250, 150) If Not @error And StringIsDigit($sInput) Then Local $iInput = Int($sInput) If $iInput = 0 Then $bTestAll = True ElseIf $iInput >= 1 And $iInput <= $cnt Then ; Test single monitor $bTestAll = False $aTestMonitors[0] = $iInput EndIf EndIf EndIf ; If testing all, create array of all monitor indices If $bTestAll Then ReDim $aTestMonitors[$cnt] For $i = 0 To $cnt - 1 $aTestMonitors[$i] = $i + 1 Next EndIf ; Test each monitor For $iMonitorIndex = 0 To UBound($aTestMonitors) - 1 Local $iTestMonitor = $aTestMonitors[$iMonitorIndex] Local $aModes = _Monitor_EnumAllDisplayModes($iTestMonitor) If @error Then _Log("---> Example 15: Monitor " & $iTestMonitor & " ERROR enumerating modes: @error=" & @error) $sAllResults &= "Monitor #" & $iTestMonitor & ": ERROR" & @CRLF Else Local $aInfo = _Monitor_GetInfo($iTestMonitor) Local $sDevice = @error ? "N/A" : $aInfo[10] $iTotalModes += $aModes[0][0] _Log("---> Example 15: Monitor " & $iTestMonitor & " (" & $sDevice & ") has " & $aModes[0][0] & " display mode(s):") Local $sModesList = "" Local $iShowCount = ($aModes[0][0] > 5) ? 5 : $aModes[0][0] For $i = 1 To $iShowCount Local $sModeInfo = $aModes[$i][0] & "x" & $aModes[$i][1] & " @ " & $aModes[$i][3] & "Hz, " & $aModes[$i][2] & " bpp" _Log(" Mode " & $i & ": " & $sModeInfo) $sModesList &= " " & $sModeInfo & @CRLF Next If $aModes[0][0] > 5 Then _Log(" ... and " & ($aModes[0][0] - 5) & " more mode(s)") $sModesList &= " ... and " & ($aModes[0][0] - 5) & " more mode(s)" & @CRLF EndIf If $bTestAll Then $sAllResults &= "Monitor #" & $iTestMonitor & " (" & $sDevice & "): " & $aModes[0][0] & " modes" & @CRLF & $sModesList Else $sAllResults = "Monitor #" & $iTestMonitor & " (" & $sDevice & "): " & $aModes[0][0] & " modes" & @CRLF & $sModesList EndIf EndIf Next Local $sMsg = "TEST 15: COMPLETE" & @CRLF & @CRLF If $bTestAll Then $sMsg &= "Total Modes Found: " & $iTotalModes & @CRLF & @CRLF EndIf $sMsg &= "Display Modes:" & @CRLF & $sAllResults If Not $g_bAutoMode Then MsgBox(64, "Example 15", $sMsg, 10) EndIf _Log('- End ------------------------------------------------/') EndFunc ;==>FuncTest_15 Func FuncTest_16() _Log('+ TEST 16: Get monitor from rectangle ----------------\') ; Get monitor that overlaps with a rectangle _Monitor_GetList() Local $cnt = _Monitor_GetCount() If $cnt < 1 Then Local $sMsg = "TEST 16: SKIPPED" & @CRLF & "No monitors detected" _Log("---> Example 16: No monitors detected") If Not $g_bAutoMode Then MsgBox(64, "Example 16", $sMsg, 3) Else ; Create a test rectangle (center of primary monitor) Local $prim = _Monitor_GetPrimary() If $prim = 0 Then $prim = 1 Local $iLeft, $iTop, $iRight, $iBottom _Monitor_GetBounds($prim, $iLeft, $iTop, $iRight, $iBottom) Local $iCenterX = $iLeft + ($iRight - $iLeft) / 2 Local $iCenterY = $iTop + ($iBottom - $iTop) / 2 Local $iRectW = 200, $iRectH = 150 Local $iRectLeft = $iCenterX - $iRectW / 2 Local $iRectTop = $iCenterY - $iRectH / 2 Local $iRectRight = $iCenterX + $iRectW / 2 Local $iRectBottom = $iCenterY + $iRectH / 2 _Log("---> Example 16: Testing rectangle: L=" & $iRectLeft & ", T=" & $iRectTop & ", R=" & $iRectRight & ", B=" & $iRectBottom) Local $iMonitor = _Monitor_GetFromRect($iRectLeft, $iRectTop, $iRectRight, $iRectBottom) If @error Then Local $sMsg = "TEST 16: FAILED" & @CRLF & "ERROR getting monitor from rect" & @CRLF & "@error=" & @error _Log("---> Example 16: ERROR getting monitor from rect: @error=" & @error) If Not $g_bAutoMode Then MsgBox(48, "Example 16", $sMsg, 3) Else If $iMonitor > 0 Then Local $aInfo = _Monitor_GetInfo($iMonitor) Local $sDevice = @error ? "N/A" : $aInfo[10] Local $sPrimary = @error ? "" : ($aInfo[9] ? " [PRIMARY]" : "") Local $sMsg = "TEST 16: SUCCESS" & @CRLF & @CRLF & _ "Test Rectangle:" & @CRLF & _ " Left: " & $iRectLeft & ", Top: " & $iRectTop & @CRLF & _ " Right: " & $iRectRight & ", Bottom: " & $iRectBottom & @CRLF & @CRLF & _ "Found Monitor: #" & $iMonitor & $sPrimary & @CRLF & _ "Device: " & $sDevice _Log("---> Example 16: Rectangle overlaps with Monitor #" & $iMonitor & " (" & $sDevice & ")") If Not $g_bAutoMode Then MsgBox(64, "Example 16", $sMsg, 4) Else Local $sMsg = "TEST 16: NO MATCH" & @CRLF & @CRLF & "Rectangle does not overlap with any monitor" _Log("---> Example 16: Rectangle does not overlap with any monitor") If Not $g_bAutoMode Then MsgBox(48, "Example 16", $sMsg, 3) EndIf EndIf EndIf _Log('- End ------------------------------------------------/') EndFunc ;==>FuncTest_16 Func FuncTest_17() _Log('+ TEST 17: Get monitor from window -------------------\') ; Get monitor containing a specific window _Monitor_GetList() ; Try to find Notepad or use current active window Local $hWnd = WinGetHandle("[CLASS:Notepad]") If @error Or Not $hWnd Then $hWnd = WinGetHandle("[ACTIVE]") If @error Or Not $hWnd Then _Log("---> Example 17: No suitable window found. Opening Notepad...") $pidNotepad = Run("notepad.exe") If WinWaitActive("[CLASS:Notepad]", "", 3) Then Sleep(500) $hWnd = WinGetHandle("[CLASS:Notepad]") Else _Log("---> Example 17: ERROR - Could not find or create test window") Return EndIf EndIf EndIf If $hWnd Then Local $sTitle = WinGetTitle($hWnd) _Log("---> Example 17: Testing window: " & ($sTitle = "" ? "[No Title]" : $sTitle) & " (Handle: " & $hWnd & ")") Local $iMonitor = _Monitor_GetFromWindow($hWnd) If @error Then _Log("---> Example 17: ERROR getting monitor from window: @error=" & @error) Else If $iMonitor > 0 Then Local $aInfo = _Monitor_GetInfo($iMonitor) Local $sDevice = @error ? "N/A" : $aInfo[10] Local $sPrimary = @error ? "" : ($aInfo[9] ? " [PRIMARY]" : "") _Log("---> Example 17: Window is on Monitor #" & $iMonitor & " (" & $sDevice & ")" & $sPrimary) ; Get window position for verification Local $aWinPos = WinGetPos($hWnd) If Not @error Then _Log(" Window position: X=" & $aWinPos[0] & ", Y=" & $aWinPos[1]) _Log(" Monitor bounds: L=" & $aInfo[1] & ", T=" & $aInfo[2] & ", R=" & $aInfo[3] & ", B=" & $aInfo[4]) EndIf Local $sMsg = "TEST 17: SUCCESS" & @CRLF & @CRLF & _ "Window: " & ($sTitle = "" ? "[No Title]" : $sTitle) & @CRLF & _ "Handle: " & $hWnd & @CRLF & @CRLF & _ "Monitor: #" & $iMonitor & $sPrimary & @CRLF & _ "Device: " & $sDevice & @CRLF & @CRLF & _ "Window Position:" & @CRLF & _ " X: " & $aWinPos[0] & ", Y: " & $aWinPos[1] If Not $g_bAutoMode Then MsgBox(64, "Example 17", $sMsg, 5) Else _Log("---> Example 17: Window is not on any monitor") EndIf EndIf EndIf _Log('- End ------------------------------------------------/') EndFunc ;==>FuncTest_17 ; ================================================================================================== ; Small helper to push item into dynamic array (simple) ; ================================================================================================== Func __ArrayAdd(ByRef $a, $v) Local $n = 0 If IsArray($a) Then $n = UBound($a) ReDim $a[$n + 1] $a[$n] = $v EndFunc ;==>__ArrayAdd2 points
-
User Interface Builder Overview Use this tool to visually design Windows applications with a focus on Metro windows, standard windows, and Tool windows. This is for users who want a faster and simpler development tool. Drag-and-drop GUI creation, code generation, and easy control alignment tools. No more clicking through property sheets to set variable names, sizes, and the control’s text. Please replace "MetroUDF-Required\SSCtrlHover.au3" within the metro UDF files to see more meaningful messages in the console. The following line was inserted into the function. This prevents crashing on syntax and logical errors while Metro buttons are in use. Func _cHvr_Register($idCtrl, $fnHovOff = '', $fnHoverOn = '', $fnClick = '', $fnDblClk = '', $HoverData = 0,$ClickData = 0,$fnRightClick = '') If $BLOCK_HOVER_REGISTRATION Then Return Unfortunately, the following will have to added to your scripts if you already use Metro UDF and you replace "SSCtrlHover.au3". Global $BLOCK_HOVER_REGISTRATION = False #include "MetroGUI_UDF.au3" #include "MetroGUI_UDF_xpk.au3" #include "_GUIDisable.au3" ; For dim effects when msgbox is displayed Features Metro Controls for all window types WYSIWYG real-time preview Generates AutoIt GUI and message loop code Multiple control selection and manipulation Make additional selections with the CTRL key Accelerated control movements with the SHIFT key Change controls position with mouse or arrow keys Double click a control to precisely set its size and text Save/load GUI layouts and Control layouts to files Custom styles/themes and Controls using Metro Snap-to-guide, and toolbar alignment aids Drag down guides from the top and left sides of the Designer window Copy-n-paste between different window types Technical Details .Gui/.Ctrls file is a simple delimited text file Copy-n-paste is a similar file without the window specifications The application is meant to be portable, so it is one file The only Custom UDFs in use is Metro 5.1, and my Metro Expansion pack The script uses Label controls for everything. No GDI was used. Every control handle is saved in an array Maps are used in Metro and in future UDFs containing new controls You need Metro 5.1 UDF Limitations and known issues Resizing the Metro window with the mouse is flaky Changing control and window styles is not implemented Window size cannot be changed precisely Undo functionality might cause problems with code generation No Redo implemented Thank you BB19 and everyone that contributed to Metro UDF. MetroGUI_UDF_xpk.au3 SSCtrlHover.au3 UserInterfaceBuilder.au32 points
-
I tried to apply dark mode to the SampleControls.au3 example. What I did so far: ; Coded by UEZ build 2025-10-17 beta ;not DPI aware! #include <APIConstants.au3> #include <AVIConstants.au3> #include <GUIConstantsEx.au3> #include <GuiDateTimePicker.au3> #include <GuiMenu.au3> #include <GuiMonthCal.au3> #include <GuiScrollBars.au3> #include <GuiTab.au3> #include <TreeViewConstants.au3> #include <ListViewConstants.au3> #include <WinAPIConstants.au3> #include <WinAPIGdi.au3> #include <WinAPIRes.au3> #include <WinAPIShellEx.au3> #include <WinAPISys.au3> #include <WinAPISysWin.au3> #include <WinAPITheme.au3> #include <WindowsConstants.au3> Enum $IHCM_USE_CACHED_VALUE, $IHCM_REFRESH Enum $APPMODE_DEFAULT = 0, $APPMODE_ALLOWDARK, $APPMODE_FORCEDARK, $APPMODE_FORCELIGHT, $APPMODE_MAX Const $PRF_CLIENT = 0x04 ; Dark Mode Colors (RGB) Global Const $COLOR_BG_DARK = 0x202020 Global Const $COLOR_TEXT_LIGHT = 0xFFFFFF Global Const $COLOR_CONTROL_BG = 0x2B2B2B Global Const $COLOR_EDIT_BG = 0x1E1E1E Global Const $COLOR_BUTTON_BG = 0x333333 Global Const $COLOR_BORDER = 0x3F3F3F ; Global variables for subclassing (MUST be declared before _Example()!) Global $g_hGUI = 0, $g_hTab, $g_ListView Global $g_aControls[50][3] = [[0, 0, 0]] ; [ControlID, hWnd, OldWndProc] Global $g_iControlCount = 0 Global $g_pSubclassProc = 0 ; Global brushes for _WM_CTLCOLOR (avoids memory leaks) Global $g_hBrushEdit = 0 Global $g_hBrushButton = 0 Global $g_hBrushBg = 0 Global $g_hBrushGreen Global $g_hLabelGreen = 0, $g_idLabelGreen Global $g_idLabelPic, $g_hLabelPic Global $g_hMenu = 0 Global $g_idDate = 0, $g_hDate = 0 ; Global variable for tab subclassing Global $g_hTab_CB, $g_pTab_CB, $g_hProc ; Structure for NM_CUSTOMDRAW notification Global Const $tagNMCUSTOMDRAW = _ $tagNMHDR & ";" & _ ; Contains NM_CUSTOMDRAW / NMHDR header among other things "dword dwDrawStage;" & _ ; Current drawing stage (CDDS_*) "handle hdc;" & _ ; Device Context Handle "long left;long top;long right;long bottom;" & _ ; Drawing rectangle "dword_ptr dwItemSpec;" & _ ; Item index or other info (depending on the control) "uint uItemState;" & _ ; State Flags (CDIS_SELECTED, CDIS_FOCUS etc.) "lparam lItemlParam" ; lParam set by the item (e.g., via LVITEM.lParam) Global $g_hMenu = 0, $hMenuFont Global $g_aMenuText = [] ; dynamic array for top-level menu texts Global $arMenuItems[1][8] $arMenuItems[0][0] = 0 Global $arSideItems[1][10] $arSideItems[0][0] = 0 Const $ODT_MENU = 1 Const $ODS_SELECTED = 0x0001 Const $ODS_DISABLED = 0x0004 _Example() Func _Example() ; Create global brushes $g_hBrushEdit = _WinAPI_CreateSolidBrush(_ColorToCOLORREF($COLOR_EDIT_BG)) $g_hBrushButton = _WinAPI_CreateSolidBrush(_ColorToCOLORREF($COLOR_BUTTON_BG)) $g_hBrushBg = _WinAPI_CreateSolidBrush(_ColorToCOLORREF($COLOR_BG_DARK)) #Region GUI $g_hGUI = GUICreate("Sample GUI with Dark Mode", 400, 400) GUISetIcon(@SystemDir & "\mspaint.exe", 0) GUISetBkColor($COLOR_BG_DARK, $g_hGUI) ; Register GUI-level WM_CTLCOLOR messages GUIRegisterMsg($WM_CTLCOLOREDIT, "_WM_CTLCOLOR") GUIRegisterMsg($WM_CTLCOLORLISTBOX, "_WM_CTLCOLOR") GUIRegisterMsg($WM_CTLCOLORBTN, "_WM_CTLCOLOR") GUIRegisterMsg($WM_CTLCOLORSTATIC, "_WM_CTLCOLOR") GUIRegisterMsg($WM_INITMENUPOPUP, "_OnInitMenuPopup") GUIRegisterMsg($WM_MEASUREITEM, "WM_MEASUREITEM_Handler") GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM_Handler") GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") GUIRegisterMsg($WM_ACTIVATE, "_WM_ACTIVATE_OverpaintLine") GUIRegisterMsg($WM_WINDOWPOSCHANGED, "_WM_WINDOWPOSCHANGED_OverpaintLine") #EndRegion GUI #Region MENU Global $g_aMenuText[4] $g_aMenuText[0] = "Menu &One" $g_aMenuText[1] = "Menu &Two" $g_aMenuText[2] = "Menu Th&ree" $g_aMenuText[3] = "Menu &Four" Local $idMenu1 = GUICtrlCreateMenu($g_aMenuText[0]) Local $idMenu2 = GUICtrlCreateMenu($g_aMenuText[1]) GUICtrlCreateMenu($g_aMenuText[2]) GUICtrlCreateMenu($g_aMenuText[3]) GUICtrlCreateMenuItem('SubMenu One &A', $idMenu1) GUICtrlCreateMenuItem('SubMenu One &B', $idMenu1) ; Owner-draw Top-Level Menu einrichten _MakeMenuOwnerDraw($g_hGUI) #EndRegion MENU #Region CONTEXT MENU Local $idContextMenu = GUICtrlCreateContextMenu() GUICtrlCreateMenuItem("Context Menu", $idContextMenu) GUICtrlCreateMenuItem("", $idContextMenu) GUICtrlCreateMenuItem("&Properties", $idContextMenu) #EndRegion CONTEXT MENU #Region PIC Local $idPic = GUICtrlCreatePic("", 0, 0, 169, 68) GUICtrlSetImage($idPic, "C:\Program Files (x86)\AutoIt3\Examples\GUI\logo4.gif") GUICtrlSetTip(-1, '#Region PIC') $g_idLabelPic = GUICtrlCreateLabel("Sample Pic", 75, 1, 53, 15) $g_hLabelPic = GUICtrlGetHandle($g_idLabelPic) #EndRegion PIC #Region AVI Local $idAvi = GUICtrlCreateAvi("C:\Program Files (x86)\AutoIt3\Examples\GUI\SampleAVI.avi", 0, 180, 10, 32, 32, $ACS_AUTOPLAY) GUICtrlSetTip(-1, '#Region AVI') GUICtrlCreateLabel("Sample avi", 175, 50) #EndRegion AVI #Region TAB Local $idTab = GUICtrlCreateTab(240, 0, 150, 70), $g_hTab = GUICtrlGetHandle($idTab) _AddControlForSubclass($idTab) GUICtrlCreateTabItem("One") GUICtrlSetTip(-1, '#Region TAB1') GUICtrlCreateLabel("Sample Tab", 250, 40) GUICtrlCreateTabItem("Two") GUICtrlSetTip(-1, '#Region TAB2') GUICtrlCreateTabItem("Three") GUICtrlSetTip(-1, '#Region TAB3') GUICtrlCreateTabItem("") $g_hTab = GUICtrlGetHandle($idTab) #EndRegion TAB #Region COMBO Local $idCombo = GUICtrlCreateCombo("Sample Combo", 250, 80, 120, 100) GUICtrlSetData($idCombo, "Item 2|Item 3", "Sample Combo") _AddControlForSubclass($idCombo) GUICtrlSetTip(-1, '#Region COMBO') #EndRegion COMBO #Region PROGRESS Local $idProgress = GUICtrlCreateProgress(60, 80, 150, 20) _AddControlForSubclass($idProgress) GUICtrlSetTip(-1, '#Region PROGRESS') GUICtrlSetData(-1, 60) GUICtrlCreateLabel("Progress:", 5, 82) #EndRegion PROGRESS #Region EDIT Local $idEdit = GUICtrlCreateEdit(@CRLF & " Sample Edit Control", 10, 110, 150, 70) _AddControlForSubclass($idEdit) GUICtrlSetTip(-1, '#Region EDIT') #EndRegion EDIT #Region LIST Local $idList = GUICtrlCreateList("", 5, 190, 100, 90) _AddControlForSubclass($idList) GUICtrlSetTip(-1, '#Region LIST') GUICtrlSetData(-1, "A.Sample|B.List|C.Control|D.Here", "B.List") #EndRegion LIST #Region ICON GUICtrlCreateIcon("explorer.exe", 0, 175, 120) GUICtrlSetTip(-1, '#Region ICON') GUICtrlCreateLabel("Icon", 180, 160, 50, 20) #EndRegion ICON #Region LIST VIEW Local $idListView = GUICtrlCreateListView("Sample|ListView|", 110, 190, 110, 80, $LVS_REPORT) _AddControlForSubclass($idListView) GUICtrlSetBkColor($idListView, $COLOR_EDIT_BG) GUICtrlSetColor($idListView, $COLOR_TEXT_LIGHT) GUICtrlSetTip(-1, '#Region LIST VIEW') GUICtrlCreateListViewItem("A|One", $idListView) GUICtrlCreateListViewItem("B|Two", $idListView) GUICtrlCreateListViewItem("C|Three", $idListView) $g_ListView = GUICtrlGetHandle($idListView) #EndRegion LIST VIEW #Region GROUP WITH RADIO BUTTONS Local $idGroup = GUICtrlCreateGroup("Sample Group", 230, 120) GUICtrlSetColor($idGroup, $COLOR_TEXT_LIGHT) Local $idRadio1 = GUICtrlCreateRadio("Radio One", 250, 140, 80) GUICtrlSetTip($idRadio1, '#Region RADIO1') GUICtrlSetState($idRadio1, $GUI_CHECKED) Local $idRadio2 = GUICtrlCreateRadio("Radio Two", 250, 165, 80) GUICtrlSetTip($idRadio2, '#Region RADIO2') GUICtrlCreateGroup("", -99, -99, 1, 1) DllCall("UxTheme.dll", "int", "SetWindowTheme", "hwnd", GUICtrlGetHandle($idGroup), "wstr", 0, "wstr", 0) DllCall("UxTheme.dll", "int", "SetWindowTheme", "hwnd", GUICtrlGetHandle($idRadio1), "wstr", 0, "wstr", 0) DllCall("UxTheme.dll", "int", "SetWindowTheme", "hwnd", GUICtrlGetHandle($idRadio2), "wstr", 0, "wstr", 0) #EndRegion GROUP WITH RADIO BUTTONS #Region UPDOWN GUICtrlCreateLabel("UpDown", 350, 115) GUICtrlSetColor(-1, $COLOR_TEXT_LIGHT) Local $idInput = GUICtrlCreateInput("42", 350, 130, 40, 20) _AddControlForSubclass($idInput) Local $idUpDown = GUICtrlCreateUpdown(-1) _AddControlForSubclass($idUpDown) #EndRegion UPDOWN #Region LABEL $g_idLabelGreen = GUICtrlCreateLabel("Green" & @CRLF & "Label", 350, 165, 40, 40) $g_hLabelGreen = GUICtrlGetHandle($g_idLabelGreen) GUICtrlSetTip($g_idLabelGreen, '#Region LABEL') $g_hBrushGreen = _WinAPI_CreateSolidBrush(_ColorToCOLORREF(0x00FF00)) ; green background #Region SLIDER GUICtrlCreateLabel("Slider:", 235, 215) Local $idSlider = GUICtrlCreateSlider(270, 210, 120, 30) _AddControlForSubclass($idSlider) GUICtrlSetTip(-1, '#Region SLIDER') GUICtrlSetData(-1, 30) #EndRegion SLIDER #Region INPUT Local $idInput2 = GUICtrlCreateInput("Sample Input Box", 235, 255, 130, 20) _AddControlForSubclass($idInput2) GUICtrlSetTip(-1, '#Region INPUT') #EndRegion INPUT #Region DATE $g_idDate = GUICtrlCreateDate("", 5, 280, 200, 20) $g_hDate = GUICtrlGetHandle($g_idDate) _AddControlForSubclass($g_idDate) GUICtrlSetTip(-1, '#Region DATE') GUICtrlCreateLabel("(Date control expands into a calendar)", 10, 305, 200, 20) #EndRegion DATE #Region BUTTON Local $idButton = GUICtrlCreateButton("Sample Button", 10, 330, 100, 30) _AddControlForSubclass($idButton) GUICtrlSetTip(-1, '#Region BUTTON') #EndRegion BUTTON #Region CHECKBOX Local $idCheckBox = GUICtrlCreateCheckbox("Checkbox", 130, 335, 80, 20) GUICtrlSetTip(-1, '#Region CHECKBOX') DllCall("UxTheme.dll", "int", "SetWindowTheme", "hwnd", GUICtrlGetHandle($idCheckBox), "wstr", 0, "wstr", 0) #EndRegion CHECKBOX #Region TREEVIEW ONE Local $idTreeView1 = GUICtrlCreateTreeView(210, 290, 80, 80) _AddControlForSubclass($idTreeView1) GUICtrlSetBkColor($idTreeView1, $COLOR_EDIT_BG) GUICtrlSetColor($idTreeView1, $COLOR_TEXT_LIGHT) GUICtrlSetTip(-1, '#Region TREEVIEW ONE') Local $idTreeViewItem = GUICtrlCreateTreeViewItem("TreeView", $idTreeView1) GUICtrlCreateTreeViewItem("Item1", $idTreeViewItem) GUICtrlCreateTreeViewItem("Item2", $idTreeViewItem) GUICtrlCreateTreeViewItem("Foo", -1) GUICtrlSetState($idTreeViewItem, $GUI_EXPAND) #EndRegion TREEVIEW ONE #Region TREEVIEW TWO Local $idTreeView2 = GUICtrlCreateTreeView(295, 290, 103, 80, $TVS_CHECKBOXES) _AddControlForSubclass($idTreeView2) GUICtrlSetBkColor($idTreeView2, $COLOR_EDIT_BG) GUICtrlSetColor($idTreeView2, $COLOR_TEXT_LIGHT) GUICtrlSetTip(-1, '#Region TREEVIEW TWO') GUICtrlCreateTreeViewItem("TreeView", $idTreeView2) GUICtrlCreateTreeViewItem("With", $idTreeView2) GUICtrlCreateTreeViewItem("$TVS_CHECKBOXES", $idTreeView2) GUICtrlSetState(-1, $GUI_CHECKED) GUICtrlCreateTreeViewItem("Style", $idTreeView2) #EndRegion TREEVIEW TWO ; Apply Dark Mode _ApplyDarkModeToAllControls() ; Handle scrollbars for windows that have them _EnableDarkScrollBars() ; Register a custom window procedure for the tab control for owner-drawing $g_hTab_CB = DllCallbackRegister('_WinProc', 'ptr', 'hwnd;uint;wparam;lparam') $g_pTab_CB = DllCallbackGetPtr($g_hTab_CB) $g_hProc = _WinAPI_SetWindowLong($g_hTab, $GWL_WNDPROC, $g_pTab_CB) GUISetState(@SW_SHOW) _OverpaintWhiteLine() _WinAPI_RedrawWindow($g_hGUI, 0, 0, BitOR($RDW_INVALIDATE, $RDW_UPDATENOW)) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE _CleanupSubclassing() _CleanupBrushes() ExitLoop EndSwitch WEnd ; Restore the original window procedure for the tab control _WinAPI_SetWindowLong($g_hTab, $GWL_WNDPROC, $g_hProc) DllCallbackFree($g_hTab_CB) GUIDelete() EndFunc ;==>_Example Func _OverpaintWhiteLine() Local $hDC = _WinAPI_GetWindowDC($g_hGUI) If Not $hDC Then Return Local $tWndRect = _WinAPI_GetWindowRect($g_hGUI) Local $iWndWidth = $tWndRect.right - $tWndRect.left ; 1. Caption height Local $iCaptionHeight = _WinAPI_GetSystemMetrics($SM_CYCAPTION) ; 2. Border height (top) Local $iBorderHeight = _WinAPI_GetSystemMetrics($SM_CYSIZEFRAME) If $iBorderHeight = 0 Then $iBorderHeight = _WinAPI_GetSystemMetrics($SM_CYFIXEDFRAME) ; 3. Determine menu height dynamically Local $iMenuHeight = _WinAPI_GetSystemMetrics($SM_CYMENU) ; standard menu height ; Alternative: get menu height via GetMenuBarInfo Local $tMenuBarInfo = DllStructCreate("dword cbSize;long left;long top;long right;long bottom;handle hwndMenu;handle hwndItem;bool fBarFocused;bool fFocused") DllStructSetData($tMenuBarInfo, "cbSize", DllStructGetSize($tMenuBarInfo)) Local $aResult = DllCall("user32.dll", "bool", "GetMenuBarInfo", "hwnd", $g_hGUI, "long", 0xFFFFFFFD, "long", 0, "ptr", DllStructGetPtr($tMenuBarInfo)) If IsArray($aResult) And $aResult[0] Then ; Calculate the actual menu height from the coordinates Local $iMenuTop = $tMenuBarInfo.top Local $iMenuBottom = $tMenuBarInfo.bottom ; Convert to window coordinates $iMenuHeight = ($iMenuBottom - $iMenuTop) EndIf ; The white line is directly below the menu Local $iWhiteLineY = $iCaptionHeight + $iBorderHeight + $iMenuHeight - _WinAPI_GetSystemMetrics($SM_CYFIXEDFRAME) * 2 ;~ ConsoleWrite("Caption: " & $iCaptionHeight & ", Border: " & $iBorderHeight & ", Menu: " & $iMenuHeight & " -> White Line at Y=" & $iWhiteLineY & @CRLF) ; Overpaint the white line (1x2 pixels) Local $tRect = DllStructCreate($tagRECT) With $tRect .left = 0 .top = $iWhiteLineY .right = $iWndWidth .bottom = $iWhiteLineY + 2 ; 2 pixels high EndWith Local $hBrush = _WinAPI_CreateSolidBrush(_ColorToCOLORREF($COLOR_BG_DARK)) ;~ Local $hBrush = _WinAPI_CreateSolidBrush(_ColorToCOLORREF(0xFF0000)) _WinAPI_FillRect($hDC, $tRect, $hBrush) _WinAPI_DeleteObject($hBrush) _WinAPI_ReleaseDC($g_hGUI, $hDC) EndFunc ;==>_OverpaintWhiteLine Func _WM_ACTIVATE_OverpaintLine($hWnd, $iMsg, $wParam, $lParam) If $hWnd <> $g_hGUI Then Return $GUI_RUNDEFMSG _OverpaintWhiteLine() Return $GUI_RUNDEFMSG EndFunc ;==>_WM_ACTIVATE_OverpaintLine Func _WM_WINDOWPOSCHANGED_OverpaintLine($hWnd, $iMsg, $wParam, $lParam) If $hWnd <> $g_hGUI Then Return $GUI_RUNDEFMSG _OverpaintWhiteLine() Return $GUI_RUNDEFMSG EndFunc ;==>_WM_WINDOWPOSCHANGED_OverpaintLine Func _OnInitMenuPopup($hWnd, $iMsg, $wParam, $lParam) ; wParam = HMENU of the popup, lParam = position/index - not needed here ; A small delay sometimes helps to ensure the popup window exists Sleep(100) ; The foreground window is most likely the new menu popup Local $hPopup = _WinAPI_GetForegroundWindow() If Not $hPopup Then Return $GUI_RUNDEFMSG Local $sCls = StringLower(_WinAPI_GetClassName($hPopup)) If $sCls <> "#32768" And $sCls <> "popupmenu" Then ; if no menu popup is detected -> do nothing Return $GUI_RUNDEFMSG EndIf ; Set Theme + AllowDarkMode on the popup itself _WinAPI_SetWindowTheme($hPopup, "DarkMode_Explorer", "") _WinAPI_AllowDarkModeForWindow($hPopup, True) ; Also apply the theme to all child windows of the popup (e.g., scrollbars) Local $hChild = _WinAPI_GetWindow($hPopup, $GW_CHILD) While $hChild Local $sChildCls = StringLower(_WinAPI_GetClassName($hChild)) ; apply theme specifically for scrollbars, UpDown, etc. If $sChildCls = "scrollbar" Or $sChildCls = "msctls_updown32" Or $sChildCls = "traynotifywnd" Then _WinAPI_SetWindowTheme($hChild, "DarkMode_Explorer", "") _WinAPI_AllowDarkModeForWindow($hChild, True) Else ; try generically _WinAPI_SetWindowTheme($hChild, "DarkMode_Explorer", "") _WinAPI_AllowDarkModeForWindow($hChild, True) EndIf $hChild = _WinAPI_GetWindow($hChild, $GW_HWNDNEXT) WEnd ; Force refresh so the change is visible immediately _WinAPI_FlushMenuThemes() _WinAPI_RefreshImmersiveColorPolicyState() _WinAPI_RedrawWindow($hPopup, 0, 0, BitOR($RDW_INVALIDATE, $RDW_UPDATENOW)) Return $GUI_RUNDEFMSG EndFunc ;==>_OnInitMenuPopup Func _ColorToCOLORREF($iColor) ;RGB to BGR Local $iR = BitAND(BitShift($iColor, 16), 0xFF) Local $iG = BitAND(BitShift($iColor, 8), 0xFF) Local $iB = BitAND($iColor, 0xFF) Return BitOR(BitShift($iB, -16), BitShift($iG, -8), $iR) EndFunc ;==>_ColorToCOLORREF Func _AddControlForSubclass($iCtrlID) Local $hCtrl = GUICtrlGetHandle($iCtrlID) If $hCtrl Then $g_aControls[$g_iControlCount][0] = $iCtrlID $g_aControls[$g_iControlCount][1] = $hCtrl $g_aControls[$g_iControlCount][2] = 0 ; Placeholder for OldWndProc $g_iControlCount += 1 EndIf EndFunc ;==>_AddControlForSubclass Func _ApplyDarkModeToAllControls() ; DWM Dark Mode for the main window _WinAPI_SetPreferredAppMode($APPMODE_FORCEDARK) ; Create subclass callback If Not $g_pSubclassProc Then $g_pSubclassProc = DllCallbackRegister("_SubclassProc", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr") EndIf ; Subclass all controls For $i = 0 To $g_iControlCount - 1 Local $hCtrl = $g_aControls[$i][1] If $hCtrl Then Local $sClass = _WinAPI_GetClassName($hCtrl) ; Use SetWindowSubclass _WinAPI_SetWindowSubclass($hCtrl, DllCallbackGetPtr($g_pSubclassProc), $i, 0) ; Special themes for different control types Switch StringLower($sClass) Case "edit", "richedit", "richedit20a", "richedit20w" _WinAPI_SetWindowTheme($hCtrl, "DarkMode_CFD", 0) Case "button" _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", 0) Case "combobox" _WinAPI_SetWindowTheme($hCtrl, "DarkMode_CFD", 0) ; Handle ComboBox child-edit Local $hEdit = _WinAPI_FindWindowEx($hCtrl, 0, "Edit", "") If $hEdit Then _WinAPI_SetWindowTheme($hEdit, "DarkMode_CFD", 0) _WinAPI_AllowDarkModeForWindow($hEdit, True) EndIf ; ComboBox dropdown list Local $hComboLBox = _WinAPI_FindWindowEx($hCtrl, 0, "ComboLBox", "") If $hComboLBox Then _WinAPI_SetWindowTheme($hComboLBox, "DarkMode_Explorer", 0) _WinAPI_AllowDarkModeForWindow($hComboLBox, True) EndIf Case "syslistview32" _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", 0) ; ListView extended styles for better dark mode _SendMessage($hCtrl, $LVS_EX_DOUBLEBUFFER, 0x00010000, 0x00010000) ; Also make the ListView header dark Local $hHeader = _SendMessage($hCtrl, $LVM_GETHEADER, 0, 0) If $hHeader Then _WinAPI_SetWindowTheme($hHeader, "DarkMode_ItemsView", 0) EndIf Case "systreeview32" _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", 0) Case "msctls_trackbar32" ; Slider _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", 0) Case "systabcontrol32" _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", "") ;must be "" ; tab-Control background _SendMessage($hCtrl, 0x132D, 0, $COLOR_BG_DARK) ; TCM_SETBKCOLOR ; Try to make the UpDown (spinner for too many tabs) dark as well Local $hUpDown = _WinAPI_FindWindowEx($hCtrl, 0, "msctls_updown32", "") If $hUpDown Then _WinAPI_SetWindowTheme($hUpDown, "DarkMode_Explorer", 0) Case "listbox" _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", 0) Case "msctls_progress32" _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", 0) Case "scrollbar" _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", 0) Case Else _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", 0) EndSwitch _WinAPI_AllowDarkModeForWindow($hCtrl, True) EndIf Next ; Update theme system _WinAPI_RefreshImmersiveColorPolicyState() _WinAPI_FlushMenuThemes() _WinAPI_DwmSetWindowAttribute($g_hGUI, $DWMWA_USE_IMMERSIVE_DARK_MODE, True) ; Redraw GUI _WinAPI_RedrawWindow($g_hGUI, 0, 0, $RDW_UPDATENOW) EndFunc ;==>_ApplyDarkModeToAllControls Func _CleanupSubclassing() ; Remove all subclasses If $g_pSubclassProc Then For $i = 0 To $g_iControlCount - 1 Local $hCtrl = $g_aControls[$i][1] If $hCtrl Then _WinAPI_RemoveWindowSubclass($hCtrl, DllCallbackGetPtr($g_pSubclassProc), $i) EndIf Next DllCallbackFree($g_pSubclassProc) $g_pSubclassProc = 0 EndIf EndFunc ;==>_CleanupSubclassing Func _SubclassProc($hWnd, $iMsg, $wParam, $lParam, $iID, $pData) Switch $iMsg Case $WM_NOTIFY Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam) Local $hFrom = $tNMHDR.hWndFrom Local $iCode = $tNMHDR.Code ; --- Adjust ListView Header text color --- If $iCode = $NM_CUSTOMDRAW Then Local $tNMCUSTOMDRAW = DllStructCreate($tagNMCUSTOMDRAW, $lParam) Local $dwDrawStage = $tNMCUSTOMDRAW.dwDrawStage Local $hDC = $tNMCUSTOMDRAW.hdc Switch $dwDrawStage Case $CDDS_PREPAINT Return $CDRF_NOTIFYITEMDRAW Case $CDDS_ITEMPREPAINT _WinAPI_SetTextColor($hDC, _ColorToCOLORREF($COLOR_TEXT_LIGHT)) ; White text _WinAPI_SetBkColor($hDC, _ColorToCOLORREF($COLOR_BG_DARK)) ; Dark background Return BitOR($CDRF_NEWFONT, $CDRF_NOTIFYPOSTPAINT) EndSwitch EndIf Case $WM_PAINT ; Custom Paint for better Dark Mode rendering Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndSwitch ; Forward standard message to DefSubclassProc Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndFunc ;==>_SubclassProc Func _MakeMenuOwnerDraw($hWnd) ; Get menu handle $g_hMenu = _GUICtrlMenu_GetMenu($hWnd) If Not $g_hMenu Then Return False Local $iCount = _GUICtrlMenu_GetItemCount($g_hMenu) If $iCount <= 0 Then Return False ReDim $g_aMenuText[$iCount] For $i = 0 To $iCount - 1 ; retrieve text via GetMenuStringW (works better than _GUICtrlMenu_GetItemText) Local $tText = DllStructCreate("wchar s[256]") Local $iLen = DllCall("user32.dll", "int", "GetMenuStringW", _ "handle", $g_hMenu, _ "uint", $i, _ "struct*", $tText, _ "int", 255, _ "uint", 0x0400) ; MF_BYPOSITION If IsArray($iLen) And $iLen[0] > 0 Then $g_aMenuText[$i] = $tText.s Else $g_aMenuText[$i] = "" EndIf ; set top-level item to owner-draw _GUICtrlMenu_SetItemType($g_hMenu, $i, $MFT_OWNERDRAW, True) Next ; redraw menu bar immediately _GUICtrlMenu_DrawMenuBar($hWnd) _WinAPI_RedrawWindow($hWnd, 0, 0, BitOR($RDW_INVALIDATE, $RDW_UPDATENOW)) Return True EndFunc ;==>_MakeMenuOwnerDraw Func WM_MEASUREITEM_Handler($hWnd, $iMsg, $wParam, $lParam) Local $tagMEASUREITEM = "uint CtlType;uint CtlID;uint itemID;uint itemWidth;uint itemHeight;ulong_ptr itemData" Local $t = DllStructCreate($tagMEASUREITEM, $lParam) If Not IsDllStruct($t) Then Return $GUI_RUNDEFMSG If $t.CtlType <> $ODT_MENU Then Return $GUI_RUNDEFMSG Local $itemID = $t.itemID ; itemID is the control ID, not the position! ; We must derive the position from the itemID Local $iPos = -1 For $i = 0 To UBound($g_aMenuText) - 1 If $itemID = ($i + 3) Then ; Offset of 3 due to internal IDs $iPos = $i ExitLoop EndIf Next ; Fallback: try the itemID directly If $iPos < 0 Then $iPos = $itemID If $iPos < 0 Or $iPos >= UBound($g_aMenuText) Then $iPos = 0 Local $sText = $g_aMenuText[$iPos] ; Calculate text dimensions Local $hDC = _WinAPI_GetDC($hWnd) Local $hFont = _SendMessage($hWnd, $WM_GETFONT, 0, 0) If Not $hFont Then $hFont = _WinAPI_GetStockObject($DEFAULT_GUI_FONT) Local $hOldFont = _WinAPI_SelectObject($hDC, $hFont) Local $tSize = _WinAPI_GetTextExtentPoint32($hDC, $sText) Local $iTextWidth = $tSize.X Local $iTextHeight = $tSize.Y _WinAPI_SelectObject($hDC, $hOldFont) _WinAPI_ReleaseDC($hWnd, $hDC) ; Set dimensions with padding $t.itemWidth = $iTextWidth + 1 $t.itemHeight = $iTextHeight + 1 Return 1 EndFunc ;==>WM_MEASUREITEM_Handler Func WM_DRAWITEM_Handler($hWnd, $iMsg, $wParam, $lParam) Local $tagDRAWITEM = "uint CtlType;uint CtlID;uint itemID;uint itemAction;uint itemState;ptr hwndItem;handle hDC;" & _ "long left;long top;long right;long bottom;ulong_ptr itemData" Local $t = DllStructCreate($tagDRAWITEM, $lParam) If Not IsDllStruct($t) Then Return $GUI_RUNDEFMSG If $t.CtlType <> $ODT_MENU Then Return $GUI_RUNDEFMSG Local $hDC = $t.hDC Local $left = $t.left Local $top = $t.top Local $right = $t.right Local $bottom = $t.bottom Local $state = $t.itemState Local $itemID = $t.itemID ; convert itemID to position Local $iPos = -1 For $i = 0 To UBound($g_aMenuText) - 1 If $itemID = ($i + 3) Then $iPos = $i ExitLoop EndIf Next If $iPos < 0 Then $iPos = $itemID If $iPos < 0 Or $iPos >= UBound($g_aMenuText) Then $iPos = 0 Local $sText = $g_aMenuText[$iPos] $sText = StringReplace($sText, "&", "") ; Colors Local $clrBG = _ColorToCOLORREF($COLOR_BG_DARK) Local $clrSel = _ColorToCOLORREF(0x505050) Local $clrText = _ColorToCOLORREF($COLOR_TEXT_LIGHT) Static $iDrawCount = 0 Static $bFullBarDrawn = False ; Count how many items were drawn in this "draw cycle" $iDrawCount += 1 ; If we are at the first item AND the bar has not yet been drawn If $iPos = 0 And Not $bFullBarDrawn Then ; Get the full window width Local $tClient = _WinAPI_GetClientRect($hWnd) Local $iFullWidth = DllStructGetData($tClient, "right") ; Fill the entire menu bar Local $tFullMenuBar = DllStructCreate($tagRECT) With $tFullMenuBar .left = 0 .top = $top .right = $iFullWidth + 3 .bottom = $bottom EndWith Local $hFullBrush = _WinAPI_CreateSolidBrush($clrBG) _WinAPI_FillRect($hDC, $tFullMenuBar, $hFullBrush) _WinAPI_DeleteObject($hFullBrush) EndIf ; After drawing all items, mark as "drawn" If $iDrawCount >= UBound($g_aMenuText) Then $bFullBarDrawn = True $iDrawCount = 0 EndIf ; Draw background for the area AFTER the last menu item If $iPos = (UBound($g_aMenuText) - 1) Then ; Last menu Local $tClient = _WinAPI_GetClientRect($hWnd) Local $iFullWidth = DllStructGetData($tClient, "right") ; Fill only the area to the RIGHT of the last menu item If $right < $iFullWidth Then Local $tEmptyArea = DllStructCreate($tagRECT) With $tEmptyArea .left = $right .top = $top .right = $iFullWidth + _WinAPI_GetSystemMetrics(7) .bottom = $bottom EndWith Local $hEmptyBrush = _WinAPI_CreateSolidBrush($clrBG) _WinAPI_FillRect($hDC, $tEmptyArea, $hEmptyBrush) _WinAPI_DeleteObject($hEmptyBrush) EndIf EndIf ; Draw item background (selected = lighter) Local $bSelected = BitAND($state, $ODS_SELECTED) Local $hBrush = _WinAPI_CreateSolidBrush($bSelected ? $clrSel : $clrBG) Local $tItemRect = DllStructCreate($tagRECT) With $tItemRect .left = $left .top = $top .right = $right .bottom = $bottom EndWith _WinAPI_FillRect($hDC, $tItemRect, $hBrush) _WinAPI_DeleteObject($hBrush) ; Setup font Local $hFont = _SendMessage($hWnd, $WM_GETFONT, 0, 0) If Not $hFont Then $hFont = _WinAPI_GetStockObject($DEFAULT_GUI_FONT) Local $hOldFont = _WinAPI_SelectObject($hDC, $hFont) _WinAPI_SetBkMode($hDC, $TRANSPARENT) _WinAPI_SetTextColor($hDC, $clrText) ; Draw text Local $tTextRect = DllStructCreate($tagRECT) With $tTextRect .left = $left + 10 .top = $top + 4 .right = $right - 10 .bottom = $bottom - 4 EndWith DllCall("user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $sText, "int", -1, "ptr", DllStructGetPtr($tTextRect), "uint", BitOR($DT_SINGLELINE, $DT_VCENTER, $DT_LEFT)) If $hOldFont Then _WinAPI_SelectObject($hDC, $hOldFont) Return 1 EndFunc ;==>WM_DRAWITEM_Handler Func _WM_CTLCOLOR($hWnd, $iMsg, $wParam, $lParam) Local $hDC = $wParam Local $hCtrl = $lParam ; If the control is the special green label -> return green background If $hCtrl = $g_hLabelGreen Then ; black text on a green background _WinAPI_SetTextColor($hDC, _ColorToCOLORREF(0x000000)) _WinAPI_SetBkColor($hDC, _ColorToCOLORREF(0x00FF00)) _WinAPI_SetBkMode($hDC, $OPAQUE) ; important, otherwise it remains transparent and you cannot see the background If $g_hBrushGreen Then Return $g_hBrushGreen EndIf ; --- Special case: Make "Sample Pic" label transparent --- If $hCtrl = $g_hLabelPic Then ; set transparent background _WinAPI_SetBkMode($hDC, $TRANSPARENT) ; set text color (if necessary) - e.g., white _WinAPI_SetTextColor($hDC, _ColorToCOLORREF($COLOR_TEXT_LIGHT)) ; return NULL_BRUSH (stock object), so Windows does NOT fill with your dark brush Local $hNull = _WinAPI_GetStockObject(5) ; 5 = NULL_BRUSH If $hNull Then Return $hNull ; Fallback if not available: Return $GUI_RUNDEFMSG EndIf ; --- Default behavior for all other statics / controls --- _WinAPI_SetTextColor($hDC, _ColorToCOLORREF($COLOR_TEXT_LIGHT)) Local $hBrush = $g_hBrushEdit Local $iColor = $COLOR_EDIT_BG Switch $iMsg Case $WM_CTLCOLORBTN $hBrush = $g_hBrushButton $iColor = $COLOR_BUTTON_BG Case $WM_CTLCOLORSTATIC $hBrush = $g_hBrushBg $iColor = $COLOR_BG_DARK EndSwitch _WinAPI_SetBkColor($hDC, _ColorToCOLORREF($iColor)) _WinAPI_SetBkMode($hDC, $TRANSPARENT) Return $hBrush EndFunc ;==>_WM_CTLCOLOR Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg, $wParam Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $tInfo, $tBuffer, $tBuffer2, $iCtrl $tNMHDR = DllStructCreate($tagNMHDR, $lParam) $hWndFrom = HWnd($tNMHDR.hWndFrom) $iIDFrom = $tNMHDR.IDFrom $iCode = $tNMHDR.Code Switch $hWndFrom Case $g_hDate ;thanks to argumentum for the code :-) Switch $iCode Case $NM_SETFOCUS ; Disable the visual theme when the DateTime control receives focus _WinAPI_SetThemeAppProperties(0) Case $DTN_DROPDOWN ; Apply dark colors when the calendar dropdown appears _WinAPI_SetWindowTheme($iCtrl, "", "") Local $iCtrl = _GUICtrlDTP_GetMonthCal($hWndFrom) _GUICtrlMonthCal_SetColor($iCtrl, $MCSC_TEXT, $COLOR_TEXT_LIGHT) _GUICtrlMonthCal_SetColor($iCtrl, $MCSC_TITLEBK, $COLOR_BG_DARK) _GUICtrlMonthCal_SetColor($iCtrl, $MCSC_TITLETEXT, $COLOR_TEXT_LIGHT) _GUICtrlMonthCal_SetColor($iCtrl, $MCSC_MONTHBK, $COLOR_BG_DARK) _GUICtrlMonthCal_SetColor($iCtrl, $MCSC_TRAILINGTEXT, $COLOR_TEXT_LIGHT) Case $DTN_CLOSEUP ; Calendar will closed EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY Func _CleanupBrushes() ; Delete all brushes If $g_hBrushEdit Then _WinAPI_DeleteObject($g_hBrushEdit) If $g_hBrushButton Then _WinAPI_DeleteObject($g_hBrushButton) If $g_hBrushBg Then _WinAPI_DeleteObject($g_hBrushBg) If $g_hBrushGreen Then _WinAPI_DeleteObject($g_hBrushGreen) EndFunc ;==>_CleanupBrushes Func _EnableDarkScrollBars() ; Try to enable Dark Mode for all scrollbars (also for TreeView with checkboxes) For $i = 0 To $g_iControlCount - 1 Local $hCtrl = $g_aControls[$i][1] If Not $hCtrl Then ContinueLoop ; 1️ Normal attempt (works for most controls) Local $tScrollInfo = _GUIScrollBars_GetScrollInfoEx($hCtrl, 1) If IsDllStruct($tScrollInfo) Then _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", 0) EndIf ; 2️ Extension: If the control has its own scrollbar child windows (e.g., TreeView with $TVS_CHECKBOXES) Local $hChild = _WinAPI_GetWindow($hCtrl, $GW_CHILD) While $hChild Local $sClass = _WinAPI_GetClassName($hChild) If StringCompare($sClass, "ScrollBar") = 0 Then ; Set DarkMode on the ScrollBar itself _WinAPI_SetWindowTheme($hChild, "DarkMode_Explorer", 0) _WinAPI_AllowDarkModeForWindow($hChild, True) EndIf $hChild = _WinAPI_GetWindow($hChild, $GW_HWNDNEXT) WEnd Next EndFunc ;==>_EnableDarkScrollBars Func _WinProc($hWnd, $iMsg, $wParam, $lParam) ; Custom window procedure for tab control with Dark Mode Switch $iMsg Case $WM_ERASEBKGND Return 1 ; Prevent background erase to avoid flicker Case $WM_PAINT Local $tPaint = DllStructCreate($tagPAINTSTRUCT) Local $hDC = DllCall("user32.dll", "handle", "BeginPaint", "hwnd", $hWnd, "struct*", $tPaint) If @error Or Not $hDC[0] Then Return _WinAPI_CallWindowProc($g_hProc, $hWnd, $iMsg, $wParam, $lParam) $hDC = $hDC[0] ; Get client rectangle Local $tClient = _WinAPI_GetClientRect($hWnd) If Not IsDllStruct($tClient) Then _WinAPI_EndPaint($hWnd, $tPaint) Return 0 EndIf Local $iWidth = $tClient.Right Local $iHeight = $tClient.Bottom ; Create memory DC for double buffering Local $hMemDC = _WinAPI_CreateCompatibleDC($hDC) Local $hBitmap = _WinAPI_CreateCompatibleBitmap($hDC, $iWidth, $iHeight) Local $hOldBmp = _WinAPI_SelectObject($hMemDC, $hBitmap) ; Fill background Local $hBrush = _WinAPI_CreateSolidBrush(_ColorToCOLORREF($COLOR_BG_DARK)) _WinAPI_FillRect($hMemDC, $tClient, $hBrush) _WinAPI_DeleteObject($hBrush) ; Get tab info Local $iTabCount = _SendMessage($hWnd, 0x1304, 0, 0) ; TCM_GETITEMCOUNT Local $iCurSel = _SendMessage($hWnd, 0x130B, 0, 0) ; TCM_GETCURSEL ; Setup font Local $hFont = _SendMessage($hWnd, $WM_GETFONT, 0, 0) If Not $hFont Then $hFont = _WinAPI_GetStockObject($DEFAULT_GUI_FONT) Local $hOldFont = _WinAPI_SelectObject($hMemDC, $hFont) _WinAPI_SetBkMode($hMemDC, $TRANSPARENT) _WinAPI_SetTextColor($hMemDC, _ColorToCOLORREF($COLOR_TEXT_LIGHT)) ; Draw each tab Local $tRect, $tRect, $iLeft, $iTop, $iRight, $iBottom For $i = 0 To $iTabCount - 1 ; Get tab rectangle using TCM_GETITEMRECT $tRect = DllStructCreate($tagRECT) $aResult = DllCall("user32.dll", "lresult", "SendMessageW", _ "hwnd", $hWnd, _ "uint", 0x130A, _ ; TCM_GETITEMRECT "wparam", $i, _ "struct*", $tRect) If @error Or Not $aResult[0] Then ContinueLoop $iLeft = $tRect.Left $iTop = $tRect.Top $iRight = $tRect.Right $iBottom = $tRect.Bottom ; Skip if rectangle is invalid If $iLeft >= $iRight Or $iTop >= $iBottom Then ContinueLoop ; Get tab text Local $tItem = DllStructCreate("uint Mask;dword dwState;dword dwStateMask;ptr pszText;int cchTextMax;int iImage;lparam lParam") Local $tText = DllStructCreate("wchar Text[256]") With $tItem .Mask = 0x0001 ; TCIF_TEXT .pszText = DllStructGetPtr($tText) .cchTextMax = 256 EndWith DllCall("user32.dll", "lresult", "SendMessageW", _ "hwnd", $hWnd, _ "uint", 0x133C, _ ; TCM_GETITEMW "wparam", $i, _ "struct*", $tItem) Local $sText = DllStructGetData($tText, "Text") ; Draw tab background Local $bSelected = ($i = $iCurSel) Local $iTabColor = $bSelected ? $COLOR_BUTTON_BG : $COLOR_BG_DARK Local $hTabBrush = _WinAPI_CreateSolidBrush(_ColorToCOLORREF($iTabColor)) Local $tTabRect = DllStructCreate($tagRECT) With $tTabRect .Left = $iLeft .Top = $iTop .Right = $iRight .Bottom = $iBottom EndWith _WinAPI_FillRect($hMemDC, $tTabRect, $hTabBrush) _WinAPI_DeleteObject($hTabBrush) ;~ Local $hTabPen = _WinAPI_CreatePen(0, 1, _ColorToCOLORREF($COLOR_BORDER)) ;~ Local $hOldTabPen = _WinAPI_SelectObject($hMemDC, $hTabPen) ;~ _WinAPI_MoveTo($hMemDC, $iLeft, $iBottom) ;~ _WinAPI_LineTo($hMemDC, $iRight, $iBottom) ;~ _WinAPI_SelectObject($hMemDC, $hOldTabPen) ;~ _WinAPI_DeleteObject($hTabPen) ; Draw selection indicator (top border for selected tab) If $bSelected Then Local $hPen = _WinAPI_CreatePen(0, 2, _ColorToCOLORREF(0x0078D4)) ; Blue accent Local $hOldPen = _WinAPI_SelectObject($hMemDC, $hPen) _WinAPI_MoveTo($hMemDC, $iLeft, $iTop) _WinAPI_LineTo($hMemDC, $iRight - 2, $iTop) _WinAPI_SelectObject($hMemDC, $hOldPen) _WinAPI_DeleteObject($hPen) EndIf ; Draw separator between tabs If $i < $iTabCount - 1 Then Local $hPenSep = _WinAPI_CreatePen(0, 1, _ColorToCOLORREF($COLOR_BORDER)) Local $hOldPenSep = _WinAPI_SelectObject($hMemDC, $hPenSep) _WinAPI_MoveTo($hMemDC, $iRight - 1, $iTop + 4) _WinAPI_LineTo($hMemDC, $iRight - 1, $iBottom - 4) _WinAPI_SelectObject($hMemDC, $hOldPenSep) _WinAPI_DeleteObject($hPenSep) EndIf ; Draw text centered in tab Local $tTextRect = DllStructCreate($tagRECT) With $tTextRect .Left = $iLeft + 6 .Top = $iTop + 3 .Right = $iRight - 6 .Bottom = $iBottom - 3 EndWith DllCall("user32.dll", "int", "DrawTextW", _ "handle", $hMemDC, _ "wstr", $sText, _ "int", -1, _ "struct*", $tTextRect, _ "uint", BitOR($DT_CENTER, $DT_VCENTER, $DT_SINGLELINE)) Next ; Draw border around entire control Local $hBorderPen = _WinAPI_CreatePen(0, 1, _ColorToCOLORREF($COLOR_BORDER)) Local $hOldBorderPen = _WinAPI_SelectObject($hMemDC, $hBorderPen) Local $hNullBrush = _WinAPI_GetStockObject(5) ; NULL_BRUSH Local $hOldBorderBrush = _WinAPI_SelectObject($hMemDC, $hNullBrush) DllCall("gdi32.dll", "bool", "Rectangle", _ "handle", $hMemDC, _ "int", 0, _ "int", 0, _ "int", $iWidth, _ "int", $iHeight) _WinAPI_SelectObject($hMemDC, $hOldBorderPen) _WinAPI_SelectObject($hMemDC, $hOldBorderBrush) _WinAPI_DeleteObject($hBorderPen) ; Copy to screen _WinAPI_BitBlt($hDC, 0, 0, $iWidth, $iHeight, $hMemDC, 0, 0, $SRCCOPY) ; Cleanup _WinAPI_SelectObject($hMemDC, $hOldFont) _WinAPI_SelectObject($hMemDC, $hOldBmp) _WinAPI_DeleteObject($hBitmap) _WinAPI_DeleteDC($hMemDC) _WinAPI_EndPaint($hWnd, $tPaint) Return 0 EndSwitch Return _WinAPI_CallWindowProc($g_hProc, $hWnd, $iMsg, $wParam, $lParam) EndFunc ;==>_WinProc Func _WinAPI_FindWindowEx($hParent, $hAfter, $sClass, $sTitle = "") Local $ret = DllCall("user32.dll", "hwnd", "FindWindowExW", "hwnd", $hParent, "hwnd", $hAfter, "wstr", $sClass, "wstr", $sTitle) If @error Or Not IsArray($ret) Then Return 0 Return $ret[0] EndFunc ;==>_WinAPI_FindWindowEx #Region DarkMode API Func _WinAPI_ShouldAppsUseDarkMode() Local $aResult = DllCall("UxTheme.dll", "bool", 132) If @error Then Return SetError(1, 0, False) Return ($aResult[0] <> 0) EndFunc ;==>_WinAPI_ShouldAppsUseDarkMode Func _WinAPI_AllowDarkModeForWindow($hWND, $bAllow = True) Local $aResult = DllCall("UxTheme.dll", "bool", 133, "hwnd", $hWND, "bool", $bAllow) If @error Then Return SetError(1, 0, False) Return ($aResult[0] <> 0) EndFunc ;==>_WinAPI_AllowDarkModeForWindow Func _WinAPI_FlushMenuThemes() Local $aResult = DllCall("UxTheme.dll", "none", 136) If @error Then Return SetError(1, 0, False) Return True EndFunc ;==>_WinAPI_FlushMenuThemes Func _WinAPI_RefreshImmersiveColorPolicyState() Local $aResult = DllCall("UxTheme.dll", "none", 104) If @error Then Return SetError(1, 0, False) Return True EndFunc ;==>_WinAPI_RefreshImmersiveColorPolicyState Func _WinAPI_IsDarkModeAllowedForWindow($hWND) Local $aResult = DllCall("UxTheme.dll", "bool", 137, "hwnd", $hWND) If @error Then Return SetError(1, 0, False) Return ($aResult[0] <> 0) EndFunc ;==>_WinAPI_IsDarkModeAllowedForWindow Func _WinAPI_GetIsImmersiveColorUsingHighContrast($iIMMERSIVE_HC_CACHE_MODE) Local $aResult = DllCall("UxTheme.dll", "bool", 106, "long", $iIMMERSIVE_HC_CACHE_MODE) If @error Then Return SetError(1, 0, False) Return ($aResult[0] <> 0) EndFunc ;==>_WinAPI_GetIsImmersiveColorUsingHighContrast Func _WinAPI_OpenNcThemeData($hWND, $tClassList) Local $aResult = DllCall("UxTheme.dll", "hwnd", 49, "hwnd", $hWND, "struct*", $tClassList) If @error Then Return SetError(1, 0, False) Return $aResult[0] EndFunc ;==>_WinAPI_OpenNcThemeData Func _WinAPI_ShouldSystemUseDarkMode() Local $aResult = DllCall("UxTheme.dll", "bool", 138) If @error Then Return SetError(1, 0, False) Return ($aResult[0] <> 0) EndFunc ;==>_WinAPI_ShouldSystemUseDarkMode Func _WinAPI_IsDarkModeAllowedForApp() Local $aResult = DllCall("UxTheme.dll", "bool", 139) If @error Then Return SetError(1, 0, False) Return ($aResult[0] <> 0) EndFunc ;==>_WinAPI_IsDarkModeAllowedForApp Func _WinAPI_AllowDarkModeForApp($bAllow = True) ;Windows 10 Build 17763 Return _WinAPI_SetPreferredAppMode($bAllow ? 1 : 0) ; 1 = AllowDark, 0 = Default EndFunc ;==>_WinAPI_AllowDarkModeForApp Func _WinAPI_SetPreferredAppMode($iPreferredAppMode) ;Windows 10 Build 18362+ Local $aResult = DllCall("UxTheme.dll", "long", 135, "long", $iPreferredAppMode) If @error Then Return SetError(1, 0, False) Return $aResult[0] EndFunc ;==>_WinAPI_SetPreferredAppMode #EndRegion DarkMode API Does anyone know how to switch the date picker to dark mode?2 points
-
MediaPlayerElement - WinRT Xaml Island
CYCho and one other reacted to WildByDesign for a topic
Thanks for getting to the bottom of this. I updated the functions from your post a couple posts up that you updated. The functions work which is great. But unfortunately the video just shows black and will not play. I'll have to do some more research into how to get this to work. The functions are good, but there must be some other requirements that I have to do.2 points -
Converting Transparency Level 0-255 To Percentage
WildByDesign and one other reacted to TheSaint for a topic
Because that can make a Pres out of U and Me ... whatever a Pres is ... maybe some kind of Trump thing. Not only that, but the truth can be stretched so much it becomes unrecognizable ... that's when Oranges can be like Apples and Bananas like Sausages ... so Gastronomy suffers and we all end up with a belly ache. I don't know about you, but I prefer to not have sausages in my Fruit Salad ... or Bananas and Mash.2 points -
Converting Transparency Level 0-255 To Percentage
donnyh13 and one other reacted to argumentum for a topic
ConsoleWrite( myPercentThing(200) & @CRLF) ConsoleWrite( myPercentThing(100) & @CRLF) ConsoleWrite( myPercentThing(50) & @CRLF) ConsoleWrite( myPercentThing(0) & @CRLF) ConsoleWrite( myPercentThing(-1000) & @CRLF) Func myPercentThing($vDecimal) $vDecimal = ($vDecimal < 0 ? 0 : $vDecimal) $vDecimal = ($vDecimal > 100 ? 100 : $vDecimal) Return Ceiling($vDecimal * 2.55) ; round up EndFunc 0 visibility is totally transparent. Make a minimum of 50 🤔2 points -
[Solved] Complex UDF simplification?
argumentum and one other reacted to water for a topic
Not if you format the function headers in the correct way, then you just need to prepare a few text files and run a script. Please see Simple Library Docs Generator2 points -
Last week I came across enumicons.au3 in the folder C:\Program Files (x86)\AutoIt3\Examples\GUI\Advanced and while testing it, I thought that a small update wouldn't hurt enumicons.au32 points
-
Trick for display your favorite directories in FileSaveDialog and FileOpenDialog with Win 11 The favorite directories are set in registry to : HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\comdlg32\Placesbar Example of Placesbar Reg File Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\comdlg32\Placesbar] "Place1"="C:\\" "Place2"="C:\\Program Files (x86)\\AutoIt3\\Include" "Place4"="D:\\" "Place0"=dword:00000011 "Place3"=dword:00000010 11 is "My Computer" and 10 the Desktop #Region ;************ Includes ************ #Include <WinAPITheme.au3> #EndRegion ;************ Includes ************ $hGui = GUICreate('', 500, 500) GUISetState() ; Default display FileSaveDialog('Save file', @WorkingDir, 'Scripts (*.au3)', $FD_PATHMUSTEXIST, '', $hGui) ; ; Display with PlacesBar _WinAPI_SetThemeAppProperties($STAP_ALLOW_NONCLIENT) FileSaveDialog('Save file', @WorkingDir, 'Scripts (*.au3)', $FD_PATHMUSTEXIST, '', $hGui) FileOpenDialog('Select a file', @WorkingDir & '\', 'Images (*.jpg;*.bmp)', $FD_FILEMUSTEXIST, '', $hGui) ; ; Reset default display _WinAPI_SetThemeAppProperties(-1) FileSaveDialog('Save file', @WorkingDir, 'Scripts (*.au3)', $FD_PATHMUSTEXIST, '', $hGui) GUIDelete($hGui) Exit2 points
-
Move window behind desktop icons (Part 2)
argumentum and one other reacted to ioa747 for a topic
Thank you for your kind words, regarding Date/Time Format, take a look at Free style DateTimeFormat2 points -
[Solved] Complex UDF simplification?
donnyh13 and one other reacted to argumentum for a topic
Some 3 month ago examples were added for what I see. Following the examples should show what each function does. I don't use spreadsheets but if I needed to, I'd have to learn that, ... in a hurry. And automate it even faster ( all this while clueless "inexperienced" ) I don't think that there is a way around "the learning curve". Maybe making wrapper functions ala "Word user defined functions" would help for the _LODoc_* functions 🤔 I believe that if something is overwhelming, it is so for the uninitiated, and not because is poorly thought-out. Ok, let's look at me. I push for forking and wrote some wrappers/ideas yet, many find it overwhelming/too much/too difficult. What can I do 🤷♂️ Nothing. Each will gain understanding as they gain experience with the concept(s) and the solution(s). Yeah. Nothing you can do other than examples for the functions and that you did.2 points -
Sorry I'm newbie In the forum So. .cursorrules it's specific file format Cursor uses as Main/system prompt it should be placed into project root You can define the AI model howto response. This is mine but you can edit it. Role You are an AutoIt Script Engineer (Windows automation, GUI apps, COM, WinAPI, file/window control, reliable tool-building). Action Understand the task and proactively clarify any gaps. Write AutoIt v3-compatible, robust, well-commented code (with UDFs where helpful). Build an event-driven GUI with status indicators and logging. Implement solid error handling (@error/@extended), return codes, and graceful cleanup. When needed: COM automation (Excel/Word), WinAPI calls, image-based detection (PixelSearch/ImageSearch UDF), window/process control. Provide self-tests per major function and basic timing/metrics. Include build/run instructions and config tips. Steps Requirements summary → inputs/outputs, target OS (Win10/11), permissions. Design → modules, UDFs (#include), GUI flow, logging strategy. Implementation → clear #Region/#EndRegion blocks, consistent naming ($g_s, $a, Func PascalCase). Error handling → guards, fallbacks, resource disposal. Tests → function self-tests, synthetic data, edge cases. Performance → tuned sleeps, correct WinWait/Control* usage. Documentation → README (run, params, known limits), changelog. Release → Aut2Exe build options, versioning, code-sign/AV false positive tips. Context Typical use-cases: desktop automation (form fill, buttons), stable GUI bots, Excel report generation, screen-based detection (icons, buttons, coordinates). Environment: Windows 10/11 x64, AutoIt v3 + SciTE; optional external UDFs (e.g., ImageSearch.au3; if unavailable, provide PixelSearch+tolerance alternative). Non-goal: brittle fixed-delay scripts; prefer state-driven and window-control-based logic. Examples GUI launcher: Start/Stop, log panel, tray icon; workflow: find window → control interaction → verify → log. Excel COM: open workbook, read ranges, export CSV, robust error handling and proper Quit(). Image locate & click: load templates from folder → tolerant search → click coordinates → verification step. WinAPI targeting: focusless ControlSend/ControlClick, class-based selection, DPI-aware settings. Format First: short Summary (goal, inputs/outputs). Then: a single .au3 code file, runnable, richly commented; sections: Config, Utils, GUI, Core, Tests, Main. Finally: README (install, run, troubleshooting, known limitations). Code display: canmore.create_doc (single file, copyable). Output language: English; variable/function names in English; logs may be mixed EN/HU if needed. Next step you should add the Autoit documentation for more robust code and less hallucination into settings Any time if you had any mistake and needs correction, just call in chat.2 points
-
So maybe i just haven't been looking hard enough, but i could not find how to make toast notifications in win8+ from AutoIt. I looked at it on and off, and finally made some progress. Github repository: https://github.com/genius257/au3toast Zip download: https://github.com/genius257/au3toast/archive/refs/tags/1.0.0.zip Enjoy!2 points
-
GIF Animation (cached)
WildByDesign and one other reacted to UEZ for a topic
When you parse the GIF anim you will get a handle to the current frame which you can resize and display appropriatly.2 points -
You're supposed to be able to set #AutoIt3Wrapper_AU3Check_Parameters with the flags you want (which would be -w- 4 for turning off the local in global scope warning) but turns out there's a bug with reading them in for the diagnostics that I'm fixing right now. `2 points
-
Displaying a new GUI (listview) in a traitment - (Moved)
ermar and one other reacted to pixelsearch for a topic
@ioa747 hello Maybe ermar asks for this : when he clicks on button "Traitement" in GUI1, then the function Traitement_intermediaire() is called, which calls gui2() and creates the listview. Now he starts to modify the listview, but suddenly he would like to cancel everything. Unfortunately, when he clicks the button "Cancel" in GUI2, the function Traitement_intermediaire() continues with this line in Traitement_intermediaire() MsgBox(0, "Suite", "cela continue") ;suite du script So we should indicate a way so the Cancel button in GUI2 reacts differently, depending on the part of the script which called gui2() 1) If gui2() was called from the function On_Button() => Case $g_idButton2 => gui2() , then no change is required 2) If gui2() was called from the function Traitement_intermediaire() => gui2() , then some code is required in case the user clicks on button Cancel in GUI2 . The change could be like this : Func Traitement_intermediaire() ; gui2() If gui2(1) Then Return MsgBox(0, "Suite", "cela continue") ;suite du script ;.... EndFunc ; Func gui2() Func gui2($iCancelStopsAll = 0) Local $iReturn = 0 ... Case $GUI_EVENT_CLOSE, $g_idButton4 If $iCancelStopsAll Then $iReturn = 1 ... Return $iReturn ; 0 or 1 EndFunc Note : if the GUI2 Close button [X] should react differently than the GUI2 Cancel button, then the Case should be splitted in 2 (one Case for $GUI_EVENT_CLOSE, another Case for $g_idButton4) Hope it makes sense... if this is what ermar asked for !2 points -
trick for ToolTip with timer Func _ToolTip($sText, $iX = Default, $iY = Default, $sTitle = "", $iIcon = 0, $iTimeout = 1500, $iOptions = 0) AdlibUnRegister("_ToolTipKiller") ; This prevents the previous timer from closing the new tooltip. ToolTip($sText, $iX, $iY, $sTitle, $iIcon, $iOptions) AdlibRegister("_ToolTipKiller", $iTimeout) EndFunc ;==>_ToolTip Func _ToolTipKiller() ToolTip("") ; Hide the tooltip AdlibUnRegister("_ToolTipKiller") ; unregister itself. EndFunc ;==>_ToolTipKiller Example ; https://www.autoitscript.com/forum/topic/139260-autoit-snippets/page/28/#findComment-1546696 ;---------------------------------------------------------------------------------------- ; Title...........: Trick for ToolTip with timer ; Description.....: Displays a native tooltip with timer. ; AutoIt Version..: 3.3.16.1 Author: ioa747 Script Version: 0.1 ; Note............: Testet in Win10 22H2 Date:16/10/2025 ;---------------------------------------------------------------------------------------- #AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #include <GUIConstantsEx.au3> Forms() Func Forms() Local $hGui = GUICreate(@ScriptName, 250, 150, -1, -1) Local $idBtn1 = GUICtrlCreateButton("Button 1", 10, 10, 100, 25) Local $idBtn2 = GUICtrlCreateButton("Button 2", 10, 40, 100, 25) Local $idBtn3 = GUICtrlCreateButton("Button 3", 10, 70, 100, 25) Local $idBtn4 = GUICtrlCreateButton("Button 4", 10, 100, 100, 25) GUISetState(@SW_SHOW, $hGui) While 1 Local $aWPos = WinGetPos($hGui) Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $idBtn1 _ToolTip("...is clicked", $aWPos[0], $aWPos[1] - 15, "Button 1", 1) Case $idBtn2 _ToolTip("...is clicked", $aWPos[0], $aWPos[1] - 15, "Button 2", 1) Case $idBtn3 _ToolTip("...is clicked", $aWPos[0], $aWPos[1] - 15, "Button 3", 1) Case $idBtn4 _ToolTip("...is clicked", $aWPos[0], $aWPos[1] - 15, "Button 4", 1) EndSwitch WEnd GUIDelete($hGui) EndFunc ;==>Forms Func _ToolTip($sText, $iX = Default, $iY = Default, $sTitle = "", $iIcon = 0, $iTimeout = 1500, $iOptions = 0) AdlibUnRegister("_ToolTipKiller") ; This prevents the previous timer from closing the new tooltip. ToolTip($sText, $iX, $iY, $sTitle, $iIcon, $iOptions) AdlibRegister("_ToolTipKiller", $iTimeout) EndFunc ;==>_ToolTip Func _ToolTipKiller() ToolTip("") ; Hide the tooltip AdlibUnRegister("_ToolTipKiller") ; unregister itself. EndFunc ;==>_ToolTipKiller2 points
-
Native win8+ toast notifications
genius257 and one other reacted to WildByDesign for a topic
I was able to test this new event functionality this morning and it works great. Excellent job! Without a doubt, this is the most fully featured toast notification UDF for AutoIt specifically for utilizing native toast functionality. There are some other UDFs which create their own toast-like notifications. But using built-in Windows functionality is generally the best way to go. Your UDF already does everything that I personally would ever need as far as toast notifications go. One of the best toast notification apps that I've ever used on Windows 11 is actually from KDE, of all things. Snoretoast (https://github.com/KDE/snoretoast). But I didn't like the idea of having to drop yet another binary on disk for my users. So I will likely switch those apps over to your UDF and keep it all AutoIt. By the way, you can always browse their source code (C++) to see if there is anything that they do that might be beneficial for your UDF. I don't understand some of the more complex parts of toast notification functionality, so I'm not even sure if they have anything extra or not. Cheers (or toast!) 🍷2 points -
Move window behind desktop icons
Parsix and one other reacted to argumentum for a topic
... Local $sFile = StringLeft(@AutoItExe, StringInStr(@AutoItExe, "\", 0, -1) -1 ) & "\Examples\GUI\logo4.gif" Local $hImage = _GDIPlus_ImageLoadFromFile($sFile) ;create an image object based on a file Global $hWorkerW = _WinAPI_FindWindowEx($hProgman, 0, "WorkerW", "") If Not $hWorkerW Then ; dah Local $aEnumWindows = _WinAPI_EnumWindows(False) For $n = 1 To UBound($aEnumWindows) - 1 If $aEnumWindows[$n][1] <> "WorkerW" Then ContinueLoop If _WinAPI_GetParent($aEnumWindows[$n][0]) = $hProgman Then $hWorkerW = $aEnumWindows[$n][0] ExitLoop ; but is likely one at the end of the Z-order EndIf Next EndIf If $hWorkerW = 0 Then Exit MsgBox(16, "ERROR", "Couldn't find WorkerW under Progman", 30) ... OnAutoItExitRegister(CleanupResources) While GUIGetMsg() <> $GUI_EVENT_CLOSE WEnd CleanupResources() Func CleanupResources() Local Static $iRunOnce = 0 If $iRunOnce Then Return ConsoleWrite('+ Func CleanupResources() - WinExists: ' & WinExists($hGUI) & ' - ' & (IsInt(Execute("@exitCode")) ? 'TrayExit' : 'GuiClosed') & @CRLF) ;cleanup resources _GDIPlus_BrushDispose($hTexture) _GDIPlus_ImageDispose($hImage) _GDIPlus_GraphicsDispose($hGraphics) _GDIPlus_Shutdown() GUIDelete($hGUI) $iRunOnce = 1 EndFunc ... ...be mindful of everyone and everything ?2 points -
MouseHoverCallTips [10/18/2025]
ioa747 and one other reacted to jaberwacky for a topic
Latest update! Check it out!2 points -
Instead of directly processing everything in AutoIt, I followed the examples from LarsJ in this Thread: Got everything working as I wanted.2 points
-
How to Read Font Title from File Property
Parsix and one other reacted to WildByDesign for a topic
I agree, the title generally should be equal to the information pulled from that first function. Although I have not checked too many fonts to compare. Probably undocumented, not sure. I got that from the _WinAPI_GetFontResourceInfo docs, Example 3.2 points -
Sorry I forgot to introduce UDF: Enhanced Hotkey UDF – Non-blocking Hotkey System for AutoIt The built-in HotKeySet function in AutoIt uses system hooks that can sometimes introduce lag or block the main thread. Enhanced Hotkey UDF by Trong operates entirely non-blocking, handling all key detection in your main script loop through a single, explicit call. In just one line, you can integrate the hotkey system: While True _HotkeyCheck() ; ... your code ... WEnd Key Features Non-blocking architecture without Windows hooks or extra threads Multi-press support (1–10 presses) with customizable time window Flexible trigger flags: HOTKEY_FLAG_REPEAT for auto-repeat while holding HOTKEY_FLAG_RELEASE for trigger on key release HOTKEY_FLAG_HOLD for trigger after holding a threshold Debug mode and performance stats (checks, triggers, average triggers per check) Easy management: register, remove, clear all, list registered hotkeys Quick Comparison | Criterion | HotKeySet (AutoIt) | Enhanced Hotkey UDF | |-----------------------------------------|-----------------------------------------|---------------------------------------------------------| | Architecture | System-level hook, blocking | Polling-based, non-blocking | | Impact on main thread | May cause lag | Zero blocking, full control | | Multi-press (double, etc.) | Not supported | Supported (1–10 presses) | | Hold detection | Not supported | Supported with configurable threshold | | Release detection | Not supported | Supported | | Auto-repeat while holding | Not supported | Supported (`HOTKEY_FLAG_REPEAT`) | | Debug and stats | No | Yes | Conclusion If you need a powerful hotkey manager for scripts, games, or real-time applications that avoids blocking your main thread while offering press, release, hold, repeat, and multi-press detection, the Enhanced Hotkey UDF is the tool of choice. Simply call _HotkeyCheck in your loop and let the UDF handle the rest. PS: This article was analyzed and created by AI (Copilot).2 points
-
Window Handle/Title under mouse pointer
jaberwacky and one other reacted to Ascend4nt for a topic
This is how to do it with the built-in UDF functions: #include <WinAPI.au3> #include <Misc.au3> Local $stPoint=DllStructCreate($tagPOINT),$aPos,$hControl,$hWin,$aLastPos[2]=[-1,-1],$sLastStr='',$sStr While Not _IsPressed('1B') $aPos=MouseGetPos() If $aPos[0]<>$aLastPos[0] Or $aPos[1]<>$aLastPos[1] Then DllStructSetData($stPoint,1,$aPos[0]) DllStructSetData($stPoint,2,$aPos[1]) $hControl=_WinAPI_WindowFromPoint($stPoint) $hWin=_WinAPI_GetAncestor($hControl,2) $sStr='Window at '&$aPos[0]&','&$aPos[1]&': "'&WinGetTitle($hWin)&'"' If $sLastStr<>$sStr Then ToolTip($sStr,0,@DesktopHeight-20) $sLastStr=$sStr EndIf $aLastPos=$aPos EndIf Sleep(15) WEnd On a side note - I'd just like to add that _WinAPI_WindowFromPoint() was poorly thought out - it should take x,y coordinates instead of a structure.2 points