1

Is there a Firemonkey equivalent for Windows' MessageBox(), i.e. where the dialog's caption/title can be set? I know I can make one myself but prefer to use an existing solution, but I can't seem to find it.

Marcus Adams
  • 53,009
  • 9
  • 91
  • 143
Mike Versteeg
  • 1,615
  • 14
  • 28
  • 1
    I dont think there is one. I ended up writing a wrapper class, which uses MessageBox on Windows and NSAlert on OSX. The build in MessageDlg also had issues with localisation. – DA. Jan 31 '14 at 05:29
  • Ah, yet another piece of code I will be writing twice. I started out using FMX thinking I could write all code once, but I find myself learning more and more about coding for the Mac :). Thanks, I'll look up NSAlert. – Mike Versteeg Jan 31 '14 at 09:46
  • What header file do I need to include to be able to use NSAlert? I cannot seem to find it, and the help does not help much (as usual). – Mike Versteeg Jan 31 '14 at 13:46

3 Answers3

3

ok here is my example how I am using NSAlert:

unit DAMessageBox;

interface

uses
  System.SysUtils,
  System.IOUtils,
  FMX.Dialogs,
  System.UITypes,
{$IFDEF MSWINDOWS}
  Winapi.ShellAPI, Winapi.Windows, Vcl.Forms;
{$ENDIF MSWINDOWS}
{$IFDEF POSIX}
  Macapi.CocoaTypes, Macapi.Foundation, Macapi.AppKit,
  Posix.Stdlib;
{$ENDIF POSIX}

type
  TDAMessageBox = class
    class function MessageDialog(const Title: String; const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; HelpCtx: Longint) : integer;
  end;

implementation


class function TDAMessageBox.MessageDialog(const Title: String; const Msg: string; DlgType: TMsgDlgType;
  Buttons: TMsgDlgButtons; HelpCtx: Integer): integer;
var
{$IFDEF MSWINDOWS}
  WinButtons : Cardinal;
  WinType : Cardinal;
{$ENDIF WINDOWS}
{$IFDEF POSIX}
  Alert: NSAlert;
  Style: NSAlertStyle;
  DlgRes : Integer;
{$ENDIF POSIX}
begin
{$IFDEF MSWINDOWS}
  case DlgType of
    TMsgDlgType.mtWarning: WinType:= MB_ICONWARNING;
    TMsgDlgType.mtError: WinType:= MB_ICONSTOP;
    TMsgDlgType.mtInformation: WinType:= MB_ICONINFORMATION;
    TMsgDlgType.mtConfirmation: WinType:= MB_ICONQUESTION;
    TMsgDlgType.mtCustom: WinType:= MB_ICONINFORMATION;
  end;

  if Buttons = mbOKCancel then begin
    WinButtons:= MB_OKCANCEL;
  end;

  if Buttons = mbYesNo then begin
    WinButtons:= MB_YESNO;
  end;

  if Buttons = mbYesNoCancel then begin
    WinButtons:= MB_YESNOCANCEL;
  end;

  Result:= MessageBox(Application.Handle, PChar(Msg), PChar(Title), WinType or WinButtons);
{$ENDIF MSWINDOWS}

{$IFDEF POSIX}
  Alert:= TNSAlert.Create;
  //map the configurations:
  //mtWarning, mtError, mtInformation, mtConfirmation

  case DlgType of
    TMsgDlgType.mtWarning: Style:= NSWarningAlertStyle;
    TMsgDlgType.mtError: Style:= NSCriticalAlertStyle;
    TMsgDlgType.mtInformation: Style:= NSInformationalAlertStyle;
    TMsgDlgType.mtConfirmation: Style:= NSInformationalAlertStyle;
    TMsgDlgType.mtCustom: Style:= NSInformationalAlertStyle;
  end;

  try
    Alert.setMessageText(NSSTR(Title));
    Alert.setInformativeText(NSSTR(Msg));
    Alert.setAlertStyle(Style);

    //add dialog buttons, note: there are only 3 buttons allowed:
    //mbAbortIgnore, mbAbortRetryIgnore, *mbOKCancel,mbYesAllNoAllCancel, mbYesAllNoAllCancel, *mbYesNo, *mbYesNoCancel
    //currently I only map the ones I need here

    if Buttons = mbOKCancel then begin
      //Writeln('mbOKCancel');
      Alert.addButtonWithTitle(NSSTR('OK'));
      Alert.addButtonWithTitle(NSSTR('Cancel'));
    end;

    if Buttons = mbYesNo then begin
      //Writeln('mbYesNo');
      Alert.addButtonWithTitle(NSSTR('Yes'));
      Alert.addButtonWithTitle(NSSTR('No'));
    end;

    if Buttons = mbYesNoCancel then begin
      //Writeln('mbYesNoCancel');
      Alert.addButtonWithTitle(NSSTR('Yes'));
      Alert.addButtonWithTitle(NSSTR('No'));
      Alert.addButtonWithTitle(NSSTR('Cancel'));
    end;

    DlgRes := Alert.runModal;

    //map the result to Delphi Consts
    //NSAlertFirstButtonReturn  = 1000,
    //NSAlertSecondButtonReturn  = 1001,
    //NSAlertThirdButtonReturn  = 1002

    if Buttons = mbOKCancel then begin
      if DlgRes = NSAlertFirstButtonReturn then Result := idYes;
      if DlgRes = NSAlertSecondButtonReturn then Result := idNo;
    end;

    if (Buttons = mbYesNo) or (Buttons = mbYesNoCancel)  then begin
      if DlgRes = NSAlertFirstButtonReturn then Result := idYes;
      if DlgRes = NSAlertSecondButtonReturn then Result := idNo;
      if DlgRes = NSAlertThirdButtonReturn then Result := idCancel;
    end;

  finally
    Alert.release;
  end;

{$ENDIF POSIX}

end;

end.

The MessagBox call is similar to the MessageDlg call in FireMonkey:

TDAMessageBox.MessageDialog('Title', 'Message Text', TMsgDlgType.mtError, mbYesNoCancel, 0);

The result looks like that:

enter image description here

DA.
  • 849
  • 6
  • 19
  • Did not even try this code as I notice there is no way to set the title, which was the reason for my post. Also, having seen NSAlert (ShowMessage translates to it) it looks like a real alert box while I need a common dialog to show some information. – Mike Versteeg Feb 03 '14 at 13:59
  • Yes you are right. I added the "title" to the example. For NSAlert you can add two texts: Alert.setMessageText(NSSTR(Title)); and Alert.setInformativeText(NSSTR(Msg));. Its not really a Window title as on Window, its showing two texts in the dialog. – DA. Feb 03 '14 at 22:39
  • Sorry for commenting on an old message. I found this solution recently and have been using it in FMX with Delphi 10.4. It gives a very annoying issue in the following way. After the message box appears click a window in another application, then click the message box again somewhere on the form (not the title bar). The main form immediately gains focus and the message box is hidden behind. The message box is still active so you can't move the main form or do anything with it to get the message box back. The only thing left to do is close the application from task manager. Any ideas so solve? – XylemFlow Jul 28 '21 at 08:36
  • Sorry no, I am no longer using Delphi :-( – DA. Jul 28 '21 at 09:06
0

Have a look at this answer. Using the Open Source SynTaskDialog for Lazarus and FireMonkey, you can define a custom message box or a message box replacement where the dialog caption can be set.

It does work on Firemonkey in Windows, but I haven't tested it under OSX until now.

Community
  • 1
  • 1
yonojoy
  • 5,486
  • 1
  • 31
  • 60
0

Another method, that works on all OS, takes almost the same time to write, and is much more flexible : Create a new Form, say with name "fmDialog1", put the Title and Text(s) you want (and possibly some images), and Buttons such as OK, Cancel, Yes, No, etc. Give each button a different value, non zero, to its ModalResult property

Then in the code where the dialog is needed, write (in C++) aa=fmDialog1->ShowModal(); or (in Pascal/Delphi) aa:=fmDialog1.ShowModal(); and test aa to see which button was selected by the user.

In Android apps, you may have to add a loop to overcome the asynchronous character of ShowModal.