• FMX 下 ShowModal 的正确姿势


    转载自QDAC官网网站,文章发现问题可能随时更新,最新版本请访问:http://blog.qdac.cc/?p=3588 ;

    1、直接调用 ShowModal 肯定是不行的,Android 下直接抛出异常。而 iOS、OSX、Windows 下是没问题的。

    2、像下面这样用循环模拟 ShowModal 也是不行的,如果只是这么简单,Delphi 早就实现了。这个代码在我手机上实测存在的主要问题就是你按回退键没响应。

    var
    F:TForm2;
    begin
    F:=TForm2.Create(nil);
    F.Show;
    while F.Visible and (F.ModalResult=mrNone) do
    begin
    Application.ProcessMessages;
    Sleep(10);
    end;
    FreeAndNil(F);
    end;
    3、像下面的用法也是错误的:

    procedure TForm1.Button1Click(Sender:TObject)
    var
    dlg: TForm2;
    begin
    dlg := TForm2.Create(nil);
    dlg.ShowModal(
    procedure(ModalResult: TModalResult)
    begin
    if ModalResult = mrOK then
    if dlg.ListBox1.ItemIndex >= 0 then
    edit1.Text := dlg.ListBox1.Items [dlg.ListBox1.ItemIndex];
    dlg.DisposeOf;
    end);
    end;
    这个的问题在于 dlg 是局部变量,ShowModal 回调的匿名函数里访问Button1Click 里的局部变量是不安全的(栈可能已经错乱)。这块 FMX 的设计真是一个败笔,应该加入实例的地址。当然了,如果 dlg 是一个全局变量,上面的代码就不存啥问题了。

    正确的用法:

    好吧,得罪了人,批判了别人的不对,总得给出一个对的方法吧。这个方法实际上也说不上真正的对,我暂时称之为对是因为这是目前我能想到的相对完美的解决方案。

    type
    TFormModalProc = reference to procedure(F: TForm);

    TFormModalHook = class(TComponent)
    private
    FForm: TForm;
    FCloseAction: TCloseAction;
    FOldClose: TCloseEvent;
    FResultProc: TFormModalProc;
    procedure DoFormClose(Sender: TObject; var Action: TCloseAction);
    public
    constructor Create(AOwner: TComponent); override;
    procedure ShowModal(AResult: TFormModalProc);
    end;

    procedure ModalDialog(F: TForm; OnResult: TFormModalProc;
    ACloseAction: TCloseAction = TCloseAction.caFree);
    var
    AHook: TFormModalHook;
    begin
    AHook := TFormModalHook.Create(F);
    AHook.FCloseAction := ACloseAction;
    AHook.ShowModal(OnResult);
    end;

    { TFormModalHook }

    constructor TFormModalHook.Create(AOwner: TComponent);
    begin
    inherited Create(AOwner);
    FForm := AOwner as TForm;
    FOldClose := FForm.OnClose;
    FForm.OnClose := DoFormClose;
    FCloseAction := TCloseAction.caFree;
    end;

    procedure TFormModalHook.DoFormClose(Sender: TObject; var Action: TCloseAction);
    begin
    if FForm.ModalResult = mrNone then
    FForm.ModalResult := mrCancel;
    Action := FCloseAction;
    if Assigned(FOldClose) then
    FOldClose(Sender, Action);
    end;

    procedure TFormModalHook.ShowModal(AResult: TFormModalProc);
    begin
    FResultProc := AResult;
    {$IFDEF ANDROID}
    FForm.ShowModal(
    procedure(AResult: TModalResult)
    var
    AHook: TFormModalHook;
    AForm: TForm;
    I: Integer;
    AChild: TComponent;
    begin
    if Screen.ActiveForm is TForm then
    AForm := Screen.ActiveForm as TForm
    else
    begin
    raise Exception.Create('You should not in here.');
    end;
    if Assigned(AForm) then
    begin
    AForm.OnClose := FOldClose;
    for I := 0 to AForm.ComponentCount - 1 do
    begin
    AChild := FForm.Components[I];
    if AChild is TFormModalHook then
    begin
    (AChild as TFormModalHook).FResultProc(AForm);
    FreeAndNil(AChild);
    Break;
    end;
    end;
    end;
    end);
    {$ELSE}
    FForm.ShowModal;
    FResultProc(FForm);
    {$ENDIF}
    end;
    好吧,代码看起来有点多,多就多吧。用法很简单,用它替换 TForm.ShowModal 方法,如:

    procedure TForm1.Button1Click(Sender: TObject);
    var
    F: TForm2;
    begin
    F := TForm2.Create(nil);
    ModalDialog(F,
    procedure(AForm: TForm)
    begin
    ShowMessage(AForm.Name + ' Modal result ready');
    end);
    end;
    【注意】

    不要在 ModalDialog 的回调函数中,在可能引发消息循环处理的地方,如:ShowMessage/MessageDlg/ProcessMessages 等函数的后面再引用 AForm 的地址,因为在 FMX 框架下,它很可能会被释放掉了。

    完整的单元文件请加入 QDAC 官方群(250530692) 后下载。

    http://bbs1.2ccc.com/topic.asp?topicid=506520

  • 相关阅读:
    HTTP method GET is not supported by this URL
    idea 报错javax/xml/bind/DatatypeConverter
    PartyBid 学习笔记 之 第二张卡片总结
    PartyBid 学习笔记 之 第一张卡片总结
    Yeoman 之 Jade自动化生成的Grunt实现
    Jade —— 简洁的HTML模版引擎
    Underscore.JS 之 消灭for循环
    SqlServer 根据时间统计数据展示图表
    C# 中使用 JavaScriptSerializer 序列化时的时间类型处理
    jQuery 插件 autocomplete 的使用
  • 原文地址:https://www.cnblogs.com/findumars/p/6351793.html
Copyright © 2020-2023  润新知