Thursday, November 20, 2003
Disabling the Window Close Button and System Close menu in a Windows Form
Ran into one of those common scenarios today where you have to dive into P/Invoke land for something that should be a lot easier to do than it is. Requirement was to disable the Window close button while a processing thread was active, re-enable when the processing thread was stopped. Found a nice solution through Google on Cory Smith's blog. Ported the code to C# and encapsulated as part of the form instead of a separate class with a little clean up of the API declaration types. The basic steps to re-use are below. You could also make this a base class type that derives from Form that you then derive your form classes from, but then you have to deal with the IDE designer going stupid sometimes.
This is the kind of silliness that comes up all the time in real apps that I hope goes away in Longhorn since the OS API is all managed. One would expect to see these kinds of capabilities exposed as part of the Form class or its equivalent in Avalon.
Basic steps are to bring in the APIs and constants as part of the form class and wrap toggling the enabled state of the close command with a property (that should have been a member of the base Form class!!).
// Declare P/Invoke methods
[DllImport("user32")]
private static extern IntPtr GetSystemMenu(IntPtr hWnd, int revert);
[DllImport("user32")]
private static extern int EnableMenuItem(IntPtr hWndMenu, int itemID, int enable);
// Declare constants to pass to the methods
private const int SC_CLOSE = 0xF060;
private const int MF_ENABLED = 0;
private const int MF_GREYED = 1;
private const int MF_BYCOMMAND = 0;
// Declare a flag to track the enabled state
private bool m_bCloseEnabled = true;
private System.Windows.Forms.Button btnToggleState; // default for WinForms
public bool CloseEnabled
{
get
{
// Return the internal flag state
return m_bCloseEnabled;
}
set
{
// Decide on the state to pass based on the value being set
int setting;
if (value) // Enabling
{
setting = MF_BYCOMMAND | MF_ENABLED;
}
else
{
setting = MF_BYCOMMAND | MF_GREYED;
}
// Make the update
EnableMenuItem(GetSystemMenu( this.Handle,0),SC_CLOSE,setting);
// Update the internal flag state
m_bCloseEnabled = value;
}
}
Then added a handler for the SizeChanged event to handle minimize/maximize redrawing of the menu to reset the state to the internally maintained state:
private void OnSizeChanged(object sender, System.EventArgs e)
{
// Reset the state with the internally maintained state
CloseEnabled = m_bCloseEnabled;
}
Then you can simply set the state of the CloseEnabled property whenever you want to change the state of the close button.
|







| August, 2008 (2) |
| July, 2008 (1) |
| June, 2008 (2) |
| May, 2008 (2) |
| April, 2008 (3) |
| February, 2008 (6) |
| January, 2008 (3) |
| December, 2007 (1) |
| November, 2007 (1) |
| October, 2007 (5) |
| September, 2007 (1) |
| July, 2007 (3) |
| June, 2007 (8) |
| April, 2007 (2) |
| March, 2007 (4) |
| February, 2007 (1) |
| December, 2006 (2) |
| November, 2006 (9) |
| October, 2006 (5) |
| September, 2006 (3) |
| August, 2006 (2) |
| July, 2006 (4) |
| June, 2006 (5) |
| May, 2006 (10) |
| April, 2006 (4) |
| March, 2006 (2) |
| February, 2006 (12) |
| January, 2006 (7) |
| December, 2005 (2) |
| November, 2005 (15) |
| October, 2005 (6) |
| September, 2005 (7) |
| August, 2005 (3) |
| July, 2005 (10) |
| June, 2005 (11) |
| May, 2005 (7) |
| April, 2005 (8) |
| March, 2005 (6) |
| February, 2005 (2) |
| January, 2005 (6) |
| December, 2004 (3) |
| November, 2004 (5) |
| October, 2004 (2) |
| September, 2004 (5) |
| August, 2004 (13) |
| July, 2004 (6) |
| June, 2004 (14) |
| May, 2004 (17) |
| April, 2004 (12) |
| March, 2004 (8) |
| February, 2004 (10) |
| January, 2004 (14) |
| December, 2003 (9) |
| November, 2003 (13) |
| October, 2003 (3) |


Sign In
|