SystemMenuManager class - A helper class that you can add an instance of to a form and remove the Move item from the system menu, which renders the form immoveable by the user, and/or disable or remove the Close item, which also disables the Close button on the title bar. When the Close item is disabled or removed the Alt+F4 key combination is also disabled. To use this class just add a single line of code similar to this to your form:
VB.NET Code:
Private myMenuManager As New SystemMenuManager(Me, False, SystemMenuManager.MenuItemState.Greyed)
Note that it does not affect any other items on the system menu as these should be accessed through properties of the form itself. Also, the Move item can only be removed as disabling it or greying it out seem to have no effect.
EDIT: I've taken the code from post #39 and incorporated it into a class that I've attached to this post. You can use this class to make your form immovable like so:
vb.net Code:
Private immobiliser As New FormImmobiliser(Me)
EDIT (8-Jan-2009): I've updated the code for the FormImmobiliser class so it's now a bit simpler and it also addresses a few issues that the old code had.
Last edited by jmcilhinney; Mar 9th, 2011 at 05:07 AM.
Thanks Rob. You give good rep. I've come from a C++ background so the succincter (sic) the code the better. I love that C code that does about fifty things in one line and there are more dots and arrows than other characters.
Thanks Rob. You give good rep. I've come from a C++ background so the succincter (sic) the code the better. I love that C code that does about fifty things in one line and there are more dots and arrows than other characters.
I know what you mean. I hate to write many lines of simple code when you can usually nest function calls inside of each other, etc. 's again.
VB/Office Guru™ (AKA: Gangsta Yoda™ ®)
I dont answer coding questions via PM. Please post a thread in the appropriate forum.
I tested it both ways and its not the same. The MF_GRAYED disables the 'x' AND the system menu Close item, but the MF_DISABLED constant only disables the 'x' and leaves the Close system menu item looking enabled but is actualy disabled.
VB/Office Guru™ (AKA: Gangsta Yoda™ ®)
I dont answer coding questions via PM. Please post a thread in the appropriate forum.
To disable that keypress sequence I believe you would have to create a WndProc to handle the message stream for that form and intercept the WM_CLOSE message and beable to determine from the lPram and wPram that it is not closing via the code but rather attempting to close from the ALT+F4.
VB/Office Guru™ (AKA: Gangsta Yoda™ ®)
I dont answer coding questions via PM. Please post a thread in the appropriate forum.
Attached is a helper class that you can use to affect the Move and Close item on a form's system menu. If you remove the Move item the user cannot move the form by dragging it. If you grey-out, disable or remove the Close item the Close button on the title bar will be disabled and so will the Alt+F4 key combination. To use it you need just one line of code. Just create an instance in your form like this:
VB Code:
Private menuManager As New SystemMenuManager(Me, False, SystemMenuManager.MenuItemState.Greyed)
and everything else is done for you. Note that if you disable the Close item then you must provide an alternative method of closing the form. Note also that this class addresses the issue that anna7 picked up earlier. It implements the solution that JuggaloBrotha suggested internally.
Edit:
Attachment removed. See post #1.
Last edited by jmcilhinney; Sep 30th, 2005 at 05:38 AM.
Re: Disable Close Button and Prevent Form Being Moved
Thanks JMC,
Excellent and easy to use, even for me.
"Imagination is more important than knowledge..."
Albert Einstein
----------------------------------------------- If my reply helped you then you really were lost, but I still took the time to help, please rate it anyway
Re: Disable Close Button and Prevent Form Being Moved
I thought I would post this for other users as I found it helpful. If you want to disable the close button of a form that is an MdiChild of another form. That is to say if at run time you have a form that loads inside another form using the
VB Code:
Me.MdiParent = TheParentOrMainForm.ActiveForm
Where "TheParentOrMainForm" is the name of the form you want the current form you’re adding this code to, to appear inside of.
Well to do that firstly add a new class and name it "SystemMenuManager" to your project. Copy the code from the file attachment above in this thread replacing any code already their.
Then add a timer component to your form from the tools menu
Add this to you child form in the code
VB Code:
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Me.MdiParent = TheParentOrMainForm.ActiveForm
Dim myMenuManager As New SystemMenuManager(Me, False, SystemMenuManager.MenuItemState.Greyed)
End Sub
Also if you want to only remove the close button but allow the form to be movable
I hope this helps other users. Don’t forget to remove the maximize and minimizes controls in the design view of your form. In the properties window set the MaximizeBox and MinimizesBox properties to false
This will basically allow you to disable a forms close button using the above topic method even if the form is a MdiChild of another form and allow you to still move the form about
I hope this makes sense and is easy to follow. And mostly I hope some one finds it as helpful as I did
Last edited by rabid lemming; Nov 24th, 2005 at 01:59 AM.
I will wait for death with a smile and a big stick
Re: Disable Close Button and Prevent Form Being Moved
Hey, hey, hey! Don't be commenting anything out. The second argument to the constructor you're using indicates whether the Move item should be present or not. Just change that argument to True or use the second overload that omits that argument if you want the form to be movable.
As for the other issue, it is an odd situation. If you create the SystemMenuManager object in the class initialisation, the constructor, the Load event handler or the Activated event handler it doesn't work. It seems that the use of a Timer is the only way, which works even if the Timer has the smallest possible Interval. I'd actually recommend using a System.Timers.Timer object with an Interval of 1 (millisecond) and the AutoReset set to False so the Elapsed event is only raised once. If you do use a System.Windows.Forms.Timer then make sure you call Stop in the Tick event handler or the Timer will continue to raise the Tick event over and over.
Re: Disable Close Button and Prevent Form Being Moved
Actually, I just tested a bit more and you don't have to use a Timer if you select Disabled or Removed but you do if you select Greyed. Love those idiosynchrasies!
Re: Disable Close Button and Prevent Form Being Moved
hummm... I found that even setting it to Disabled or Removed and the form will be contained with in the main form container but the close button is still visible ?
I will wait for death with a smile and a big stick
Re: Disable Close Button and Prevent Form Being Moved
You only have to Disable/Remove the Close menu item once. After that you would have to consciously put it back for it to be available again. There's no need to keep doing it over and over, unless there is some other quirky MDI behaviour that I don't know about. If you allow your Timer to keep raising its Tick event then you are wasting resources on it. The AutoReset property is specifically designed to differentiate between a once only Timer and a continuous one, although it is only a member of the Timers.Timer and not the Windows.Forms.Timer. If you use that one you have to explicitly Stop it. The Timers.Timer is on the Components tab of the Toolbox.
Re: Disable Close Button and Prevent Form Being Moved
Originally Posted by rabid lemming
hummm... I found that even setting it to Disabled or Removed and the form will be contained with in the main form container but the close button is still visible ?
Create the SystemMenuManager in the Load event handler and it should work, as it did for me. If you declare the SMM at the class-level and create it on the same line it will not work.
Re: Disable Close Button and Prevent Form Being Moved
All I did was put this code in the form's Load event handler:
VB Code:
Dim smm As New SystemMenuManager(Me, SystemMenuManager.MenuItemState.Removed)
Nothing else was required. Also, I don't understand why you're setting the form's MdiParent property. The normal thing to do is set the parent from the outside before you call Show. A form setting it's own parent seems very odd.
Re: Disable Close Button and Prevent Form Being Moved
lol now i just feel silly . You are of course absolutely right, So sorry...I have been up 24 hours so that’s my only excuse thanks for putting me right and putting up with my ignorance
I will wait for death with a smile and a big stick
The drawback with that is that you must inherit your form from that class. My class can be added to any form you like, which makes it a little simpler to use. I'd guess that that author has used the same method of disabling the Move menu item though.
Re: Disable Close Button and Prevent Form Being Moved
I had run into that problem before where the button becomes reenabled after resizing the form. I no longer have that problem.
I think I fixed it by declaring the API PROPERLY!
Yes it's wrong that way, and many API will fail sometimes without an Alias.
For example the proper way:
Code:
Declare Function apiEnableMenuItem Lib "user32" Alias "EnableMenuItem" (ByVal hMenu As IntPtr, ByVal item As Int32, ByVal enab As Int32) As Boolean
Where the alias name should be different than the function name.
I'll see if I can indeed verify that as the reason, unless the IntPtr may also cause a problem.
Re: Disable Close Button and Prevent Form Being Moved
Originally Posted by TTn
I had run into that problem before where the button becomes reenabled after resizing the form. I no longer have that problem.
I think I fixed it by declaring the API PROPERLY!
Yes it's wrong that way, and many API will fail sometimes without an Alias.
For example the proper way:
Code:
Declare Function apiEnableMenuItem Lib "user32" Alias "EnableMenuItem" (ByVal hMenu As IntPtr, ByVal item As Int32, ByVal enab As Int32) As Boolean
Where the alias name should be different than the function name.
I'll see if I can indeed verify that as the reason, unless the IntPtr may also cause a problem.
No, that incorrect as in .NET its most proper to use the dllimport attribute as alias' are not used or allowed as EntryPoint is used.
Code:
<System.Runtime.InteropServices.DllImport("User32.dll", CharSet:=Runtime.InteropServices.CharSet.Auto, EntryPoint:="EnableMenuItem")> _
Private Shared Function EnableMenuItem(ByVal hMenu As IntPtr, ByVal item As Int32, ByVal enab As Int32) As Boolean
End Function
VB/Office Guru™ (AKA: Gangsta Yoda™ ®)
I dont answer coding questions via PM. Please post a thread in the appropriate forum.
Re: Disable Close Button and Prevent Form Being Moved
Sorry to refresh an old thread, but I have found a simple (yet far from ideal solution) to blocking the Alt + F4 key combination. It's sloppy, but extremely easy to do. Just set a menu item's shortcut key combination to Alt + F4 and every press will fire the menu item's Clicked event instead of closing the form. Tested and works perfectly.
Re: Disable Close Button and Prevent Form Being Moved
It's come to my attention that this class will not prevent the form moving if the ControlBox property is set to False. The following code seems to work in all cases:
vb.net Code:
Private Structure WINDOWPOS
Public hwnd As Int32
Public hWndInsertAfter As Int32
Public x As Int32
Public y As Int32
Public cx As Int32
Public cy As Int32
Public flags As Int32
End Structure
Const WM_WINDOWPOSCHANGING As Int32 = &H46
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = WM_WINDOWPOSCHANGING Then
Dim pos As WINDOWPOS = DirectCast(Runtime.InteropServices.Marshal.PtrToStructure(m.LParam, _
Re: Disable Close Button and Prevent Form Being Moved
Hi jm!
Your work is great it helps me alot and I implemented it in my apps.
I have a main form (not MDI) a treeview menu when user clicked a certain menu it opens another form on top of the main form. Whenever i click the icon of the form found in the start bar the form will minimized but when I click it again I was expecting that it would display it back but it is not restoring. I even tried right click then maximize or restore and its not working. Is it possible that whenever I click the icon in the start bar it will not minimize?
To give is always to be NOBLE...
To received is always to be BLESSED....
Each day strive to be NOBLE
Each day strive to be BLESSED
If this post has helped you. Please take time to rate it.