简体   繁体   English

使用C#和Win API移动屏幕键盘(osk.exe)

[英]Move On-Screen Keyboard (osk.exe) with C# & Win API

I've made this little .ps1 script as it allows me to run C# without using a compiler (directly at least). 我已经制作了这个小的.ps1脚本,因为它允许我在不使用编译器的情况下运行C#(至少直接)。 I'd like to move the "Accessibility On-Screen Keyboard" that opens with cmd /c osk.exe as I can't really use TabTip - the panned touchscreen keyboard on Win8+. 我想移动用cmd /c osk.exe打开的“辅助功能屏幕键盘”,因为我无法真正使用TabTip - Win8 +上的平移触摸屏键盘。

As the On-Screen Keyboard isn't really that pretty like the panned keyboard, I'd like to move the keyboard to a desired location and resize it. 由于屏幕键盘不像平移键盘那么漂亮,我想键盘移动到所需位置调整大小。 I noticed the OSK has a child window ( OSKMainClassDirectUIHWND ), so I went even for that, but no luck. 我注意到OSK有一个子窗口( OSKMainClassDirectUIHWND ),所以我去了,但没有运气。 On the other hand, the same code for a single window works for notepad and correctly places and resizes it. 另一方面,单个窗口的相同代码适用于记事本并正确放置和调整大小。

I put Process.Start() into the if, so that it gave back some feedback, therefore I see it found the child window - that's nice. 我将Process.Start()放入if中,以便它给出一些反馈,因此我看到它找到了子窗口 - 这很好。 BUT , it didn't move it. 但是 ,它没有移动它。

An interesting thing appeared when I pressed Alt+Tab and held the Alt - the OSK window appeared like a grey fullscreen one (metro-like style). 一个有趣的事情出现了,当我按下Alt+Tab并举行Alt -在OSK窗口出现像灰色全屏一个(地铁般的风格)。 I'm not sure if that's an intended behavior for a parent window or not. 我不确定这是否是父窗口的预期行为。

Also, I thought it'd be the window styles' thingy, but no, the styles are almost the same (except two unrelated styles), so I'm without any clue how to continue. 此外,我认为它是窗口样式的东西,但不,样式几乎相同(除了两个不相关的样式),所以我没有任何线索如何继续。 Any ideas? 有任何想法吗?

Code: 码:

$CSsource = @"
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace Win {
    public static class API {
        [DllImport("user32.dll")]
        static extern IntPtr FindWindow(
            string lpClassName,
            string lpWindowName
        );

        [DllImport("user32.dll")]
        public static extern IntPtr FindWindowEx(
            IntPtr parentHwnd,
            IntPtr childAfter,
            string className,
            string windowTitle
        );

        [DllImport("user32.dll")]
        static extern bool ShowWindow(
            IntPtr hWnd,
            int nCmdShow
        );

        [DllImport("user32.dll")]
        static extern bool MoveWindow(
            IntPtr hWnd,
            int X, int Y,
            int Width, int Height,
            bool Repaint
        );

        public static void Move(
            string wClass, string wName,
            string childClass,
            int top, int left,
            int width, int height
        ) {
            IntPtr hwnd = FindWindow(wClass, wName);
            if ((int) hwnd > 0) {
                IntPtr subHwnd;
                if (childClass != String.Empty) {
                    subHwnd = FindWindowEx(hwnd, IntPtr.Zero, childClass, null);
                } else {
                    subHwnd = IntPtr.Zero;
                }

                if ((int) subHwnd > 0) {
                    MoveWindow(subHwnd, left, top, width, height + 50, true);
                    Process.Start("cmd"); //feedback from loop, heh
                } else {
                    MoveWindow(hwnd, left, top, width, height + 50, true);
                }
            }
        }
    }
}
"@

add-type -TypeDefinition $CSsource
#[Win.API]::Move('OSKMainClass', 'On-Screen Keyboard', 'DirectUIHWND', 50, 50, 200, 100)
#[Win.API]::Move('OSKMainClass', 'Accessibility On-Screen Keyboard', 'DirectUIHWND', 50, 50, 200, 100)
[Win.API]::Move('OSKMainClass', 'Accessibility On-Screen Keyboard', '', 50, 50, 200, 100)
[Win.API]::Move('Notepad', 'Untitled - Notepad', '', 50, 50, 200, 100)

OSK window styles: OSK窗口样式:

  • WS_CAPTION WS_CAPTION
  • WS_VISIBLE WS_VISIBLE
  • WS_CLIPSIBLINGS WS_CLIPSIBLINGS
  • WS_CLIPCHILDREN WS_CLIPCHILDREN
  • WS_SYSMENU WS_SYSMENU
  • WS_THICKFRAME WS_THICKFRAME
  • WS_OVERLAPPED WS_OVERLAPPED
  • WS_MINIMIZEBOX WS_MINIMIZEBOX
  • WS_EX_LEFT WS_EX_LEFT
  • WS_EX_LTRREADING WS_EX_LTRREADING
  • WS_EX_TOPMOST WS_EX_TOPMOST
  • WS_EX_WINDOWEDGE WS_EX_WINDOWEDGE
  • WS_EX_APPWINDOW WS_EX_APPWINDOW
  • WS_EX_LAYERED WS_EX_LAYERED
  • WS_EX_NOACTIVATE WS_EX_NOACTIVATE

Notepad window styles: 记事本窗口样式:

above + 高于+

  • WS_RIGHTSCROLLBAR WS_RIGHTSCROLLBAR
  • WS_ACCEPTFILES WS_ACCEPTFILES

OSK has UIAccess="true" in its manifest so it runs at a higher integrity level (slightly above medium). OSK在其清单中具有UIAccess="true" ,因此它以更高的完整性级别运行(略高于中等)。

To interact with it you need to: 要与它进行交互,您需要:

  1. Run your app elevated 升级运行您的应用

or 要么

  1. Put UIAccess="true" in your manifest 将UIAccess =“true”放入清单中
  2. Sign the .exe ( This blog post indicates that you can self sign during testing) 签署.exe( 此博客文章表明您可以在测试期间自签名)
  3. Put the .exe somewhere inside the Program Files folder 将.exe放在Program Files文件夹中的某个位置

You can also try to disable UAC to verify that your lack of UIAccess is the problem. 您还可以尝试禁用UAC以验证您是否缺少UIAccess。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM