Recent

Author Topic: I need some more advanced message box?  (Read 8609 times)

CM630

  • Hero Member
  • *****
  • Posts: 1082
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
I need some more advanced message box?
« on: February 21, 2018, 08:36:26 am »
I need some more advanced message box than the ones available in Lazarus, or precisely I need:
 1. Vertical positioning of buttons (per setting). Hopefully when buttons are vertically positioned they have equal widths.
 2. Translatable button captions.
 3. No Delphi-like icons on the buttons.
 4. Text of the message to be displayed in a text box (not in a label), so it could be copied.
 5. A „don't show again‟ check box.

Could someone offer me a ready solution?
« Last Edit: February 21, 2018, 08:39:58 am by CM630 »
Лазар 3,2 32 bit (sometimes 64 bit); FPC3,2,2; rev: Lazarus_3_0 on Win10 64bit.

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: I need some more advanced message box?
« Reply #1 on: February 21, 2018, 08:41:57 am »
try syntaskdialog https://github.com/synopse/mORMot/blob/master/SynTaskDialog.pas I have no idea what is the coverage rate for your requirements but it is more advanced than the default lcl dialogs.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: I need some more advanced message box?
« Reply #2 on: February 21, 2018, 05:19:21 pm »
Lazarus 1.8 has TTaskDialog.

Bart

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: I need some more advanced message box?
« Reply #3 on: February 21, 2018, 06:10:39 pm »
I need some more advanced message box than the ones available in Lazarus, or precisely I need:
 1. Vertical positioning of buttons (per setting). Hopefully when buttons are vertically positioned they have equal widths.
 ...

Do you need an arbitrary number of buttons, and what should be their layout in relation to the copyable message (one line or multi-line?) and checkbox?
Do you always need a Close or Cancel or OK button?

CM630

  • Hero Member
  • *****
  • Posts: 1082
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: I need some more advanced message box?
« Reply #4 on: February 23, 2018, 08:58:16 pm »
Currently I use QuestionDialog.
1. It is quite okay for up to three buttons, but when I got to four, they became too narrow.
Buttons do not contain Yes, No... but rather: "Close App, Save all open files", "Close App, do not save files", ""Close App, save only tihs file" and "Don't close app, I have reconsidered"...

So vertical positioning becomes necessary.
2. QuestionDialog prints content of the message in a label instead in a(n uneditable) text box, so it cannot copied to the clipboard. Quite inconvenient for error messages when user needs to search help for the issue. There could be a popup menu "With copy to clipboard" at least.
3. I have never needed a "Do not show again" checkbox but some day I might.


Thanks, I will check TTaskDialog. syntaskdialog has no example and documentation, so I shooting in the dark might take more time than modifying QuestionDIalog (or sth. else)
« Last Edit: February 23, 2018, 09:03:57 pm by CM630 »
Лазар 3,2 32 bit (sometimes 64 bit); FPC3,2,2; rev: Lazarus_3_0 on Win10 64bit.

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: I need some more advanced message box?
« Reply #5 on: February 23, 2018, 10:25:34 pm »
AFAIK QuestionDlg calls a native dialog, and most of the WS support copying the message to the clipboard.

Very long button captions are IMO more often than not confusing.

I foy want to build your own, maybe take a look at the CreateMesageDialog function, IIRC it also has a vertical layout (it uses that for small screens).

Bart

RAW

  • Hero Member
  • *****
  • Posts: 868
Re: I need some more advanced message box?
« Reply #6 on: February 23, 2018, 10:45:07 pm »
A simple function can do the job...
- Form + Memo + Buttons + ModalResult + Whatever...  :)

Maybe something like this for example...
Code: Pascal  [Select][+][-]
  1. Function TForm1.DialogWnd
  2.  (strWndTxt, strTxt: String; wndCalcPos: TForm; booOkBtn: Boolean): String;
  3.   Const
  4.    MyFont = 'Arial';
  5.   Var
  6.    Wnd: TForm; Memo: TMemo;
  7.    btnYes, btnNo, btnCancel: TButton;
  8.  
  9.    iBtnX, iBtnY, iDlgX, iDlgY, iDlgTop, iDlgLeft,
  10.    iWorkAreaX, iWorkAreaY, iWALeft, iWATop: Integer;
  11.  Begin
  12.   Try
  13.    Result:= '';
  14.     wnd:= TForm.Create(Nil);
  15.      Try
  16.       wnd.Color         := clBtnFace;
  17.       wnd.Caption       := strWndTxt;
  18.       wnd.BorderStyle   := bsSizeable;
  19.       wnd.DoubleBuffered:= True;
  20.       wnd.BorderIcons   := [];
  21.  
  22.       iDlgX:= wndCalcPos.Width;
  23.       iDlgY:= wndCalcPos.Height;
  24.  
  25.       If iDlgX < 300 Then iDlgX:= 300;
  26.       If iDlgY < 200 Then iDlgY:= 200;
  27.  
  28.       If iDlgX >= 800 Then iDlgX:= iDlgX Div 2;
  29.       If iDlgY >= 550 Then iDlgY:= iDlgY Div 2;
  30.  
  31.       iDlgLeft:= wndCalcPos.Left+((wndCalcPos.Width -iDlgX) Div 2);
  32.       iDlgTop := wndCalcPos.Top +((wndCalcPos.Height-iDlgY) Div 2);
  33.  
  34.       iWorkAreaX:= Screen.WorkAreaWidth;
  35.       iWorkAreaY:= Screen.WorkAreaHeight;
  36.       iWALeft   := Screen.WorkAreaLeft;
  37.       iWATop    := Screen.WorkAreaTop;
  38.  
  39.       If iDlgLeft < iWALeft Then iDlgLeft:= iWALeft+40;
  40.       If iDlgTop  < iWATop  Then iDlgTop := iWATop +40;
  41.  
  42.       If iDlgTop   > (iWorkAreaY-iDlgY)
  43.       Then iDlgTop:= (iWorkAreaY-iDlgY-40);
  44.  
  45.       If iDlgLeft   > (iWorkAreaX-iDlgX)
  46.       Then iDlgLeft:= (iWorkAreaX-iDlgX-40);
  47.  
  48.       wnd.SetBounds(iDlgLeft, iDlgTop, iDlgX, iDlgY);
  49.  
  50.       wnd.Constraints.MinHeight:= wnd.Height;
  51.       wnd.Constraints.MaxHeight:= wnd.Height;
  52.       wnd.Constraints.MinWidth := wnd.Width;
  53.       wnd.Constraints.MaxWidth := wnd.Width;
  54.  
  55.       btnYes               := TButton.Create(wnd);
  56.       btnYes.Caption       := 'YES';
  57.       btnYes.Font.Name     := MyFont;
  58.       btnYes.Font.Quality  := fqAntialiased;
  59.       btnYes.Font.Style    := [fsBold];
  60.       btnYes.DoubleBuffered:= True;
  61.       btnYes.ModalResult   := mrYes;
  62.       btnYes.Parent        := wnd;
  63.  
  64.       btnNo               := TButton.Create(wnd);
  65.       btnNo.Caption       := 'NO';
  66.       btnNo.Font.Name     := MyFont;
  67.       btnNo.Font.Quality  := fqAntialiased;
  68.       btnNo.Font.Style    := [fsBold];
  69.       btnNo.DoubleBuffered:= True;
  70.       btnNo.ModalResult   := mrNo;
  71.       btnNo.Parent        := wnd;
  72.  
  73.       btnCancel               := TButton.Create(wnd);
  74.       btnCancel.Caption       := 'CANCEL';
  75.       btnCancel.Font.Name     := MyFont;
  76.       btnCancel.Font.Quality  := fqAntialiased;
  77.       btnCancel.Font.Style    := [fsBold];
  78.       btnCancel.DoubleBuffered:= True;
  79.       btnCancel.ModalResult   := mrCancel;
  80.       btnCancel.Parent        := wnd;
  81.  
  82.       iBtnX:= (wnd.ClientWidth-20) Div 3;
  83.       iBtnY:= iBtnX Div 5;
  84.  
  85.       btnYes.SetBounds(5, wnd.ClientHeight-iBtnY, iBtnX, iBtnY);
  86.       btnNo.SetBounds((wnd.ClientWidth-iBtnX) Div 2, btnYes.Top, iBtnX, iBtnY);
  87.       btnCancel.SetBounds(wnd.ClientWidth-iBtnX-5, btnYes.Top, iBtnX, iBtnY);
  88.  
  89.       Canvas.Font.Size   := 1;
  90.       Canvas.Font.Name   := MyFont;
  91.       Canvas.Font.Style  := btnCancel.Font.Style;
  92.       Canvas.Font.Quality:= fqAntialiased;
  93.  
  94.       While Not (Canvas.TextWidth('CANCEL') > iBtnX-20)
  95.       Do Canvas.Font.Size:= Canvas.Font.Size+1;
  96.  
  97.       While (Canvas.TextHeight('CANCEL') > btnCancel.ClientHeight)
  98.       Do Canvas.Font.Size:= Canvas.Font.Size-1;
  99.  
  100.       btnYes.Font.Size   := Canvas.Font.Size;
  101.       btnNo.Font.Size    := btnYes.Font.Size;
  102.       btnCancel.Font.Size:= btnYes.Font.Size;
  103.  
  104.       Memo               := TMemo.Create(wnd);
  105.       Memo.Font.Name     := MyFont;
  106.       Memo.Font.Size     := wnd.ClientWidth Div 20;
  107.       Memo.Font.Style    := [fsBold];
  108.       Memo.Font.Quality  := fqAntialiased;
  109.       Memo.Font.Color    := clBtnText;
  110.       Memo.Color         := clBtnFace;
  111.       Memo.Alignment     := taCenter;
  112.       Memo.BorderStyle   := bsNone;
  113.       Memo.HideSelection := True;
  114.       Memo.Text          := strTxt;
  115.       Memo.ReadOnly      := True;
  116.       Memo.WordWrap      := True;
  117.       Memo.WantTabs      := False;
  118.       Memo.DoubleBuffered:= True;
  119.       Memo.WantReturns   := False;
  120.       Memo.ScrollBars    := ssAutoVertical;
  121.       Memo.SetBounds     (0, 0, wnd.ClientWidth, wnd.ClientHeight-iBtnY-10);
  122.       Memo.Parent        := wnd;
  123.  
  124.       If booOkBtn
  125.       Then
  126.        Begin
  127.         btnYes.Hide;
  128.         btnCancel.Hide;
  129.         btnNo.Caption:= 'OK';
  130.         wnd.ActiveControl:= btnNo;
  131.        End
  132.       Else wnd.ActiveControl:= btnYes;
  133.  
  134.       wnd.ShowModal;
  135.  
  136.       Case wnd.ModalResult
  137.       Of
  138.        mrYes   : Result:= 'YES';
  139.        mrNo    : Result:= 'NO';
  140.        mrCancel: Result:= 'CANCEL';
  141.       End;
  142.      Finally
  143.       wnd.Release;
  144.       wnd:= Nil;
  145.      End;
  146.   Except
  147.   End;
  148.  End;

Code: Pascal  [Select][+][-]
  1. Procedure TForm1.FormClick(Sender: TObject);
  2.  Begin
  3.   Case DialogWnd('MyProgram', 'ERROR XYZ...', Self, False)
  4.   Of
  5.    'YES'   : ShowMessage('YES');
  6.    'NO'    : ShowMessage('NO');
  7.    'CANCEL': ShowMessage('CANCEL');
  8.   End;
  9.  End;
Windows 7 Pro (x64 Sp1) & Windows XP Pro (x86 Sp3).

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: I need some more advanced message box?
« Reply #7 on: February 23, 2018, 11:01:39 pm »
Very long button captions are IMO more often than not confusing.
+1 the option description is to be shown on the message it self not the buttons its not by accident that the only choices on buttons are yes, yes to all, no, no to all, ok, cancel.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: I need some more advanced message box?
« Reply #8 on: February 24, 2018, 12:37:15 am »
You could try something like the attached project.

RAW

  • Hero Member
  • *****
  • Posts: 868
Re: I need some more advanced message box?
« Reply #9 on: February 24, 2018, 06:03:56 am »
Works good for me... thanks for sharing... :)
Windows 7 Pro (x64 Sp1) & Windows XP Pro (x86 Sp3).

CM630

  • Hero Member
  • *****
  • Posts: 1082
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: I need some more advanced message box?
« Reply #10 on: March 02, 2018, 10:53:54 am »
You could try something like the attached project.
Since caption need to be localised I tried this:


Code: Pascal  [Select][+][-]
  1. ...
  2.  
  3. type
  4.  
  5.  
  6.   TButtonArray = array of TButton;
  7.  
  8.  
  9.   TLocalisationStrings= record
  10.     DoNotShowAgain:string;
  11.     CopyToClipboard: string;
  12.   end;
  13.  
  14.  
  15. type
  16.   TDlgForm = class(TForm)
  17.   private
  18.     FButtonModalResult: TModalResult;
  19.     FButtons: TButtonArray;
  20.     FCheckBox: TCheckBox;
  21.     FMessage: TEdit;
  22.     FMessagePopup: TPopupMenu;
  23.     function GetCheckBoxChecked: Boolean;
  24.     procedure ButtonClick(Sender: TObject);
  25.     procedure PopupClick({%H-}Sender: TObject);
  26.   public
  27.     constructor Create(anOwner: TComponent; aButtons: array of const;
  28.                        const aCaption, aMsg: String;
  29.                        aShowCheckBox: Boolean=False;
  30.                        aMargin: Integer=15; LocalisationStrings: TLocalisationStrings); reintroduce;
  31.     property ButtonModalResult: TModalResult read FButtonModalResult;
  32.     property CheckBoxChecked: Boolean read GetCheckBoxChecked;
  33.   end;    
  34. ...
But it complains „Default parameter required for "LOCALISATIONSTRINGS"‟.
Then I added default values and compiler said sth. like „Default parameters cannot be provided for this type‟.
Same with


Code: Pascal  [Select][+][-]
  1.  
  2. function QuestionVDlg(const aCaption, aMsg: String; Buttons: array of const;
  3.                       out CheckBoxChecked: Boolean;
  4.                       showCheckBox: Boolean=False; aMargin: Integer = 15; LocalisationStrings: TLocalisationStrings): TModalResult;
  5.  
I googled around, there are some examples with records as input parameters for routines, what is wrong with mine?
« Last Edit: March 02, 2018, 10:59:28 am by CM630 »
Лазар 3,2 32 bit (sometimes 64 bit); FPC3,2,2; rev: Lazarus_3_0 on Win10 64bit.

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: I need some more advanced message box?
« Reply #11 on: March 02, 2018, 11:41:59 am »
Parameters with default values must be last in the parameter list.
So simply move the localization record ahead in the list:
Code: Pascal  [Select][+][-]
  1.     constructor Create(anOwner: TComponent; aButtons: array of const;
  2.                        const aCaption, aMsg: String;
  3.                        LocalisationStrings: TLocalisationStrings;
  4.                        aShowCheckBox: Boolean=False;
  5.                        aMargin: Integer=15); reintroduce;
                 

CM630

  • Hero Member
  • *****
  • Posts: 1082
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: I need some more advanced message box?
« Reply #12 on: March 02, 2018, 12:52:25 pm »
Parameters with default values must be last in the parameter list.
So simply move the localization record ahead in the list:

Silly me... too bad I cannot provide defaults for a record, anyway.
I suppose I can overload.

After trying to use, it crashes. Seems 'IsCancel' is not implemented (and respectively 'IsDefault').[/size]
  mr:=QuestionVDlg('Closing this app', 'Should any files be saved?',
                   [mrYesToAll, 'Close App, save ALL open files',
                    mrNo,       'Close App, do NOT save files',
                    mrYes,      'Close App, save ONLY this file',
                    mrIgnore,   'Don''t close app, I have reconsidered','IsCancel'],
                    bool,LocStr, False, 20);   
« Last Edit: March 02, 2018, 01:37:44 pm by CM630 »
Лазар 3,2 32 bit (sometimes 64 bit); FPC3,2,2; rev: Lazarus_3_0 on Win10 64bit.

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: I need some more advanced message box?
« Reply #13 on: March 02, 2018, 02:41:58 pm »
No you cannot have a record as a default, but you could have two string parameters as a default that you later combined into a record (if needed).
For help with the crash you would need to share a simple compilable project that shows the problem.

CM630

  • Hero Member
  • *****
  • Posts: 1082
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: I need some more advanced message box?
« Reply #14 on: March 02, 2018, 03:32:11 pm »
Sample attached- your unmodified component, I have only added 'IsCancel' (as described in my previous post), which is handled by (together with 'IsDefault') the inbuilt QuestionDialog.
Лазар 3,2 32 bit (sometimes 64 bit); FPC3,2,2; rev: Lazarus_3_0 on Win10 64bit.

 

TinyPortal © 2005-2018