I have coded a Delphi FMX form for data entry on an Android app. This consists of several controls arranged vertically and aligned with horizontal centers. The controls are also all placed on a TVertScrollBox, so the controls can be scrolled into (and out of) view. There are a few TEdits, 2 TComboboxes, and 1 TComboEdit. I have also added the following code to my form
procedure TfrmMain.FormKeyDown(Sender: TObject; var Key: Word;
var KeyChar: Char; Shift: TShiftState);
begin
if Key = vkReturn then
begin
Key := vkTab;
KeyDown(Key, KeyChar, Shift);
end;
end;
Now this works fabulously for the TEdit controls in that the user can use the enter key (typically I set the TEdit.ReturnKeyType
property to Next) to navigate the list of controls, entering data for each one and hitting the enter key to move the focus to the next one.
There are 2 problems here.
As soon as the control is a TCombobox, the virtual keyboard disappears. In other words, there is no .keyboardtype
or .ReturnKeyType
property on a TCombobox. So after selecting an entry for the combobox from the dropdown, they have to "reach in" and select the next control manually. Often they miss.
The TEditCombo is a strange descendent indeed. It has a .Keyboardtype
property, but it doesn't have a .ReturnKeyType
property. This has my users very confused because although they can type into this combobox, the return key doesn't say "Next" when this control has focus like it does on the TEdits.
How can I make all the controls on this form show the keyboard and have the "return key" move to the next control irrespective of the type of the current control or the next one?
Was I privileged to have programmed Windows apps using the VCL?
On the Comboboxes and TComboEdits, add the following event handlers:
procedure TForm1.ComboBox1CanFocus(Sender: TObject; var ACanFocus: Boolean);
begin
Combobox1.DropDown;
end;
procedure TForm1.ComboBox1Exit(Sender: TObject);
var
keyboard: IFMXVirtualKeyboardService;
begin
keyboard := TPlatformServices.Current.GetPlatformService(IFMXVirtualKeyboardService) as IFMXVirtualKeyboardService;
if keyboard.HideVirtualKeyboard then
Label1.text := 'hidden';
end;
procedure TForm1.ComboBox1KeyDown(Sender: TObject; var Key: Word;
var KeyChar: Char; Shift: TShiftState);
begin
label1.Text := IntToStr(Key);
if Key = vkReturn then
begin
Key := vkTab;
KeyDown(Key, KeyChar, Shift);
end;
end;
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; var KeyChar: Char;
Shift: TShiftState);
begin
label1.Text := IntToStr(Key);
if Key = vkReturn then
begin
Key := vkTab;
KeyDown(Key, KeyChar, Shift);
end;
end;
procedure TForm1.ComboBox1ClosePopup(Sender: TObject);
var
keyboard: IFMXVirtualKeyboardService;
MS: TmessageSender;
begin
keyboard := TPlatformServices.Current.GetPlatformService(IFMXVirtualKeyboardService) as IFMXVirtualKeyboardService;
if keyboard.showVirtualKeyboard(ComboBox1) then
Label1.Text := 'Shown';
MS := tmessageSender.Create;
try
Ms.SendMessage<TReturnKeyType>(MM_EDIT_RETURNKEYTYPE_CHANGED, TReturnKeyType.Next);
finally
MS.Free;
end;
end;
It works like this:
When the combobox receives focus, it immediately drops down.
Immediately after the user selects an item from the dropdownlist, the Keyboard gets shown and it's return key display is changed to "Next".
The keydown event handler of the combobox seems to intercept the return key, as there's no .keypreview
property in FMX forms, so it has it's own event handler to "change" the return key to a tab key, so that the next control (in tab order) gets focus.
As the combobox gets exited (from), the keyboard is hidden.
I cribbed the SendMessage code from the FMX.Edit.pas unit. It seems to work.