CJC Delphi 技巧馆's Archiver

share Posted at 2014-10-23 10:59

7.XE7 安卓模式化对话框及设置是否可以点击对话框区域外面 1.1

(* ************************************************ *)
(*                         *)
(*  修改:爱吃猪头肉 & Flying Wang 2013-09-19   *)
(*      上面的版权声明请不要移除。      *)
(*                         *)
(*          禁止发布到城通网盘。        *)
(*                         *)
(* ************************************************ *)

找到安装目录下的
FMX.Platform.Android.pas
将他们另存到(复制到)其他目录,例如您的工程目录。

将新复制出的文件加入到您的工程中。

【第一步】
打开 FMX.Platform.Android.pas

添加如下信息
(* ************************************************ *)
(*                         *)
(*  修改:爱吃猪头肉 & Flying Wang 2013-09-19   *)
(*      上面的版权声明请不要移除。      *)
(*                         *)
(*          禁止发布到城通网盘。        *)
(*                         *)
(* ************************************************ *)
这是我的版权,请您尊重下。



【第二步】 找到 implementation
在 implementation 之前添加如下内容
//Add By Flying Wang
var
  /// <summary>
  ///   <para>
  ///     是否允许点击对话框区域之外
  ///   </para>
  ///   <para>
  ///     对于默认返回值为 mbHelp 或错误默认值的对话框,本选项无效,肯定禁止
  ///   </para>
  /// </summary>
  MessageDialog_CanceledOnTouchOutsid: Boolean = True;
  /// <summary>
  ///   <para>
  ///     是否允许用返回按钮取消对话框
  ///   </para>
  ///   <para>
  ///     对于默认返回值为 mbHelp 或错误默认值的对话框,本选项无效,肯定禁止
  ///   </para>
  ///   <para>
  ///     目前不起作用
  ///   </para>
  ///   <para>
  ///     也可能是用来决定是否在右上角显示一个关闭按钮。
  ///   </para>
  /// </summary>
  MessageDialog_Canceleable: Boolean = True;

  /// <summary>
  ///   模式化(Modaled or Blocking)对话框内部用等待毫秒数
  /// </summary>
  BlockingMessageWaitMilliSeconds: Integer = 5;

/// <summary>
///   Show a bocking message box
/// </summary>
procedure ShowMessageWait(const AMessage: string);


【第三步】 在 implementation  之后 的 uses 之后添加如下内容
procedure ShowMessageWait(const AMessage: string);
var
  RetVal: Integer;
begin
  RetVal := MessageDlg(AMessage, TMsgDlgType.mtCustom, [TMsgDlgBtn.mbOK], 0,
    //故意设置这个错误的默认值
    System.UITypes.TMsgDlgBtn.mbHelp);
end;


【第四步】 找到 TFMXDialogListener = class(TJavaLocal, JFMXDialogListener)
修改这个类的定义代码,改成如下内容。
//Fix By Flying Wang
  TFMXDialogListener = class(TJavaLocal, JFMXDialogListener)
  private
    [Weak] FParentList: TList<TFmxDialogListener>;
    FValues: array of string;
    FDefaultButtonIndex: Integer;
    FModalResult: TModalResult;
    FInputCloseQueryProc: TInputCloseQueryProc;
    procedure DoDialogClosed;
    procedure SetParentList(const AList: TList<TFmxDialogListener>);
  public
    constructor Create(const AInputCloseQueryProc: TInputCloseQueryProc;
      ADefaultButtonIndex: Integer);
    procedure onDialogClosed(modalResult: Integer; values: TJavaObjectArray<JString>); cdecl;
    property ParentList: TList<TFmxDialogListener> read FParentList write SetParentList;
  end;

【第五步】 找到
function TPlatformAndroid.MessageDialog(const AMessage: string; const ADialogType: TMsgDlgType;
  const AButtons: TMsgDlgButtons;        const ADefaultButton: TMsgDlgBtn; const AX, AY: Integer; const AHelpCtx: LongInt;
  const AHelpFileName: string): Integer;
修改这个函数的代码,改成如下内容。
//Fix By Flying Wang
function TPlatformAndroid.MessageDialog(const AMessage: string; const ADialogType: TMsgDlgType;
  const AButtons: TMsgDlgButtons;        const ADefaultButton: TMsgDlgBtn; const AX, AY: Integer; const AHelpCtx: LongInt;
  const AHelpFileName: string): Integer;
var
  ARetVal: Integer;
begin
  //raise ENotImplemented.CreateFmt(SNotImplementedOnPlatform, [SBlockingDialogs]);
  Result := -1;
  ARetVal := -1;
  MessageDialog(AMessage, ADialogType, AButtons, ADefaultButton, AX, AY, AHelpCtx, AHelpFileName,
    procedure(const AResult: TModalResult)
      begin
        ARetVal := AResult;
      end);
  while ARetVal < 0 do
  begin
    Sleep(BlockingMessageWaitMilliSeconds);
    Application.ProcessMessages;
  end;
  Result := ARetVal;
end;


【第六步】 找到
procedure TPlatformAndroid.MessageDialog(const AMessage: string; const ADialogType: TMsgDlgType;
  const AButtons: TMsgDlgButtons;        const ADefaultButton: TMsgDlgBtn; const AX, AY: Integer; const AHelpCtx: LongInt;
  const AHelpFileName: string; const ACloseDialogProc: TInputCLoseDialogProc);
修改这个函数的代码,改成如下内容。
//Fix By Flying Wang
procedure TPlatformAndroid.MessageDialog(const AMessage: string; const ADialogType: TMsgDlgType;
  const AButtons: TMsgDlgButtons;        const ADefaultButton: TMsgDlgBtn; const AX, AY: Integer; const AHelpCtx: LongInt;
  const AHelpFileName: string; const ACloseDialogProc: TInputCLoseDialogProc);
var
  DialogFactory: JFMXDialogFactory;
  DialogListener: TFMXDialogListener;
  AlertDialog: JFMXStandardDialog;
  PosButton, NegButton, NeutralButton: Integer;
  B: TMsgDlgBtn;
  DefaultButton,
  ButtonIndex: Integer;
  ButtonsCount: Integer;
  LCaptions: TJavaObjectArray<JString>;
begin
  ButtonsCount := 0;
  ButtonIndex := 0;
  PosButton := -1;
  NegButton := -1;
  NeutralButton := -1;
  //这里不能用 -1;
  DefaultButton := 0;

  for B in AButtons do
    Inc(ButtonsCount);
  ButtonsCount := Min(ButtonsCount, 3);

  LCaptions := TJavaObjectArray<JString>.Create(ButtonsCount);

  for B in AButtons do
  begin
    if ButtonIndex < ButtonsCount then
    begin
      LCaptions.Items[ButtonIndex] := StringToJString(ButtonCaptions[B]);
      if ADefaultButton = B then
      begin
        DefaultButton := ModalResults[B];
      end;
      case ButtonIndex of
        0: PosButton := ModalResults[B];
        1: NegButton := ModalResults[B];
        2: NeutralButton := ModalResults[B];
      end;
    end;
    Inc(ButtonIndex);
  end;

  DialogFactory := TJFMXDialogFactory.JavaClass.getFactory;
  if DialogFactory <> nil then
  begin
    CallInUIThreadAndWaitFinishing(
      procedure
      begin
        AlertDialog := DialogFactory.createMessageDialog(MainActivity, GetNativeTheme, StringToJString(AMessage),
          Ord(ADialogType), LCaptions, PosButton, NegButton, NeutralButton);

        if AlertDialog <> nil then
        begin
          if DefaultButton > 0 then
          begin
            AlertDialog.getRealDialog.setCancelable(MessageDialog_Canceleable);
            AlertDialog.getRealDialog.setCanceledOnTouchOutside(
              MessageDialog_CanceledOnTouchOutsid);
          end
          else
          begin
            AlertDialog.getRealDialog.setCancelable(False);
            AlertDialog.getRealDialog.setCanceledOnTouchOutside(False);
          end;
          if Assigned(ACloseDialogProc) then
          begin
            DialogListener := TFMXDialogListener.Create(
              procedure (const AResult: TModalResult; const AValues: array of string)
              begin
                ACloseDialogProc(AResult);
              end, DefaultButton);
            DialogListener.ParentList := FAlertListeners;
            AlertDialog.setListener(DialogListener);
          end;
          AlertDialog.show;
        end;
      end);
  end;
end;



【第七步】 找到
function TPlatformAndroid.InputQuery(const ACaption: string; const APrompts: array of string;
        var AValues: array of string; const ACloseQueryFunc: TInputCloseQueryFunc): Boolean;
修改这个函数的代码,改成如下内容。
//Fix By Flying Wang
function TPlatformAndroid.InputQuery(const ACaption: string; const APrompts: array of string;
        var AValues: array of string; const ACloseQueryFunc: TInputCloseQueryFunc): Boolean;
var
  ARetVal: Integer;
begin
  //raise ENotImplemented.CreateFmt(SNotImplementedOnPlatform, [SBlockingDialogs]);
  Result := False;
  ARetVal := -1;
  InputQuery(ACaption, APrompts, AValues,
    procedure(const AResult: TModalResult; const AValues: array of string)
      begin
        ARetVal := AResult;
        if ARetVal = mrOK then
          if Assigned(ACloseQueryFunc) then
            ACloseQueryFunc(AValues);
      end);
  while ARetVal < 0 do
  begin
    Sleep(BlockingMessageWaitMilliSeconds);
    Application.ProcessMessages;
  end;
  Result := ARetVal = mrOK;
end;


【第八步】 找到
procedure TPlatformAndroid.InputQuery(const ACaption: string; const APrompts, ADefaultValues: array of string;
        const ACloseQueryProc: TInputCloseQueryProc);
修改这个函数的代码,改成如下内容。
//Fix By Flying Wang
procedure TPlatformAndroid.InputQuery(const ACaption: string; const APrompts, ADefaultValues: array of string;
        const ACloseQueryProc: TInputCloseQueryProc);
var
  DialogFactory: JFMXDialogFactory;
  QueryDialog: JFMXStandardDialog;
  JavaPrompts: TJavaObjectArray<JString>;
  JavaDefaultValues: TJavaObjectArray<JString>;
  DialogListener: TFMXDialogListener;
  LCaptions: TJavaObjectArray<JString>;
  I: Integer;
begin
  if Length(ADefaultValues) < Length(APrompts) then
    raise EInvalidOperation.Create(SPromptArrayTooShort);
  if Length(APrompts) = 0 then
    raise EInvalidOperation.Create(SPromptArrayEmpty);

  JavaPrompts := TJavaObjectArray<JString>.Create(Length(APrompts));
  JavaDefaultValues := TJavaObjectArray<JString>.Create(Length(ADefaultValues));
  for I := 0 to Length(APrompts) - 1 do
    JavaPrompts[I] := StringToJString(APrompts[I]);
  for I := 0 to Length(ADefaultValues) - 1 do
    JavaDefaultValues[I] := StringToJString(ADefaultValues[I]);
  LCaptions := TJavaObjectArray<JString>.Create(2);
  LCaptions.Items[0] := StringToJString(ButtonCaptions[TMsgDlgBtn.mbOK]);
  LCaptions.Items[1] := StringToJString(ButtonCaptions[TMsgDlgBtn.mbCancel]);
  DialogFactory := TJFMXDialogFactory.JavaClass.getFactory;
  if DialogFactory <> nil then
  begin
    CallInUIThreadAndWaitFinishing(
      procedure
        begin
          QueryDialog := DialogFactory.createInputQueryDialog(MainActivity, GetNativeTheme, StringToJString(ACaption),
            JavaPrompts, JavaDefaultValues, LCaptions);
          if QueryDialog <> nil then
          begin
            QueryDialog.getRealDialog.setCancelable(MessageDialog_Canceleable);
            QueryDialog.getRealDialog.setCanceledOnTouchOutside(
              MessageDialog_CanceledOnTouchOutsid);
            if Assigned(ACloseQueryProc) then
            begin
              DialogListener := TFMXDialogListener.Create(ACloseQueryProc,
                ModalResults[TMsgDlgBtn.mbCancel]);
              DialogListener.ParentList := FAlertListeners;
              QueryDialog.setListener(DialogListener);
            end;
            QueryDialog.show;
          end;
        end);
  end;
end;

【第九步】 找到
constructor TFMXDialogListener.Create(const AInputCloseQueryProc: TInputCloseQueryProc;
      ADefaultButtonIndex: Integer); 和 procedure TFMXDialogListener.DoDialogClosed;
修改这两个函数的代码,改成如下内容。

//Fix By Flying Wang.
constructor TFMXDialogListener.Create(const AInputCloseQueryProc: TInputCloseQueryProc;
      ADefaultButtonIndex: Integer);
begin
  inherited Create;
  FDefaultButtonIndex := ADefaultButtonIndex;
  FInputCloseQueryProc := AInputCloseQueryProc;
end;

//Fix By Flying Wang.
procedure TFMXDialogListener.DoDialogClosed;
begin
  //非常幸运的是,正常的返回都大于 0 。
  if FModalResult <= 0 then
    FModalResult := FDefaultButtonIndex;
  FInputCloseQueryProc(FModalResult, FValues);
  if FParentList <> nil then
    FParentList.Remove(Self);
  FParentList := nil;
end;



【使用方法】

//Add By Flying Wang.
procedure ShowMessageWait(const AMessage: string);
var
  RetVal: Integer;
begin
{$IFDEF ANDROID}
  FMX.Platform.Android.ShowMessageWait(AMessage);
{$ELSE}
  ShowMessage(AMessage);
{$ENDIF ANDROID}
end;

procedure TMessageAlertsForm.btnStandardAlertClick(Sender: TObject);
begin
  //Fix By Flying wang
{$IFDEF ANDROID}
  MessageDialog_CanceledOnTouchOutsid := CheckBox1.IsChecked;
  MessageDialog_Canceleable := CheckBox2.IsChecked;
{$ENDIF ANDROID}
  ShowMessageWait('还有一个对话框');
  ShowMessageWait('Hello World!' + sLineBreak + 'Test Other Button.');
end;


//下面的两个例子,也可以改造成 BLOCKING 模式,并且可以不使用匿名函数。
procedure TMessageAlertsForm.btnMultiButtonAlertClick(Sender: TObject);
begin
  //Fix By Flying wang
{$IFDEF ANDROID}
  MessageDialog_CanceledOnTouchOutsid := CheckBox1.IsChecked;
  MessageDialog_Canceleable := CheckBox2.IsChecked;
{$ENDIF ANDROID}
  MessageDlg('Choose a button:', System.UITypes.TMsgDlgType.mtInformation,
    [
      System.UITypes.TMsgDlgBtn.mbYes,
      System.UITypes.TMsgDlgBtn.mbNo,
      System.UITypes.TMsgDlgBtn.mbCancel
    ], 0, System.UITypes.TMsgDlgBtn.mbCancel,
    procedure(const AResult: TModalResult)
    begin
      if AResult = mrYES then
         ShowMessage('You chose Yes') else
      if AResult = mrNo then
         ShowMessage('You chose No') else
      if AResult = mrCancel then
         ShowMessage('You chose Cancel');
      end);
end;

//Add By Flying Wang.
procedure TMessageAlertsForm.ButtonInputQueryClick(Sender: TObject);
var
  AString: string;
begin
  AString := 'Old string';
  //Fix By Flying wang
{$IFDEF ANDROID}
  MessageDialog_CanceledOnTouchOutsid := CheckBox1.IsChecked;
  MessageDialog_Canceleable := CheckBox2.IsChecked;
{$ENDIF ANDROID}
  InputBox('输入对话框',
    'Input a text:', AString,
    procedure(const AResult: TModalResult; const AValue: string)
    begin
      AString := AValue;
      if AResult = mrOK then
         ShowMessage('Youer input text is:' + AString) else
      if AResult = mrCancel then
         ShowMessage('You chose Cancel');
    end);

end;

Page: [1]
CJC好玩背单词最新版本 - 是目前最好的背单词软件,游戏好玩,功能强大,词库众多,还有真人语音,免费下载,免费试用 !

Powered by Discuz! Archiver 6.1.0  © 2001-2007 Comsenz Inc.