Jump to content
PeterPanettone

Centered message?

Recommended Posts

Each Application.MessageBox, MessageBox (MessageBox API), MessageDlg show the dialog in the center of the SCREEN.

 

Is it possible to have any of them centered on the Application Form?

Edited by PeterPanettone

Share this post


Link to post

One could argue that positioning a message dialog in the middle of the screen is the default behavior in Windows. But from my point of view, that argument is from the prehistoric time when monitors still had the size of a postage stamp. Today, more and more people use large (if not huge) monitors. Therefore, if an action is performed with a control on a form and that action leads to a change on the form (so the user's attention is focused on the form), centering a message dialog on the form would be a better user experience.

Edited by PeterPanettone
  • Like 2

Share this post


Link to post
32 minutes ago, David Heffernan said:

Note that only applies to MessageDlg() and other custom dialogs.  For the Win32 MessageBox() function, and the VCL's Application.MessageBox() (which just calls the Win32 MessageBox()), you would have to hook into the Win32 API via SetWindowsHookEx() or SetWinEventHook() in order to capture the dialog window, and then you can reposition it as needed.

Share this post


Link to post

Hi...:classic_cool:

Quote

MessageDlg show the dialog in the center of the SCREEN

...you programming a own MessageDialog. :classic_tongue:

 

MessageDlg.thumb.png.a892504d1f612b699d8c032f9aa169f7.png

 

TOwnMessageDialog = class
  strict private
    // own formular
    class function ShowMessage(MessageCaption: string; MsgType: TMsgDlgType; Buttons: TMsgDlgButtons; MessageLines: TStrings; Help: LongInt = 0; MessageColor: Integer = clBlack; Parent: TForm = nil): Integer;
  public
    constructor Create;
    destructor Destroy; override;
    class function MessageDlg(MessageText: string; MsgType: TMsgDlgType; Buttons: TMsgDlgButtons; Help: LongInt = 0; MessageColor: Integer = clBlack; Parent: TForm = nil): Integer; overload; // wie MessageDialog Original
    class function MessageDlg(MessageText: string; MessageHeader: string; MsgType: TMsgDlgType; Buttons: TMsgDlgButtons; MessageColor: Integer = clBlack; Parent: TForm = nil): Integer; overload;
    class function MessageDlg(MessageLines: TStrings; MessageHeader: string; MsgType: TMsgDlgType; Buttons: TMsgDlgButtons; MessageColor: Integer = clBlack; Parent: TForm = nil): Integer; overload;
    class function MessageDlg(E: EDatabaseError; MessageHeader: string; MsgType: TMsgDlgType; Buttons: TMsgDlgButtons; MessageColor: Integer = clBlack; Parent: TForm = nil): Integer; overload;
  end;

Advantages:

1. own formular with corporate design

2. Parent for the message

3. own high (Count of MessageLines)

4. own with (longest text in MessageLines)

5. own Colors (Text)

6. scalable...dialog with every controls you want (inheritance)

...and so on. :classic_wink:

 

 

Edited by haentschman
  • Like 1

Share this post


Link to post

I may introduce a different option, what I use successfully for years now.

 

Instead of any dialog, I use specialzed messages, for TMessage/TMessageManager, which are pushed to the system.

There is only one central place in my apps which handle the dialog requests.

Can be a normal MessageBox, can be TFrame-based, can be a special component or 3rd party solution, etc.

 

What and how I do there, is up to my mood or customers requirements.

 

The main advantages:

1. all the dialogs in my apps are looking same

2. changing the UI is just changing an entry in the uses

3. last but not least: unit testing messages works nicely, nothing to get headaches

 

Hope you like this idea as much as I do.

 

 

 

 

Share this post


Link to post
1 hour ago, haentschman said:

programming a own MessageDialog

Very nice. Do you also make your own INPUT dialogs?

Share this post


Link to post

Hi...

Quote

INPUT dialogs

I have not needed it yet. But..." scalable...dialog with every controls you want (inheritance)" :classic_cool:

 

...you must programming it by yourself. :classic_happy:

 

You must have:

1. A base (form) dialog, where the others inherited from. This form encapsulates the logic for the Buttons, Colors, Parent.

2. A new one inherited from the base.

3. design your dialog with treeview, checkboxes, edits, animations...

4. programming the logic for your controls

5. overload the class function with your new dialog

 

...in saxony (Germany) we say "Fertsch" (like finish) :classic_cool:

 

 

Edited by haentschman

Share this post


Link to post

For not that important applications I'm using MessageDlg, but for more advanced ones I always use my own "message dialog". Fully customizable, with a short (and if needed) an extended version of the message which is visible if the user clicks the down arrow. It uses the system's icons, but follows themeing correctly. I included a class function "Confirm" which returns a boolean and displays the dialog in "confirm" mode (question icon, yes and no buttons visible) and a .Error class procedure, which takes an exception and dumps as much information as possible in the extended text. I'm also planning to add a "Report" button to errors, which would send me an e-mail with the information collected; I was just too lazy to to do so until now (and I did not look for a component. Worst case, I'll implement my own lightweight SMTP client, idk yet).

Based on this logic I also created a multi-input form, where my application can request multiple inputs validated (number only, can be null, predefined values from a combobox, multi-line text, etc.

The problem is, this input form became so versatile and useful, most of my applications are heavily depending on it now.

 

So yeah, I completely support @haentschman in this. Just write your own, and you will have a truly cross-platform solution satisfying all your needs.

Edited by aehimself

Share this post


Link to post
10 hours ago, aehimself said:

So yeah, I completely support @haentschman in this. Just write your own, and you will have a truly cross-platform solution satisfying all your needs.

Yes, absolutely.

I would add: Write once, use anywhere.

 

A clever design concept is a good pay-off.

 

Edited by Rollo62
  • Like 1

Share this post


Link to post
On 7/11/2020 at 8:54 AM, Rollo62 said:

A clever design concept is a good pay-off.

I started to see this at my biggest project. I broke it in the smallest pieces possible (random number generator, pseudorandom generator, encrypter, (de)serializer, hell I have a separate class for the application itself). Whenever I start a new project, I realize that most of these modules are now in my "Common" folder. It just started to become logical not to write a code again (or copy-and-paste) if I already wrote it once.

The only bad thing in this is that if I make a bugfix in one of the units I have to recompile 4-5 applications now instead of one 🙂

Share this post


Link to post
23 minutes ago, aehimself said:

The only bad thing in this is that if I make a bugfix in one of the units I have to recompile 4-5 applications now instead of one 🙂

No, this is the good thing 😉 I've a batch file for building the release versions.

 

Share this post


Link to post
43 minutes ago, aehimself said:

It just started to become logical not to write a code again (or copy-and-paste) if I already wrote it once.

The only bad thing in this is that if I make a bugfix in one of the units I have to recompile 4-5 applications now instead of one 🙂

You mean it's a bad thing that, instead of fixing the bug in 4-5 applications and compile them, you now have to fix the bug only once and still compile 4-5 applications?

Share this post


Link to post
2 hours ago, dummzeuch said:

You mean it's a bad thing that, instead of fixing the bug in 4-5 applications and compile them, you now have to fix the bug only once and still compile 4-5 applications?

No; that was not my intention to mean that. Obviously fixing at one place is more convenient and time effective, no one doubts that. All I wanted to say was that I don't really have a dependency (or rather - uses) list, which clearly says which application is using the particular unit I am working in.

I think I'll write a recursive crawler to discover any custom units in the uses clauses of all my applications. As a result, I can enter a unit name and see which applications I have to rebuild. An other way is to distribute each unit as a separate library and my auto updater will take care of the updates of said files. This, however, increases the number of files my application is using and the attack surface of course. Even the beginner Hacker Henry will know to check the exports of MyEncryptor.dll and launch a brute force attack on encrypted data.

And however I don't deal with credit card / bank account numbers or personal data; I like to prepare for the worst.

 

Anyhow, we are sliding off the original topic. This is just one thing to consider with the cherished "Write once, use anywhere" method - which is THE WAY to go.

Share this post


Link to post
On 7/12/2020 at 7:09 PM, aehimself said:

The only bad thing in this is that if I make a bugfix in one of the units I have to recompile 4-5 applications now instead of one

Poor man's solution: Project group with all your 100 projects -> open in RAD -> build all -> go make yourself some tea

  • Like 1

Share this post


Link to post
4 hours ago, Fr0sT.Brutal said:

Poor man's solution: Project group with all your 100 projects -> open in RAD -> build all -> go make yourself some tea

While the idea clearly works, there's a huge flaw with it: I don't like tea.

  • Haha 2

Share this post


Link to post
2 hours ago, aehimself said:

While the idea clearly works, there's a huge flaw with it: I don't like tea.

You'd get used to it. 😉

Share this post


Link to post

As suggested by everyone else:

 - I've just created my own custom dialog Form too.

 

But how do I override automatically every ShowMessage('...') funtion in my program globally?

 

- I do not want to replace the word  "ShowMessage" in all 900+ places, because maybe next time I will forget to type my own function name.

 (Also Delphi is auto-replacing to that if is type: "smg").

- Also do not want to put a new unit to all 110+ PAS files one by one.

 

I'd also like to override InputBox later with similar method.

Thanks for any help!

Edited by PizzaProgram

Share this post


Link to post

Well, not much left, either hook it runtime or put your own Dialogs.pas / Vcl.Dialogs.pas into the project dir. Don't forget to implement the needed methods first.

Share this post


Link to post

I think that what you are asking for at this point would not be "at all acceptable", from the point of view of good programming practices! (I hate these words: "Good programming practices")

 

Why? Simple, replacing something already enshrined in the environment, whatever it may be, programming, social relationships, etc... is, at the very least, exhausting, not to say, many times, impractical! (even if possible).

 

If you insist in this direction, be aware that you will certainly have a lot of headaches... not too far away!

To make such a maneuver, change a class, or even a function as common as "ShowMessage", you should first assess the risk of compromising your project today and all the rest!

You would have to assess the consequences of such a drastic change!

 

My advice: forget this wish, and ask the genie in Aladdin's lamp for another one.

 

You can try the following:

  1. if you don't have or don't want to use another tool, for example, NOTEPAD++ to replace an occurrence with another occurrence! - this tool lets you do it in a simplified way!
  2.  using the "reFind" tool (which is in the "BIN" directory of RAD Studio), you could find a given occurrence and replace it with another one!

However, you need to "move" your brain a little to create your desired command. Anyway, you can read about this command on the Embarcadero page (DocWiki) or even on the Embarcadero Blob about "reFIND".

Share this post


Link to post

Look, ShowMessage calls indiretly "MessageDlgPosHelp(Msg, DlgType, Buttons, HelpCtx, X, Y, '');".. then you can define "X,Y" values for your position desired!

... a little more deep... you'll find a called to "TTaskMessageDialog"... then, use it directly!

 

INPUT dialogs, in fact, is a "FORM" customized!  just do yours!

Edited by programmerdelphi2k

Share this post


Link to post
1 hour ago, programmerdelphi2k said:

Look, ShowMessage calls indiretly "MessageDlgPosHelp(Msg, DlgType, Buttons, HelpCtx, X, Y, '');".. then you can define "X,Y" values for your position desired!

There is also ShowMessagePos() for that purpose.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×