不在同一程序内,如何在光标处(当前有焦点的窗体输入框)输入字符
2023-09-11 14:16:54 时间
因测试一个程序,该程序的安卓端执行扫描条码二维码操作,然后服务器端需要在PC当前处于激活状态的窗体的当前光标处显示安卓程序扫描到的条形码。这是博主“小李飞菜刀”的扫描宝服务程序。场景就是苦于手边没有扫描枪,又想测试条码扫描。“小李飞菜刀”同学使用的是 "SendKeys"的“Send”方法。这是同一应用才能有效的办法。如果需要在其他应用的光标处输入字符,就只有使用"SendMessage"的windows api了。经过一番搜索,抄到段代码,测试了一下没有效果,TNND。请围观:
[DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); [DllImport("user32.dll")] static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId); [DllImport("user32.dll")] static extern bool GetGUIThreadInfo(uint idThread, ref GUITHREADINFO lpgui); [StructLayout(LayoutKind.Sequential)] public struct GUITHREADINFO { public int cbSize; public int flags; public IntPtr hwndActive; public IntPtr hwndFocus; public IntPtr hwndCapture; public IntPtr hwndMenuOwner; public IntPtr hwndMoveSize; public IntPtr hwndCaret; public RECT rectCaret; } public static GUITHREADINFO? GetGuiThreadInfo(IntPtr hwnd) { if (hwnd != IntPtr.Zero) { //Mbox.Info(GetTitle(hwnd), "O"); uint threadId = GetWindowThreadProcessId(hwnd, IntPtr.Zero); GUITHREADINFO guiThreadInfo = new GUITHREADINFO(); guiThreadInfo.cbSize = Marshal.SizeOf(guiThreadInfo); if (GetGUIThreadInfo(threadId, ref guiThreadInfo) == false) return null; return guiThreadInfo; } return null; } public static void SendText(string text) { IntPtr hwnd = GetForegroundWindow(); if (String.IsNullOrEmpty(text)) return; Hwindow.GUITHREADINFO? guiInfo = Hwindow.GetGuiThreadInfo(hwnd); if (guiInfo != null) { IntPtr ptr = (IntPtr)guiInfo.Value.hwndCaret; if (ptr != IntPtr.Zero) { for (int i = 0; i < text.Length; i++) { SendMessage(ptr, Message.WM_CHAR, (IntPtr)(int)text[i], IntPtr.Zero); } } } }
这是csdn抄的,原文:C#怎么获得当前屏幕光标的位置,然后在光标的位置上输入想输入数据。
发现RECT没办法被感知,又一番搜索发现是个结构体:
[StructLayout(LayoutKind.Sequential)] public struct RECT { int left; int top; int right; int bottom; }
加上之后可以编译成功。但是没效果,仔细调试下来对方法“SendText”进行了修改。代码的主要思路:用GetForegroundWindow找到焦点窗体,
然后GetWindowThreadProcessId和GetGUIThreadInfo找到含有光标的控件句柄,即GUITHREADINFO中的hwndCaret,然后用该句柄发送消息。
下面贴上修改后有效果的代码:
[DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); [DllImport("user32.dll")] static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId); [DllImport("user32.dll")] static extern bool GetGUIThreadInfo(uint idThread, ref GUITHREADINFO lpgui); [StructLayout(LayoutKind.Sequential)] public struct GUITHREADINFO { public int cbSize; public int flags; public IntPtr hwndActive; public IntPtr hwndFocus; public IntPtr hwndCapture; public IntPtr hwndMenuOwner; public IntPtr hwndMoveSize; public IntPtr hwndCaret; public RECT rectCaret; } [StructLayout(LayoutKind.Sequential)] public struct RECT { int left; int top; int right; int bottom; } public GUITHREADINFO? GetGuiThreadInfo(IntPtr hwnd) { if (hwnd != IntPtr.Zero) { uint threadId = GetWindowThreadProcessId(hwnd, IntPtr.Zero); GUITHREADINFO guiThreadInfo = new GUITHREADINFO(); guiThreadInfo.cbSize = Marshal.SizeOf(guiThreadInfo); if (GetGUIThreadInfo(threadId, ref guiThreadInfo) == false) return null; return guiThreadInfo; } return null; } protected void SendText(string text) { IntPtr hwnd = GetForegroundWindow(); if (String.IsNullOrEmpty(text)) return; GUITHREADINFO? guiInfo = GetGuiThreadInfo(hwnd); if (guiInfo != null) { for (int i = 0; i < text.Length; i++) { SendMessage(guiInfo.Value.hwndFocus, 0x0102, (IntPtr)(int)text[i], IntPtr.Zero); } } }
主要发现 “IntPtr ptr = (IntPtr)guiInfo.Value.hwndCaret;”,这里始终是0.改成: SendMessage(guiInfo.Value.hwndFocus, 0x0102, (IntPtr)(int)text[i], IntPtr.Zero);
hwndFocus字面意思就是当前光标处的句柄。搞定,收工!
相关文章
- php 查找字符串里面中文字符第一次出现的位置,并插入字符串
- linux驱动开发--字符设备:自动创建设备节点
- Linux字符设备驱动
- Objective-C之用C的字符来处理NSString相关的字符替换和拼接的问题
- Java实现 LeetCode 424 替换后的最长重复字符
- MySQL字符数据类型char与varchar的区别
- 可以屏蔽某些输入字符的TextBox
- 【STM32H7教程】第52章 STM32H7的LTDC应用之点阵字体和字符编码(重要)
- textarea限制输入字符demo效果示例(整理)
- iOS swift UITextField 限制输入指定的字符 限制输入字符的长度
- Java基础,字节字符
- 【华为机试真题 Python实现】删除字符串中字符最少字符
- 习题 7.10 写一个函数,输入一行字符,将此字符串中最长的单词输出。
- 习题 8.8 输入一行文字,找出其中大写字母、小写字母、空格、数字以及其他字符各有多少。
- 习题5.9 从键盘上输入一个字符串和一个字符,从该字符串中删除给定的字符。
- C语言实现用指定字符切割字符串并返回数组
- C++中三种风格的字符表示法
- Bufferread有readline()使得字符输入更加方便
- 字符数据的运算及输出
- python 提取字符串中的中文字符