【发布时间】:2014-07-11 23:06:33
【问题描述】:
使用 ShellExecuteEx() 启动 osk.exe 后,我想相对于数据输入字段定位键盘窗口,这样它就不会覆盖它们。
调用前如何设置osk的窗口位置?
另外,完成后如何让应用程序隐藏 osk?
【问题讨论】:
-
@Mason:这是 Windows“屏幕键盘”辅助功能小部件。
使用 ShellExecuteEx() 启动 osk.exe 后,我想相对于数据输入字段定位键盘窗口,这样它就不会覆盖它们。
调用前如何设置osk的窗口位置?
另外,完成后如何让应用程序隐藏 osk?
【问题讨论】:
您可以使用FindWindow 使用窗口类“OSKMainClass”来获取窗口句柄,然后在该句柄上使用SetWindowPos 将其定位到您想要的坐标。 (您可能需要使用控件的 ClientToScreen 方法来转换为正确的坐标,但我会让您弄清楚这部分。)
// Off the top of my head - not at a machine that has a Delphi compiler at
// the moment.
var
OSKWnd: HWnd;
begin
OSKWnd := FindWindow(PChar('OSKMainClass'), nil);
if OSKWnd <> 0 then
begin
SetWindowPos(OSKWnd,
HWND_BOTTOM,
NewPos.Left,
NewPos.Top,
NewPos.Width,
NewPos.Height,
0);
end;
end;
部分代码来自与同一主题相关的CodeProject article。我使用 AutoHotKey 的 Window Spy 实用程序获得了窗口类。
注意事项:
Remy Lebeau 在评论中指出,您应该确保使用CreateProcess() 或ShellExecuteEx(),以便在调用FindWindow() 之前取回可以传递给WaitForInputIdle() 的进程句柄。否则,可能会在 OSK 创建窗口之前调用FindWindow()。
mghie 在评论中指出,他可以让它工作的唯一方法是以管理员身份运行应用程序;否则对 SetWindowPos() 的调用会导致“拒绝访问 (5)”。
【讨论】:
CreateProcess() 或ShellExecuteEx() 而不是ShellExecute(),以便在调用FindWindow() 之前为您提供一个可以传递给WaitForInputIdle() 的进程HANDLE。否则你可能会在 OSK 创建它的窗口之前调用它。
如上所述,我不能移动窗口。 使用 Win32 命令,SetWindow 或 MoveWindow 不适用于屏幕键盘。 它仅在以 admin 权限 运行 exe 时起作用。
我认为这不是一个好的解决方案。 我找到了另一个解决方案。 请通过这个。 尝试使用注册表值后,它运行良好,我可以在我的应用程序中移动屏幕键盘
试试
{
RegistryKey myKey = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Osk", true);
myKey.SetValue("WindowLeft", oskLeft, RegistryValueKind.DWord);
myKey.SetValue("WindowTop", oskTop, RegistryValueKind.DWord);
}
catch
{
//Log the error
}
【讨论】: