I have the following code written in Delphi 10.1 Berlin, that tries to simulate a Shift+Right Arrow key on Windows in order to select text in a memo. This is a Delphi Firemonkey project, but that should not matter for my problem. The problem is that this code does what it is supposed to do on some Windows machines (selects text letter by letter), but it fails on others (only moves cursor pos, as if shift key is ignored). The failing of the code appears not to be specific to a Windows version, as it works on win 8.1 as well as on some Win 10 Fall Creatores Updates, but fails on some Win 10 Fall Creators installations. It seems also not specific to the SendInput mehtod, as the same phenomenon shows up using keybd_event. Anybody any ideas ?
unit Unit63;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo;
type
TForm63 = class(TForm)
mmo1: TMemo;
btn1: TButton;
procedure btn1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form63: TForm63;
implementation
uses windows;
{$R *.fmx}
procedure SendShiftRight;
var
KeyInputs: array of TInput;
KeyInputCount: Integer;
procedure KeybdInput(VKey: Byte; Flags: DWORD);
begin
Inc(KeyInputCount);
SetLength(KeyInputs, KeyInputCount);
KeyInputs[KeyInputCount - 1].Itype := INPUT_KEYBOARD;
with KeyInputs[KeyInputCount - 1].ki do
begin
wVk := VKey;
wScan := MapVirtualKey(wVk, 0);
dwFlags := Flags;
time := 0;
dwExtraInfo := 0;
end;
end;
begin
KeyInputCount := 0;
KeybdInput(VK_SHIFT, 0); // Shift
KeybdInput(VK_RIGHT, 0); // Right
KeybdInput(VK_RIGHT, KEYEVENTF_KEYUP); // Right
KeybdInput(VK_SHIFT, KEYEVENTF_KEYUP); // Shift
SendInput(KeyInputCount, KeyInputs[0], SizeOf(KeyInputs[0]));
end;
procedure PostKeyEx32(key: Word; const shift: TShiftState; specialkey: Boolean);
{************************************************************
* Procedure PostKeyEx32
*
* Parameters:
* key : virtual keycode of the key to send. For printable
* keys this is simply the ANSI code (Ord(character)).
* shift : state of the modifier keys. This is a set, so you
* can set several of these keys (shift, control, alt,
* mouse buttons) in tandem. The TShiftState type is
* declared in the Classes Unit.
* specialkey: normally this should be False. Set it to True to
* specify a key on the numeric keypad, for example.
* Description:
* Uses keybd_event to manufacture a series of key events matching
* the passed parameters. The events go to the control with focus.
* Note that for characters key is always the upper-case version of
* the character. Sending without any modifier keys will result in
* a lower-case character, sending it with [ssShift] will result
* in an upper-case character!
// Code by P. Below
************************************************************}
type
TShiftKeyInfo = record
shift: Byte;
vkey: Byte;
end;
byteset = set of 0..7;
const
shiftkeys: array [1..3] of TShiftKeyInfo =
((shift: Ord(ssCtrl); vkey: VK_CONTROL),
(shift: Ord(ssShift); vkey: VK_SHIFT),
(shift: Ord(ssAlt); vkey: VK_MENU));
var
flag: DWORD;
bShift: ByteSet absolute shift;
i: Integer;
begin
for i := 1 to 3 do
begin
if shiftkeys[i].shift in bShift then
keybd_event(shiftkeys[i].vkey, MapVirtualKey(shiftkeys[i].vkey, 0), 0, 0);
end; { For }
if specialkey then
flag := KEYEVENTF_EXTENDEDKEY
else
flag := 0;
keybd_event(key, MapvirtualKey(key, 0), flag, 0);
flag := flag or KEYEVENTF_KEYUP;
keybd_event(key, MapvirtualKey(key, 0), flag, 0);
for i := 3 downto 1 do
begin
if shiftkeys[i].shift in bShift then
keybd_event(shiftkeys[i].vkey, MapVirtualKey(shiftkeys[i].vkey, 0),
KEYEVENTF_KEYUP, 0);
end; { For }
end; { PostKeyEx32 }
procedure TForm63.btn1Click(Sender: TObject);
begin
mmo1.SetFocus;
SendShiftRight;
// PostKeyEx32(vkRight, [ssShift], False); // doesn't work either
end;
end.