Need to determine the size (width, height) and position (left, top) of TabTip.exe (virtual keyboard) on windows 10?
The task is to move the panel, on which all the components are located, so that the input field to which the input focus was transferred was above the virtual keyboard.
Working with Windows 10 is not under the admin, but the compiled project is run as administrator!
The following solutions work in Windows 7,Windows 8, in Windows 10 they do not work:
uses ..., Winapi.Windows, Winapi.Dwmapi
...
procedure TForm1.SizeKeyboard;
var KeyBoardRect: TRect;
KeyboardWindow : HWND;
begin
KeyboardWindow := FindWindow('IPTip_Main_Window', nil);
if (KeyboardWindow <> 0) then
KeyBoardRect := GetRect1(KeyboardWindow);
...
end;
...
function TForm1.GetRect1(AKeyboardWindow : HWND): Trect;
var KeyBoardRect: Trect;
begin
GetWindowRect(AKeyboardWindow, KeyBoardRect);
Result := KeyBoardRect;
end;
function TForm1.GetRect2(AKeyboardWindow : HWND): Trect;
var KeyBoardRect: Trect;
begin
DwmGetWindowAttribute(AKeyboardWindow, DWMWA_EXTENDED_FRAME_BOUNDS, @KeyBoardRect, sizeof(KeyBoardRect));
Result := KeyBoardRect;
end;
but
The Windows 10 touch keyboard is a UWP application. UWP applications do not have native windows, and can not be referenced through HWNDs. You can use UI Automation to get the bounding rectangle of the touch keyboard Get size of Windows 10 touch keyboard window!
https://msdn.microsoft.com/en-us/library/windows/desktop/ee671425(v=vs.85).aspx!
Loaded type library - UIAutomationClient interfaces IUIAutomation, IUIAutomationElement (UIAutomationClient_TLB)
function TForm1.getRect4(AKeyboardWindow : HWND): Trect;
var AUTOMATION : IUIAutomation;
Root : IUIAutomationElement;
rRect:UIAutomationClient_TLB.tagRECT;
begin
AUTOMATION := CoCUIAutomation.Create;
AUTOMATION.GetRootElement(Root);
AUTOMATION.ElementFromHandle(Pointer(AKeyboardWindow), Root);
Root.Get_CurrentBoundingRectangle(rRect);
Result := TRect(rRect);
end;
function TForm1.getRect5(AKeyboardWindow : HWND): Trect;
var AUTOMATION : IUIAutomation;
Root : IUIAutomationElement;
olRect: OleVariant;
rRect:UIAutomationClient_TLB.tagRECT;
begin
AUTOMATION := CoCUIAutomation.Create;
AUTOMATION.GetRootElement(Root);
AUTOMATION.ElementFromHandle(Pointer(AKeyboardWindow), Root);
Root.GetCurrentPropertyValue(BoundingRectangle, olRect);
AUTOMATION.VariantToRect(olRect, rRect);
Result := TRect(rRect);
end;
keypad call
function ExpandEnvironmentVar(var Value: string): Boolean;
var
R: Integer;
Expanded: string;
procedure StrResetLength(var S: string);
var
I: Integer;
begin
for I := 0 to Length(S) - 1 do
if S[I + 1] = #0 then
begin
SetLength(S, I);
Exit;
end;
end;
begin
SetLength(Expanded, 1);
R := ExpandEnvironmentStrings(PChar(Value), PChar(Expanded), 0);
SetLength(Expanded, R);
Result := ExpandEnvironmentStrings(PChar(Value), PChar(Expanded), R) <> 0;
if Result then
begin
StrResetLength(Expanded);
Value := Expanded;
end;
end;
procedure TForm1.btnCloseClick(Sender: TObject);
var
MyHandle1: THandle;
begin
MyHandle1 := FindWindow('IPTip_Main_Window', nil);
if MyHandle1 <> 0 then
PostMessage(MyHandle1, WM_SYSCOMMAND, SC_CLOSE, 0);
end;
procedure TForm1.btnOpenClick(Sender: TObject);
var
S: string;
begin
btnClose.Click;
S := '%CommonProgramW6432%\microsoft shared\ink\tabtip.exe';
ExpandEnvironmentVar(S);
ShellExecute(0, PChar('open'), PChar(S), nil, nil, SW_SHOWNORMAL);
end;
Nothing succeeded(left = 0 top = 0 width = 0 height = 0)! Has anyone done something like this, or does he know what to do?
You should implement IFrameworkInputPaneHandler
:
Enables an app to be notified when the input pane (the on-screen keyboard or handwriting panel) is being shown or hidden. This allows the app window to adjust its display so that no input areas (such as a text box) are obscured by the input pane.
See this blog post for details and example code.