Disable the Close Button ('X') on a Form
Disable the Close Button ('X') on a Form
Disable the Close Button ('X') on a Form
Disable the Close Button ('X') on a Form
Disable the Close Button ('X') on a Form
Disable the Close Button ('X') on a Form Disable the Close Button ('X') on a Form Disable the Close Button ('X') on a Form Disable the Close Button ('X') on a Form Disable the Close Button ('X') on a Form Disable the Close Button ('X') on a Form Disable the Close Button ('X') on a Form Disable the Close Button ('X') on a Form
Disable the Close Button ('X') on a Form Disable the Close Button ('X') on a Form
Disable the Close Button ('X') on a Form
Go Back  Xtreme Visual Basic Talk > > > Disable the Close Button ('X') on a Form


Reply
 
Thread Tools Display Modes
  #1  
Old 03-25-2008, 12:30 PM
BridgeGuy BridgeGuy is offline
Newcomer
 
Join Date: Dec 2003
Location: Tallahassee, FL
Posts: 22
Question Disable the Close Button ('X') on a Form


I am attempting to disable the close button "X" in the controlbox of a form and keep the maximize and minimize buttons. There does not appear to be a way to accomplish this with conventional VB code or using the Form's Properties.

So I ventured into the realm of API's.


I declared the following API Calls and Constants:

Declare Function GetSystemMenu Lib "user32" Alias "GetSystemMenu" _
(ByVal hwnd As Long, ByVal bRevert As Long) As Long

Declare Function EnableMenuItem Lib "user32" Alias "EnableMenuItem" _
(ByVal hMenu As Long, ByVal wIDEnableItem As Long, ByVal wEnable As Long) As Long

Private Const SC_CLOSE = &HF060&
Private Const MF_GRAYED = &H1&


In the Form_Load event I placed the following code:

Dim n As Long = EnableMenuItem(GetSystemMenu(Me.Handle, 0), SC_CLOSE, MF_GRAYED)

When I run this code I get the following error message:

PInvokeStackImbalance was detected
Message: A call to PInvoke function 'PT Column!PT_Column.frmSlndrColAnalysisProgress::GetSystemMenu' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.

Could somebody point out why this doesn't work.

Thanks,

Jim
Reply With Quote
  #2  
Old 03-25-2008, 01:41 PM
AtmaWeapon's Avatar
AtmaWeaponDisable the Close Button ('X') on a Form AtmaWeapon is offline
Fabulous Florist

Forum Leader
* Guru *
 
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,500
Default

One of the more curious features of VB6 is that it used 16-bit Integer types. Since the Win32 API uses 32-bit integer types, this means that any VB6 code that wants to reference Win32 API code must use the 32-bit Long data type.

Here's a pseudo-explanation of how it happened; I don't pretend to know all the details or even be completely correct, but at a high level I know I am right.

VB .NET uses the CLR's Int32 data type for Integer, so Integer is 32 bits. Long uses Int64, a 64-bit integer. To pass parameters, programs shove them onto the stack, and the first thing the function does is remove its parameters from the stack so they can be stored. GetSystemMenu expects a 32-bit integer and a 32-bit integer for a total of 64 bits of parameters. When you pass two Longs, you actually place 128 bits on the stack. GetSystemMenu doesn't know this, so it only removes 64 bits. .NET is telling you this when it tells you there's a stack imbalance: the stack is larger when the function exits than it was before calling the function.

To solve the problem, use Integer when you need a 32-bit integer value for an API function, and always check http://www.pinvoke.net. The site is a compilation of the proper signatures for API functions, and generally they are right.

*Edit* I don't think this will do what you want though; I don't think I've ever seen the Close button disabled, which tends to indicate it's either not possible or tricky. You are disabling a menu item, not a button, with this code.

Last edited by AtmaWeapon; 03-25-2008 at 01:47 PM.
Reply With Quote
  #3  
Old 03-25-2008, 03:46 PM
Csharp's Avatar
CsharpDisable the Close Button ('X') on a Form Csharp is offline
Senior Contributor

* Expert *
 
Join Date: Jul 2003
Location: Ashby, Leicestershire.
Posts: 967
Default

to disable / enable the close button ( X ) on your form, you can do this ...
Code:
    Private Declare Function DrawMenuBar Lib "user32.dll" (ByVal hwnd As IntPtr) As IntPtr
    Private Declare Function GetSystemMenu Lib "user32.dll" (ByVal hwnd As IntPtr, ByVal bRevert As Int32) As IntPtr
    Private Declare Function GetMenuItemCount Lib "user32.dll" (ByVal hMenu As IntPtr) As Int32
    Private Declare Function RemoveMenu Lib "user32.dll" (ByVal hMenu As IntPtr, ByVal nPosition As Int32, ByVal wFlags As Int32) As Int32
    Private Const MF_BYPOSITION As Int32 = &H400I
    Private Const MF_REMOVE As Int32 = &H1000I

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        '/// DISABLE CLOSE BUTTON ( GREY IT OUT )
        Dim hMenu As IntPtr = GetSystemMenu(MyBase.Handle, False)
        Dim nCount As Int32 = GetMenuItemCount(hMenu)

        If nCount > 2 Then
            RemoveMenu(hMenu, nCount - 1, MF_REMOVE Or MF_BYPOSITION)
            RemoveMenu(hMenu, nCount - 2, MF_REMOVE Or MF_BYPOSITION)

            DrawMenuBar(MyBase.Handle)
        End If

    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        '/// ENABLE CLOSE BUTTON
        GetSystemMenu(MyBase.Handle, True)

        DrawMenuBar(MyBase.Handle)
    End Sub
hope it helps.
__________________
~~ please don't PM me regarding code, I only reply to personnal messages ~~
Reply With Quote
  #4  
Old 03-26-2008, 05:25 AM
BridgeGuy BridgeGuy is offline
Newcomer
 
Join Date: Dec 2003
Location: Tallahassee, FL
Posts: 22
Default

Quote:
Originally Posted by AtmaWeapon View Post
One of the more curious features of VB6 is that it used 16-bit Integer types. Since the Win32 API uses 32-bit integer types, this means that any VB6 code that wants to reference Win32 API code must use the 32-bit Long data type.

Here's a pseudo-explanation of how it happened; I don't pretend to know all the details or even be completely correct, but at a high level I know I am right.

VB .NET uses the CLR's Int32 data type for Integer, so Integer is 32 bits. Long uses Int64, a 64-bit integer. To pass parameters, programs shove them onto the stack, and the first thing the function does is remove its parameters from the stack so they can be stored. GetSystemMenu expects a 32-bit integer and a 32-bit integer for a total of 64 bits of parameters. When you pass two Longs, you actually place 128 bits on the stack. GetSystemMenu doesn't know this, so it only removes 64 bits. .NET is telling you this when it tells you there's a stack imbalance: the stack is larger when the function exits than it was before calling the function.

To solve the problem, use Integer when you need a 32-bit integer value for an API function, and always check http://www.pinvoke.net. The site is a compilation of the proper signatures for API functions, and generally they are right.

*Edit* I don't think this will do what you want though; I don't think I've ever seen the Close button disabled, which tends to indicate it's either not possible or tricky. You are disabling a menu item, not a button, with this code.
Thank You for your help. It did indeed work. The close button was successfully disabled using this code. I changed all the parameters to integer in the declare statements and it worked, just as you had suspected. Thanks again for your time. Your insight was valuable.

Bridge Guy
Reply With Quote
  #5  
Old 03-26-2008, 08:26 AM
AtmaWeapon's Avatar
AtmaWeaponDisable the Close Button ('X') on a Form AtmaWeapon is offline
Fabulous Florist

Forum Leader
* Guru *
 
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,500
Default

Honestly CSharp's code looks more reliable to me; he handles more of the API's "When you call this method you must do x" cases.
Reply With Quote
  #6  
Old 03-28-2008, 08:52 AM
gnappi gnappi is offline
Freshman
 
Join Date: Mar 2006
Posts: 33
Default Disable X button

I use this, it's a lot simpler:

Private Sub form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
' prevents the user from clicking the RED X to close
e.Cancel = True
MsgBox("X Button Disabled, use EXIT Button")
End Sub
Reply With Quote
  #7  
Old 03-28-2008, 10:46 AM
AtmaWeapon's Avatar
AtmaWeaponDisable the Close Button ('X') on a Form AtmaWeapon is offline
Fabulous Florist

Forum Leader
* Guru *
 
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,500
Default

gnappi, while your code is functional, from a UI standpoint it's not the same, and it actually can cause unexpected behavior.

First, a disabled button is better than displaying a dialog when the button is clicked, because the user can tell at a glance the action is not allowed. It's annoying to click a button, only to have to click another button after the program tells me that the button is not supposed to be clicked. Sure, it's more work, but it's better.

Second, consider this example application that implements your method:
Code:
Public Class MainForm
    Inherits Form

    Dim _child As ChildForm

    Public Sub New()
        Dim btn As New Button()
        btn.Text = "Close child"
        AddHandler btn.Click, AddressOf ButtonOnClick
        Me.Controls.Add(btn)
    End Sub

    Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
        MyBase.OnLoad(e)
        _child = New ChildForm()
        _child.Show()
    End Sub

    Private Sub ButtonOnClick(ByVal sender As Object, ByVal e As EventArgs)
        _child.Close()
    End Sub

End Class

Public Class ChildForm
    Inherits Form

    Protected Overrides Sub OnClosing(ByVal e As System.ComponentModel.CancelEventArgs)
        e.Cancel = True
        MessageBox.Show("Not allowed.")
    End Sub
End Class
You cannot click the X button of the child form to close it. What happens when the main form tries to close the child form? It can't be closed at all! In order to disable the X button but still allow closing the form via other circumstances, you have to implement logic to indicate to the event handler whether it's a valid close request or not. Isn't this just as complicated?
Reply With Quote
  #8  
Old 11-11-2008, 09:11 PM
aries1104 aries1104 is offline
Newcomer
 
Join Date: Nov 2008
Posts: 1
Thumbs up

Quote:
Originally Posted by Csharp View Post
to disable / enable the close button ( X ) on your form, you can do this ...
Code:
    Private Declare Function DrawMenuBar Lib "user32.dll" (ByVal hwnd As IntPtr) As IntPtr
    Private Declare Function GetSystemMenu Lib "user32.dll" (ByVal hwnd As IntPtr, ByVal bRevert As Int32) As IntPtr
    Private Declare Function GetMenuItemCount Lib "user32.dll" (ByVal hMenu As IntPtr) As Int32
    Private Declare Function RemoveMenu Lib "user32.dll" (ByVal hMenu As IntPtr, ByVal nPosition As Int32, ByVal wFlags As Int32) As Int32
    Private Const MF_BYPOSITION As Int32 = &H400I
    Private Const MF_REMOVE As Int32 = &H1000I

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        '/// DISABLE CLOSE BUTTON ( GREY IT OUT )
        Dim hMenu As IntPtr = GetSystemMenu(MyBase.Handle, False)
        Dim nCount As Int32 = GetMenuItemCount(hMenu)

        If nCount > 2 Then
            RemoveMenu(hMenu, nCount - 1, MF_REMOVE Or MF_BYPOSITION)
            RemoveMenu(hMenu, nCount - 2, MF_REMOVE Or MF_BYPOSITION)

            DrawMenuBar(MyBase.Handle)
        End If

    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        '/// ENABLE CLOSE BUTTON
        GetSystemMenu(MyBase.Handle, True)

        DrawMenuBar(MyBase.Handle)
    End Sub
hope it helps.
Thank Bro your code work to my code......
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Forum Jump

Advertisement:





Free Publications
The ASP.NET 2.0 Anthology
101 Essential Tips, Tricks & Hacks - Free 156 Page Preview. Learn the most practical features and best approaches for ASP.NET.
subscribe
Programmers Heaven C# School Book -Free 338 Page eBook
The Programmers Heaven C# School book covers the .NET framework and the C# language.
subscribe
Build Your Own ASP.NET 3.5 Web Site Using C# & VB, 3rd Edition - Free 219 Page Preview!
This comprehensive step-by-step guide will help get your database-driven ASP.NET web site up and running in no time..
subscribe
Disable the Close Button ('X') on a Form
Disable the Close Button ('X') on a Form
Disable the Close Button ('X') on a Form Disable the Close Button ('X') on a Form
Disable the Close Button ('X') on a Form
Disable the Close Button ('X') on a Form
Disable the Close Button ('X') on a Form Disable the Close Button ('X') on a Form Disable the Close Button ('X') on a Form Disable the Close Button ('X') on a Form Disable the Close Button ('X') on a Form Disable the Close Button ('X') on a Form Disable the Close Button ('X') on a Form
Disable the Close Button ('X') on a Form
Disable the Close Button ('X') on a Form
 
Disable the Close Button ('X') on a Form
Disable the Close Button ('X') on a Form
 
-->