4

I'm struggling to get a FireMonkey TEdit nested inside a FireMonkey TPopup to receive keyboard input. Happens both for desktop and mobile projects, though it's the latter I'm interested in:

  1. Create a new FMX project.

  2. Add a TButton and a TPopup to the form, and a TEdit to the TPopup.

  3. Set the popup's Placement property to plCenter and its PlacementTarget to Button1.

  4. Handle the button's OnClick event by setting the popup's IsOpen property to True.

  5. Run the project, click/tap the button, and try to enter text in the edit control.

Any ideas? The correct answer may of course be: keyboard input isn't supported, but the documentation doesn't say either way.

Chris Rolliston
  • 4,788
  • 1
  • 16
  • 20

4 Answers4

2

Had same problem, but fixed behavior with few overrides. Changed form to TFormStyle.Normal and handled OnDeactivate event.

    TPopup2 = class(TPopup)

    protected
      function CreatePopupForm: TFmxObject; override;
    end;

    TPopupForm2 = class(TCustomPopupForm)

    private
      procedure OnDeactivateEvent(Sender: TObject);
    public
      constructor CreateNew(AOwner: TComponent; Dummy: NativeInt = 0); override;
    end;

function TPopup2.CreatePopupForm: TFmxObject;
var
  NewStyle: TStyleBook;
  NewForm: TPanelForm;
begin
  NewForm := nil;
  try
    if not Assigned(StyleBook) and Assigned(Scene) then
      NewStyle := Scene.GetStyleBook
    else
      NewStyle := StyleBook;
    NewForm := TPopupForm2.Create(Self, NewStyle, PlacementTarget);
  except
    FreeAndNil(NewForm);
    Raise;
  end;
  Result := NewForm;
end;

constructor TPopupForm2.CreateNew(AOwner: TComponent; Dummy: NativeInt);
begin
  inherited;
  BeginUpdate;
  try
    FormStyle := TFormStyle.Normal;
    BorderStyle := TFmxFormBorderStyle.None;
    Fill.Kind := TBrushKind.None;
    Transparency := True;
    OnDeactivate := OnDeactivateEvent;
  finally
    EndUpdate;
  end;

end;

procedure TPopupForm2.OnDeactivateEvent(Sender: TObject);
begin
  Close;
end;
izzum_
  • 21
  • 2
  • Thanks for sharing. I am looking for a real solution for this problems for months. Your solutions seems to work partially. I have a TEdit that I use as a searchbox, I can now type in, but it does not show the carent and the letters are invisible. (I have TPopup + TPanel and a TEdit and TListbox that are child of this TPanel). There is a av that happens when I use backspace and has nothing else to delete. – Eduardo Elias Apr 29 '15 at 03:37
1

use Popup1.popup(true) instead of changing the isOpen property

ThisGuy
  • 1,405
  • 1
  • 24
  • 51
  • Thanks - this works for Windows, but unfortunately raises an exception on Android where the parameterless ShowModal isn't supported. – Chris Rolliston Jan 02 '14 at 21:33
  • This solution is probably not wanted - because the popup window is a modal window then and does not close if the user click outside. The solution below work as real non-modal popup. – BitBumper Nov 27 '14 at 15:45
1

Keyboard Input seems not to work on TPopup. An easy solution is to use a TForm as popup form:

unit Popup;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls, FMX.Edit;

type
  TfmPopup = class(TForm)
    Edit1: TEdit;
    Panel1: TPanel;
    procedure FormDeactivate(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState);
  private
  protected
  public
  end;

var
  fmPopup: TfmPopup;

implementation

{$R *.fmx}

procedure TfmPopup.FormDeactivate(Sender: TObject);
begin
  Close;
end;

procedure TfmPopup.FormKeyDown(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState);
begin
  if Key = vkEscape then begin
    Close;
  end;
end;

end.

The form resources:

object fmPopup: TfmPopup
  Left = 0
  Top = 0
  BorderStyle = None
  Caption = 'Form1'
  ClientHeight = 94
  ClientWidth = 142
  FormFactor.Width = 320
  FormFactor.Height = 480
  FormFactor.Devices = [Desktop, iPhone, iPad]
  OnDeactivate = FormDeactivate
  OnKeyDown = FormKeyDown
  DesignerMobile = False
  DesignerWidth = 0
  DesignerHeight = 0
  DesignerDeviceName = ''
  DesignerOrientation = 0
  DesignerOSVersion = ''
  object Panel1: TPanel
    Align = Client
    Height = 94.000000000000000000
    Width = 142.000000000000000000
    TabOrder = 1
    object Edit1: TEdit
      Touch.InteractiveGestures = [LongTap, DoubleTap]
      TabOrder = 1
      Position.X = 20.000000000000000000
      Position.Y = 32.000000000000000000
      Width = 100.000000000000000000
      Height = 22.000000000000000000
    end
  end
end

Of course you can improve this simple example: Do not place the TEdit on this form but inherit this form and place the edit there. E.g.:

TfmMyPopup = class(TfmPopup)
  Edit1: TEdit;
private
protected
public
end;

Improve the base class of TfmPopup with some features like TPopup: E.g. placement. May you can use a never shown TPopup within TfmPopup to use the placement routines of the TPopup without rewriting this code.

BitBumper
  • 369
  • 1
  • 10
0

Had similar case with a TPopup like this:

TPopup with TEdit

but even though on hover the TEdit shows appropriate input cursor, when clicking it the popup would close.

So I use the following:

procedure TStoryItemOptions.actionChangeUrlActionExecute(Sender: TObject);
begin
  TDialogServiceAsync.InputQuery('URL', ['URL'], [StoryItem.GetUrlAction], procedure(const AResult: TModalResult; const AValues: array of string)
    begin
    if (AResult = mrOk) then
      begin
      editUrlAction.Text := AValues[0]; //this will call "OnChangeTracking" handler
      //ShowPopup;
      end;
    end
  );
  ShowPopup;
end;

procedure TStoryItemOptions.editUrlActionChangeTracking(Sender: TObject);
begin
  StoryItem.SetUrlAction(editUrlAction.Text);
end;

procedure TStoryItemOptions.editUrlActionMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
begin
  actionChangeUrlAction.Execute;
end;

procedure TStoryItemOptions.ShowPopup;
begin
  CheckCreatePopup;

  if Assigned(FPopup) then
    FPopup.IsOpen := true;
end;

Async Input dialog for TPopup

Note that I show the Popup again - this causes it only to appear during the input so that user isn't confused from the modal input that is shown. I tried also to add ShowPopup at the end of the anonymous method that the input dialog shows (note an async dialog is needed for Android, sync one is not supported currently at Delphi 11 for Android) to show popup again after OK is pressed but didn't work. Probably it is executed at other thread (and ignore), haven't tried telling it to do from the UI thread, or try else with a timeout to do it a moment later

The code is at StoryItemOptions frame code in http://github.com/zoomicon/READCOM_App (still under heavy development)

George Birbilis
  • 2,782
  • 2
  • 33
  • 35