不在同一程序内,如何在光标处(当前有焦点的窗体输入框)输入字符
2016-08-21 23:26
495 查看
因测试一个程序,该程序的安卓端执行扫描条码二维码操作,然后服务器端需要在PC当前处于激活状态的窗体的当前光标处显示安卓程序扫描到的条形码。这是博主“小李飞菜刀”的扫描宝服务程序。场景就是苦于手边没有扫描枪,又想测试条码扫描。“小李飞菜刀”同学使用的是 "SendKeys"的“Send”方法。这是同一应用才能有效的办法。如果需要在其他应用的光标处输入字符,就只有使用"SendMessage"的windows api了。经过一番搜索,抄到段代码,测试了一下没有效果,TNND。请围观:
这是csdn抄的,原文:C#怎么获得当前屏幕光标的位置,然后在光标的位置上输入想输入数据。
发现RECT没办法被感知,又一番搜索发现是个结构体:
加上之后可以编译成功。但是没效果,仔细调试下来对方法“SendText”进行了修改。代码的主要思路:用GetForegroundWindow找到焦点窗体,
然后GetWindowThreadProcessId和GetGUIThreadInfo找到含有光标的控件句柄,即GUITHREADINFO中的hwndCaret,然后用该句柄发送消息。
下面贴上修改后有效果的代码:
主要发现 “IntPtr ptr = (IntPtr)guiInfo.Value.hwndCaret;”,这里始终是0.改成: SendMessage(guiInfo.Value.hwndFocus, 0x0102, (IntPtr)(int)text[i], IntPtr.Zero);
hwndFocus字面意思就是当前光标处的句柄。搞定,收工!
[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字面意思就是当前光标处的句柄。搞定,收工!
相关文章推荐
- ime-焦点不在输入框,则切换为默认的英文输入法状态,激活游戏中快捷键
- 在窗体上放置saveFileDialog、openFileDialog两个控件。实现功能:1)程序运行时,在文本框(注意文本框多行、带垂直滚动条)中输入汉字、字符等,单击保存按钮,即可将文本框中内容保
- 搜索栏和网页里的输入框无法输入字符连光标都不显示故障的解决
- C#让TopMost窗体弹出并置顶层但不获取当前输入焦点的终极办法
- 如何指定输入框能输入的字符
- URL输入框不是Edit Text,是Searchable。如何输入字符?调用Robotium的什么函数?
- 如何向当前的html文档输入一段字符
- 解决js函数replace禁止输入框输入非法字符,光标回到文字最后问题(兼容ie、谷歌)
- 如何得到 TextBox 或 richTextBox 的当前输入光标的屏幕坐标
- URL输入框不是Edit Text,是Searchable。如何输入字符?调用Robotium的什么函数?
- C#让TopMost窗体弹出并置顶层但不获取当前输入焦点的终极办法
- 利用栈的基本操作编写一个行编辑程序,当前一个字符有误时,输入#消除,当前面一行有误时,输入@消除前面行的字符序列
- 解决js函数replace禁止输入框输入非法字符,光标回到文字最后问题
- 记录:MUI框架中如何在多个input输入框失去焦点时获取当前input的value值
- Delphi MDI程序 父窗体如何调用当前活动子窗体的函数/过程
- 试利用栈的基本操作编写一个行编辑程序,当前一个字符有误时,输入#消除,当前面一行有误时,输入@消除前面行的字符序列
- C#让TopMost窗体弹出并置顶层但不获取当前输入焦点的终极办法
- 如何将光标在一进入页面就定位在你所想输入的那个输入框里面?
- .Net - C# 如何判断程序里某个窗体是否为Windows的当前活动窗体?(附代码)
- 提问:如何控制控制台程序的输入/输出焦点的位置