Custom Query
Results (19 - 21 of 3841)
Ticket | Resolution | Summary | Owner | Reporter |
---|---|---|---|---|
#3930 | No Bug | DllStructs created in one scope gets dropped if chained with a function that returns a re-structured-by-pointer version of it | AutoXenon | |
Description |
GUICreate('') Local $unreliable_data, $reliable_data, $intermediate_ref, $labelunreliable = GUICtrlCreateLabel('',0,0,400,25), $labelreliable = GUICtrlCreateLabel('',0,30,400,25) GUISetState() HotKeySet('{esc}',quit) While True $unreliable_data = parseStruct(createStruct()) ; struct technically goes out of scope, this saves a "slave struct" but the master struct gets dropped when it goes out of parseStruct's scope $intermediate_ref = createStruct() ; struct scope gets transferred, this is a "master struct" $reliable_data = parseStruct($intermediate_ref) ; a "slave struct" of a master struct that is scoped here Sleep(100) ; wait some time for garbage to get written into the freed memory GUICtrlSetData($labelunreliable,DllStructGetData($unreliable_data,'msg')) GUICtrlSetData($labelreliable,DllStructGetData($reliable_data,'msg')) WEnd Func createStruct() Local $struct = DllStructCreate('char[16]') DllStructSetData($struct,1,'hello world') Return $struct EndFunc Func parseStruct($struct) Return DllStructCreate('char msg[16]',DllStructGetPtr($struct)) EndFunc Func quit() Exit EndFunc The question is, should create-by-pointer structs count as valid references? I can imagine that if it is change to be so, it might cause headaches with ad-hoc throwaway "lens" structs unintentionally preventing the memory from being freed if the programmer is expecting it to not count as valid references. I guess it's up to you to decide on which tradeoff to pick. |
|||
#3928 | Works For Me | WinWaitActive() prevents Raw Input's WM_INPUT messages from queueing up (drops messages?), resulting in poor responsiveness | nurupo | |
Description |
Calling into WinWaitActive() somehow results in 1) fewer WM_INPUT messages being delivered and 2) in WM_INPUT messages not queueing up at all. To illustrate this problem, here is a minimal reproducible example I came up with. I will further explain what it does and how to use it. #include <AutoItConstants.au3> #include <WinAPISys.au3> #include <WindowsConstants.au3> Opt("MustDeclareVars", 1) Opt("WinWaitDelay", 0) Local $hForm = GUICreate("") Local $tRID = DllStructCreate($tagRAWINPUTDEVICE) DllStructSetData($tRID, 'UsagePage', 0x01) DllStructSetData($tRID, 'Usage', 0x02) DllStructSetData($tRID, 'Flags', $RIDEV_INPUTSINK) DllStructSetData($tRID, 'hTarget', $hForm) _WinAPI_RegisterRawInputDevices($tRID) GUIRegisterMsg($WM_INPUT, 'WM_INPUT') While 1 TrayGetMsg() WEnd Func WM_INPUT($hWnd, $iMsg, $wParam, $lParam) #forceref $iMsg, $wParam If $hWnd <> $hForm Then Return Local $tRIM = DllStructCreate($tagRAWINPUTMOUSE) If Not _WinAPI_GetRawInputData($lParam, $tRIM, DllStructGetSize($tRIM), $RID_INPUT) Then Return Local $iFlags = DllStructGetData($tRIM, 'ButtonFlags') If BitAND($iFlags, $RI_MOUSE_WHEEL) Then OnMouseWheel() EndIf EndFunc Func OnMouseWheel() Local Static $iCount = 0 Local Static $iSec = @SEC If $iSec <> @SEC Then ConsoleWrite("Counted " & $iCount & " mouse wheel scrolls in the past second" & @CRLF) $iCount = 0 $iSec = @SEC EndIf $iCount += 1 ;LessResponsive() ;Local $iDelay = ? ; <-- set to the ms number you get in console when running LessResponsive() ;MoreResponsive($iDelay) EndFunc Func LessResponsive() Local $hWndCurrent = WinGetHandle("[ACTIVE]") Local $hWndNotepad = WinActivate("[CLASS:Notepad]") Local $hTimer = TimerInit() WinWaitActive($hWndNotepad, "", 1) Local $iTimerDiff1 = TimerDiff($hTimer) ControlSend($hWndNotepad, "", "Edit1", @MSEC & "{Enter}") WinActivate($hWndCurrent) $hTimer = TimerInit() WinWaitActive($hWndCurrent, "", 1) Local $iTimerDiff2 = TimerDiff($hTimer) ConsoleWrite("LessResponsive: Waited on window for " & ($iTimerDiff1+$iTimerDiff2)/2 & "ms" & @CRLF) EndFunc Func MoreResponsive($iDelay) Local $hWndCurrent = WinGetHandle("[ACTIVE]") Local $hWndNotepad = WinActivate("[CLASS:Notepad]") Local $hTimer = TimerInit() _WinWaitActive($hWndNotepad, "", 1, $iDelay) Local $iTimerDiff1 = TimerDiff($hTimer) ControlSend($hWndNotepad, "", "Edit1", @MSEC & "{Enter}") WinActivate($hWndCurrent) $hTimer = TimerInit() _WinWaitActive($hWndCurrent, "", 1, $iDelay) Local $iTimerDiff2 = TimerDiff($hTimer) ConsoleWrite("MoreResponsive: Waited on window for " & ($iTimerDiff1+$iTimerDiff2)/2 & "ms" & @CRLF) EndFunc Func _WinWaitActive($hWnd, $unused, $iTimeout, $iDelay) Local $iActiveFlag = Null $iTimeout *= 1000 Local $hTimer = TimerInit() Do Local $iState = WinGetState($hWnd) $iActiveFlag = BitAND($iState, $WIN_STATE_ACTIVE) Until $iActiveFlag Or TimerDiff($hTimer) >= $iTimeout If $iActiveFlag Then _Sleep($iDelay) EndIf Return $iActiveFlag ? $hWnd : 0 EndFunc ; Seelps in intervals of 1ms for total of $delay ms Func _Sleep($delay) Local $iLeftToSleep = $delay Local $hTimer If $iLeftToSleep > 1 Then ; sleep in 1ms intervals Local Static $hNtdll = DllOpen("ntdll.dll") Local Static $hWinmmdll = DllOpen("winmm.dll") DllCall($hWinmmdll, "int", "timeBeginPeriod", "int", 1) Local $iTimerDiff Do $hTimer = TimerInit() DllCall($hNtdll, "dword", "NtDelayExecution", "int", 0, "int64*", -5000) $iTimerDiff = TimerDiff($hTimer) $iLeftToSleep -= $iTimerDiff Until $iLeftToSleep <= $iTimerDiff DllCall($hWinmmdll, "int", "timeEndPeriod", "int", 1) EndIf ; hot loop for the remaining <= 1ms If $iLeftToSleep > 0 Then $hTimer = TimerInit() Do Until TimerDiff($hTimer) >= $iLeftToSleep EndIf EndFunc What the example above doesThe example above expects a Notepad to be running and you focus SciTE window before scrolling the mouse wheel. Whenever you scroll the mouse wheel, OnMouseWheel() gets called, recording how many scrolls you have done during the current second, printing that out to the console on the next second. OnMouseWheel() also calls into LessResponsive() or MoreResponsive(), if one of them is uncommented. They both activate the Notepad window, send some text to it and activate the SciTE window back. The difference is that LessResponsive() uses WinWaitActive(), while MoreResponsive() uses my own imitation version of WinWaitActive() called _WinWaitActive(). --- How to use the exampleFirstly, just run it as it is.
(I typically get around 10 scrolls per second) Now uncomment the LessResponsive() call and redo the same 1-5 steps. Notice how the number of scrolls per second has reduced. For me it went from 10 when LessResponsive() was commented out, to 4 with LessResponsive() uncommented. Take note of the window wait time being printed to the console. (I get around 19ms window wait time). Now comment out LessResponsive() and uncomment MoreResponsive(). Set $iDelay to the window wait time you got when running LessResponsive(), e.g. I have set mine to 19. Redo steps 1-5 and notice how you get a lot more scrolls per second now. I went from 4 back to 10 as it was before LessResponsive() and MoreResponsive() were uncommented. That's a huge increase in responsiveness! What is more, if you scroll too fast, it will start queueing the unprocessed WM_INPUT messages, i.e. you can stop scrolling and the OnMouseWheel() will continue to get called until all the queued up messages are processed! This didn't happen with LessResponsive(), somehow WinWaitActive() prevented the messages from queueing up. --- You could say "Why don't you just use your _WinWaitActive() then?". Well, the issue is that while my _WinWaitActive() is a lot more responsive than AutoIt's WinWaitActive(), it's not really comparable in functionality to WinWaitActive(), it's pretty much just a custom Sleep() function that happened to check if a window is in the active state. It doesn't know when a window becomes active the same way WinWaitActive() does. Window's state is always set to active, visible and enabled right after calling WinActivate() on it, so if not for the custom sleep, _WinWaitActive() would have returned right away (under 0.1ms), while WinWaitActive() is somehow able to wait just the right amount of time for the window to get activates, drawn and be ready to receive keyboard input (around 19ms on my computer). As such, _WinWaitActive() is not very usable to me because it doesn't know how long to wait for, and while WinWaitActive() knows for how long to wait for, it's also not very unusable to me but due to it resulting in sluggish message processing and no message queueing. (I assume that WinWaitActivate() knows how long to wait for, it would be funny if it's too just a glorified wrapper for a Sleep() call with an arbitrarily chosen sleep time). Could you fix WinWaitActive() so that 1) the message processing doesn't become as sluggish and 2) the messages queue properly? |
|||
#3926 | Fixed | _GUICtrlTreeView_SetChildren functionality has changed | Jpm | office@… |
Description |