All I want is that my messagebox should show my application's icon (or any other icon) in its titlebar, but it doesnt, why not?
问题:
回答1:
The MessageBox
in WPF is simply a wrapper for the standard MessageBox
in user32.dll
, which is exactly the same function that Windows itself calls to display a dialog box. It's not going to look any different in your WPF applications than it does in any other app that relies on the Win32 API (including WinForms, MFC, etc.).
Using Reflector, you can verify this by looking at the relevant function called by MessageBox
in WPF. Note specifically the last line of code, where it calls UnsafeNativeMethods.MessageBox
:
[SecurityCritical]
private static MessageBoxResult ShowCore(IntPtr owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult, MessageBoxOptions options)
{
if (!IsValidMessageBoxButton(button))
{
throw new InvalidEnumArgumentException("button", (int) button, typeof(MessageBoxButton));
}
if (!IsValidMessageBoxImage(icon))
{
throw new InvalidEnumArgumentException("icon", (int) icon, typeof(MessageBoxImage));
}
if (!IsValidMessageBoxResult(defaultResult))
{
throw new InvalidEnumArgumentException("defaultResult", (int) defaultResult, typeof(MessageBoxResult));
}
if (!IsValidMessageBoxOptions(options))
{
throw new InvalidEnumArgumentException("options", (int) options, typeof(MessageBoxOptions));
}
if ((owner != IntPtr.Zero) && ((options & (MessageBoxOptions.ServiceNotification | MessageBoxOptions.DefaultDesktopOnly)) != MessageBoxOptions.None))
{
throw new ArgumentException(SR.Get(SRID.CantShowMBServiceWithOwner, new object[0]));
}
int type = (int) (((button | ((MessageBoxButton) ((int) icon))) | DefaultResultToButtonNumber(defaultResult, button)) | ((MessageBoxButton) ((int) options)));
IntPtr zero = IntPtr.Zero;
if ((options & (MessageBoxOptions.ServiceNotification | MessageBoxOptions.DefaultDesktopOnly)) == MessageBoxOptions.None)
{
if (owner == IntPtr.Zero)
{
zero = UnsafeNativeMethods.GetActiveWindow();
}
else
{
zero = owner;
}
}
return Win32ToMessageBoxResult(UnsafeNativeMethods.MessageBox(new HandleRef(null, zero), messageBoxText, caption, type));
}
As you've noticed, this message box does not display an icon on its title bar. This is because its window is created without specifying the WS_CAPTION
and WS_SYSMENU
styles. And while possible, there's no easy way to subclass the user32.dll-provided MessageBox
and change its window styles to display an icon on its title bar. The resulting code is fugly and frankly not worth the trouble.
The best solution is to simply create your own dialog box and call this one from your code instead. This has plenty of other advantages beyond the ability to add an icon, including fixing any interoperability problems with WPF (you'll be using entirely managed code) and allowing you to theme the dialog box as necessary to match a custom theme used in your application. Try something like this to help get you started.
- http://blogsprajeesh.blogspot.com/2009/12/wpf-messagebox-custom-control.html
Alternatively, if you don't need to target previous versions of Windows (those prior to Vista), you can use the TaskDialog
provided in version 6 of COMCTRL32.DLL, which replaces and enhances the standard MessageBox
. However, this is not included as a standard class in the .NET Framework, so you'll have to P/Invoke. See here for one of many available examples.
There are also a couple of sample projects worth looking into that utilize the TaskDialog
on versions of Windows where it is available and emulate it in previous versions where it is not. (I personally use something very similar in many of my .NET applications.)
http://www.codeproject.com/KB/vb/vdialog.aspx
http://www.codeproject.com/KB/WPF/WPFTaskDialogVistaAndXP.aspx
http://www.codeproject.com/KB/vista/TaskDialogWinForms.aspx
回答2:
You could create your own custom message box - just a create user control (with your images, animation, video or whatever...) and call ShowDialog, you can start from this example.