Necris Posted May 25, 2014 Share Posted May 25, 2014 (edited) Autoit is a great tool for several diverse tasks. One such task is holding down buttons. I managed to simulate it nicely by changing hold-down time and looping keypresses: expandcollapse popup;;================================================================================ ;; Setup and Initialize ;;================================================================================ Opt("SendKeyDelay", 0) ;5 milliseconds - Pause between two consecutive SendKey Opt("SendKeyDownDelay", 50) ;1 millisecond - The lenght of time the key is down ;;-------------------------------------------------------------------------------- ;; Hotkeys ;;-------------------------------------------------------------------------------- HotKeySet('{END}', 'Quit') ;;-------------------------------------------------------------------------------- ;; Global Variables ;;-------------------------------------------------------------------------------- Global $Exiting = False Global $ClientHandle ;;================================================================================ ;; Main ;;================================================================================ If WinWaitActive("Untitled", "", 10) <> 0 Then $ClientHandle = WinGetHandle("") Else MsgBox(4096,"Error","Can't get handle of active window",3) Exit 0 EndIf While WinExists($ClientHandle) If $Exiting Then Exit 0 Else Sleep(25) EndIf ControlSend($ClientHandle, "", "", "{F4}") WEnd Exit 0 ;;-------------------------------------------------------------------------------- ;; Quit() ;;-------------------------------------------------------------------------------- Func Quit() $Exiting = Not $Exiting EndFunc ;==>Quit To me, this code should work perfectly, and most of the time it does. After a while though, the mouse cursor starts to flicker, and somehow the shift key is spammed. I am fairly good at c++ and I have for some time trying to make a program that sends keys to a Direct Input application, I just can't get it right though. The AutoIt Script, however, succedes in doing just that with ControlSend. So, does anyone know how ControlSend does this? Firstly, is AutoIt made in c/c++ or another language? If it is made in any of those, is it known what functions it uses to "ControlSend"? In C++ I have tried SendInput, SendMessage, SendMessageCallback. For SendInput I tried with both virtual and non-virtual key presses. None of these manages to send keys to the Direct Input application the way ControlSend does it. I would really like to solve this and any input is appriciated. Edited May 25, 2014 by Necris Link to comment Share on other sites More sharing options...
JohnOne Posted May 25, 2014 Share Posted May 25, 2014 That's a lovely story. AutoIt Absolute Beginners Require a serial Pause Script Video Tutorials by Morthawt ipify Monkey's are, like, natures humans. Link to comment Share on other sites More sharing options...
Booo Posted May 25, 2014 Share Posted May 25, 2014 Autoit is a great tool for several diverse tasks. One such task is holding down buttons. I managed to simulate it nicely by changing hold-down time and looping keypresses: used send function https://www.autoitscript.com/autoit3/docs/functions/Send.htm u can used my code Local $arr[7] = ["{W}", "{D}", "{A}","{S}"] ; keys While 1 Local $iRandom = Random(0,UBound($arr)-1,1) Send($arr[$iRandom]) ; keypresses: Sleep(3000) ; time 3 sec WEnd Link to comment Share on other sites More sharing options...
Necris Posted May 25, 2014 Author Share Posted May 25, 2014 (edited) That's a lovely story. Not just a story, there are questions too: "So, does anyone know how ControlSend does this? Firstly, is AutoIt made in c/c++ or another language? If it is made in any of those, is it known what functions it uses to "ControlSend"?" used send function https://www.autoitscript.com/autoit3/docs/functions/Send.htm The Send function won't work. It has to work on a window without focus. To clarify, I either wan't information that will help me reverse engineer ControlSend in c++, or I would like an UDF similar to ControlSend but where the Shift key don't start spamming. Is there such an UDF? If not, does anyone have any ideas where to start in making one? Why is it that the Shift key starts spamming even though the script I am using don't affect it? Edited May 25, 2014 by Necris Link to comment Share on other sites More sharing options...
JohnOne Posted May 25, 2014 Share Posted May 25, 2014 Not just a story, there are questions too: There are now, but there were not earlier. AutoIt is created in C++ I believe SendInput function would be used for AutoIt Send() function but I doubt it for ControlSend(), I believe it would be SendMessage, using both the WM_KEYDOWN and WM_KEYUP messages. I did make it once while learning C++ but was a couple of years ago and never really used it beyond testing as AutoIt was much simpler. How is it that you determine the shift key is "spammed"? Xandy 1 AutoIt Absolute Beginners Require a serial Pause Script Video Tutorials by Morthawt ipify Monkey's are, like, natures humans. Link to comment Share on other sites More sharing options...
Necris Posted May 25, 2014 Author Share Posted May 25, 2014 (edited) There are now, but there were not earlier. AutoIt is created in C++ I believe SendInput function would be used for AutoIt Send() function but I doubt it for ControlSend(), I believe it would be SendMessage, using both the WM_KEYDOWN and WM_KEYUP messages. I did make it once while learning C++ but was a couple of years ago and never really used it beyond testing as AutoIt was much simpler. How is it that you determine the shift key is "spammed"? Yeah, sorry about that. While fiddeling with the code section of my post I somehow accidentaly posted it. I'm almost sure that ControlSend don't use SendMessage, since earlier today I failed to send input to an application to it, whereas ControlSend succeded. ofcourse, that could have been due to some misstake by me, or simply the application being in another state between the two trials. Just now, I found a post about a simmilar issue as mine, and in that case switching from SendMessage to PostMessage fixed the issue. I'll try that tomorrow. I know the shift key is affected by my AutoIt script since, after some hours runtime, my typing gets messed up. If I type 50 letters quickly, 35 of them will be capitalized and the rest won't. Sometimes 5 in a row will be in the same state, and sometimes every other will be in a different state than the previous. This only happens when this script have been running for a long time. Also, this is the only script running. Apparently moddifier keys can be left in a pressed state even while using Send, atleast according to: '?do=embed' frameborder='0' data-embedContent>> Alhough, in my case the Shift key "flickers" without even being used in the script. Edited May 25, 2014 by Necris Link to comment Share on other sites More sharing options...
JohnOne Posted May 25, 2014 Share Posted May 25, 2014 (edited) It is possible that the shift key is getting stuck some how, not by the script, well partly by the script I suppose. I imagine during your typing you are using the shift key, say you press shift down and your script sends some text to your target control while it is, or the shift up is missed while script is processing another key send event. I don't know exactly the ins and out of why something like that might happen, it just feels like there might be undefined behaviour while input from multiple locations are being processed simultaneously! Just a thought. EDIT: You might test it, when the problem starts next, open up some window and type only in lower case to see if the problem persists. Edited May 25, 2014 by JohnOne AutoIt Absolute Beginners Require a serial Pause Script Video Tutorials by Morthawt ipify Monkey's are, like, natures humans. Link to comment Share on other sites More sharing options...
Necris Posted May 26, 2014 Author Share Posted May 26, 2014 (edited) It is possible that the shift key is getting stuck some how, not by the script, well partly by the script I suppose. I imagine during your typing you are using the shift key, say you press shift down and your script sends some text to your target control while it is, or the shift up is missed while script is processing another key send event. I don't know exactly the ins and out of why something like that might happen, it just feels like there might be undefined behaviour while input from multiple locations are being processed simultaneously! Just a thought. EDIT: You might test it, when the problem starts next, open up some window and type only in lower case to see if the problem persists. After having used the computer for some hours with the script running, the shift spamming started again. During those hours I have used the shift key numerous times. It might be that each press of the shift key have a low probability of causing this behaviour, or maybe it was something else. However, typing to notepad, in strictly lowercase, during this "shift spam" session resulted in something simmilar to this; AAAAAaaAAaAAaaaAAAaAAaaaAAAAaaaAaaAAaaAAAAa I did not press and hold the "a" key, I made full pressses. However, that is no longer an issue since I succeded in emulating "ControlSend" in c++, infact, simulating a key being held down worked better than I have ever managed in AutoIt. You were right about SendMessage would work, I had simply forgotten about using administrator rights. Both SendMessage and PostMessage works for the specific application. It turns out that simulating a held down key is harder than what it seems at first glance. In case someone might need this in the future I'll share it here. Simply sending a key_down event, pausing, and then sending a key_up holds the key down during the pause. PostMessage(windowHandle, WM_KEYDOWN, VK_F4, 0); Sleep(2000); PostMessage(windowHandle, WM_KEYUP, VK_F4, 0); // or SendMessage(windowHandle, WM_KEYDOWN, VK_F4, 0); Sleep(2000); SendMessage(windowHandle, WM_KEYUP, VK_F4, 0); But that won't cause applications to behave as you would expect them to while holding down a button. Some might, I did not test that many, but none that I tested "repeated" the keypress (like what is seen while typing and holding down a letter". Instead, the key_down event needs to be looped. Here is a working example. #include <iostream> #include <windows.h> using namespace std; int main() { HWND windowHandle = FindWindow(NULL, "The complete title of the target app"); while(!(GetAsyncKeyState(VK_ESCAPE))) { if(windowHandle != NULL) { int i = 0; while (i < 250) { SendMessage(windowHandle, WM_KEYDOWN, VK_F4, 0); Sleep(40); i++; } SendMessage(windowHandle, WM_KEYUP, VK_F4, 0); } else { cout << "Failed, cant find hwnd\n"; Sleep(5000); } } cout << "Complete\n"; cin.get(); cin.sync(); return 0; } This will emulate {F4} being held down for ten seconds, released and instantly held down again. Thanks alot for the guidance JohnOne, without you I would not have tested SendMessage() again. The Shift spamming is interesting, but I consider this closed and solved now. Edited May 26, 2014 by Necris Link to comment Share on other sites More sharing options...
JohnOne Posted May 26, 2014 Share Posted May 26, 2014 (edited) Ace. Seems odd though that requiring admin rights is needed, unless of course the window you are sending to was started with admin rights. EDIT: I think PostMessage and SendMessage are the same, only one is asynchronous posted to the message queue and returns immediately. Edited May 26, 2014 by JohnOne AutoIt Absolute Beginners Require a serial Pause Script Video Tutorials by Morthawt ipify Monkey's are, like, natures humans. Link to comment Share on other sites More sharing options...
Zedna Posted May 27, 2014 Share Posted May 27, 2014 Search internet for autoit-v3.1.0-src.exe On AutoIt's forum it has been removed some time ago from archive download section. There is "srcsendkeys.cpp" where is detailed source of Send/ControlSend ... Resources UDF ResourcesEx UDF AutoIt Forum Search 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