Never ever close me – how to disable close button in WPF

26 בספטמבר 2007

3 תגובות

[This blog was migrated. You will not be able to comment here.
The new URL of this post is http://khason.net/blog/never-ever-close-me-how-to-disable-close-button-in-wpf/]


Well, there is no such option in WPF. The only thing you can do is to go a bit down to unmanaged and hook WM messages to apply your own style to the system menu. How to do it? 


First of all, we have to know to to hook system events in WPF. For such action, we have HwndSource. I wrote a bit about it here and here, so it's the simple one.




protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);

HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource;

if (hwndSource != null)
{
hwndSource.AddHook(
new HwndSourceHook(this.hwndSourceHook));
}

}

IntPtr hwndSourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
 

Next, let's do a bit of Interop




[DllImport("user32.dll")]
static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[
DllImport("user32.dll")]
static extern bool EnableMenuItem(IntPtr hMenu, uint uIDEnableItem, uint uEnable);



const uint MF_BYCOMMAND = 0x00000000;
const uint MF_GRAYED = 0x00000001;
const uint MF_ENABLED = 0x00000000;

const uint SC_CLOSE = 0xF060;

const int WM_SHOWWINDOW = 0x00000018;
const int WM_CLOSE = 0x10;
 

And now, we can hook WM_SHOWWINDOW and WM_CLOSE to apply those styles




IntPtr hwndSourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == WM_SHOWWINDOW)
{
IntPtr hMenu = GetSystemMenu(hwnd, false);
if (hMenu != IntPtr.Zero)
{
EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);
}
}
else if (msg == WM_CLOSE)
{
handled =
true;
}
return IntPtr.Zero;
}
 

We done. Now just think about how to close such window 🙂 Happy programming

הוסף תגובה
facebook linkedin twitter email

כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *

3 תגובות

  1. Gagan Rajpal27 בספטמבר 2007 ב 4:51

    There is a much simpler but WPF solution too:

    Just subscribe to the Windows Closing Event and in the handler set e.Cancel = true

    eg:

    public partial class Window1 : Window
    {
    public Window1()
    {
    InitializeComponent();
    this.Closing += new System.ComponentModel.CancelEventHandler(Window1_Closing);
    }

    void Window1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
    {
    e.Cancel = true;
    }
    }

    הגב
  2. Tamir Khason27 בספטמבר 2007 ב 16:50

    Gagan, thank you for response. The point in this article is not to prevent the window from closing, but disable close button in the window system menu

    הגב
  3. Ron19 ביולי 2008 ב 1:19

    Great post. Please add:

    using System.Windows.Interop;
    using System.Runtime.InteropServices;

    הגב