Recent

Author Topic: Improving custom message box  (Read 841 times)

pascal111

  • Sr. Member
  • ****
  • Posts: 420
  • Un trabajo en equipo para programas serias.
Improving custom message box
« on: June 29, 2022, 07:19:39 pm »
Hi! everyone! this is a unit has a procedure taken from another page in the forum for making a custom message box. And this is the code with my small changes. I would like to add "mtInformation" icon and don't know how to do it, and you can tell me with any more improvements for this custom message box, and I'll appreciate that.

the unit with my changes:

https://github.com/pascal111-fra/Lazarus-programs/blob/main/helper1.pas

Original code here:
https://forum.lazarus.freepascal.org/index.php?topic=34704.0
La chose par la chose est rappelé.

wp

  • Hero Member
  • *****
  • Posts: 9906
Re: Improving custom message box
« Reply #1 on: June 29, 2022, 10:20:48 pm »
I reworked your code, added the "Information" icon from the Lazarus resource, removed memory leaks and the crash when other_form is nil, and auto-aligned the controls in the form. Set the BiDiMode of your main form the bdRightToLeft to get right-to-left text direction.

Code: Pascal  [Select][+][-]
  1. uses
  2.   LCLType;
  3.  
  4. procedure MessageBox2(title_string, msg_string:string; other_form:tform);
  5. var
  6.   frmDialog : TForm;
  7.   lblMsg : TLabel;
  8.   btnClose: TBitBtn;
  9.   panel: TPanel;
  10.   img: TImage;
  11. begin
  12.  
  13.   // Original code is in:
  14.   // https://forum.lazarus.freepascal.org/index.php?topic=34704.0
  15.  
  16.   frmDialog:=TForm.CreateNew(nil);
  17.   try
  18.     with frmDialog do
  19.     begin
  20.       panel := TPanel.Create(frmDialog);
  21.       panel.Align := alClient;
  22.       panel.caption := '';
  23.       panel.BevelOuter := bvNone;
  24.       panel.Parent := frmDialog;
  25.       panel.AutoSize := true;
  26.       panel.Constraints.MinWidth := 300;
  27.      
  28.       img := TImage.Create(frmDialog);
  29.       img.Align := alLeft;
  30.       img.BorderSpacing.Around := 12;
  31.       img.AutoSize := true;
  32.       img.Parent := panel;
  33.       img.Picture.Assign(GetDialogIcon(idDialogInfo));
  34.       // Other options to be used by GetDialogIcon are
  35.       //  idDialogWarning, idDialogError, idDialogConfirm, idDialogShield
  36.  
  37.       lblMsg := TLabel.Create(frmDialog);
  38.       lblMsg.AutoSize:=True;
  39.       lblMsg.Align:=alClient;
  40.       lblMsg.BorderSpacing.Around := 12;
  41.       lblMsg.Caption:=msg_string;
  42.       lblMsg.Wordwrap := true;
  43.       lblMsg.Parent:=panel;
  44.  
  45.       btnClose := TBitBtn.Create(frmDialog);
  46.       btnClose.Parent:=frmDialog;
  47.       btnClose.Kind:=bkOK;
  48.       btnClose.Align:=alBottom;
  49.       btnClose.AutoSize := true;
  50.       btnClose.BorderSpacing.Around := 6;
  51.  
  52.       AutoSize := True;
  53.       BorderStyle:=bsDialog;
  54.       BiDiMode := Application.MainForm.BiDiMode;
  55.       caption:=title_string;
  56.       if other_form <> nil then
  57.       begin
  58.         top:=other_form.Top+(other_form.Width div 3);
  59.         left:=other_form.Left+(other_form.height div 2);
  60.       end else
  61.         Position := poMainFormCenter;
  62.       ShowModal;
  63.     end;
  64.   finally
  65.     frmDialog.Free;
  66.   end;
  67. end;

pascal111

  • Sr. Member
  • ****
  • Posts: 420
  • Un trabajo en equipo para programas serias.
Re: Improving custom message box
« Reply #2 on: June 30, 2022, 12:50:07 am »
Good job! @wp,
I can say it's perfect if I could have the power of moving the icon as I want little to right or bottom, also if I can move the label little to the left or to bottom, also if  I can make the OK button narrower. How can I do that if I liked? I tried to modify some properties and faild to do it.

I made small changes in your code and made some tests:

https://i.postimg.cc/MKtTKbc5/pas2-Untitled-1-copy.jpg

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls,
  9.   LCLIntf, Buttons, helper1, LCLType, ExtCtrls;
  10.  
  11. type
  12.  
  13.   { TForm1 }
  14.  
  15.   TForm1 = class(TForm)
  16.     Button1: TButton;
  17.     Label1: TLabel;
  18.     procedure Button1Click(Sender: TObject);
  19.     procedure FormCreate(Sender: TObject);
  20.   private
  21.  
  22.   public
  23.  
  24.   end;
  25.  
  26. var
  27.   Form1: TForm1;
  28.  
  29.  
  30. procedure MessageBox3(title_string, msg_string:string; other_form:tform);
  31.  
  32. implementation
  33.  
  34. {$R *.lfm}
  35.  
  36. { TForm1 }
  37.  
  38. procedure TForm1.FormCreate(Sender: TObject);
  39.  
  40.  
  41.  
  42. begin
  43.  
  44.  
  45.  
  46. end;
  47.  
  48. procedure TForm1.Button1Click(Sender: TObject);
  49. begin
  50.     MessageBox3('أهلاً','بسم الله الرحمن الرحيم'#13#10'الحمد لله'#13#10'كيف حالكم' ,form1);
  51.  
  52.     //MessageBox3('أهلاً','عُذراً' ,form1);
  53. end;
  54.  
  55. procedure MessageBox3(title_string, msg_string:string; other_form:tform);
  56. var
  57.   frmDialog : TForm;
  58.   lblMsg : TLabel;
  59.   btnClose: TBitBtn;
  60.   panel: TPanel;
  61.   img: TImage;
  62. begin
  63.  
  64.   // Original code is in:
  65.   // https://forum.lazarus.freepascal.org/index.php?topic=34704.0
  66.  
  67.   frmDialog:=TForm.CreateNew(nil);
  68.   try
  69.     with frmDialog do
  70.     begin
  71.       panel := TPanel.Create(frmDialog);
  72.       panel.Align := alClient;
  73.       panel.caption := '';
  74.       panel.BevelOuter := bvNone;
  75.       panel.Parent := frmDialog;
  76.       panel.AutoSize := true;
  77.       panel.Constraints.MinWidth := 300;
  78.  
  79.       img := TImage.Create(frmDialog);
  80.       img.Align := alLeft;
  81.       img.BorderSpacing.Around := 12;
  82.       img.AutoSize := true;
  83.       img.Parent := panel;
  84.       img.Picture.Assign(GetDialogIcon(idDialogInfo));
  85.       // Other options to be used by GetDialogIcon are
  86.       //  idDialogWarning, idDialogError, idDialogConfirm, idDialogShield
  87.  
  88.       lblMsg := TLabel.Create(frmDialog);
  89.       lblMsg.AutoSize:=True;
  90.       lblMsg.Align:=alRight;
  91.       lblMsg.BorderSpacing.Around := 12;
  92.       lblMsg.Caption:=msg_string;
  93.       lblMsg.Wordwrap := true;
  94.       lblMsg.Parent:=panel;
  95.  
  96.       btnClose := TBitBtn.Create(frmDialog);
  97.       btnClose.Parent:=frmDialog;
  98.       btnClose.Kind:=bkOK;
  99.       btnClose.Align:=alBottom;
  100.       btnClose.AutoSize := true;
  101.       btnClose.BorderSpacing.Around := 6;
  102.       btnClose.Caption:='حسناً';
  103.  
  104.       AutoSize := True;
  105.       BorderStyle:=bsDialog;
  106.       BiDiMode := Application.MainForm.BiDiMode;
  107.       caption:=title_string;
  108.       if other_form <> nil then
  109.       begin
  110.         top:=other_form.Top+(other_form.Width div 3);
  111.         left:=other_form.Left+(other_form.height div 2);
  112.       end else
  113.         Position := poMainFormCenter;
  114.       ShowModal;
  115.     end;
  116.   finally
  117.     frmDialog.Free;
  118.   end;
  119. end;
  120.  
  121.  
  122.  
  123. end.
  124.  
  125.  
La chose par la chose est rappelé.

wp

  • Hero Member
  • *****
  • Posts: 9906
Re: Improving custom message box
« Reply #3 on: June 30, 2022, 11:53:29 am »
Please attach images to your forum posts instead of some third-party cloud sites which will be gone at some time in the future.

The controls in the messagebox are aligned, anchored and auto-sized to avoid any size-calculations. Therefore, you cannot move them by changing their Left, Top, etc properities. Due due this kind of layout their position is determined by the BorderSpacing properties. I now replace the BorderSpacing.Around (which applies to all sides) by individual parameters BorderSpacing.Left, BorderSpacing.Top, etc. The attached modified code contains comments which explain to which distance parameter the current value of the BorderSpacing applies.

My layout is designed for left-to-right reading direction, such as in Europe. If you want to have right-to-left mode like in the Near-East, you should set the BiDiMode of the form to bdRightToLeft, and this should exchange the left and right coordinates and render text from right to left. In case of the messagebox, the messagebox takes the BiDiMode value of the main form and sets its own BiDiMode accordingly. Test in the attached demo.
« Last Edit: June 30, 2022, 11:59:31 am by wp »

pascal111

  • Sr. Member
  • ****
  • Posts: 420
  • Un trabajo en equipo para programas serias.
Re: Improving custom message box
« Reply #4 on: June 30, 2022, 12:42:08 pm »
Quote
Please attach images to your forum posts instead of some third-party cloud sites which will be gone at some time in the future.


I tried some other ways and failed maybe due our internet here in my area in Egypt. This is the best site I have. If you know better way, tell me.

I think I like your last configurations on your code, and can't ask you to do more efforts, it's not my right, and you denoted it to us freely, thanks for that and I hope I can help you too as a reward.

I tested the code under Red Hat platform and it seems so nice:
https://i.postimg.cc/76Jw2pKq/Screenshot-from-2022-06-30-06-29-56.png

So small changes I made in your code:

Code: Pascal  [Select][+][-]
  1. procedure MessageBox3(title_string, msg_string:string; other_form:tform);
  2. var
  3.   frmDialog : TForm;
  4.   lblMsg : TLabel;
  5.   btnClose: TBitBtn;
  6.   panel: TPanel;
  7.   img: TImage;
  8. begin
  9.  
  10.   // Original code is in:
  11.   // https://forum.lazarus.freepascal.org/index.php?topic=34704.0
  12.  
  13.   frmDialog:=TForm.CreateNew(nil);
  14.   try
  15.     with frmDialog do
  16.     begin
  17.       BiDiMode := bdRightToLeft;  //Application.MainForm.BiDiMode;
  18.  
  19.       panel := TPanel.Create(frmDialog);
  20.       panel.Align := alClient;
  21.       panel.caption := '';
  22.       panel.BevelOuter := bvNone;
  23.       panel.Parent := frmDialog;
  24.       panel.AutoSize := true;
  25.       panel.Constraints.MinWidth := 300;
  26.  
  27.       img := TImage.Create(frmDialog);
  28.       if BiDiMode = bdRightToLeft then
  29.       begin
  30.         img.Align := alRight;
  31.         img.BorderSpacing.Right := 12;  // Distance of image to right side of form
  32.       end else
  33.       begin
  34.         img.Align := alLeft;
  35.         img.BorderSpacing.Left := 12;   // Distance of image to left side of form
  36.       end;
  37.       img.BorderSpacing.Top := 12;      // Distance of image to top side of form
  38.       img.AutoSize := true;
  39.       img.Parent := panel;
  40.       img.Picture.Assign(GetDialogIcon(idDialogInfo));
  41.       // Other options to be used by GetDialogIcon are
  42.       //  idDialogWarning, idDialogError, idDialogConfirm, idDialogShield
  43.  
  44.       lblMsg := TLabel.Create(frmDialog);
  45.       lblMsg.AutoSize:=True;
  46.       lblMsg.Align := alClient;
  47.       if BiDiMode = bdRightToLeft then
  48.       begin
  49.         lblMsg.BorderSpacing.Right := 12;  // Distance of label to image
  50.         lblMsg.BorderSpacing.Left := 12;   // Distance of label to left side of form
  51.       end else
  52.       begin
  53.         lblMsg.BorderSpacing.Left := 12;   // Distance of label to image
  54.         lblMsg.BorderSpacing.Right := 12;  // Distance of label to right side of form
  55.       end;
  56.       lblMsg.BorderSpacing.Top := 12;
  57.       lblMsg.Caption:=msg_string;
  58.       lblMsg.Wordwrap := true;
  59.       lblMsg.Parent:=panel;
  60.  
  61.       panel := TPanel.Create(frmDialog);
  62.       panel.Align := alBottom;
  63.       panel.AutoSize := true;
  64.       panel.BevelOuter := bvNone;
  65.       panel.Caption := '';
  66.       panel.Parent := frmDialog;
  67.      
  68.       btnClose := TBitBtn.Create(frmDialog);
  69.       btnClose.Parent := panel;
  70.       btnClose.Kind:=bkOK;
  71.       btnClose.Anchors := [akLeft, akTop];
  72.       btnClose.AnchorSideLeft.Control := panel;
  73.       btnClose.AnchorSideLeft.Side := asrCenter;
  74.       btnClose.AutoSize := true;
  75.       btnClose.BorderSpacing.Top := 12;     // Distance of button to image or label, whichever is nearer
  76.       btnClose.BorderSpacing.Bottom := 6;   // Distance of button to bottom side of form
  77.       btnClose.Caption:='حسناً';
  78.  
  79.       AutoSize := True;
  80.       BorderStyle:=bsDialog;
  81.       caption:=title_string;
  82.       if other_form <> nil then
  83.       begin
  84.         top:=other_form.Top+(other_form.Width div 3);             // shouldn't be other_form.Height here?
  85.         left:=other_form.Left+(other_form.height div 2);          // and other_form.Width here?
  86.       end else
  87.         Position := poMainFormCenter;
  88.       ShowModal;
  89.     end;
  90.   finally
  91.     frmDialog.Free;
  92.   end;
  93. end;
  94.  
  95.  
La chose par la chose est rappelé.

wp

  • Hero Member
  • *****
  • Posts: 9906
Re: Improving custom message box
« Reply #5 on: June 30, 2022, 01:27:30 pm »
Quote
Please attach images to your forum posts instead of some third-party cloud sites which will be gone at some time in the future.
I tried some other ways and failed maybe due our internet here in my area in Egypt. This is the best site I have. If you know better way, tell me.
I meant: If you want to attach an image to your forum post, click on "Attachments and other options" below the forum's edit box, and specify the name of the file to be attached in the "Attach" box. But note that the max upload size is 500 KB only which you can easily exceed with images. Always use a compressed format such as .jpg or .png. You can also add projects this way: Add the .pas, .lfm, .lpr and .lpi files to a common .zip which you can upload this way. Do not add the other files, and particularly not the binary because this will exceed the upload limit (and we don't need them anyway because we want to compile the project and see the issues ourselves).

pascal111

  • Sr. Member
  • ****
  • Posts: 420
  • Un trabajo en equipo para programas serias.
Re: Improving custom message box
« Reply #6 on: June 30, 2022, 04:55:55 pm »
Quote
I meant: If you want to attach an image to your forum post, click on "Attachments and other options" below the forum's edit box, and specify the name of the file to be attached in the "Attach" box. But note that the max upload size is 500 KB only which you can easily exceed with images. Always use a compressed format such as .jpg or .png. You can also add projects this way: Add the .pas, .lfm, .lpr and .lpi files to a common .zip which you can upload this way. Do not add the other files, and particularly not the binary because this will exceed the upload limit (and we don't need them anyway because we want to compile the project and see the issues ourselves).

I think you mentioned "500 KB"! is it per each time? I think that.

I modified my new unit "helper1" with code you provided me:

https://github.com/pascal111-fra/Lazarus-programs/blob/main/helper1.pas
La chose par la chose est rappelé.

wp

  • Hero Member
  • *****
  • Posts: 9906
Re: Improving custom message box
« Reply #7 on: June 30, 2022, 06:08:53 pm »
Did you see my comments that I added to the Top/Left calculation? I think other_form.Width and other_form.Height must be exchanged. And why "div 3" in one case, and "div 2" in the other?

pascal111

  • Sr. Member
  • ****
  • Posts: 420
  • Un trabajo en equipo para programas serias.
Re: Improving custom message box
« Reply #8 on: June 30, 2022, 06:16:14 pm »
Did you see my comments that I added to the Top/Left calculation? I think other_form.Width and other_form.Height must be exchanged. And why "div 3" in one case, and "div 2" in the other?

I didn't notice that. Ok! I'll fix it.
La chose par la chose est rappelé.

pascal111

  • Sr. Member
  • ****
  • Posts: 420
  • Un trabajo en equipo para programas serias.
Re: Improving custom message box
« Reply #9 on: June 30, 2022, 06:35:28 pm »
I fixed it, and why "div 2" now, because I'm searching for any proper ratio that places the message box close to the center of its calling form.

https://github.com/pascal111-fra/Lazarus-programs/blob/main/helper1.pas
La chose par la chose est rappelé.

wp

  • Hero Member
  • *****
  • Posts: 9906
Re: Improving custom message box
« Reply #10 on: June 30, 2022, 07:02:27 pm »
With this corrected, your code is placing the left/top corner of the message box over the center of the calling form. Is this intended? Or do you want to have the center of the message box over the center of the calling form? In this case you must also subtract half of the messagebox width and height from Left/Top (but it could be that the messagebox size is not yet known at this moment due to autosizing). If you set the message box's Position property to poOwnerForm and create the message box with the other form as owner you get this for free, without doing any calculation:
Code: Pascal  [Select][+][-]
  1.   frmDialog:=TForm.CreateNew(other_form);   // other_form rather than nil!
  2.   with frmDialog do begin
  3.   ...
  4.     if other_form <> nil then
  5.       Position := poOwnerFormCenter    // remove the Top/Left calculation that was here...
  6.     else
  7.       Position := poMainFormCenter;
  8.     ShowModal;
 

pascal111

  • Sr. Member
  • ****
  • Posts: 420
  • Un trabajo en equipo para programas serias.
Re: Improving custom message box
« Reply #11 on: June 30, 2022, 07:12:59 pm »
With this corrected, your code is placing the left/top corner of the message box over the center of the calling form. Is this intended? Or do you want to have the center of the message box over the center of the calling form? In this case you must also subtract half of the messagebox width and height from Left/Top (but it could be that the messagebox size is not yet known at this moment due to autosizing). If you set the message box's Position property to poOwnerForm and create the message box with the other form as owner you get this for free, without doing any calculation:
Code: Pascal  [Select][+][-]
  1.   frmDialog:=TForm.CreateNew(other_form);   // other_form rather than nil!
  2.   with frmDialog do begin
  3.   ...
  4.     if other_form <> nil then
  5.       Position := poOwnerFormCenter    // remove the Top/Left calculation that was here...
  6.     else
  7.       Position := poMainFormCenter;
  8.     ShowModal;


I think you are right, but regardless of the intended position I liked to place the message box in to its calling form, your code is higher of my current knowledge in Lazarus. I don't understand everything on it, and kept that to a later time when I increase my knowledge in Lazarus. Lazarus has incredibly huge libraries and tools. I didn't see a language has that volume except a language called "D", it's so huge too as I think.

I'll keep your code on my mind, and let's make discussing its details to another time.
« Last Edit: June 30, 2022, 07:14:44 pm by pascal111 »
La chose par la chose est rappelé.

Handoko

  • Hero Member
  • *****
  • Posts: 4683
  • My goal: build my own game engine using Lazarus
Re: Improving custom message box
« Reply #12 on: July 03, 2022, 04:14:47 am »
That code basically means:

Create a form and set the set its_owner = caller
...
   if
its_owner has been set then
      Position := center_based_on_the_owner
   else
      Position := center_based_on_main_form

 

TinyPortal © 2005-2018