Reputation: 39
We are looking to move our service technicians from laptops to Windows tablets. One issue while testing is that when the onscreen keyboard pops up, it obscures the bottom part of the application. How can we catch when the keyboard pops up and resize the application so this doesn't happen? App currently in Delphi XE5, but moving to Delphi 11.1.
Upvotes: 2
Views: 204
Reputation: 2214
You need to use IFrameworkInputPaneHandler Here is sample unit implementing it.
unit UFrameworkInputPaneHandler;
interface
uses
Winapi.Windows;
const
CLSID_FrameworkInputPane: TGUID = '{D5120AA3-46BA-44C5-822D-CA8092C1FC72}';
SID_IFrameworkInputPane = '{5752238B-24F0-495A-82F1-2FD593056796}';
SID_IFrameworkInputPaneHandler = '{226C537B-1E76-4D9E-A760-33DB29922F18}';
type
IFrameworkInputPaneHandler = interface(IInterface)
[SID_IFrameworkInputPaneHandler]
function Showing(var AInputPaneScreenLocation: TRect;
AEnsureFocusedElementInView: BOOL): HResult; stdcall;
function Hiding(AEnsureFocusedElementInView: BOOL): HResult; stdcall;
end;
IFrameworkInputPane = interface(IInterface)
[SID_IFrameworkInputPane]
function Advise(AWindow: IUnknown; AHandler: IFrameworkInputPaneHandler;
var Cookie: DWORD): HRESULT; stdcall;
function AdviseWithHWND(AWnd: HWND; const AHandler: IFrameworkInputPaneHandler;
var Cookie: DWORD): HRESULT; stdcall;
function Unadvise(dwCookie: DWORD): HRESULT; stdcall;
function Location(var rcInputPaneScreenLocation: TRect): HRESULT; stdcall;
end;
TTouchKeyboardChangeEvent = procedure(Sender: TObject; const IsShowing: Boolean; var Rect: TRect;
const EnsureFocusedElementInView: Boolean) of object;
TFrameworkInputHandler = class(TInterfacedObject, IFrameworkInputPaneHandler)
strict private
FAdviseCookie: DWORD;
FInputPane: IFrameworkInputPane;
FOnTouchKeyboardVisibilityChanged: TTouchKeyboardChangeEvent;
public
{ IFrameworkInputPaneHandler }
function Showing(var AInputPaneScreenLocation: TRect; AEnsureFocusedElementInView: BOOL): HRESULT; stdcall;
function Hiding(AEnsureFocusedElementInView: BOOL): HRESULT; stdcall;
constructor Create(const AWnd: HWND);
destructor Destroy; override;
function GetLocation(var ARect: TRect): Boolean;
property OnTouchKeyboardChanged: TTouchKeyboardChangeEvent
read FOnTouchKeyboardVisibilityChanged write FOnTouchKeyboardVisibilityChanged;
property InputPane: IFrameworkInputPane read FInputPane;
end;
implementation
uses
Winapi.ActiveX, System.Win.ComObj, System.Types;
constructor TFrameworkInputHandler.Create(const AWnd: HWND);
var
HR: HRESULT;
begin
inherited Create();
FAdviseCookie := 0;
FInputPane := nil;
FOnTouchKeyboardVisibilityChanged := nil;
HR := CoCreateInstance(CLSID_FrameworkInputPane, nil, CLSCTX_ALL,
StringToGUID(SID_IFrameworkInputPane), FInputPane);
if (not FAILED(HR)) and Assigned(FInputPane) then
begin
FInputPane.AdviseWithHWND(AWnd, Self, FAdviseCookie);
end;
end;
destructor TFrameworkInputHandler.Destroy();
begin
if Assigned(FInputPane) then
begin
FInputPane.Unadvise(FAdviseCookie);
FInputPane := nil;
end;
inherited Destroy();
end;
function TFrameworkInputHandler.GetLocation(var ARect: TRect): Boolean;
begin
Result := False;
ARect := TRect.Empty;
if Assigned(FInputPane) then
begin
Result := not FAILED(FInputPane.Location(ARect));
end;
end;
function TFrameworkInputHandler.Hiding(AEnsureFocusedElementInView: BOOL): HRESULT;
begin
if Assigned(FOnTouchKeyboardVisibilityChanged) then
begin
var Rect := TRect.Empty;
FOnTouchKeyboardVisibilityChanged(Self, False, Rect, AEnsureFocusedElementInView);
end;
Result := S_OK;
end;
function TFrameworkInputHandler.Showing(var AInputPaneScreenLocation: TRect;
AEnsureFocusedElementInView: BOOL): HRESULT;
begin
if Assigned(FOnTouchKeyboardVisibilityChanged) then
begin
FOnTouchKeyboardVisibilityChanged(Self, True, AInputPaneScreenLocation,
AEnsureFocusedElementInView);
end;
Result := S_OK;
end;
end.
In your form declare it as
FInputHandler: IFrameworkInputPaneHandler;
and create it as
if not Assigned(FInputHandler) then
begin
FInputHandler := TFrameworkInputHandler.Create(Handle);
(FInputHandler as TFrameworkInputHandler).OnTouchKeyboardChanged := OnTouchKeyboardChanged;
end;
In OnTouchKeyboardChanged it will give you position of onscreen keyboard
Upvotes: 4