Переместить экранную клавиатуру (osk.exe) с C# и Win API

Я сделал это немного .ps1 скрипт, так как он позволяет мне запускать C# без использования компилятора (по крайней мере, напрямую). Я хочу переместить "Экранную клавиатуру специальных возможностей", которая открывается cmd /c osk.exe как я не могу использовать TabTip - панорамированная сенсорная клавиатура на Win8+.

Поскольку экранная клавиатура на самом деле не очень похожа на панорамированную клавиатуру, я бы хотел переместить клавиатуру в нужное место и изменить ее размер. Я заметил, что в ОСК есть дочернее окно (OSKMainClassDirectUIHWND), поэтому я пошел даже на это, но не повезло. С другой стороны, тот же код для одного окна работает для блокнота и правильно размещает и изменяет его размер.

я кладу Process.Start() в if, так что он дал некоторую обратную связь, поэтому я вижу, что нашел дочернее окно - это хорошо. НО это не двигало это.

Интересная вещь появилась, когда я нажал Alt+Tab и провел Alt - окно OSK выглядело как серое полноэкранное (в стиле metro). Я не уверен, является ли это предполагаемым поведением для родительского окна или нет.

Кроме того, я подумал, что это будут вещи из оконных стилей, но нет, стили почти одинаковы (за исключением двух не связанных между собой стилей), поэтому я понятия не имею, как продолжить. Есть идеи?

Код:

$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:

  • 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

Стили окна блокнота:

выше +

  • WS_RIGHTSCROLLBAR
  • WS_ACCEPTFILES

1 ответ

Решение

ОСК имеет UIAccess="true" в своем манифесте, поэтому он работает на более высоком уровне целостности (чуть выше среднего).

Для взаимодействия с ним необходимо:

  1. Запустите ваше приложение с повышенными правами

или же

  1. Поместите UIAccess="true" в манифест
  2. Подпишите файл.exe ( это сообщение в блоге означает, что вы можете самостоятельно подписаться во время тестирования)
  3. Поместите.exe куда-нибудь в папку Program Files

Вы также можете попытаться отключить UAC, чтобы убедиться, что проблема заключается в отсутствии UIAccess.

Другие вопросы по тегам