gpt4 book ai didi

c# - 模拟非ASCII字符的输入

转载 作者:可可西里 更新时间:2023-11-01 10:26:28 27 4
gpt4 key购买 nike

我正在寻找一种使用 Windows API 模拟非 ASCII 字符(例如 CJK 字符)输入的方法。 keybd_eventSendInput 不会 工作,因为输入的字符可能不是有效的虚拟键。

我想要什么

我想使用 Windows API 模拟 Unicode 字符的输入,而不需要编写 IME 或 TSF 提供程序。

我尝试过的

我已尝试将 WM_IME_CHAR 消息发送到当前获得焦点的窗口:

// Gets the currently 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 my computer is CP950 (Big5)
byte[] b = Encoding.Default.GetBytes("我"); // one single Chinese character
IntPtr activeHwnd = GetActiveWindowControl();
if (activeHwnd != IntPtr.Zero)
{
int ch = 0;
for (int i = 0; i < 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)
}
}

遇到的问题

到目前为止,这段代码似乎在大多数情况下都运行良好,但是它不适用于 Notepad++。我得到的不是所需的字符,而是垃圾输入。

使用 Spy++ 的进一步调查表明,当使用 IME 输入时,没有 WM_IME_CHAR 消息发送到 Notepad++ 编辑窗口。我得到的是 WM_IME_STARTCOMPOSITIONWM_IME_ENDCOMPOSITIONWM_IME_REQUESTWM_IME_NOTIFYWM_IME_SETCONTEXT。 Notepad++ 处理 IME 输入的方式似乎与其他程序不同。 (而且我相信还有更多类似于 Notepad++ 的程序,但我还没有找到。)

此外,如果字符不在目标操作系统的默认字符编码范围内(例如,简体中文不适用于 Big5),则此代码将不起作用。

我想阻止的事情

  • 将字符放入剪贴板并调用粘贴到目标窗口

附加信息

我发现 Windows 7 Tablet PC 输入面板可以很好地执行文本插入(甚至适用于 GTK+ 应用程序)。我试图模拟它发送的内容,但它似乎只是重复最后一个 IME 输入的字符。即使看起来与 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);

我还找到了一个 SendKeys .NET 中的类。它可以用在我的应用程序中吗?

最佳答案

经过更多的搜索,结果是 SendInput 实际上可以用于发送带 KEYEVENTF_UNICODE 的 Unicode 输入。 .

现在我的代码看起来像这样(InputSender 是我自己的类):

internal static void InputString(string str)
{
char[] chars = str.ToCharArray();
InputSender.Input[] inputs = new InputSender.Input[chars.Length * 2];

for (int i = 0; i < 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 up
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);
}

但事实证明,它doesn't work quite well with GTK+ programs .一点搜索表明它 should be fixed a while ago但是使用旧版本 GTK+ 的程序可能仍会遇到问题。刚用最新的 GTK+ 和 Geany 尝试了最新的 GTK+ 没问题,而 Inkscape 拒绝解释输入。

无论如何,如果我忽略 GTK+ 的问题,使用 SendInput 就足够了(而且应该比 WM_IME_CHAR 更好)。我没试过this answer which fixes GTK+'s problem因为我不知道怎么做,认为不可行。

关于c# - 模拟非ASCII字符的输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15743053/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com