qt8gt0bxhw|20009F4EEE83|RyanMain|subtext_Content|Text|0xfbffbe0000000000ac00000001000400
There are times that you'll see a Window that has a close button in the titlebar, but it is disabled. This is often found in applications where the dialog/window changes it's status past a stoppable point so the Windows close action is removed so the user cannot close the dialog to stop the process (For example when installing a Windows service pack). You might want to produce this same effect in your own applications. While there is nothing built into the .NET Framework to do so, with a few Win32API calls the task becomes simple.
The Win32API calls we'll be using will give you access to the windows system menu items. We'll remove the “Close” menu item and by doing so it will also disable all associated “Close” actions for the window. That is, not only will the “Close” item in the system menu be removed, but a side-effect is that the Close button (the 'X' in the far right of the titlebar) will also be disabled. Let's take a look at the code.
using System.Runtime.InteropServices;
// ...
[DllImport("user32.dll", EntryPoint="GetSystemMenu")]
private static extern IntPtr GetSystemMenu(IntPtr hwnd, int revert);
[DllImport("user32.dll", EntryPoint="GetMenuItemCount")]
private static extern int GetMenuItemCount(IntPtr hmenu);
[DllImport("user32.dll", EntryPoint="RemoveMenu")]
private static extern int RemoveMenu(IntPtr hmenu, int npos, int wflags);
[DllImport("user32.dll", EntryPoint="DrawMenuBar")]
private static extern int DrawMenuBar(IntPtr hwnd);
private const int MF_BYPOSITION = 0x0400;
private const int MF_DISABLED = 0x0002;
// ...
IntPtr hmenu = GetSystemMenu(this.Handle, 0);
int cnt = GetMenuItemCount(hmenu);
// remove 'close' action
RemoveMenu(hmenu, cnt-1, MF_DISABLED | MF_BYPOSITION);
// remove extra menu line
RemoveMenu(hmenu, cnt-2, MF_DISABLED | MF_BYPOSITION);
DrawMenuBar(this.Handle);
What we have going on there is we first get a handle to the system menu and get the count of items in it. Since the raw system menu will have “Close” at the bottom, we remove that but also need to move the line separator that was previously above it. BTW, I emphasized raw system menu because some applications, such as Ultramon, will all items to the system menus. That's ok and it will not screw this up. After removing those menu items we force a redraw of the menu and we've done it. As I pointed out earlier, since we remove the system menu's “Close” item, this also disables the “Close” action for the window. So as a side-effect the Close button will become disabled.
You'll see what the end result looks like. Both the Close menu is removed and you'll find that the Close button is disabled. Notice in this screenshot that even with the Ultramon menus added to the system menu that the assertion that the Close menu item is last on the list still gives us the desired results. |
|
|