|
|
|
To modify an item in the Visual Basic Control menu (also known as the System menu), you need to use the SetMenuItemInfo API function. You can use ModifyMenuItem or EnablemenuItem api, both functions work. However it appears that Visual Basic re-enables the menu item whose ID is SC_CLOSE. This is why it may appear as if the ModifyMenu or EnableMenuItem function failed. . This article describes how to enable/disable or check/uncheck the Close menu item in the Control menu.
If you do not want the user to close a window via the Control menu or the Close box on your Form's title bar, you can disable the Close menu item on the Control menu. This method also disables double-clicking the Control box and disables the Close button on the Form's title bar.
The following code sample enables/disables and checks/unchecks the Close command in the Visual Basic Control menu.
Step-By-Step Example
- Start a new standard EXE project. Form1 is added by default. - Add three CommandButtons to Form1. - Add the following code to Form1: |
Click here to copy the following block | Option Explicit
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 MFS_CHECKED As Long = &H8&
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 Const xSC_CLOSE As Long = -10 Private Const SwapID As Long = 1 Private Const ResetID As Long = 2
Private hMenu As Long Private MII As MENUITEMINFO
Private Sub Command1_Click() Dim Ret As Long
Ret = SetId(SwapID) If Ret <> 0 Then If MII.fState = (MII.fState Or MFS_GRAYED) Then MII.fState = MII.fState - MFS_GRAYED Else MII.fState = (MII.fState Or MFS_GRAYED) End If
MII.fMask = MIIM_STATE Ret = SetMenuItemInfo(hMenu, MII.wID, False, MII) If Ret = 0 Then Ret = SetId(ResetID) End If
Ret = SendMessage(Me.hwnd, WM_NCACTIVATE, True, 0) SetButtons End If End Sub
Private Sub Command2_Click() Dim Ret As Long
If MII.fState = (MII.fState Or MFS_CHECKED) Then MII.fState = MII.fState - MFS_CHECKED Else MII.fState = (MII.fState Or MFS_CHECKED) End If
MII.fMask = MIIM_STATE Ret = SetMenuItemInfo(hMenu, MII.wID, False, MII) SetButtons End Sub
Private Sub Command3_Click() Unload Me End Sub
Private Function SetId(Action As Long) As Long Dim MenuID As Long Dim Ret As Long
MenuID = MII.wID If MII.fState = (MII.fState Or MFS_GRAYED) Then If Action = SwapID Then MII.wID = SC_CLOSE Else MII.wID = xSC_CLOSE End If Else If Action = SwapID Then MII.wID = xSC_CLOSE Else MII.wID = SC_CLOSE End If End If
MII.fMask = MIIM_ID Ret = SetMenuItemInfo(hMenu, MenuID, False, MII) If Ret = 0 Then MII.wID = MenuID End If SetId = Ret End Function
Private Sub SetButtons() If MII.fState = (MII.fState Or MFS_GRAYED) Then Command1.Caption = "Enable" Else Command1.Caption = "Disable" End If If MII.fState = (MII.fState Or MFS_CHECKED) Then Command2.Caption = "Uncheck" Else Command2.Caption = "Check" End If Command3.Caption = "Exit" End Sub
Private Sub Form_Load() Dim Ret As Long
hMenu = GetSystemMenu(Me.hwnd, 0) MII.cbSize = Len(MII) MII.dwTypeData = String(80, 0) MII.cch = Len(MII.dwTypeData) MII.fMask = MIIM_STATE MII.wID = SC_CLOSE Ret = GetMenuItemInfo(hMenu, MII.wID, False, MII) SetButtons End Sub |
- Now press F5 to run the project
Visual Basic handles enabling and disabling the standard Control menu items, including Restore, Size, Move, Minimize, and Maximize (the Close menu is always enabled). Generally, Visual Basic enables/disables the menu items depending on the window's state (minimized, maximized, or normal) by referencing these menu items by their menu item IDs.
As a result, if we merely add or remove MFS_GRAYED from a menu's fState, Visual Basic immediately resets it. The workaround is to change the menu item's ID (which also renders the item inoperable).
Using this workaround, we can effectively disable a menu item that Visual Basic intends to be enabled, but we cannot enable a menu item Visual Basic intends to be disabled (the menu item must have its regular ID to be operable).
Enabling a menu item that Visual Basic intends to be disabled requires removing the item and replacing it with a menu item of our own (this is not covered in this article).
When the Close menu item is enabled or disabled, the Close box on the title bar should also be normal or grayed, respectively. Sending the message WM_NCACTIVATE (nonclient activate) notifies the window to refresh its title bar so the Close box is updated to appear normal or grayed.
Additional Constants |
|
|
|
Submitted By :
Nayan Patel
(Member Since : 5/26/2004 12:23:06 PM)
|
|
|
Job Description :
He is the moderator of this site and currently working as an independent consultant. He works with VB.net/ASP.net, SQL Server and other MS technologies. He is MCSD.net, MCDBA and MCSE. In his free time he likes to watch funny movies and doing oil painting. |
View all (893) submissions by this author
(Birth Date : 7/14/1981 ) |
|
|