We help IT Professionals succeed at work.

Check out our new AWS podcast with Certified Expert, Phil Phillips! Listen to "How to Execute a Seamless AWS Migration" on EE or on your favorite podcast platform. Listen Now


Disable Word Close Button Programmatically in VB.Net

CurtHugo asked
Medium Priority
Last Modified: 2012-06-27
I need the program code to disable Word 2003 Close(X) Button from a VB.Net application.
Watch Question

To do so, you would need to get a handle on the actual word process, you cannot simply do this using the COM interface.



I took the sample code in the ms link you provided and copied it into my application. It ran ok. The example referenced PowerPoint. I modified the code to get the handle for Word.

Now that I have the code working to get the handle of the Word Process I'm automating, what is the code to disable the Close button?

        Dim objWord As Microsoft.Office.Interop.Word.Application = Nothing
        objWord = CType(CreateObject("Word.Application"),  _
        objWord.Caption = "New Caption Supplied by Program"
        Dim hWndXl As Long
        hWndXl = FindWindow("XLMAIN", objWord.Caption)
        'objWord.Caption = Nothing 'Set the original caption back

        objWord.Visible = True
        MsgBox("hWndXl ( " & Hex(hWndXl) & " ) contains the Window Handle " & _
               "of the Word application created by this program." & vbCr & _
               "You can use this Window Handle in various Win 32 APIs, " & _
               "such as SetForeGroundWindow," & vbCr & _
               "which require a Window Handle parameter to be supplied." & vbCr _
               & vbCr & "All Done.  Click OK to close Word.", vbMsgBoxSetForeground)

        objWord = Nothing

Another idea occurred to me. What if you didn't hack into the word handle to disable the button, but instead just handled the word Quit event. You could simply prevent allowing the user to quit of close the document.
Event      Object      Description
Close      Document      Occurs when a document is closed.
Quit      Application      Occurs when the user quits Word.

If you handle these two events you could simply set Cancel to true and prevent the user quitting from doing anything.


Imports Microsoft.Office.Interop
Private WithEvents oWord As Word.ApplicationClass
     oWord = CreateObject("Word.Application")
Private Sub wdapp_BeforeClose(ByVal Doc As Document, Cancel As Boolean) Handles oWord.ApplicationEvents3_Event_Quit
     Cancel = True
End Sub

Open in new window


I'm not sure this would work in my case.
I have a custom macro the user is supposed to use instead of the X button to close the Word document.
Wouldn't the wdapp_BeforeClose event fire if they selected the custom Close macro and prevent the document from closing?
All you have to do is detect the close mode. I don't remember the details, but you'll see when you handle the event, there is a integer that indicates whether the window is closing because the user clicked the button, because the system is shutting down, because code told it to close, etc. All you do is check the state, and if it's because the user clicked it, set cancel to true!

I'm pretty sure I did this before with an excel window, let me see if I can find the exact code...

I used this for before I workbook was closed:

Public Sub CloseBook(ByRef Cancel As Boolean) _
                Handles xlBook.BeforeClose
        If Not ExcernalCellEditedHandler Is Nothing Then
            If InvokeRequired Then
                Invoke(ExternalSaveFileHandler, New Object() {Cancel})
            End If
            Cancel = True
            MsgBox("Error: The application is not in a state where it can be saved.")
        End If
    End Sub

Open in new window

I see, the way I did this with the excel window is that I stripped away all the elements of the main window from the handle and used SetParent to hijack the application and integrate the excel window into my own application. It was pretty neat actually. I'll attach the form. Maybe you could make a few adjustments and turn it into something that hijacks a word application. I'm sure it would be extremely similar. Just download the zip and remove .txt from the extensions.

It basically ended up being a whole bunch of special calls such as:
xlApp.ExecuteExcel4Macro("SHOW.TOOLBAR(""Ribbon"",False)") 'Hides all the menu items and the ribbon (fast)
Word probably has an equivalent.

Things that minimized the user's ability to mess around with the application.

You can remove the menu item "Quit" from word with code attached in the snippet. I also have simple code for getting the handle.

I'm sure you could reproduce most of these to configure Word to be unquittable.

'Get application handle'
    'The application.Hwnd property does not exist on earlier versions of excel'
    appHWnd = xlApp.Hwnd
Catch ex As Exception
    'This method works for all versions of excel, but is less reliable because it may find'
    'a window that the user is currently using and not the one created by the application'
    appHWnd = CInt(FindWindow("XLMAIN", xlApp.Caption))
End Try
'Remove a menu item'
    Private Declare Function RemoveMenu Lib "user32" (ByVal hMenu As Integer, ByVal nPosition As Integer, ByVal wFlags As Integer) As Integer
    Private Const REMOVE_BYPOSITION As Integer = 5120
'(This code removes all removable menu items)'
Dim hMenu As Integer = GetSystemMenu(appHWnd, False)
        If (hMenu > 0) Then
            Dim menuItemCount As Integer = GetMenuItemCount(hMenu)
            For i As Integer = menuItemCount - 1 To 0 Step -1
                RemoveMenu(hMenu, i, REMOVE_BYPOSITION)
        End If

Open in new window


It's getting close to quiting time for me so I'll get back to you tomorrow.
I'm thinking I'd prefer to disable the X button rather than do it this way. Either way, there's a bunch of hoops to make it work.
I will think about which way makes more sense to me.
Anyway, thanks for help. You're the only one who's responded to my question.


After thinking about the situation, I'd prefer to go the route of disabling the close button.
I've done this before in VB6 Forms and I think it's a simpler approach then the other approach you offered.
Please let me know if you can provide me with the code to disable the close button. I already have the code to find the handle.
Well, try this, although you might have to experiment with the exact structure and order of unknown menu items.

Good luck with it.

Private Declare Function GetSystemMenu Lib "user32" (ByVal hWnd As Long, _
    ByVal bRevert As Long) As Long
Private Declare Function EnableMenuItem Lib "user32" (ByVal hMenu As _
    Long, ByVal wIDEnableItem As Long, ByVal wEnable As Long) As Long
Const MF_GRAYED = &H1&
Const SC_CLOSE = &HF060&
'Disable the Menu Option
    objWord.CommandBars("File").Controls("Exit").Enabled = blnExitState
'Disable the CLose Button Option
    Dim hWnd As Long
    Dim wFlags As Long
    Dim hMenu As Long
    hWnd = objWord.hWndAccessApp
    hMenu = GetSystemMenu(hWnd, 0)
    result = EnableMenuItem(hMenu, SC_CLOSE, wFlags)

Open in new window


I get the syntax error message 'Option Strict On disallows late binding' on this line of code;
    hWnd = objWord.hWndAccessApp
In VB.Net 2008, which is the version of VB.Net I'm using, hWndAccessApp is not an option you can choose from and therefore the error. Our standard and what is recommended is to use Option Strict On in our applications.
Also for your information, in VB.Net 2008, I have found you must declare the variables in the API's as Integer instead of Long. If specified as long, the function does not work correctly.  Here's how I have it:

    ' These API's are used to disable the Close Button (X) in Word
    Private Declare Function GetSystemMenu Lib "user32" (ByVal hWnd As Integer, _
    ByVal bRevert As Integer) As Integer
    Private Declare Function EnableMenuItem Lib "user32" (ByVal hMenu As _
        Integer, ByVal wIDEnableItem As Integer, ByVal wEnable As Integer) As Integer
    Public Const MF_GRAYED As Integer = &H1&
    Public Const MF_BYCOMMAND As Integer = &H0&
    Public Const SC_CLOSE As Integer = &HF060&

Let me know if you have any suggestions around this syntax error.
Thanks, Curt
hmm, in that case maybe use the hWnd that you already got for the word object using more complicated methods. I should have seen hWndAccessApp couldn't possibly be a property for a Word application :p. I was trying to adapt some similar code for an Access application as you can see. If you can't see any properties of objWord that would give you the handle in a straightforward way, go ahead and try the above code with the handle you got using FindWindow.

Unlock this solution and get a sample of our free trial.
(No credit card required)
Unlock this solution and get a sample of our free trial.
(No credit card required)
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a sample view!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.


Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.