LAttilaD Posted September 25, 2008 Share Posted September 25, 2008 Please help me to translate a function from Autohotkey to Autoit 3. I found the original function in an Autohotkey forum and used it for a long time for my keyboard remapper. It is called as uni(code), where code is one or more Unicode character code(s) in hex, for example, uni("0171"). The purpose is to send the text to the keyboard (in the example, a Hungarian accented letter).I would like to use this code in Autoit, but my knowledge isn't enough. Would somebody be so kind to help me to translate it?Thank you in advance!uni( p_text ); 4 DllCalls/char + 1, reduced from 20/char + 1 { event_count := ( StrLen(p_text)//4 )*2 VarSetCapacity( events, 28*event_count, 0 ) base = 0 Loop % event_count//2 { StringMid code, p_text, 4*A_Index-3, 4 code = 0x4%code% DllCall("RtlFillMemory", "uint", &events + base, "uint",1, "uint", 1) DllCall("ntoskrnl.exe\RtlFillMemoryUlong", "uint",&events+base+6, "uint",4, "uint",code) base += 28 DllCall("RtlFillMemory", "uint", &events + base, "uint",1, "uint", 1) DllCall("ntoskrnl.exe\RtlFillMemoryUlong", "uint",&events+base+6, "uint",4, "uint",code|(2<<16)) base += 28 } result := DllCall( "SendInput", "uint", event_count, "uint", &events, "int", 28 ) if ( ErrorLevel or result < event_count ) MsgBox SendInput failed`nErrorLevel = %ErrorLevel%`n%result% events of %event_count% } Láng Attila D., LAttilaD.org Link to comment Share on other sites More sharing options...
LAttilaD Posted September 29, 2008 Author Share Posted September 29, 2008 Meanwhile, I've created a translation. I did my best, but it won't work, it always returns with @error = 2. Can anybody help me what's wrong? func uni($code) $eventcount=2 $events=$empty $base=0 $code=dec($code) DllCall("", "", "RtlFillMemory", "uint", ptr($events+$base), "uint", 1, "uint", 1) DllCall("ntoskrnl.exe", "", "RtlFillMemoryUlong", "uint", ptr($events+$base+6), "uint", 4, "uint", $code) $base+=28 DllCall("", "", "RtlFillMemory", "uint", ptr($events+$base), "uint", 1, "uint", 1) DllCall("ntoskrnl.exe", "", "RtlFillMemoryUlong", "uint", ptr($events+$base+6), "uint", 4, "uint", bitor($code, bitshift(2, -4))) $base+=28 $result=DllCall("", "", "SendInput", "uint", $eventcount, "uint", ptr($events), "int", 28) if @Error or $result < $eventcount then MsgBox("", "", @error&@crlf&$result) endif endfunc Note that $empty is a global containing for $a=1 to 2*28 $empty&=chr(0) next Many thanks for any help! Láng Attila D., LAttilaD.org Link to comment Share on other sites More sharing options...
Zedna Posted September 29, 2008 Share Posted September 29, 2008 VarSetCapacity( events, 28*event_count, 0 ) $events = _MemGlobalAlloc(28*$event_count, 2 ) you need #Include <Memory.au3> Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
LAttilaD Posted September 29, 2008 Author Share Posted September 29, 2008 Thanks for the help, Zedna. I've added the modification. However, the function still returns with an error. Láng Attila D., LAttilaD.org Link to comment Share on other sites More sharing options...
Zedna Posted September 29, 2008 Share Posted September 29, 2008 Thanks for the help, Zedna. I've added the modification. However, the function still returns with an error.Your translation is still wrong.- DllCall("", "", "RtlFillMemory", "uint", ptr($events+$base), "uint", 1, "uint", 1) --> first parameter is mandatory as far as I know- SendInput --> replace it by Send() Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
LAttilaD Posted September 29, 2008 Author Share Posted September 29, 2008 Your translation is still wrong.Just an attempt. I'm a total newbie in dll calling.- DllCall("", "", "RtlFillMemory", "uint", ptr($events+$base), "uint", 1, "uint", 1) --> first parameter is mandatory as far as I knowOkay, it may be, but what should it be?- SendInput --> replace it by Send()If I send the keys with Send, what does the rest of the function do? >_< Láng Attila D., LAttilaD.org Link to comment Share on other sites More sharing options...
Zedna Posted September 29, 2008 Share Posted September 29, 2008 (edited) Okay, it may be, but what should it be?Maybe "Kernel32.dll"If I send the keys with Send, what does the rest of the function do? >_< Translation before Send()SendInput doesn't exists in neither in AutoIt nor in Windows system DLLs as far as I know. Edited September 29, 2008 by Zedna Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
LAttilaD Posted September 29, 2008 Author Share Posted September 29, 2008 Update: After some googling, I've entered the missing dll names and specified a return type for the last dll call. Now the code looks like below. It doesn't report any error but it doesn't send any key! Heeeelp... #Include <Memory.au3> hotkeyset("{f1}", "uu") while 1 sleep(1000) wend func uu() uni("0126") exit endfunc while 1 sleep(1000) wend func uni($code) $eventcount=2 $events = _MemGlobalAlloc(28*$eventcount, 2 ) $base=0 $code=dec($code) DllCall("kernel32.dll", "", "RtlFillMemory", "uint", ptr($events+$base), "uint", 1, "uint", 1) DllCall("ntoskrnl.exe", "", "RtlFillMemoryUlong", "uint", ptr($events+$base+6), "uint", 4, "uint", $code) $base+=28 DllCall("kernel32.dll", "", "RtlFillMemory", "uint", ptr($events+$base), "uint", 1, "uint", 1) DllCall("ntoskrnl.exe", "", "RtlFillMemoryUlong", "uint", ptr($events+$base+6), "uint", 4, "uint", bitor($code, bitshift(2, -4))) $base+=28 $result=DllCall("user32.dll", "uint", "SendInput", "uint", $eventcount, "uint", ptr($events), "int", 28) if @Error or $result < $eventcount then MsgBox("", "", @error&@crlf&$result) endif endfunc Láng Attila D., LAttilaD.org Link to comment Share on other sites More sharing options...
LAttilaD Posted September 29, 2008 Author Share Posted September 29, 2008 Maybe "Kernel32.dll"Yes, it is; both of us were posting at the same time.Translation before Send()SendInput doesn't exists in neither in AutoIt nor in Windows system DLLs as far as I know.OK, I've remarked the call for SendInput and added a send(chrw($code)). Now I get response: a letter H appears in MS Word. Unfortunately, U+0126 is a H with a stroke, so the diacritic has been removed. Láng Attila D., LAttilaD.org Link to comment Share on other sites More sharing options...
Zedna Posted September 29, 2008 Share Posted September 29, 2008 (edited) Update: After some googling, I've entered the missing dll names and specified a return type for the last dll call. Now the code looks like below. It doesn't report any error – but it doesn't send any key! Heeeelp... 1) Function ptr() doesn't exists 2) try to call _GetLastErrorMessage() after each DllCall() to see "silent errors" example: DllCall("kernel32.dll", "", "RtlFillMemory", "uint", ptr($events+$base), "uint", 1, "uint", 1) If @error Then _GetLastErrorMessage ("RtlFillMemory - error after DllCall 1") Func _GetLastErrorMessage ($DisplayMsgBox = "") Local $ret, $s Local $p = DllStructCreate("char[4096]") Local Const $FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000 If @error Then Return "" $ret = DllCall("Kernel32.dll", "int", "GetLastError") $ret = DllCall("kernel32.dll", "int", "FormatMessage", _ "int", $FORMAT_MESSAGE_FROM_SYSTEM, _ "ptr", 0, _ "int", $ret[0], _ "int", 0, _ "ptr", DllStructGetPtr($p), _ "int", 4096, _ "ptr", 0) $s = DllStructGetData($p, 1) $p = 0 If $DisplayMsgBox <> "" Then MsgBox(0, "_GetLastErrorMessage", $DisplayMsgBox & @CRLF & $s) Return $s EndFunc ;==>_GetLastErrorMessage Edited September 29, 2008 by Zedna Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
LAttilaD Posted September 29, 2008 Author Share Posted September 29, 2008 1) Function ptr() doesn't existsOuch. Doesn't it? I found it in the Autoit documentation, and Autoit never said I'm calling an undefined function. 2) try to call _GetLastErrorMessage() after each DllCall() to see "silent errors"Here you are: I've getting errors after all dll calls. (Not including SendInput, which is in a remark now.) Is @error reset to zero between each call? Or am I calling the functions as wrongly as it seems? I reckon I am. Láng Attila D., LAttilaD.org Link to comment Share on other sites More sharing options...
Zedna Posted September 29, 2008 Share Posted September 29, 2008 (edited) Ouch. Doesn't it? I found it in the Autoit documentation, and Autoit never said I'm calling an undefined function. Sorry my mistake, Ptr() exists but I think you can't use it this way - but I'm not sure about it. Edited September 29, 2008 by Zedna Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
LAttilaD Posted September 29, 2008 Author Share Posted September 29, 2008 Sorry my mistake, Ptr() exists but I think you can't use it this way - but I'm not sure about it.Meanwhile, I've removed ptr calls and added *'s after the preceding type declarators, as the documentation suggests it. Unfortunately, nothing changes. There are four error reports, and a diacriticless letter H appears. Láng Attila D., LAttilaD.org Link to comment Share on other sites More sharing options...
ProgAndy Posted September 29, 2008 Share Posted September 29, 2008 Some Time Ago, i posted a SendInput for Unicode on Autoit.de Here it is: expandcollapse popup#include <WinAPI.au3> $process = Run("notepad.exe") ;~ $NotepadHWND = "Untitled - " ; EN $NotepadHWND = "Unbenannt - " ; DE WinActivate($NotepadHWND) WinWaitActive($NotepadHWND) _SendUnicode(ChrW(0x398) & ChrW(0x3B8)) ;~ InputBox("It should be:","It should be this char: Copy it to Notpad and see, that it is accepted",$text) ; Prog@ndy :) Func _SendUnicode($text) Local Const $tagINPUT_Keyboard = "DWORD type; ushort wVk; ushort wScan; DWORD dwFlags; DWORD time; ULONG_PTR dwExtraInfo;dword;ULONG_PTR;" Local Const $INPUT_KEYBOARD = 1 Local Const $KEYEVENTF_UNICODE = 0x4 Local Const $KEYEVENTF_KEYUP = 0x2 Local $tinp = DllStructCreate($tagINPUT_Keyboard & $tagINPUT_Keyboard) Local $sendDLL = DllOpen("user32.dll") $text = StringSplit($text, "") Local $ret For $i = 1 To $text[0] DllStructSetData($tinp, 1, $INPUT_KEYBOARD) DllStructSetData($tinp, 7, $INPUT_KEYBOARD) DllStructSetData($tinp, 2, 0) DllStructSetData($tinp, 8, 0) DllStructSetData($tinp, 3, AscW($text[$i])) DllStructSetData($tinp, 9, AscW($text[$i])) DllStructSetData($tinp, 4, $KEYEVENTF_UNICODE) DllStructSetData($tinp, 10, BitOR($KEYEVENTF_KEYUP, $KEYEVENTF_UNICODE)) DllStructSetData($tinp, 5, 0) DllStructSetData($tinp, 11, 0) DllStructSetData($tinp, 6, 0) DllStructSetData($tinp, 12, 0) $ret = DllCall($sendDLL, "uint", "SendInput", "uint", 2, "ptr", DllStructGetPtr($tinp), "int", DllStructGetSize($tinp)/2) Next DllClose($sendDLL) EndFunc ;==>_SendUnicode *GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes Link to comment Share on other sites More sharing options...
LAttilaD Posted September 29, 2008 Author Share Posted September 29, 2008 (edited) Oh… ProgAndy, it looks like you solved my problem.The real problem was that I wanted to remap keys with something likehotkeyset("g", "proc") func proc() uni("0430") endfuncwhere uni is a function to send a unicode character. I tried two ways. Send("{asc …}") is incompatible with my numpad mouse script and, additionally, doesn't work in certain editors. Clipput() and send("^v") works properly, but if I keep the key pressed, it sometimes produces unwanted results (random keystrokes appear, dialog boxes open and so on). Then, I tried to deactivate the hotkey before processing the send and activate it again after. This is good, but results in things like aaaaaaaaaaagaaaaaaaaaagaaaaaaaaaaaag… where a is the character wanted and g is the one originally given by the hotkey. The best result I could get was to assign the hotkey to a dead function (func dead() endfunc) before sending the key and reassign after. But the keys are obviously slower than undefined ones.I tested your function for several keys in a short time, and I didn't see any problem. I wonder how could I miss this function in the forum – I was searching for ages before asking for help.Now, I believe I can write my key mapper. May I give you a credit? Edited September 29, 2008 by LAttilaD Láng Attila D., LAttilaD.org 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