using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
namespace WpfHelpers
{
///
/// A class that encapsulates the functionality for a Dialog window. It derives
/// from the base WPF window and customizes the appearance to look like a typical
/// Windows dialog.
///
public class DialogWindow : Window
{
#region Constructors
///
/// Default constructor.
///
public DialogWindow()
{
}
#endregion
#region DependencyProperties
public static readonly DependencyProperty IsSystemMenuVisibleProperty =
DependencyProperty.Register("IsSystemMenuVisible", typeof(bool), typeof(DialogWindow),
new FrameworkPropertyMetadata(false, OnPropertyChanged));
public static readonly DependencyProperty IsHelpButtonVisibleProperty =
DependencyProperty.Register("IsHelpButtonVisible", typeof(bool), typeof(DialogWindow),
new FrameworkPropertyMetadata(false, OnPropertyChanged));
///
/// Gets or sets whether the dialog's system menu should be visible.
/// For a dialog, the default is no system menu.
///
public bool IsSystemMenuVisible
{
get { return (bool)GetValue(IsSystemMenuVisibleProperty); }
set { SetValue(IsSystemMenuVisibleProperty, value); }
}
///
/// Gets or sets whether the dialog's context help button should be visible.
/// For a dialog, the default is false.
///
public bool IsHelpButtonVisible
{
get { return (bool)GetValue(IsHelpButtonVisibleProperty); }
set { SetValue(IsHelpButtonVisibleProperty, value); }
}
#endregion
#region Event handlers
///
/// Overrides the base source initialization and sets the appropriate
/// window styles for dialogs.
///
///
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
SetWindowStyle();
}
///
/// Handles when one of DialogWindow's dependency properties has changed.
///
/// Object instance on which the property changed.
/// Event args
static void OnPropertyChanged(object obj, DependencyPropertyChangedEventArgs e)
{
DialogWindow dialog = (DialogWindow)obj;
dialog.SetWindowStyle();
}
#endregion
#region Helper method
///
/// Sets the appropriate window style for the dialog window based on the
/// IsSystemMenuVisible and IsHelpButtonVisible properties.
///
/// Note: this makes several calls into native Windows methods to deliver
/// this functionality. NativeMethods is a wrapper for native Windows
/// calls.
///
protected virtual void SetWindowStyle()
{
// Gets a window handle for this dialog window.
WindowInteropHelper wih = new WindowInteropHelper(this);
IntPtr hwnd = wih.Handle;
// Gets the current windows StyleEx value.
int windowStyle = NativeMethods.GetWindowLongPtr(hwnd, NativeMethods.GWL_EXSTYLE).ToInt32();
// Turns modal dialog frame on/off depending on whether we want to show
// the system menu.
if (IsSystemMenuVisible)
{
windowStyle &= ~NativeMethods.WS_EX_DLGMODALFRAME;
}
else
{
windowStyle |= NativeMethods.WS_EX_DLGMODALFRAME;
}
// Turns context help on/off for the dialog depending is we want it shown.
if (IsHelpButtonVisible)
{
windowStyle |= NativeMethods.WS_EX_CONTEXTHELP;
}
else
{
windowStyle &= ~NativeMethods.WS_EX_CONTEXTHELP;
}
// Now, sets the new windows StyleEx value.
NativeMethods.SetWindowLongPtr(hwnd, NativeMethods.GWL_EXSTYLE, new IntPtr(windowStyle));
if (!IsSystemMenuVisible && this.ResizeMode == ResizeMode.NoResize)
{
// Note: this is a workaround for a WPF bug. When NoResize is chosen,
// the system menu doesn't get set up correctly. The code below disables
// the appropriate system menu items in this case.
IntPtr hmenu = NativeMethods.GetSystemMenu(hwnd, false);
NativeMethods.EnableMenuItem(hmenu, NativeMethods.SysMenuPos_Maximize,
NativeMethods.MF_DISABLE | NativeMethods.MF_BYPOSITION);
NativeMethods.EnableMenuItem(hmenu, NativeMethods.SysMenuPos_Minimize,
NativeMethods.MF_DISABLE | NativeMethods.MF_BYPOSITION);
NativeMethods.EnableMenuItem(hmenu, NativeMethods.SysMenuPos_Size,
NativeMethods.MF_DISABLE | NativeMethods.MF_BYPOSITION);
NativeMethods.EnableMenuItem(hmenu, NativeMethods.SysMenuPos_Restore,
NativeMethods.MF_DISABLE | NativeMethods.MF_BYPOSITION);
NativeMethods.DrawMenuBar(hwnd);
}
}
#endregion
}
}