Swimlanes Posted June 1, 2022 Share Posted June 1, 2022 Hi all, I'm really new to AutoIt and encountered an issue with my script. I'd be happy if someone could point me in the right direction to solve the issue. First a few words about what the script does: Every given time interval, it will perform a bunch of actions. Between these actions, I am running a loop, which prints text on screen, updating every 100ms and showing the remaining time in seconds until the next action will be triggered. All of this runs in a permanent while loop until terminated. The issue: Randomly the program will generate a huge colored rectangle the size of my monitor, just offset to the bottom right by the same distance at which my info text is off-set. When this happens, interaction with my task bar is also corrupted, with the task bar display being randomly offset as I interact with elements. Using the task manager is not possible, as it is hidden by the colored rectangle. Interaction with the tray icons is not possible, as the arrow to expand tray icons is corrupted and won't properly open. This always happens at some random point while the countdown is running. It never happens during the execution of the main actions. Always during the countdown. The script is below. Given the corruption only happens during the countdown, I guess it must happen during the do-loop in lines 19-22. That's where all the GUI functions get called (which I mostly obtained from various snippets around the forums/internet). I have no clue why the script updates the counter perfectly fine for several hundred iterations and then just randomly it starts corrupting like explained above. Does anyone have an idea what is happening? Thanks in advance! expandcollapse popup#include <GUIConstants.au3> ; ####### CONFIG ####### Global $text = "Next action in " ; Info text to show on screen Global $txtcolor = 0xFF0000 ; Text color Global $printInfo = 1 ; Show info text at all? ; ##### END CONFIG ##### Global $delay = 0.0 Global $hwnd = GUICreate("Text Region", @DesktopWidth, @DesktopHeight, 10, 10, $WS_POPUP, BitOR($WS_EX_TOPMOST,$WS_EX_TOOLWINDOW)) GUISetBkColor($txtcolor) ; text color While 1 $time = TimerInit() do If $printInfo Then DrawNotice($hwnd, $text, Round(($delay - TimerDiff($time))/1000)) Sleep(100) until TimerDiff($time) >= $delay Action() $delay = Random(52,71,1)*1000 WEnd Func DrawNotice($hwnd, $text, $delay) Local $message = $text & $delay & "s" Local $rgn = CreateTextRgn($hwnd, $message, 100, "Arial", 500) SetWindowRgn($hwnd,$rgn) GUISetState() EndFunc Func SetWindowRgn($h_win, $rgn) DllCall("user32.dll", "long", "SetWindowRgn", "hwnd", $h_win, "long", $rgn, "int", 1) EndFunc Func CreateTextRgn(ByRef $CTR_hwnd,$CTR_Text,$CTR_height,$CTR_font="Microsoft Sans Serif",$CTR_weight=1000) Local Const $ANSI_CHARSET = 0 Local Const $OUT_CHARACTER_PRECIS = 2 Local Const $CLIP_DEFAULT_PRECIS = 0 Local Const $PROOF_QUALITY = 2 Local Const $FIXED_PITCH = 1 Local Const $RGN_XOR = 3 If $CTR_font = "" Then $CTR_font = "Microsoft Sans Serif" If $CTR_weight = -1 Then $CTR_weight = 1000 Local $gdi_dll = DLLOpen("gdi32.dll") Local $CTR_hDC= DLLCall("user32.dll","int","GetDC","hwnd",$CTR_hwnd) Local $CTR_hMyFont = DLLCall($gdi_dll,"hwnd","CreateFont","int",$CTR_height,"int",0,"int",0,"int",0, _ "int",$CTR_weight,"int",0,"int",0,"int",0,"int",$ANSI_CHARSET,"int",$OUT_CHARACTER_PRECIS, _ "int",$CLIP_DEFAULT_PRECIS,"int",$PROOF_QUALITY,"int",$FIXED_PITCH,"str",$CTR_font ) Local $CTR_hOldFont = DLLCall($gdi_dll,"hwnd","SelectObject","int",$CTR_hDC[0],"hwnd",$CTR_hMyFont[0]) DLLCall($gdi_dll,"int","BeginPath","int",$CTR_hDC[0]) DLLCall($gdi_dll,"int","TextOut","int",$CTR_hDC[0],"int",0,"int",0,"str",$CTR_Text,"int",StringLen($CTR_Text)) DLLCall($gdi_dll,"int","EndPath","int",$CTR_hDC[0]) Local $CTR_hRgn1 = DLLCall($gdi_dll,"hwnd","PathToRegion","int",$CTR_hDC[0]) Local $CTR_rc = DLLStructCreate("int;int;int;int") DLLCall($gdi_dll,"int","GetRgnBox","hwnd",$CTR_hRgn1[0],"ptr",DllStructGetPtr($CTR_rc)) Local $CTR_hRgn2 = DLLCall($gdi_dll,"hwnd","CreateRectRgnIndirect","ptr",DllStructGetPtr($CTR_rc)) DLLCall($gdi_dll,"int","CombineRgn","hwnd",$CTR_hRgn2[0],"hwnd",$CTR_hRgn2[0],"hwnd",$CTR_hRgn1[0],"int",$RGN_XOR) DLLCall($gdi_dll,"int","DeleteObject","hwnd",$CTR_hRgn1[0]) DLLCall("user32.dll","int","ReleaseDC","hwnd",$CTR_hwnd,"int",$CTR_hDC[0]) DLLCall($gdi_dll,"int","SelectObject","int",$CTR_hDC[0],"hwnd",$CTR_hOldFont[0]) DLLClose($gdi_dll) Return $CTR_hRgn2[0] EndFunc Func Action() ; Main program activity goes here EndFunc Link to comment Share on other sites More sharing options...
Swimlanes Posted June 1, 2022 Author Share Posted June 1, 2022 Small update: The huge rectangle initially does not get drawn. Initially only Windows UI and other programs get visually corrupted. When I ctrl alt del and start the task manager, the rectangle turns visible as soon as the desktop is shown again. From this moment on, I can foreground the task bar again normally, by clicking on the small segment that's visible on the left, given the rectangle's offset. Interacting with the tray-icon arrow is then possible normally and I can terminate the Autoit script from there. I still don't get why this happens in the first place, especially since it always does hundreds of iterations (even dozens of iterations of the outer while-loop) without any issues... Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted June 1, 2022 Moderators Share Posted June 1, 2022 Swimlanes, Welcome to the AutoIt forum. I will leave the GDI gurus to look into your problem, but could I point you to my Notify or Toast UDFs (the links are in my sig below) either of which look to be something which would do exactly what you say you want: Quote showing the remaining time in seconds until the next action will be triggered it might be quicker then trying to debug what you already have. And I would be happy to help you integrate either into your script. M23 Swimlanes 1 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
Swimlanes Posted June 1, 2022 Author Share Posted June 1, 2022 Thanks Melba, those sound interesting. I'll take a look at those! Link to comment Share on other sites More sharing options...
Solution LarsJ Posted June 2, 2022 Solution Share Posted June 2, 2022 Most of these issues related to GDI and GDI+ code is about memory leaks. That's also the case here. There are two memory leaks in the code: neither $CTR_hMyFont[0] nor $CTR_hRgn2[0] are deleted using the DeleteObject() function. Fix these errors and the code will probably run forever. I would write the code this way: expandcollapse popup#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #AutoIt3Wrapper_UseX64=Y Opt( "MustDeclareVars", 1 ) #include <GUIConstants.au3> Example() Func Example() Local $text = "Next action in " ; Info text to show on screen Local $txtcolor = 0xFF0000 ; Text color Local $printInfo = 1 ; Show info text at all? Local $delay = 0.0 Local $hwnd = GUICreate("Text Region", 800, 200, 10, 10, $WS_POPUP, BitOR($WS_EX_TOPMOST,$WS_EX_TOOLWINDOW)) GUISetBkColor($txtcolor) ; text color GUISetState() While 1 Local $time = TimerInit() do If $printInfo Then CreateTextRgn($hwnd, $text & Round(($delay - TimerDiff($time))/1000) & "s", 100, "Arial", 500) Sleep(100) until TimerDiff($time) >= $delay $delay = Random(52,71,1)*1000 Action() WEnd EndFunc Func CreateTextRgn($CTR_hwnd,$CTR_Text,$CTR_height,$CTR_font="Microsoft Sans Serif",$CTR_weight=1000) Local Const $ANSI_CHARSET = 0, $OUT_CHARACTER_PRECIS = 2, $CLIP_DEFAULT_PRECIS = 0, $PROOF_QUALITY = 2, $FIXED_PITCH = 1, $RGN_XOR = 3 If $CTR_font = "" Then $CTR_font = "Microsoft Sans Serif" If $CTR_weight = -1 Then $CTR_weight = 1000 Local Static $gdi_dll = DLLOpen("gdi32.dll") Local Static $CTR_hDC= DLLCall("user32.dll","int","GetDC","hwnd",$CTR_hwnd) Local Static $CTR_hMyFont = DLLCall($gdi_dll,"hwnd","CreateFont","int",$CTR_height,"int",0,"int",0,"int",0, _ "int",$CTR_weight,"int",0,"int",0,"int",0,"int",$ANSI_CHARSET,"int",$OUT_CHARACTER_PRECIS, _ "int",$CLIP_DEFAULT_PRECIS,"int",$PROOF_QUALITY,"int",$FIXED_PITCH,"str",$CTR_font ) Local Static $CTR_hOldFont = DLLCall($gdi_dll,"hwnd","SelectObject","int",$CTR_hDC[0],"hwnd",$CTR_hMyFont[0]) DLLCall($gdi_dll,"int","BeginPath","int",$CTR_hDC[0]) DLLCall($gdi_dll,"int","TextOut","int",$CTR_hDC[0],"int",0,"int",0,"str",$CTR_Text,"int",StringLen($CTR_Text)) DLLCall($gdi_dll,"int","EndPath","int",$CTR_hDC[0]) Local $CTR_hRgn1 = DLLCall($gdi_dll,"hwnd","PathToRegion","int",$CTR_hDC[0]) Local $CTR_rc = DLLStructCreate("int;int;int;int") DLLCall($gdi_dll,"int","GetRgnBox","hwnd",$CTR_hRgn1[0],"ptr",DllStructGetPtr($CTR_rc)) Local $CTR_hRgn2 = DLLCall($gdi_dll,"hwnd","CreateRectRgnIndirect","ptr",DllStructGetPtr($CTR_rc)) DLLCall($gdi_dll,"int","CombineRgn","hwnd",$CTR_hRgn2[0],"hwnd",$CTR_hRgn2[0],"hwnd",$CTR_hRgn1[0],"int",$RGN_XOR) DllCall("user32.dll", "long", "SetWindowRgn", "hwnd", $CTR_hwnd, "long", $CTR_hRgn2[0], "int", 1) ;DLLCall($gdi_dll,"int","DeleteObject","hwnd",$CTR_hMyFont[0]) ; Memory leak <<<<<<<<<<<<<<<<<<<< DLLCall($gdi_dll,"int","DeleteObject","hwnd",$CTR_hRgn1[0]) ;DLLCall("user32.dll","int","ReleaseDC","hwnd",$CTR_hwnd,"int",$CTR_hDC[0]) ;DLLCall($gdi_dll,"int","SelectObject","int",$CTR_hDC[0],"hwnd",$CTR_hOldFont[0]) DLLCall($gdi_dll,"int","DeleteObject","hwnd",$CTR_hRgn2[0]) ; Memory leak <<<<<<<<<<<<<<<<<<<<<<< ;DLLClose($gdi_dll) #forceref $CTR_hOldFont EndFunc Func Action() ; Main program activity goes here EndFunc Swimlanes and mLipok 2 Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions Link to comment Share on other sites More sharing options...
Swimlanes Posted June 5, 2022 Author Share Posted June 5, 2022 Sorry for the late reply, I was pretty busy the last days. Lars, your adjustments did it! I used your code and had it run for a couple of thousand iterations without any of these weird corruptions. Seems to be working fine now. And the parts you mentioned as memleaks also make sense, now that you pointed it out. Thanks a lot! Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now