Markos Posted April 23, 2009 Posted April 23, 2009 Hello,I am trying to translate ControlSend to C#.I have been successful with sending to windows that actually have some controls (like notepad has Edit) but not to windows that dont have any controls (such as games).I know it HAS to be possible, since Autoits' ControlSend function CAN send to window without controls.I have tried to find answer in AutoIt SourceCode that Jon released a long, long time ago, but i wasn't succesful.So what I want to do:Be able to use ControlSend feature without actually calling ControlSend. If we can accomplis this in AutoIt, I can translate it to C#.If the window has controls, I can simply get the control handle and succesfully send to it:#include <sendmessage.au3> #Include <String.au3> $hwnd = WinGetHandle('[CLASS:Notepad]') $child = _GetTopChild($hwnd) Global $WM_CHAR = 0x102 _SendMessage($Child, $WM_CHAR, '0x' & _StringToHex('d'), 0) Func _GetTopChild($aParent) Local $last_top Local $hwnd_top = $aParent Do $last_top = $hwnd_top ConsoleWrite('last top: ' & $last_top & @CRLF) $hwnd_top = _GetTopWindow($last_top) Until $hwnd_top = 0 Return $last_top EndFunc Func _GetTopWindow($hwnd) Local $ret = DllCall('user32.dll', 'hwnd', 'GetTopWindow', 'hwnd', $hwnd) Return $ret[0] EndFuncThis does not work with windows that dont have any controls (like games). I have tried to search in the AutoIt source code and I think that autoit just Attaches to window and if it does not find any controls it sends to main window. (but it is probably wrong, since it does not work too)This is my translation from AutoIt source code to autoit code, which does not work and needs some improvement.expandcollapse popup#include <winapi.au3> #include <WindowsConstants.au3> #Include <String.au3> $hwnd = WinGetHandle('[CLASS:Notepad]') $vk = 0x44;D $scan = _MapVirtualKey($vk, 0) _WinAttach($hwnd, True) $lparam = BitOR( 0x00000001, BitShift($scan, -16) ) $ret = _WinAPI_PostMessage($hwnd, $WM_KEYDOWN, $vk, $lparam) ConsoleWrite($ret & @CRLF) Sleep(100);sleep between keyDown and keyUp $lparam = BitOR( 0xC0000001, BitShift($scan, -16) ) $ret = _WinAPI_PostMessage($hwnd, $WM_KEYUP, $vk, $lparam) ConsoleWrite($ret & @CRLF) Func _MapVirtualKey($uCode, $uMapType) $ret = DllCall('user32.dll', 'int', 'MapVirtualKey', 'int', $uCode, 'int', $uMapType) ConsoleWrite('scan: ' & $ret[0] & @CRLF) Return $ret[0] EndFunc Func _WinAttach($hWnd, $fAttach) Local $myThread = _GetCurrentThreadId(); Local $curthread, $newThread If $fAttach Then $curthread = _GetWindowThreadProcessId(_GetForegroundWindow() , 0) _AttachThreadInput($myThread, $curthread, 1) If $hWnd Then $newThread = _GetWindowThreadProcessId($hwnd, 0) _AttachThreadInput($curthread, $newThread, 1) _AttachThreadInput($myThread, $newThread, 1) EndIf Else EndIf EndFunc Func _GetCurrentThreadId() Local $ret = DllCall('kernel32.dll', 'int', 'GetCurrentThreadId') ConsoleWrite('currentThreadID: ' & $ret[0] & @CRLF) Return $ret[0] EndFunc Func _GetWindowThreadProcessId($hwnd, $processid) Local $ret = DllCall('user32.dll', 'int', 'GetWindowThreadProcessId', 'hwnd', $hwnd, 'int', $processid) ConsoleWrite('GetWindowThreadProcessId: ' & $ret[0] & @CRLF) Return $ret[0] EndFunc Func _GetForegroundWindow() Local $ret = DllCall('user32.dll', 'int', 'GetForegroundWindow') ConsoleWrite('GetForegroundWindow: ' & $ret[0] & @CRLF) Return $ret[0] EndFunc Func _AttachThreadInput($idAttach, $idAttachTo, $fAttach) Local $ret = DllCall('user32.dll', 'int', 'AttachThreadInput', 'int', $idAttach, 'int', $idAttachTo, 'int', $fAttach) ConsoleWrite('AttachThreadInput: ' & $ret[0] & @CRLF) Return $ret[0] EndFuncSo if ANYBODY has ANY idea, I would be glad to see it,Markos
enaiman Posted April 23, 2009 Posted April 23, 2009 If you don't have any "identifiable" controls then ControlSend will behave exactly like Send: you need the application to be active at the moment of sending. Have a look at "SendKeepActive" - it might help you. SNMP_UDF ... for SNMPv1 and v2c so far, GetBulk and a new example script wannabe "Unbeatable" Tic-Tac-Toe Paper-Scissor-Rock ... try to beat it anyway :)
Markos Posted April 24, 2009 Author Posted April 24, 2009 This one quite didnt help since i dont want to use controlsend as I wrote before.
enaiman Posted April 26, 2009 Posted April 26, 2009 Well - you have plenty of time to think about. Good luck. SNMP_UDF ... for SNMPv1 and v2c so far, GetBulk and a new example script wannabe "Unbeatable" Tic-Tac-Toe Paper-Scissor-Rock ... try to beat it anyway :)
Markos Posted April 27, 2009 Author Posted April 27, 2009 Well, I am sorry to be rude. If you dont want to help, dont post anything please. You obviously didnt read my post. ControlSend without control specified does not behave exactly like send. It just behaves exactly like controlsend witjout control specified. But thanx for your advices.
Authenticity Posted April 27, 2009 Posted April 27, 2009 What you've posted is correct but is not what you expect it to do because ControlSend will do the same (almost, apart from VK_* processing etc..). Take these two snippet for example: $hwnd = WinGetHandle('[CLASS:Notepad]') ControlSend($hwnd, '', '', '123')oÝ÷ Ù©Ýjëh×6$hEdit = ControlGetHandle('[CLASS:Notepad]', '', 'Edit1') ControlSend($hEdit, '', '', '123') The latter is working as expected (assuming on both, the window is minimized or hidden) because the window handle on PostMessage is the edit control's while the former is trying to send to the parent window handle which may not work on your example or ControlSend. Sending to games without controls is implemented using keybd_event() or SendInput() if the game window is the foreground window and implemented using PostMessage() otherwise. In short, the code you posted and ControlSend will produce the input almost identically.
Markos Posted April 27, 2009 Author Posted April 27, 2009 Justo clarify what I wanted to say: Some games dont have ANY controls. For example Guild Wars. $hWnd = WinGetHandle('Guild Wars') ControlSend($hwnd, '', '', 'My Text to send') I am 100 % sure that this works with guild wars on non-active window (my friend told me that i works for WoW too, but I didnt try it). It does not have any controls, so I am not specifying any control as Authenticity said nor I am sending text to active window as enaiman said. I tried to send using Sendmessage or Postmessage directly to the hwnd but it does not work. But it DOES work (100 %) with controlsend (as I wrote in 1st post and you dont believe me). So I believe autoit does "something" jsut before the postmessage, and I dont know what exactly. The autoit source code is huge so its not so easy to find. Thats what I wanted to get help with. So one more time: I am hundred percent sure that sending to GW using ControlSend withou using any control to non-active window works.
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