4
votes

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.

  1. 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.

  2. 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?

1

1 Answers

1
votes

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.