0

I call MessageBox() with one button ok (or ok/cancel). Can I center this msg-box to some window from my app (i use Delphi, i have window handle h). Not center to entire screen.

manuell
  • 7,528
  • 5
  • 31
  • 58
Prog1020
  • 4,530
  • 8
  • 31
  • 65
  • 2
    You can do this with a CBT hook. Sertac Akyuz has an answer on this site that shows how. You probably should not do this if you want your app to work well on future windows. – David Heffernan Feb 22 '14 at 23:08
  • 2
    On Vista+, you should use `TaskDialog/Indirect()` instead of `MessageBox()`. They are much more flexible. For instance, `TaskDialogIndirect()` has a `TDF_POSITION_RELATIVE_TO_WINDOW` flag to center the dialog on its parent window. – Remy Lebeau Feb 23 '14 at 03:15

3 Answers3

3

No, there's no documented way to position a standard Windows MessageBox dialog.

You can, however, use MessageDlgPos instead (in the Dialogs unit):

MessageDlgPos('This is my dialog', mtInformation, [mbOk], 0, 100, 100);

The difficult part will be calculating the coordinates to properly center within your window, as the dialog is sized automatically based on the text provided.

The documentation linked is for the XE5 documentation, but the function exists in earlier versions of Delphi as well. I've confirmed it exists in Delphi 2007 also.

Ken White
  • 123,280
  • 14
  • 225
  • 444
  • 2
    This will result in a native Task Dialog in themed Windows Vista+. – Andreas Rejbrand Feb 22 '14 at 23:37
  • @Andreas: True, but MessageBox under those versions of Windows is quite similar in appearance. Of course, MessageBox also allows you to set the window caption and provide a parent window handle, and MessageDlg/MessageDlgPos don't. – Ken White Feb 23 '14 at 00:24
2

This is possible with a window procedure hook, as shown in this answer.

With that unit(s), you can center any native dialog, such as: MessageBox, TFindDialog, TOpenDialog, TFontDialog, TPrinterSetupDialog, etc... The main unit provides two routines, both with some optional parameters:

function ExecuteCentered(Dialog: TCommonDialog;
  WindowToCenterIn: HWND = 0): Boolean;
function MsgBox(const Text: String; Flags: Cardinal = DefFlags;
  const Caption: String = DefCaption;
  WindowToCenterIn: HWND = 0): Integer;

Wherelse you would use OpenDialog1.Execute and let Windows decide where to show the dialog, you now use ExecuteCentered(OpenDialog1) and the dialog is centered in the screen's active form.

To show message dialogs, use MsgBox, a wrapper around Application.MessageBox (which in turn is a wrapper around Windows.MessageBox). Some examples:

  • MsgBox('Hello world!');
  • MsgBox('Cancel saving?', MB_YESNO or MB_ICONQUESTION or MB_DEFBUTTON2);
  • MsgBox('Please try again.', MB_OK, 'Error');
  • MsgBox('I''m centered in the toolbar.', MB_OK, 'Fun!', Toolbar1.Handle);
Community
  • 1
  • 1
NGLN
  • 43,011
  • 8
  • 105
  • 200
0

You could create your own dialog that automatically centers on a TWinControl passed to it. I did just that and it's available as part of my dzlib libraryunder the MPL. The unit to add to your program is w_dzDialog in the subdirectory src\forms.

You use it like this:

Tf_dzDialog.ShowMessage(mtWarning, _('Your message goes here.'#13#10
  + 'I can have multiple lines and even' + #13#10
  + #13#10
  + 'empty lines as the one above', [dbeOK], Self);

The last parameter (here: Self) is the control on which the dialog centers. It must be a TWinControl, so a form is fine. But with large monitors and windows that span the whole monitor (or even multiple monitors) it might be convenient to e.g. pass a button or a panel so the dialog centers on the area where the user's attention is currently focused.

The dialog looks and behaves much like the standard ShowMessage Dialog in Windows XP (which might be a problem if you want to get Windows 7 look) but is a lot more flexible than that.

[/shameless plug]

dummzeuch
  • 10,975
  • 4
  • 51
  • 158