简体   繁体   中英

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). 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+.

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. 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. 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). 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:

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

Notepad window styles:

above +

  • WS_RIGHTSCROLLBAR
  • WS_ACCEPTFILES

OSK has UIAccess="true" in its manifest so it runs at a higher integrity level (slightly above medium).

To interact with it you need to:

  1. Run your app elevated

or

  1. Put UIAccess="true" in your manifest
  2. Sign the .exe ( This blog post indicates that you can self sign during testing)
  3. Put the .exe somewhere inside the Program Files folder

You can also try to disable UAC to verify that your lack of UIAccess is the problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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