How to disable the Close button on the title bar of a console application by using Visual Basic 2005 or Visual Basic .NET (818361)



The information in this article applies to:

  • Microsoft Visual Basic 2005 Express Edition
  • Microsoft Visual Basic .NET (2003)
  • Microsoft Visual Basic .NET (2002)

SUMMARY

This step-by-step article describes how to disable the Close button on the title bar of a console application. To do this, you must declare references to external procedures that are members of the User32.dll file, obtain a handle to the system menu of the console application, and then delete the Close menu item from the system menu of the console application.

Note The whole source code is available in the "Complete code listing (Module1.vb)" section.

Requirements

The following list outlines the recommended hardware, software, network infrastructure, and service packs that you need:
  • Microsoft Windows 2000, Microsoft Windows XP, or Microsoft Windows Server 2003
  • Microsoft Visual Basic 2005 or Microsoft Visual Basic .NET
This article assumes that you are familiar with the following topics:
  • Visual Basic 2005 or Visual Basic .NET
  • Writing unmanaged code in Visual Basic 2005 or in Visual Basic .NET

Declare references to external procedures that are in User32.dll

  1. Run Microsoft Visual Studio 2005 or Microsoft Visual Studio .NET.
  2. Point to New on the File menu, and then click Project.
  3. Under Project Types, click to select Visual Basic Projects.

    Note In Visual Studio 2005, click to select Visual Basic instead of Visual Basic Projects.
  4. Under Templates, click to select Console Application.
  5. In the Name text box, type MyConsoleApplication, and then click OK.

    By default, Module1.vb is created.
  6. If the following code is not added by default when the you create the project, add the following code to Module1.vb before the Module Module1 statement.
    Option Strict On
  7. Add the following code to Module1.vb before the Sub Main statement.
    ' Declaring references to external procedures that are in user32.dll.
    Private Declare Function DeleteMenu Lib "user32" (ByVal hMenu As Integer, _
       ByVal uPosition As Integer, ByVal uFlags As Integer) As Boolean
    Private Declare Function GetForegroundWindow Lib "user32" () As Integer
    Private Declare Function GetSystemMenu Lib "user32" (ByVal hWnd As Integer, _
       ByVal bRevert As Boolean) As Integer
    Private Declare Function GetWindow Lib "user32" (ByVal hWnd As Integer, _
       ByVal uCmd As Integer) As Integer
    Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
       (ByVal hWnd As Integer, ByVal lpString As String, ByVal nMaxCount As Integer) As Integer

Obtain a handle to the console application window

  1. Append the following code to Module1.vb after the End Sub statement.
    Private Function ObtainWindowHandle(ByVal lpstrCaption As String) As Integer
    
       ' To store the handle to a window.
       Dim hWnd As Integer
       ' Maximum number of characters in the GetWindowText method.
       Dim nMaxCount As Integer
       ' Actual number of characters copied in the GetWindowText method.
       Dim nCopiedLength As Integer
       ' To store the text of the title bar of the window.
       Dim lpString As String
    
       nMaxCount = 255
       ' Obtain a handle to the first window.
       hWnd = GetForegroundWindow
    
       ' Loop through the various windows until you encounter the console application window, _
       ' or there are no more windows.
       While hWnd <> 0
    
          ' Fill lpString with spaces.
          lpString = Space(nMaxCount)
          ' Get the text of the title bar of the window in lpString.
          nCopiedLength = GetWindowText(hWnd, lpString, nMaxCount)
    
          ' Verify that lpString is neither empty, nor NULL.
          If Len(Trim(lpString)) <> 0 And Asc(Trim(lpString)) <> 0 Then
             ' Verify that the title of the retrieved window is the same as the title of the console application window.
             If CType(InStr(Left(lpString, nCopiedLength), lpstrCaption), Boolean) Then
                ' Return hWnd to the Main method.
                Return hWnd
             End If
          End If
    
          ' Get the next window.
          hWnd = GetWindow(hWnd, 2)
    
       End While
    
       ' If no corresponding windows are found, return 0.
       Return 0
    
    End Function
  2. Add the following code to Module1.vb, after the Sub Main statement.
    ' Obtain a handle to the console application window by passing the title of your application.
    Dim hWnd As Integer = ObtainWindowHandle("<MyConsoleApplication>")
    Note Replace <MyConsoleApplication> with the name of your console application.
You can also use the FindWindow function to obtain a handle to the console application window. For more information about FindWindow, visit the following Microsoft Developer Network (MSDN) Web site:

Obtain a handle to the console application system menu

Append the following code to Module1.vb before the End Sub statement.
' Obtain a handle to the console application system menu.
Dim hMenu As Integer = GetSystemMenu(hWnd, False)

Delete the Close menu item from the console application system menu

Append the following code to Module1.vb before the End Sub statement, and then click Save All on the File menu.
' Delete the Close menu item from the console application system menu.
' This will automatically disable the Close button on the console application title bar.
' 6 indicates the position of the Close menu item.
' 1024 indicates that the second parameter is a positional indicator.
DeleteMenu(hMenu, 6, 1024)
System.Console.WriteLine("Press ENTER to quit")
' Wait for the user to press the ENTER key.
System.Console.ReadLine()

Complete code listing (Module1.vb)

Option Strict On

Module Module1
   ' Declaring references to external procedures that are in user32.dll.
   Private Declare Function DeleteMenu Lib "user32" (ByVal hMenu As Integer, _
      ByVal uPosition As Integer, ByVal uFlags As Integer) As Boolean
   Private Declare Function GetForegroundWindow Lib "user32" () As Integer
   Private Declare Function GetSystemMenu Lib "user32" (ByVal hWnd As Integer, _
      ByVal bRevert As Boolean) As Integer
   Private Declare Function GetWindow Lib "user32" (ByVal hWnd As Integer, _
      ByVal uCmd As Integer) As Integer
   Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
      (ByVal hWnd As Integer, ByVal lpString As String, ByVal nMaxCount As Integer) As Integer

   Sub Main()
      ' Obtain a handle to the console application window by passing the title of your application.
      ' Replace <MyConsoleApplication> with the name of your Console Application.
      Dim hWnd As Integer = ObtainWindowHandle("<MyConsoleApplication>")
      ' Obtain a handle to the console application system menu.
      Dim hMenu As Integer = GetSystemMenu(hWnd, False)
      ' Delete the Close menu item from the console application system menu.
      ' This will automatically disable the Close button on the console application title bar.
      ' 6 indicates the position of the Close menu item.
      ' 1024 indicates that the second parameter is a positional indicator.
      DeleteMenu(hMenu, 6, 1024)
      System.Console.WriteLine("Press ENTER to quit")
      ' Wait for the user to press the ENTER key.
      System.Console.ReadLine()
   End Sub

   Private Function ObtainWindowHandle(ByVal lpstrCaption As String) As Integer

      ' To store the handle to a window.
      Dim hWnd As Integer
      ' Maximum number of characters in the GetWindowText method.
      Dim nMaxCount As Integer
      ' Actual number of characters copied in the GetWindowText method.
      Dim nCopiedLength As Integer
      ' To store the text of the title bar of the window.
      Dim lpString As String

      nMaxCount = 255
      ' Obtain a handle to the first window.
      hWnd = GetForegroundWindow

      ' Loop through the various windows until you encounter the console application window, _
      ' or there are no more windows.
      While hWnd <> 0

         ' Fill lpString with spaces.
         lpString = Space(nMaxCount)
         ' Get the text of the window title bar in lpString.
         nCopiedLength = GetWindowText(hWnd, lpString, nMaxCount)

         ' Verify that lpString is neither empty, nor NULL.
         If Len(Trim(lpString)) <> 0 And Asc(Trim(lpString)) <> 0 Then
            ' Verify that the title of the retrieved window is the same as the title of the console application window.
            If CType(InStr(Left(lpString, nCopiedLength), lpstrCaption), Boolean) Then
               ' Return hWnd to the Main method.
               Return hWnd
            End If
         End If

         ' Get the next window.
         hWnd = GetWindow(hWnd, 2)

      End While

      ' If no corresponding windows are found, return 0.
      Return 0

   End Function

End Module
Note Replace <MyConsoleApplication> with the name of your console application.

Verify that it works

  1. On the Build menu, click Build Solution.
  2. On the Debug menu, click Start to run the application.

    A console appears with the following text:
    Press ENTER to quit
  3. Try to click the Close button.

    You cannot click the Close button because it is disabled. To quit the application, press the ENTER key in the console.

    Note The application may take some time to obtain a handle to its console window. Therefore, the application may also take some time to disable the Close button.

Troubleshoot

  • If you declare the GetWindowText method and do not specify an alias, you may receive an 'EntryPointNotFoundException' unhandled exception.

    To work around this issue, replace
    Private Declare Function GetWindowText Lib "user32" (ByVal hWnd As Integer, ByVal lpString As String, ByVal nMaxCount As Integer) As Integer
    with
    Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hWnd As Integer, ByVal lpString As String, ByVal nMaxCount As Integer) As Integer
  • If you run your console application from the command prompt, the Close button remains disabled even after the application quits. Therefore, Microsoft recommends that you double-click the executable file in Visual Studio .NET to run your application.

Modification Type:MajorLast Reviewed:2/10/2006
Keywords:kbvs2005swept kbvs2005applies kbAPI kbConsole kbProgramming kbHOWTOmaster KB818361