Pinvoke SetFocus 到特定控件
Posted
技术标签:
【中文标题】Pinvoke SetFocus 到特定控件【英文标题】:Pinvoke SetFocus to a particular control 【发布时间】:2012-02-29 16:37:22 【问题描述】:简单的问题:是否可以将焦点设置在另一个应用程序的文本框上(使用它的 ClassName)。我将窗口作为“intptr”等,但只需要一些关于哪些功能/API 可用的指导!
问题是,我使用 SetForegroundWindow API 来获取窗口焦点,但它不允许我发送 Ctrl+L 键来关注文本框!
任何帮助都会很棒!
【问题讨论】:
只是几个问题:您是否使用 SendKeys 来执行此操作?您确定 Ctrl+L 将您带到文本框,而不是 Alt+L? 【参考方案1】:...据我回忆,这是我必须用来完成这项工作的代码 - 在我的应用程序和较新的 Windows 等上运行良好。
void SetFocus(IntPtr hwndTarget, string childClassName)
// hwndTarget is the other app's main window
// ...
IntPtr targetThreadID = WindowsAPI.GetWindowThreadProcessId(hwndTarget, IntPtr.Zero); //target thread id
IntPtr myThreadID = WindowsAPI.GetCurrentThread(); // calling thread id, our thread id
try
bool lRet = WindowsAPI.AttachThreadInput(myThreadID, targetThreadID, -1); // attach current thread id to target window
// if it's not already in the foreground...
lRet = WindowsAPI.BringWindowToTop(hwndTarget);
WindowsAPI.SetForegroundWindow(hwndTarget);
// if you know the child win class name do something like this (enumerate windows using Win API again)...
var hwndChild = EnumAllWindows(hwndTarget, childClassName).FirstOrDefault();
if (hwndChild == IntPtr.Zero)
// or use keyboard etc. to focus, i.e. send keys/input...
// SendInput (...);
return;
// you can use also the edit control's hwnd or some child window (of target) here
WindowsAPI.SetFocus(hwndChild); // hwndTarget);
finally
bool lRet = WindowsAPI.AttachThreadInput(myThreadID, targetThreadID, 0); //detach from foreground window
...所以一些类似的东西(它按照正确的顺序执行您需要的操作,不要忘记分离等 - 但您需要根据您的特定条件调整它,控制/编辑 hwnd 等. - 你可能还有其他与目标窗口/应用程序相关的问题,这适用于大多数情况,但并非在所有情况下,这是一个很长的故事,正如我所说的取决于你的具体情况),
(我相信 WindowsAPI 是典型的 PInvoke 包装器) 基本上你需要附加到另一个线程进行“输入”操作, 我相信这是官方的解释“这也允许线程共享它们的输入状态,因此它们可以调用 SetFocus 函数将键盘焦点设置到不同线程的窗口。” 谷歌 AttachThreadInput 获取更多信息(了解原因),它也经常与 SetFocus 和其他输入/键盘操作相关联。 此外,自动化 API 可以按照建议提供帮助 - 这是“最干净”的方式 - 但取决于目标应用程序是否正确地公开和处理它 - 对于大多数应用程序来说仍然“不存在”,不一致等 - 如果你想处理你的“自己的应用程序”,那么你需要问自己什么是最好的场景等等。 希望这会有所帮助
注意:必须有十几个指向类似解决方案的链接(以及在 SO 上),因为这是众所周知的事情,但我找不到正确的链接
编辑:我为您的具体案例和儿童关注点做了一些澄清编辑(2): 该代码是此规范的示例。案例并基于工作代码 - 但可能需要测试和解决一些细节(这似乎超出了这个问题的范围),例如...WindowsAPI 持有 Windows API 和本机调用的 PInvoke 签名(类似于 MS.Win32.UnsafeNativeMethods)并且它是一个静态类(参见该类或 http://pinvoke.net/ - 也称为 Accessing Microsoft.Win32.UnsafeNativeMethods?),应命名为 (Safe/Unsafe)NativeMethods (http://msdn.microsoft.com/en-us/library/ms182161.aspx) - 也参见 @ 987654324@(IntPtr 有点“旧”风格)EnumAllWindows 使用 EnumChildWindows 和 GetClassName Win API(我猜这是另一个问题)并且需要一个包装器方法才能有用(它EnumAllWindows 是 - 它只是通过窗口递归地枚举检查类名)。
【讨论】:
对于IntPtr targetThreadID = WindowsAPI.GetWindowThreadProcessId(w, IntPtr.Zero);
行,我得到了一个重载方法。 w 是:IntPtr w = FindWindow("Window Name", null);"
请查看编辑后的答案 - 它是“[DllImport("user32.dll")] public static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);”,该 API 的简化版本(应该是(HandleRef,out)——你可以为同一个 API 有不同的签名,不同的故事)——你需要解决一些细节,这意味着更多的“伪”代码,但应该回答核心点(而且很漂亮如果您提供自己的 Enum 方法,很多工作都“原样”)以上是关于Pinvoke SetFocus 到特定控件的主要内容,如果未能解决你的问题,请参考以下文章
如何在不丢失setfocus的情况下将光标设置到文本框的末尾?