Recent

Author Topic: [SOLVED] How to make 2 improvements to function dialogs.MessageDlg ?  (Read 2328 times)

Hartmut

  • Hero Member
  • *****
  • Posts: 749
I want something like function dialogs.MessageDlg(), but with 2 improvements:
  • I want it's position to change from the center of the monitor to the center of the calling Form
  • I want to be able to increase the default width of the dialog.
That means, I want a dialog which has a caption and shows a message and has some buttons and optional an icon. And has both above improvements.

My question is: must I reinvent the wheel or is there a component which I can use, where I only have to add those 2 improvements? I want this for Windows and Linux for Lazarus 2.0.10 / FPC 3.2.0.

Thanks in advance.
« Last Edit: November 27, 2022, 06:54:23 pm by Hartmut »

Thaddy

  • Hero Member
  • *****
  • Posts: 14371
  • Sensorship about opinions does not belong here.
Re: How to make 2 improvements to function dialogs.MessageDlg ?
« Reply #1 on: November 21, 2022, 07:19:40 pm »
Hey, OOP, so simply create a derived class.
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

balazsszekely

  • Guest
Re: How to make 2 improvements to function dialogs.MessageDlg ?
« Reply #2 on: November 21, 2022, 07:26:40 pm »
@Hartmut
Quote
I want something like function dialogs.MessageDlg(), but with 2 improvements:

    I want it's position to change from the center of the monitor to the center of the calling Form
    I want to be able to increase the default width of the dialog.

That means, I want a dialog which has a caption and shows a message and has some buttons and optional an icon. And has both above improvements.

My question is: must I reinvent the wheel or is there a component which I can use, where I only have to add those 2 improvements? I want this for Windows and Linux for Lazarus 2.0.10 / FPC 3.2.0.

Thanks in advance.

Maybe this:
Code: Pascal  [Select][+][-]
  1. function MessageDlgEx(const ACaption, AMsg: string; ADlgType: TMsgDlgType;
  2.   AButtons: TMsgDlgButtons; AParent: TForm): TModalResult;
  3. var
  4.   MsgFrm: TForm;
  5. begin
  6.   MsgFrm := CreateMessageDialog(ACaption, AMsg, ADlgType, AButtons);
  7.   try
  8.     MsgFrm.FormStyle := fsSystemStayOnTop;
  9.     if AParent <> nil then
  10.     begin
  11.       MsgFrm.Position := poDefaultSizeOnly;
  12.       MsgFrm.Left := AParent.Left + (AParent.Width - MsgFrm.Width) div 2;
  13.       MsgFrm.Top := AParent.Top + (AParent.Height - MsgFrm.Height) div 2;
  14.     end
  15.     else
  16.       MsgFrm.Position := poWorkAreaCenter;
  17.     Result := MsgFrm.ShowModal;
  18.   finally
  19.     MsgFrm.Free
  20.   end;
  21. end;
  22.  
  23. procedure TForm1.Button1Click(Sender: TObject);
  24. begin
  25.   MessageDlgEx('This is the caption',
  26.                'This is a very, very............................................................................. long message!',
  27.                 mtConfirmation,
  28.                 [mbYes, mbNo, mbCancel],
  29.                 Form1);
  30. end;  

wp

  • Hero Member
  • *****
  • Posts: 11916
Re: How to make 2 improvements to function dialogs.MessageDlg ?
« Reply #3 on: November 21, 2022, 08:10:09 pm »
An alternative could be the TTaskDialog which is very flexible (https://wiki.freepascal.org/TTaskDialog):
- Select the buttons from the CommonButtons property (or add specific ones by means of the Buttons property).
- Enter the message text in the Text property
- Select the iocn from the MainIcon property options
- Check the option tfPositionRelativeToWindow to center the dialog relative to the calling form.
- Double-click on the TaskDialog icon to see what it is looking like
- One important oddity of the TaskDialog: The return value of the Execute method indicates that the dialog could be created, but not that OK has been pressed. Check the modal result for this purpose.
- You can also add radiobuttons, or a checkbox ("Do not show again").

Hartmut

  • Hero Member
  • *****
  • Posts: 749
Re: How to make 2 improvements to function dialogs.MessageDlg ?
« Reply #4 on: November 22, 2022, 10:41:50 am »
Hey, OOP, so simply create a derived class.
Hey Thaddy, dialogs.MessageDlg() is a function, not a class. So which class should I derive? That was my question...



Thanks a lot GetMem for that demo. I tested it and it centers the dialog to the calling Form. But I found no way to increase the width of the dialog (*including* the message width). And a litte disadvantage is, that the Buttons have (on Linux) now a caption in English, not in German like with dialogs.MessageDlg().

Do you have an idea to change one of them or both?



Thanks a lot to wp for that suggestion. I will elaborate on it and see what I can implement. If I'll have problems I will report them ;-)

madref

  • Hero Member
  • *****
  • Posts: 949
  • ..... A day not Laughed is a day wasted !!
    • Nursing With Humour
Re: How to make 2 improvements to function dialogs.MessageDlg ?
« Reply #5 on: November 22, 2022, 11:36:57 am »
Or just make your own MessageDlg from a form and let that be on tom until a button is pressed on that form.
You treat a disease, you win, you lose.
You treat a person and I guarantee you, you win, no matter the outcome.

Lazarus 3.99 (rev main_3_99-649-ge13451a5ab) FPC 3.3.1 x86_64-darwin-cocoa
Mac OS X Monterey

Hartmut

  • Hero Member
  • *****
  • Posts: 749
Re: How to make 2 improvements to function dialogs.MessageDlg ?
« Reply #6 on: November 22, 2022, 04:38:03 pm »
An alternative could be the TTaskDialog which is very flexible (https://wiki.freepascal.org/TTaskDialog):
- Select the buttons from the CommonButtons property (or add specific ones by means of the Buttons property).
- Enter the message text in the Text property
- Select the iocn from the MainIcon property options
- Check the option tfPositionRelativeToWindow to center the dialog relative to the calling form.
- Double-click on the TaskDialog icon to see what it is looking like
- One important oddity of the TaskDialog: The return value of the Execute method indicates that the dialog could be created, but not that OK has been pressed. Check the modal result for this purpose.
- You can also add radiobuttons, or a checkbox ("Do not show again").

I played with 'TTaskDialog' and found it very mighty. Especially the possibility to add your own buttons and to have a checkbox like "Don't show me again". So I'm sure I will use this dialog in the future. Thanks a lot to wp for you informations, with these it was easy for me to get it to run. I did not know 'TTaskDialog' before.

But for my current needs I face 2 disadvantages:
 - I found no way to influence the width of the dialog. Is this possible?
 - if no 'Title' is used, then still a huge space is reserved for that (see screenshot). Beside 'caption' and 'message' I need no 3rd text. Is it possible to get rid of this extra space?
Thanks in advance.

wp

  • Hero Member
  • *****
  • Posts: 11916
Re: How to make 2 improvements to function dialogs.MessageDlg ?
« Reply #7 on: November 22, 2022, 05:16:05 pm »
- I found no way to influence the width of the dialog. Is this possible?
It is prepared internally, but there is no property for it. Please make the following changes:
  • unit dialogs.pp (in folder lcl of your Lazarus installation), declaration of TCustomTaskDialog:
    • After field FVerificationText:TTranslateString add a new field:
        FWidth: Integer;
    • At the end of the public declarations of TCustomTaskDialog add:
        property Width: Integer read FWidth write FWidth default 0;
    • At the end of the published declarations of TTaskDialog add:
        property Width;
  • file taskdialog.inc (in folder lcl/include):
    • function TCustomTaskDialog.DoExecute: Search for TaskDlg.Execute. You'll find a function call with many parameters. In the second line, between "DefRB" and "ParentWnd", there is a "0". Replace this 0 by FWidth.
  • Rebuild the IDE. When the new IDE starts the TTaskDialog will have a new property "Width". You will only be able to increase the width of the dialog, it will not be possible to shrink it.
Test the new property. It should work, but I would like to hear your feedback before I commit these changes to Laz/main.

- if no 'Title' is used, then still a huge space is reserved for that (see screenshot). Beside 'caption' and 'message' I need no 3rd text. Is it possible to get rid of this extra space?
From your screenshot I see that you seem to be on a Linux where the emulated version of the original Windows TaskDialog is called. On Windows, however, the main icon and title areas are hidden when the icon is tdiNone and the Text is empty. So, this seems to be a bug in the emulation in unit LCLTaskDialog. Please post a bug report.

wp

  • Hero Member
  • *****
  • Posts: 11916
Re: How to make 2 improvements to function dialogs.MessageDlg ?
« Reply #8 on: November 22, 2022, 06:06:37 pm »
You will only be able to increase the width of the dialog, it will not be possible to shrink it.[/li][/list]
This was my observation on Windows where the native TaskDialog is used. When I switch it to use the emulated dialog, however, I found that I can make the IDE non-responsive by making Width too small. Therefore, please make another change. Now open the file lcl/lcltaskdialog.pas. Search for if aWidth=0 (no spaces around "="!). Replace the entire "if" block by the following code:
Code: Pascal  [Select][+][-]
  1.     if aWidth<=0 then begin
  2.       aWidth := Dialog.Form.Canvas.TextWidth(Inst);
  3.       if (aWidth>300) or (Dialog.Form.Canvas.TextWidth(Content)>300) or
  4.          (length(Buttons)>40) then
  5.         aWidth := 480 else
  6.         aWidth := 420;
  7.     end else
  8.       if aWidth<120 then aWidth := 120;
Rebuild the IDE again, and the IDE should be safe now. You will be able to decrease the width down to 120 px. The native TaskDialog will ignore shrinking widths as already noted.

Hartmut

  • Hero Member
  • *****
  • Posts: 749
Re: How to make 2 improvements to function dialogs.MessageDlg ?
« Reply #9 on: November 22, 2022, 07:12:49 pm »
Hello wp, thank you so much for your idea to improve dialog 'TTaskDialog' with a property 'width'.

- I found no way to influence the width of the dialog. Is this possible?
It is prepared internally, but there is no property for it. Please make the following changes:
...
You will only be able to increase the width of the dialog, it will not be possible to shrink it.
To increase is absolutely enough, *if* the width of the message increases accordingly.
Will this be the case (on Windows and Linux)? Otherwise it would not help me...

Quote
Test the new property. It should work, but I would like to hear your feedback...
I will do this test, but give me some time for this. My newest Lazarus is 2.0.10 with FPC 3.2.0. I hope this is ok?

Quote
... before I commit these changes to Laz/main.
That would be great for the future.

Quote
From your screenshot I see that you seem to be on a Linux...
that's right

Quote
... on Linux where the emulated version of the original Windows TaskDialog is called.
I did not know of this before

Quote
On Windows, however, the main icon and title areas are hidden when the icon is tdiNone and the Text is empty. So, this seems to be a bug in the emulation in unit LCLTaskDialog. Please post a bug report.
I tested this on Win7 and (an older) Win10 (with Lazarus 2.0.10 / FPC 3.2.0), but in both cases I have the same output (huge wasted space, see new screenshot) as in Linux.

You will only be able to increase the width of the dialog, it will not be possible to shrink it.
This was my observation on Windows where the native TaskDialog is used. When I switch it to use the emulated dialog, however, I found that I can make the IDE non-responsive by making Width too small. Therefore, please make another change. Now open the file lcl/lcltaskdialog.pas. Search for if aWidth=0 (no spaces around "="!). Replace the entire "if" block by the following code:
OK.

madref

  • Hero Member
  • *****
  • Posts: 949
  • ..... A day not Laughed is a day wasted !!
    • Nursing With Humour
Re: How to make 2 improvements to function dialogs.MessageDlg ?
« Reply #10 on: November 22, 2022, 07:16:48 pm »
I have created my own flexible message dialogs.
Here are two examples. And you can create a lot more.
This is a form which stays on top until a button is pressed.
You treat a disease, you win, you lose.
You treat a person and I guarantee you, you win, no matter the outcome.

Lazarus 3.99 (rev main_3_99-649-ge13451a5ab) FPC 3.3.1 x86_64-darwin-cocoa
Mac OS X Monterey

wp

  • Hero Member
  • *****
  • Posts: 11916
Re: How to make 2 improvements to function dialogs.MessageDlg ?
« Reply #11 on: November 22, 2022, 07:26:23 pm »
To increase is absolutely enough, *if* the width of the message increases accordingly.
You mean that the width of the dialog should increase automatically depending on the length of the displaye message? No, this will not work. The new Width property must be known before-hand, independently of the message which simply will wrap if it is too long.

My newest Lazarus is 2.0.10 with FPC 3.2.0. I hope this is ok?
v2.0.10 already has the TaskDialog, and a quick scan over the code showed that the relevant parts are the same (there were some changes with the icons, though). The patch should compile. But to be on the safe side, make sure to have a backup copy of the files to be changed before doing anything.

I tested this on Win7 and (an older) Win10 (with Lazarus 2.0.10 / FPC 3.2.0), but in both cases I have the same output (huge wasted space, see new screenshot) as in Linux.
Well, there was some rework with the dialog recently, and I only checked it with Laz/main.


Hartmut

  • Hero Member
  • *****
  • Posts: 749
Re: How to make 2 improvements to function dialogs.MessageDlg ?
« Reply #12 on: November 23, 2022, 10:44:51 am »
To increase is absolutely enough, *if* the width of the message increases accordingly.
You mean that the width of the dialog should increase automatically depending on the length of the displaye message? No, this will not work. The new Width property must be known before-hand, independently of the message which simply will wrap if it is too long.

No, there we misunderstood. I mean, if I set a higher dialog Width (by your new property, before calling TTaskDialog.Execute, e.g. setting TTaskDialog.Width:=800), will then this extra horizontal space also be used to display and wordwrap the message-text (on Windows and Linux)?

wp

  • Hero Member
  • *****
  • Posts: 11916
Re: How to make 2 improvements to function dialogs.MessageDlg ?
« Reply #13 on: November 23, 2022, 12:36:57 pm »
Yes - see screenshot. Wrapping works for native and emulated mode of the TaskDialog. But in Windows there is an issue that the width is specified in "dialog units". It seems that I have to divide the Width property value by 2 before passing it to the TaskDialogIndirect windows function, but I am not sure whether this is correct all the time. Windows documentation wants me to call the "GetDialogBaseUnits" function (https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdialogbaseunits), but this returns unreasonably large numbers.

Hartmut

  • Hero Member
  • *****
  • Posts: 749
Re: How to make 2 improvements to function dialogs.MessageDlg ?
« Reply #14 on: November 23, 2022, 03:45:18 pm »
Yes - see screenshot. Wrapping works for native and emulated mode of the TaskDialog.
That's great and exactly what I was for :-))

Quote
But in Windows there is an issue that the width is specified in "dialog units". It seems that I have to divide the Width property value by 2 before passing it to the TaskDialogIndirect windows function, but I am not sure whether this is correct all the time.
Maybe this has to do with High-DPI-Awareness? Then the factor should depend on your DPI-settings in Windows... (don't know more about that).

I'm unsure how to rebuild the IDE. I did it once 3 years ago and forgot everything and the dialog now seems to contain other fields:
In Lazarus in the Tools-menu I found menu "Build Lazarus with Profile: Normal IDE" and menu "Configure 'Build Lazarus' ..." which opens a dialog with many options (see screenshot). Which menu should I use and what must I enter if you want me to use the 2nd menu (for Windows and Linux)?

 

TinyPortal © 2005-2018