c# - Simulate input of non-ASCII characters -
i looking way simulate input of non-ascii characters (e.g. cjk characters) using windows apis. keybd_event
or sendinput
won't work because input characters may not valid virtual keys.
what want
i want simulate input of unicode character(s) using windows api, without needing write ime or tsf provider.
what i've tried
i've tried send wm_ime_char
message focused window:
// gets focused input control (if any) internal static intptr getactivewindowcontrol() { intptr activewin = getforegroundwindow(); if (activewin == intptr.zero) { return intptr.zero; } uint threadid = getwindowthreadprocessid(activewin, intptr.zero); guithreadinfo guithreadinfo = new guithreadinfo(); guithreadinfo.cbsize = marshal.sizeof(guithreadinfo); getguithreadinfo(threadid, ref guithreadinfo); if (guithreadinfo.hwndfocus == intptr.zero) { return activewin; // example: console } else { return guithreadinfo.hwndfocus; } } internal void simulateinput() { // encoding.default on computer cp950 (big5) byte[] b = encoding.default.getbytes("我"); // 1 single chinese character intptr activehwnd = getactivewindowcontrol(); if (activehwnd != intptr.zero) { int ch = 0; (int = 0; < b.length; i++) // assumed b has <=2 elements { ch = (ch << 8) | b[i]; } uint wm_ime_char = 0x0286; sendmessage(activehwnd, wm_ime_char, (intptr)ch, (intptr)0) } }
problem encountered
so far code seems have worked quite in cases, however doesn't work on notepad++. instead of desired character, got garbage input instead.
further investigation using spy++ shows when using ime input, there isn't wm_ime_char
message sent notepad++ edit window. wm_ime_startcomposition
, wm_ime_endcomposition
, wm_ime_request
, wm_ime_notify
, wm_ime_setcontext
. seems notepad++ handles ime input different other programs. (also believe there exist more programs acts similar notepad++, haven't found 1 yet.)
also, code not work if character(s) outside default character encoding of target operating system (e.g. simplified chinese not work big5).
things want prevent
- putting character(s) in clipboard , invoking paste on target window
additional information
i realize windows 7 tablet pc input panel perform text insertion nicely (even works on gtk+ applications). tried emulate sends appears repeat last ime-entered character. doesn't work appears same seen in spy++.
sendmessage(active, wm_ime_startcomposition, (intptr)0, (intptr)0); //sendmessage(active, wm_ime_composition, (intptr)ch, (intptr)0x0800); sendmessage(active, wm_ime_composition, (intptr)0xa7da, (intptr)0x0800); sendmessage(active, wm_ime_notify, (intptr)0x010d, (intptr)0); sendmessage(active, wm_ime_endcomposition, (intptr)0, (intptr)0); sendmessage(active, wm_ime_notify, (intptr)0x010e, (intptr)0);
i've found sendkeys
class in .net. used in application?
after bit more searching, turned out sendinput
could used send unicode input keyeventf_unicode
.
now code looks (inputsender
own class):
internal static void inputstring(string str) { char[] chars = str.tochararray(); inputsender.input[] inputs = new inputsender.input[chars.length * 2]; (int = 0; < chars.length; i++) { ushort ch = (ushort)chars[i]; // key down inputs[i * 2].type = inputsender.inputtype.keyboard; inputs[i * 2].ki.wscan = ch; inputs[i * 2].ki.dwflags = inputsender.keyboardeventflags.unicode; // key inputs[i * 2 + 1].type = inputsender.inputtype.keyboard; inputs[i * 2 + 1].ki.wscan = ch; inputs[i * 2 + 1].ki.dwflags = inputsender.keyboardeventflags.unicode | inputsender.keyboardeventflags.keyup; } inputsender.sendinput(inputs); }
but turned out doesn't work quite gtk+ programs. bit searching shows should fixed while ago programs uses older version of gtk+ may still encounter problems. tried newest gtk+ geany newest gtk+ fine, while inkscape refuses interpret input.
anyway if ignore problem of gtk+, using sendinput
sufficient (and should better wm_ime_char
). haven't tried this answer fixes gtk+'s problem because don't know how , believe not feasible.
Comments
Post a Comment