Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Disable vs. Removing System Menu Item (Excel) 2

Status
Not open for further replies.

rmikesmith

Technical User
Apr 29, 2002
1,215
US
Hello All,

I am trying to disable Excel's system menu 'Close' command using the EnableMenuItem API function, in VBA. I cannot get this to work, although the similar RemoveMenuItem function works perfectly. Here is the procedure I've written:

Code:
Sub DisableSysMenuClose()
Dim hwnd As Long
Dim hSysMenu As Long
Dim retVal As Long
Dim Count As Long
Dim wCaption As String

    wCaption = String$(256, 0)
    hwnd = GetActiveWindow
    retVal = GetWindowText(hwnd, wCaption, 255)
    wCaption = Left$(wCaption, retVal)
    If InStr(1, wCaption, "Microsoft Excel", vbTextCompare) = 0 Then
      Exit Sub
    End If
    hSysMenu = GetSystemMenu(hwnd, 0)
    Count = GetMenuItemCount(hSysMenu)

' The following call does not seem to work
Code:
    Call EnableMenuItem(hSysMenu, Count - 1, MF_GRAYED Or MF_BYPOSITION)
' While these next 2 calls perform as expected (removing
' the Close menu item and the separator line above it)
Code:
    Call RemoveMenu(hSysMenu, Count - 1, MF_REMOVE Or MF_BYPOSITION)
    Call RemoveMenu(hSysMenu, Count - 2, MF_REMOVE Or MF_BYPOSITION)

End Sub

Some additional info: The call to EnableMenuItem worked when I ran the procedure from within the VBA Editor. I have single-stepped through the code when running from the main Excel window and it appears to be registering this (i.e. the code to read the window caption is returning "Microsoft Excel") but after returning from the EnableMenuItem function call, there is no apparent change to the system menu. I have also tried using the MF_DISABLED constant with and without MF_GRAYED, without success.

Any help is greatly appreciated.
Mike
 
I tried your code above and it also didn't work. But if I use GetForegroundWindow() instead of GetActiveWindow() it does work.
It must have something to with the fact that Excel consists of many windows, and GetActiveWindow doesn't get the right one, or no one at all.

I hope it works for you too,
Remedy
 
Remedy,

Thanks for your reply. I have tried GetForegroundWindow with the same result. In fact, GetForegroundWindow and GetActiveWindow return the exact same window handle when called. When I think about it, the fact that RemoveMenuItem works tells me the correct handles are being retrieved/passed, and the problem may involve the EnableMenuItem function. Any other suggestions?

Regards,
Mike
 
I use :

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

l_lMenuHandle = GetSystemMenu(l_lProcessWindow, ByVal 0)
l_lReturnValue = DeleteMenu(l_lMenuHandle, CInt(SC_CLOSE), CInt(MF_BYCOMMAND))
 
Thanks StewartJ for the input. By using RemoveMenu I can effectively eliminate use of the Close menu item, since it is removed from the Excel system menu. What I am trying to work out is how to instead use EnableMenuItem to only disable/gray out this choice. I can't figure out why this call appears to do nothing while a call to RemoveMenu works properly. Any suggestions?

Thanks again.
Mike
 
The system menu is dynamic as far as graying/enabling is concerned. In other words it checks what the status of the various menu items should be each time the menu is initialised - so no matter what you do, Windows changes it to what it expects.

So you need to subclass the menu, and then do your graying/enabling in response to the system menu's WM_INITMENU message.
 
strongm,

Thanks for the reply. This makes sense to me. I have encountered something similiar when changing the application title ("Microsoft Excel") using API calls; it works, but certain tasks cause a reversion to the original.

Can you give me an idea (or point to some reference) on how I sublclass the menu, as I have zero experience with this? Can this be done using VBA (i.e. from within Excel's programming environment -- I'm using Excel 97)?

Again, thank you for your assistance.

Mike
 
A well-deserved Thank You to all who replied! Special thanks to:

Strongm -- You made sense of what was happening.

Paul Bent -- Your link had example code I was able to modify and use to solve the problem.

Mike
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top