delphi XE模拟Android手机PDA设备的虚拟键盘按键及扫码过程输入焦点及信号接收
今天,群里有几位同学讨论这个问题,汇总了一下,分享出来,供同学们学习研究。
一、直接上代码示例
1、屏蔽应用Terminated ;如果按了虚拟键:返回键; 如果按了物理菜单键
procedure TfmxTestGYListview1.FormKeyUp(
Sender: TObject; var Key: Word;
var KeyChar: Char; Shift: TShiftState);
var
CanUse: Boolean;
begin
if Key = vkHardwareBack then // 如果按了虚拟键:返回键
begin
Key := 0; //:屏蔽应用Terminated
// CanUse := true; Key := GoBack(CanUse); // 调用返回功能,包括退出功能
Image_0201Click(Sender);
end;
if Key = vkMenu then // 如果按了物理菜单键
begin
if PopupMenu.Visible = true then
HidePopupMenu
else
Image_0202Click(Sender); // 显示快捷菜单
Key := 0; //:屏蔽应用Terminated
exit;
end;
end;
2、控制TEdit和TMemo的虚拟键盘
二、取数原理
System.UITypes.pas 第197行-384行
const
{ Virtual Keys, Standard Set }
vkLButton = $01; { 1 }
vkRButton = $02; { 2 }
vkCancel = $03; { 3 }
vkMButton = $04; { 4 }
vkXButton1 = $05; { 5 }
vkXButton2 = $06; { 6 }
vkBack = $08; { 8 }
vkTab = $09; { 9 }
vkLineFeed = $0A; { 10 }
vkClear = $0C; { 12 }
vkReturn = $0D; { 13 }
vkShift = $10; { 16 }
vkControl = $11; { 17 }
vkMenu = $12; { 18 }
vkPause = $13; { 19 }
vkCapital = $14; { 20 }
vkKana = $15; { 21 }
vkHangul = $15; { 21 }
vkJunja = $17; { 23 }
vkFinal = $18; { 24 }
vkHanja = $19; { 25 }
vkKanji = $19; { 25 }
vkConvert = $1C; { 28 }
vkNonConvert = $1D; { 29 }
vkAccept = $1E; { 30 }
vkModeChange = $1F; { 31 }
vkEscape = $1B; { 27 }
vkSpace = $20; { 32 }
vkPrior = $21; { 33 }
vkNext = $22; { 34 }
vkEnd = $23; { 35 }
vkHome = $24; { 36 }
vkLeft = $25; { 37 }
vkUp = $26; { 38 }
vkRight = $27; { 39 }
vkDown = $28; { 40 }
vkSelect = $29; { 41 }
vkPrint = $2A; { 42 }
vkExecute = $2B; { 43 }
vkSnapshot = $2C; { 44 }
vkInsert = $2D; { 45 }
vkDelete = $2E; { 46 }
vkHelp = $2F; { 47 }
{ vk0 thru vk9 are the same as ASCII '0' thru '9' ($30 - $39) }
vk0 = $30; { 48 }
vk1 = $31; { 49 }
vk2 = $32; { 50 }
vk3 = $33; { 51 }
vk4 = $34; { 52 }
vk5 = $35; { 53 }
vk6 = $36; { 54 }
vk7 = $37; { 55 }
vk8 = $38; { 56 }
vk9 = $39; { 57 }
{ vkA thru vkZ are the same as ASCII 'A' thru 'Z' ($41 - $5A) }
vkA = $41; { 65 }
vkB = $42; { 66 }
vkC = $43; { 67 }
vkD = $44; { 68 }
vkE = $45; { 69 }
vkF = $46; { 70 }
vkG = $47; { 71 }
vkH = $48; { 72 }
vkI = $49; { 73 }
vkJ = $4A; { 74 }
vkK = $4B; { 75 }
vkL = $4C; { 76 }
vkM = $4D; { 77 }
vkN = $4E; { 78 }
vkO = $4F; { 79 }
vkP = $50; { 80 }
vkQ = $51; { 81 }
vkR = $52; { 82 }
vkS = $53; { 83 }
vkT = $54; { 84 }
vkU = $55; { 85 }
vkV = $56; { 86 }
vkW = $57; { 87 }
vkX = $58; { 88 }
vkY = $59; { 89 }
vkZ = $5A; { 90 }
vkLWin = $5B; { 91 }
vkRWin = $5C; { 92 }
vkApps = $5D; { 93 }
vkSleep = $5F; { 95 }
vkNumpad0 = $60; { 96 }
vkNumpad1 = $61; { 97 }
vkNumpad2 = $62; { 98 }
vkNumpad3 = $63; { 99 }
vkNumpad4 = $64; { 100 }
vkNumpad5 = $65; { 101 }
vkNumpad6 = $66; { 102 }
vkNumpad7 = $67; { 103 }
vkNumpad8 = $68; { 104 }
vkNumpad9 = $69; { 105 }
vkMultiply = $6A; { 106 }
vkAdd = $6B; { 107 }
vkSeparator = $6C; { 108 }
vkSubtract = $6D; { 109 }
vkDecimal = $6E; { 110 }
vkDivide = $6F; { 111 }
vkF1 = $70; { 112 }
vkF2 = $71; { 113 }
vkF3 = $72; { 114 }
vkF4 = $73; { 115 }
vkF5 = $74; { 116 }
vkF6 = $75; { 117 }
vkF7 = $76; { 118 }
vkF8 = $77; { 119 }
vkF9 = $78; { 120 }
vkF10 = $79; { 121 }
vkF11 = $7A; { 122 }
vkF12 = $7B; { 123 }
vkF13 = $7C; { 124 }
vkF14 = $7D; { 125 }
vkF15 = $7E; { 126 }
vkF16 = $7F; { 127 }
vkF17 = $80; { 128 }
vkF18 = $81; { 129 }
vkF19 = $82; { 130 }
vkF20 = $83; { 131 }
vkF21 = $84; { 132 }
vkF22 = $85; { 133 }
vkF23 = $86; { 134 }
vkF24 = $87; { 135 }
vkCamera = $88; { 136 }
vkHardwareBack = $89; { 137 }
vkNumLock = $90; { 144 }
vkScroll = $91; { 145 }
vkLShift = $A0; { 160 }
vkRShift = $A1; { 161 }
vkLControl = $A2; { 162 }
vkRControl = $A3; { 163 }
vkLMenu = $A4; { 164 }
vkRMenu = $A5; { 165 }
vkBrowserBack = $A6; { 166 }
vkBrowserForward = $A7; { 167 }
vkBrowserRefresh = $A8; { 168 }
vkBrowserStop = $A9; { 169 }
vkBrowserSearch = $AA; { 170 }
vkBrowserFavorites = $AB; { 171 }
vkBrowserHome = $AC; { 172 }
vkVolumeMute = $AD; { 173 }
vkVolumeDown = $AE; { 174 }
vkVolumeUp = $AF; { 175 }
vkMediaNextTrack = $B0; { 176 }
vkMediaPrevTrack = $B1; { 177 }
vkMediaStop = $B2; { 178 }
vkMediaPlayPause = $B3; { 179 }
vkLaunchMail = $B4; { 180 }
vkLaunchMediaSelect= $B5; { 181 }
vkLaunchApp1 = $B6; { 182 }
vkLaunchApp2 = $B7; { 183 }
vkSemicolon = $BA; { 186 }
vkEqual = $BB; { 187 }
vkComma = $BC; { 188 }
vkMinus = $BD; { 189 }
vkPeriod = $BE; { 190 }
vkSlash = $BF; { 191 }
vkTilde = $C0; { 192 }
vkLeftBracket = $DB; { 219 }
vkBackslash = $DC; { 220 }
vkRightBracket = $DD; { 221 }
vkQuote = $DE; { 222 }
vkPara = $DF; { 223 }
vkOem102 = $E2; { 226 }
vkIcoHelp = $E3; { 227 }
vkIco00 = $E4; { 228 }
vkProcessKey = $E5; { 229 }
vkIcoClear = $E6; { 230 }
vkPacket = $E7; { 231 }
vkAttn = $F6; { 246 }
vkCrsel = $F7; { 247 }
vkExsel = $F8; { 248 }
vkErEof = $F9; { 249 }
vkPlay = $FA; { 250 }
vkZoom = $FB; { 251 }
vkNoname = $FC; { 252 }
vkPA1 = $FD; { 253 }
vkOemClear = $FE; { 254 }
vkNone = $FF; { 255 }
FMX.Types.pas 第568行~615行
TVirtualKeyboardType = (Default, NumbersAndPunctuation, NumberPad, PhonePad, Alphabet, URL, NamePhonePad,
EmailAddress, DecimalNumberPad);
TVirtualKeyboardTypeHelper = record helper for TVirtualKeyboardType
const
vktDefault = TVirtualKeyboardType.Default deprecated 'Use TVirtualKeyboardType.Default';
vktNumbersAndPunctuation = TVirtualKeyboardType.NumbersAndPunctuation deprecated 'Use TVirtualKeyboardType.NumbersAndPunctuation';
vktNumberPad = TVirtualKeyboardType.NumberPad deprecated 'Use TVirtualKeyboardType.NumberPad';
vktPhonePad = TVirtualKeyboardType.PhonePad deprecated 'Use TVirtualKeyboardType.PhonePad';
vktAlphabet = TVirtualKeyboardType.Alphabet deprecated 'Use TVirtualKeyboardType.Alphabet';
vktURL = TVirtualKeyboardType.URL deprecated 'Use TVirtualKeyboardType.URL';
vktNamePhonePad = TVirtualKeyboardType.NamePhonePad deprecated 'Use TVirtualKeyboardType.NamePhonePad';
vktEmailAddress = TVirtualKeyboardType.EmailAddress deprecated 'Use TVirtualKeyboardType.EmailAddress';
end;
TVirtualKeyboardState = (AutoShow, Visible, Error, Transient);
TVirtualKeyboardStateHelper = record helper for TVirtualKeyboardState
const
vksAutoShow = TVirtualKeyboardState.AutoShow deprecated 'Use TVirtualKeyboardState.AutoShow';
vksVisible = TVirtualKeyboardState.Visible deprecated 'Use TVirtualKeyboardState.Visible';
vksError = TVirtualKeyboardState.Error deprecated 'Use TVirtualKeyboardState.Error';
vksTransient = TVirtualKeyboardState.Transient deprecated 'Use TVirtualKeyboardState.Transient';
end;
TVirtualKeyboardStates = set of TVirtualKeyboardState;
TReturnKeyType = (Default, Done, Go, Next, Search, Send);
TReturnKeyTypeHelper = record helper for TReturnKeyType
const
rktDefault = TReturnKeyType.Default deprecated 'Use TReturnKeyType.Default';
rktDone = TReturnKeyType.Done deprecated 'Use TReturnKeyType.Done';
rktGo = TReturnKeyType.Go deprecated 'Use TReturnKeyType.Go';
rktNext = TReturnKeyType.Next deprecated 'Use TReturnKeyType.Next';
rktSearch = TReturnKeyType.Search deprecated 'Use TReturnKeyType.Search';
rktSend = TReturnKeyType.Send deprecated 'Use TReturnKeyType.Send';
end;
IVirtualKeyboardControl = interface
['{41127080-97FC-4C30-A880-AB6CD351A6C4}']
procedure SetKeyboardType(Value: TVirtualKeyboardType);
function GetKeyboardType: TVirtualKeyboardType;
property KeyboardType: TVirtualKeyboardType read GetKeyboardType write SetKeyboardType;
//
procedure SetReturnKeyType(Value: TReturnKeyType);
function GetReturnKeyType: TReturnKeyType;
property ReturnKeyType: TReturnKeyType read GetReturnKeyType write SetReturnKeyType;
//
function IsPassword: Boolean;
end;
三、TEdit、TMemo等输入组件的焦点与虚拟键盘隐藏
1、
procedure TFormlogin_allinone_beijing.Image_0201Click(Sender: TObject);
begin
if Assigned(self.Focused) then // 如果你的该页面有编辑控件,一定要加上这个,按返回键可以去掉键盘框
begin
if ((self.Focused.GetObject is TEdit) or (self.Focused.GetObject is TMemo)) then
begin
self.Focused := nil; // 退出键盘显示
exit;
end;
end;
2、
procedure TForm_ship.EditShowEnter(Sender: TObject);
begin
VKAutoShowMode := TVKAutoShowMode.Always; // 此窗口弹出输入法
//VKAutoShowMode := TVKAutoShowMode.Never; // 此窗口不弹出输入法
end;
unit FMX.VirtualKeyboard.Android;
function TVirtualKeyboardAndroid.IsAutoShow: Boolean;
begin
Result := VKAutoShowMode in [TVKAutoShowMode.Always, TVKAutoShowMode.DefinedBySystem];
end;
unit FMX.Types;
TVKAutoShowModeHelper = record helper for TVKAutoShowMode
const
vkasDefinedBySystem = TVKAutoShowMode.DefinedBySystem deprecated 'Use TVKAutoShowMode.DefinedBySystem';
vkasNever = TVKAutoShowMode.Never deprecated 'Use TVKAutoShowMode.Never';
vkasAlways = TVKAutoShowMode.Always deprecated 'Use TVKAutoShowMode.Always';
end;
3、应用案例: PDA扫码
PDA接收扫码结果有两种方式,(1、焦点录入,就是要先点击一下输入框,让输入框处于焦点等待输入模式,扫码时就等同于键入录入后按回车键::::我的意见,这种模式下,不要去获取焦点、焦点等待、模拟回车键,直接:扫码完成后(要用到线程来负责扫码,扫码成功后直接同步UI赋值给TEdit)立即赋值给TEdit,TEdit(最好换位TText或TLabel等非输入组件)组件接收赋值的OnChange事件,翻译并显示出条码等后续处理。
(2、广播模式,不需要点击输入框,无焦点状态下由APP负责侦听扫描结果并处理。相当于 Android下的一个 TNotification服务。
其实呢,无论 焦点模式也好、广播推送通知模式也好,其背后的本质还是线程及线程的同步问题,如果熟悉 线程及线程的同步问题,事件及其事件通知,就变得简单啦。扫码及其通知的过程:进入匿名线程,扫码开始,扫码成功后:线程同步UI通知接收组件的OnChange事件显示条码,条码显示的接收组件OnChange等等事件被触发有怎样怎样.......
四、关联
1、 delphi系统键盘输入捕获或手势捕获 https://blog.csdn.net/pulledup/article/details/104374215
喜欢的话,就在下面点个赞、收藏就好了,方便看下次的分享: