ANSI code: Yes, it works in not Unicode aware applications I tried so far. The only difference I found is that sending "0008" in MS Word and Notepad works as BackSpace (deleting characters to left), but in MultiEdit it produces an unknown character placeholder, in NotePad2: the bold, inverted letters "BS". It probably has nothing to do with ANSI- or Unicode, just how an application handles non-printable characters. I just hoped a simulated Unicode hotstring could contain the right number of BackSpace characters encoded in the replacement string, but this does not seem to work universally.
In the mean time, I tried SendInputU in my keyboard remapping scripts. It works as expected, but a little too slow, due to the 20 DllCalls for each character plus one DllCall for send. I made the following modifications for a 5-fold speedup (in the cost of readability)
SendInputU( 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%
}
If only a single Unicode character is to be sent (like in keyboard remapping) a further factor of two speedup is possible (and desirable). The data structure is set up in the beginning of the script just once with a single call of SendUinit(), and subsequent SendU(Unicode) calls just overwrite the necessary part.
SendUinit()
{
Global SendUbuf, SendU4, SendU6
DllCall("LoadLibrary", "str", "ntoskrnl.exe")
SendU4 := 4 << 16 ; KEYEVENTF_UNICODE
SendU6 := 6 << 16 ; KEYEVENTF_KEYUP|KEYEVENTF_UNICODE
VarSetCapacity( SendUbuf, 56, 0 )
DllCall("RtlFillMemory", "uint",&SendUbuf, "uint",1, "uint", 1)
DllCall("RtlFillMemory", "uint",&SendUbuf+28, "uint",1, "uint", 1)
}
SendU( p_uchar ) ; 3 DllCalls, needs one prior call to SendUinit()
{
Global SendUbuf, SendU4, SendU6
DllCall("ntoskrnl.exe\RtlFillMemoryUlong", "uint",&SendUbuf+6, "uint",4, "uint", p_uchar | SendU4)
DllCall("ntoskrnl.exe\RtlFillMemoryUlong", "uint",&SendUbuf+34, "uint",4, "uint", p_uchar | SendU6)
Return DllCall( "SendInput", "uint", 2, "uint", &SendUbuf, "int", 28 )
}