Переместить экранную клавиатуру (osk.exe) с C# и Win API
Я сделал это немного .ps1
скрипт, так как он позволяет мне запускать C# без использования компилятора (по крайней мере, напрямую). Я хочу переместить "Экранную клавиатуру специальных возможностей", которая открывается cmd /c osk.exe
как я не могу использовать TabTip
- панорамированная сенсорная клавиатура на Win8+.
Поскольку экранная клавиатура на самом деле не очень похожа на панорамированную клавиатуру, я бы хотел переместить клавиатуру в нужное место и изменить ее размер. Я заметил, что в ОСК есть дочернее окно (OSKMainClass
→ DirectUIHWND
), поэтому я пошел даже на это, но не повезло. С другой стороны, тот же код для одного окна работает для блокнота и правильно размещает и изменяет его размер.
я кладу 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"
в своем манифесте, поэтому он работает на более высоком уровне целостности (чуть выше среднего).
Для взаимодействия с ним необходимо:
- Запустите ваше приложение с повышенными правами
или же
- Поместите UIAccess="true" в манифест
- Подпишите файл.exe ( это сообщение в блоге означает, что вы можете самостоятельно подписаться во время тестирования)
- Поместите.exe куда-нибудь в папку Program Files
Вы также можете попытаться отключить UAC, чтобы убедиться, что проблема заключается в отсутствии UIAccess.