PDA

Click to See Complete Forum and Search --> : Classic VB - How can I Hide/Unhide the Form's "X" Button


MartinLiss
Nov 1st, 2005, 01:42 PM
Credit for the Hide/Unhide code goes to crptcblade.

Public Declare Function GetSystemMenu Lib "user32" (ByVal hwnd _
As Long, ByVal bRevert As Long) As Long
Public Declare Function RemoveMenu Lib "user32" (ByVal hMenu _
As Long, ByVal nPosition As Long, ByVal wFlags As Long) As Long
Public Declare Function DrawMenuBar Lib "user32" (ByVal hwnd _
As Long) As Long

Private Const MF_BYCOMMAND = &H0&
Private Const SC_CLOSE = &HF060&

Public Sub SetXState(frm As Form, blnState As Boolean)
Dim hMenu As Long

hMenu = GetSystemMenu(frm.hwnd, blnState)
Call RemoveMenu(hMenu, SC_CLOSE, MF_BYCOMMAND)
Call DrawMenuBar(frm.hwnd)

End Sub

Example of Usage:
Private Sub Command1_Click()
If opt(0).Value = True Then
SetXState Me, True 'enable the X button
ElseIf opt(1).Value = True Then
SetXState Me, False 'disable the X button
End If
End Sub

You can however avoid all that and just do this
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
If UnloadMode = vbFormControlMenu Then
cmdExit = True ' Change cmdExit to the name of your exit command button
' and the code behind that button will be executed
End If
End Sub

si_the_geek
Nov 1st, 2005, 04:57 PM
An alternative method is to disable both the close button, and the close menu option from the system menu.

To do that you can use this code: (originally posted by Hack (http://www.vbforums.com/showpost.php?p=2211767&postcount=3))
Private Const SC_CLOSE As Long = &HF060&
Private Const MIIM_STATE As Long = &H1&
Private Const MIIM_ID As Long = &H2&
Private Const MFS_GRAYED As Long = &H3&
Private Const WM_NCACTIVATE As Long = &H86

Private Type MENUITEMINFO
cbSize As Long
fMask As Long
fType As Long
fState As Long
wID As Long
hSubMenu As Long
hbmpChecked As Long
hbmpUnchecked As Long
dwItemData As Long
dwTypeData As String
cch As Long
End Type

Private Declare Function GetSystemMenu Lib "user32" ( _
ByVal hWnd As Long, ByVal bRevert As Long) As Long

Private Declare Function GetMenuItemInfo Lib "user32" Alias _
"GetMenuItemInfoA" (ByVal hMenu As Long, ByVal un As Long, _
ByVal b As Boolean, lpMenuItemInfo As MENUITEMINFO) As Long

Private Declare Function SetMenuItemInfo Lib "user32" Alias _
"SetMenuItemInfoA" (ByVal hMenu As Long, ByVal un As Long, _
ByVal bool As Boolean, lpcMenuItemInfo As MENUITEMINFO) As Long

Private Declare Function SendMessage Lib "user32" Alias _
"SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, _
ByVal wParam As Long, lParam As Any) As Long

Private Declare Function IsWindow Lib "user32" _
(ByVal hWnd As Long) As Long

' Enables / Disables the close button on the titlebar and in the system menu
' of the form window passed.
' Return Values:
'
' 0 Close button state changed succesfully / nothing to do.
' -1 Invalid Window Handle (hWnd argument) Passed to the function
' -2 Failed to switch command ID of Close menu item in system menu
' -3 Failed to switch enabled state of Close menu item in system menu

Public Function EnableCloseButton(ByVal hWnd As Long, Enable As Boolean)
As Integer
Const xSC_CLOSE As Long = -10
' Check that the window handle passed is valid
EnableCloseButton = -1
If IsWindow(hWnd) = 0 Then Exit Function
' Retrieve a handle to the window's system menu
Dim hMenu As Long
hMenu = GetSystemMenu(hWnd, 0)
' Retrieve the menu item information for the close menu item/button
Dim MII As MENUITEMINFO
MII.cbSize = Len(MII)
MII.dwTypeData = String(80, 0)
MII.cch = Len(MII.dwTypeData)
MII.fMask = MIIM_STATE

If Enable Then
MII.wID = xSC_CLOSE
Else
MII.wID = SC_CLOSE
End If
EnableCloseButton = -0
If GetMenuItemInfo(hMenu, MII.wID, False, MII) = 0 Then Exit Function
' Switch the ID of the menu item so that VB can not undo the action itself
Dim lngMenuID As Long
lngMenuID = MII.wID

If Enable Then
MII.wID = SC_CLOSE
Else
MII.wID = xSC_CLOSE
End If
MII.fMask = MIIM_ID
EnableCloseButton = -2
If SetMenuItemInfo(hMenu, lngMenuID, False, MII) = 0 Then Exit Function
' Set the enabled / disabled state of the menu item
If Enable Then
MII.fState = (MII.fState Or MFS_GRAYED)
MII.fState = MII.fState - MFS_GRAYED
Else
MII.fState = (MII.fState Or MFS_GRAYED)
End If
MII.fMask = MIIM_STATE
EnableCloseButton = -3
If SetMenuItemInfo(hMenu, MII.wID, False, MII) = 0 Then Exit Function
SendMessage hWnd, WM_NCACTIVATE, True, 0
EnableCloseButton = 0
End Function
Usage:
Private Sub Form_Load()
'enabled
EnableCloseButton Me.hWnd, True
End Sub

Private Sub Command1_Click()
'disabled
EnableCloseButton Me.hWnd, False
End Sub

Mark Gambo
Nov 30th, 2005, 09:28 AM
A simpler way is to just catch the form close event:
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
If UnloadMode = vbFormControlMenu Or UnloadMode = 1 Then
'the X has been clicked or the user has pressed Alt+F4
Cancel = True
End If
End Sub