-
2 Attachment(s)
Disable Close Button and Prevent Form Being Moved
C# version here.
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.
-
Re: Disable Close button
Nice code John. Good job. ;) Its about time MS added the EnableMenuItem API. ;)
Probably would be better if it was a prublic function in a class somewhere so you can call it throughout your project. :)
-
Re: Disable Close button
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. :sick:
-
Re: Disable Close button
Quote:
Originally Posted by jmcilhinney
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. :sick:
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. :thumb:'s again.
-
Re: Disable Close button
Hey, John. What about using MF_DISABLED instead of MF_GRAYED?
-
Re: Disable Close button
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.
-
Re: Disable Close button
How about disabling the ALT+F4?
-
Re: Disable Close button
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. ;)
-
Re: Disable Close button
thanks for this code! I needed it :thumb:
Bye, :wave:
Anna
-
Re: Disable Close button
i have one small problem. When I maximize o minimize the form, close button turns enabled. :confused:
-
Re: Disable Close button
Quote:
Originally Posted by anna7
i have one small problem. When I maximize o minimize the form, close button turns enabled. :confused:
in the form's ReSize event put jmcilhinney's code in so it'll re-disable the form's titlebar close button
-
Re: Disable Close button
-
Re: Disable Close button
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.
-
Re: Disable Close button
awsome, thanx jmcilhinney it looks good, i may start using it for some of my app's :)
-
Re: Disable Close Button and Prevent Form Being Moved
Thanks JMC,
Excellent and easy to use, even for me.
-
Re: Disable Close Button and Prevent Form Being Moved
Why doesnt my window load center screen with this? Its half off.
-
Re: Disable Close Button and Prevent Form Being Moved
Real clean code. Nice commenting, and works great.
Bill
-
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
set the Flase to True like so
VB Code:
(Me, True, SystemMenuManager.MenuItemState.Greyed)
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 :thumb:
-
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
oops sorry jmcilhinney, I have amended my post now. As for the
Quote:
AutoReset set to False so the Elapsed event is only raised once
Do you mean that once the timer has fired once you can disable it and the form should still act as a child form and have the close button disabled ? :ehh:
-
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 ? :ehh:
-
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
Quote:
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 ? :ehh:
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
Yer i got it working using :
VB Code:
Private Sub LoadTimer_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles LoadTimer.Tick
Me.MdiParent = PhoneExchange.ActiveForm
' this is my own bug fix :
Me.Left = Me.Left + 1
LoadTimer.Stop()
End Sub
As I found the form close button didn’t disable until you moved the form by dragging it. So I made it move automatically with the timer on tick event
Thanks for all your help again :thumb: :afrog: :wave: :D :bigyello: :)
-
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 :blush: . You are of course absolutely right, So sorry...I have been up 24 hours so that’s my only excuse :sick: thanks for putting me right and putting up with my ignorance :rolleyes:
-
Re: Disable Close Button and Prevent Form Being Moved
-
Re: Disable Close Button and Prevent Form Being Moved
Quote:
Originally Posted by shakti5385
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
Hey,
I thought I would post this and see if it helps...a simple way to disable the close button in vb 2005
Code Code:
Private Const SC_CLOSE As Integer = &HF060
Private Const MF_ENABLED As Integer = &H0
Private Const MF_GRAYED As Integer = &H1
Private Const MF_DISABLED As Integer = &H2
Declare Function GetSystemMenu Lib "user32" (ByVal hWnd As IntPtr, ByVal revert As Boolean) As IntPtr
Declare Function EnableMenuItem Lib "user32" (ByVal hMenu As IntPtr, ByVal item As Integer, ByVal enab As Integer) As Boolean
Public Sub EnableExit(ByVal ok As Boolean)
Try
Dim hdl As IntPtr = GetSystemMenu(Me.Handle, False)
Dim arg As Integer = MF_ENABLED
If Not ok Then arg = MF_DISABLED + MF_GRAYED
EnableMenuItem(hdl, SC_CLOSE, arg)
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
'call EnableExit(False) in your form load event to disable the clode button
Just thought it might be worth posting this :thumb:
-
Re: Disable Close Button and Prevent Form Being Moved
Quote:
Originally Posted by rabid lemming
Hey,
I thought I would post this and see if it helps...a simple way to disable the close button in vb 2005
Code Code:
Private Const SC_CLOSE As Integer = &HF060
Private Const MF_ENABLED As Integer = &H0
Private Const MF_GRAYED As Integer = &H1
Private Const MF_DISABLED As Integer = &H2
Declare Function GetSystemMenu Lib "user32" (ByVal hWnd As IntPtr, ByVal revert As Boolean) As IntPtr
Declare Function EnableMenuItem Lib "user32" (ByVal hMenu As IntPtr, ByVal item As Integer, ByVal enab As Integer) As Boolean
Public Sub EnableExit(ByVal ok As Boolean)
Try
Dim hdl As IntPtr = GetSystemMenu(Me.Handle, False)
Dim arg As Integer = MF_ENABLED
If Not ok Then arg = MF_DISABLED + MF_GRAYED
EnableMenuItem(hdl, SC_CLOSE, arg)
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
'call EnableExit(False) in your form load event to disable the clode button
Just thought it might be worth posting this :thumb:
Have you read my code? That's exactly how it works, but I wrapped it in a class that you can reuse instead of having to add that code to every form.
-
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
I wasn't able to reproduce the quirk, but my comment still stands for API declares.
-
Re: Disable Close Button and Prevent Form Being Moved
Opps sorry jmcilhinney my bad :blush: :eek:
-
Re: Disable Close Button and Prevent Form Being Moved
-
Re: Disable Close Button and Prevent Form Being Moved
Quote:
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
-
Re: Disable Close Button and Prevent Form Being Moved
Quote:
Originally Posted by kalboako1987
should i use imports?
What does this mean?
-
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. :D 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, _
GetType(WINDOWPOS)), _
WINDOWPOS)
pos.x = Me.Left
pos.y = Me.Top
Runtime.InteropServices.Marshal.StructureToPtr(pos, m.LParam, True)
End If
MyBase.WndProc(m)
End Sub
See the first post for a downloadable class that incorporates this code.
-
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?
-
Re: Disable Close Button and Prevent Form Being Moved
Quote:
Originally Posted by Simply Me
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?
Are you saying that your second form is using my FormImmobiliser class and it won't restore after being minimised?
-
Re: Disable Close Button and Prevent Form Being Moved
Yes. My second form uses your FormImmobiliser class. My second form BorderStyle is FixedToolWindow. Whenever I click the form's name in the task bar it automatically minimizes and when I right click and choose restore or maximize it is not restoring.
-
Re: Disable Close Button and Prevent Form Being Moved
Quote:
Originally Posted by Simply Me
Yes. My second form uses your FormImmobiliser class. My second form BorderStyle is FixedToolWindow. Whenever I click the form's name in the task bar it automatically minimizes and when I right click and choose restore or maximize it is not restoring.
I've changed the code for the FormImmobiliser class. Download the new version from post #1 and see if that addresses the issue.
-
Re: Disable Close Button and Prevent Form Being Moved
Great it works now!
Thanks!
-
Re: Disable Close Button and Prevent Form Being Moved
Hi JM
I am using both of your classes after loading a form (frmSixQs) from a child form (frmProfiles). All runs as expected, except when I click off the form (frmSixQs), it closes.
How do I make my form focused exclusively until the user closes it intentionally?
-
Re: Disable Close Button and Prevent Form Being Moved
Quote:
Originally Posted by Always_Confused
Hi JM
I am using both of your classes after loading a form (frmSixQs) from a child form (frmProfiles). All runs as expected, except when I click off the form (frmSixQs), it closes.
How do I make my form focused exclusively until the user closes it intentionally?
That doesn't sound like anything that would be caused by my code but I'll run some tests just to make sure.
-
Re: Disable Close Button and Prevent Form Being Moved
Quote:
Originally Posted by Always_Confused
Hi JM
I am using both of your classes after loading a form (frmSixQs) from a child form (frmProfiles). All runs as expected, except when I click off the form (frmSixQs), it closes.
How do I make my form focused exclusively until the user closes it intentionally?
I tested my classes with all combinations of Show and ShowDialog with 1, 2 and 3 forms and saw no such behaviour, so I can only assume that it's something to do with your own code. What happens if you remove my classes? Do you still see that behaviour?
-
Re: Disable Close Button and Prevent Form Being Moved
The SystemMenuManager class doesn't seem to have any effect on the close button of a FixedToolWindow form. Problem encountered in Windows Vista SP1. I tried setting the SMM both to disable and to remove the close button, with absolutely no effect whatsoever. Here's the declaration:
Code:
Private smm As New SystemMenuManager(Me, SystemMenuManager.MenuItemState.Removed)
For now, I've set the ControlBox property to False, however I'd also like to block the Alt + F4 key combination, which seems to work, albeit erratically. I will explore the problem further and attempt to narrow down the source of the problem. I'll keep you posted as best I can, given my poor internet connection.
-
Re: Disable Close Button and Prevent Form Being Moved
Quote:
Originally Posted by obi1kenobi
The SystemMenuManager class doesn't seem to have any effect on the close button of a FixedToolWindow form. Problem encountered in Windows Vista SP1. I tried setting the SMM both to disable and to remove the close button, with absolutely no effect whatsoever. Here's the declaration:
Code:
Private smm As New SystemMenuManager(Me, SystemMenuManager.MenuItemState.Removed)
For now, I've set the ControlBox property to False, however I'd also like to block the Alt + F4 key combination, which seems to work, albeit erratically. I will explore the problem further and attempt to narrow down the source of the problem. I'll keep you posted as best I can, given my poor internet connection.
I probably never tested that scenario. I'll have a look myself too, when I get the chance. Out of town visiting my dad for this Australia Day long weekend. Submitting this using his brand new Internet connection.
-
Re: Disable Close Button and Prevent Form Being Moved
What Is the value of the Size menu Item? I would like to disable form sizing but, I need to have it have a sizable border style? I hope I didn't pass over it while scanning the forum. I have tried Googleing it but, that results in "Set the border style to something with Fixed in it."
Thanks!
E
-
Re: Disable Close Button and Prevent Form Being Moved
Hi,
I was using your formImmobiliser.vb class only since i use vb .net 2005.
Then i declared Dim frmMove As New FormImmobilisre(Me) in 'declarations' region. That's it?
but it doen't work properly. where to declare dim statement and anything else to do?
form will move only upwards (no left, right, down).
can you give code sample how to use your class?
-
Re: Disable Close Button and Prevent Form Being Moved
Quote:
Originally Posted by
obi1kenobi
The SystemMenuManager class doesn't seem to have any effect on the close button of a FixedToolWindow form. Problem encountered in Windows Vista SP1. I tried setting the SMM both to disable and to remove the close button, with absolutely no effect whatsoever. Here's the declaration:
Code:
Private smm As New SystemMenuManager(Me, SystemMenuManager.MenuItemState.Removed)
For now, I've set the ControlBox property to False, however I'd also like to block the Alt + F4 key combination, which seems to work, albeit erratically. I will explore the problem further and attempt to narrow down the source of the problem. I'll keep you posted as best I can, given my poor internet connection.
I'm having the same trouble on Windows XP. Everything works great! Thank you very much! I'll take a look at things and report if I find anything to make it work with fixed tool windows.
-
Re: Disable Close Button and Prevent Form Being Moved
Code:
myMenuManager = New SystemMenuManager(_handle, True, SystemMenuManager.MenuItemState.Enabled)
oh my god i can't enabled my close button :sick:
-
Re: Disable Close Button and Prevent Form Being Moved
Quote:
Originally Posted by
medsont
Code:
myMenuManager = New SystemMenuManager(_handle, True, SystemMenuManager.MenuItemState.Enabled)
oh my god i can't enabled my close button :sick:
Um, huh? The Close button is enabled by default, so you don't have to do anything to enable it. The whole point of this thread is to disable it. Are you saying, without actually saying, that you have already disabled it and then you want to re-enable it at some point?
-
Re: Disable Close Button and Prevent Form Being Moved
Sounds like its being disabled but they are not able to re-enable it. Since its probably a coding issue not directly related I would suggest posting a new thread in the VB.NET forum and link/reference this codebank thread so all can assist you better. :)
-
Re: Disable Close Button and Prevent Form Being Moved
ok Thank you Mr.SuperModerator.....
-
Re: Disable Close Button and Prevent Form Being Moved
Hi, I know this is an old thread but I was hoping someone could help me. I am using the Form Immobilizer and it is working great. What I would like to know is if it is possible to enable/disable the feature during run time or by changing a setting in an ini file?
Thanks
-
Re: Disable Close Button and Prevent Form Being Moved
Quote:
Originally Posted by
Zaxxan
Hi, I know this is an old thread but I was hoping someone could help me. I am using the Form Immobilizer and it is working great. What I would like to know is if it is possible to enable/disable the feature during run time or by changing a setting in an ini file?
Thanks
This is the part that actually stops the form moving:
Code:
Protected Overrides Sub WndProc(ByRef m As Message)
If m.Msg = WM_MOVING Then
Marshal.StructureToPtr(New RECT(Me.target.Bounds), _
m.LParam, _
False)
m.Result = New IntPtr([TRUE])
End If
MyBase.WndProc(m)
End Sub
If you want to allow the form to move then all you need to do is not execute that bit of code. It's already in an If block so all you have to do is add a flag to that If statement that can be set from outside, e.g.
vb.net Code:
Public Property CanMove As Boolean
Protected Overrides Sub WndProc(ByRef m As Message)
If Not CanMove AndAlso m.Msg = WM_MOVING Then
Marshal.StructureToPtr(New RECT(Me.target.Bounds), _
m.LParam, _
False)
m.Result = New IntPtr([TRUE])
End If
MyBase.WndProc(m)
End Sub
-
Re: Disable Close Button and Prevent Form Being Moved