HOWTO: Disable Close Command in VB Control Menu (System Menu)

ID: Q82876


The information in this article applies to:


SUMMARY

To modify an item in the Visual Basic Control menu (also known as the System menu), you need to call the API functions GetSystemMenu and ModifyMenu. This article describes how to disable the Close command in the Control menu.


MORE INFORMATION

If you do not want the user to be able to choose the Close command from the Control menu or to be able to double-click the Control-menu box to end the application, you can disable the Close command. GetSystemMenu returns the handle to the Control menu. That handle can be used by ModifyMenu to change the control menu.

The following code example disables (grays out) the Close command in the Visual Basic Control menu.

  1. Start Visual Basic or from the File menu, choose New Project (ALT, F, N) if Visual Basic is already running. Form1 is created by default.


  2. Place a command button (Command1) on Form1. Change its Caption property to Disable Close.


  3. Place another command button (Command2) on Form1. Change its caption to Exit.


  4. Add the following declarations and constants to the general Declarations section of Form1:
    
       ' Enter each Declare statement as one, single line:
       Declare Function GetSystemMenu Lib "User" (ByVal hWnd%,
          ByVal bRevert%) as Integer
       Declare Function ModifyMenu Lib "User" (ByVal hMenu%, ByVal nPosition%,
          ByVal wFlags%, ByVal wIDNewItem%, ByVal lpNewItem as Any) as Integer
    
       Const MF_BYCOMMAND = &H0
       Const MF_GRAYED = &H1
       Const SC_CLOSE = &HF060
     
    NOTE: Other constants to disable other menu items in the Control menu are described in the CONSTANT.TXT file.


  5. Add the following code to the Command1 Click event:
    
       Sub Command1_Click ()
          ' See the notes at the end of this article for important additional
          ' information about this code.
          nPosition% = SC_CLOSE
          idNewItem%=-10
          s$ = "Close"
          hMenu% = GetSystemMenu(hWnd, 0)
          wFlags% = MF_BYCOMMAND Or MF_GRAYED
          success% = ModifyMenu(hMenu%, nPosition%, wFlags%, idNewItem%, s$)
       End Sub 


  6. Add the following code to the Command2 Click event:
    
       Sub Command2_Click ()
          End
       End Sub 


  7. Press the F5 key to run the program.


  8. Click the Control-menu box to see that all the menu items are available.


  9. Click the Disable Close command button. Then click the Control-menu box. Notice that the Close menu command is unavailable.

    The user cannot end the application by either choosing Close from the Control menu or by double-clicking the Control-menu box. The only way to end this program is to choose the Exit command button.


Notes on the Use of ModifyMenu() in the Code

The code listed above uses the ModifyMenu() function, but the EnableMenuItem() may be more appropriate in your particular situation.

Here's the syntax for ModifyMenu():

ModifyMenu(hMenu, SC_CLOSE, MF_BYCOMMAND|MF_GRAYED, SC_CLOSE, "Close") 
Here's the syntax for EnableMenuItem():

EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND|MF_GRAYED) 
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.

To work around this problem in the code listed above, the second to last argument (idNewItem%) is set to -10 (0 would also work):

ModifyMenu(hMenu, SC_CLOSE, MF_BYCOMMAND|MF_GRAYED, -10, "Close") 
This works because Visual Basic looks for a menu item with ID SC_CLOSE to re-enable and cannot find one because it has been changed to 0 or -10. So Visual Basic can't re-enable the Close menu item.

However, because of this workaround, another limitation is introduced. The problem is that the ID of the Close menu item is changed to -10. If you want the program to be able to re-enable the Close item, you'll need to use this alternative version:

ModifyMenu(hMenu, -10, MF_BYCOMMAND|MF_GRAYED, SC_CLOSE, "Close") 
This is a good workaround to Visual Basic's re-enabling of Close. Don't use 0 because menu separators also have the ID 0 and you will run into problems when you try to re-enable Close. 0xFFFF is a good ID to use.

Another alternative solution is to use DeleteMenu to remove Close and the separator above it, and use InsertMenu to add the Close and the separator.


REFERENCES

"Microsoft Windows Programmer's Reference Book and Online Resource" (Visual Basic Add-on kit number 1-55615-413-5)

For information on the 32-bit equivalent, please see the following article in the Microsoft Knowledge Base:

Q184686 : HOWTO: Disable the Close Option on Control Menu of a VB Form

Additional query words: control box controlbox


Keywords          : kbVBp kbVBp300 
Version           : WINDOWS:1.0,2.0,3.0
Platform          : WINDOWS 
Issue type        : kbhowto 

Last Reviewed: June 8, 1999