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 SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

X-Button

Status
Not open for further replies.

davejazz

Programmer
Nov 3, 2000
42
0
0
US
What is the best way to disable the 'X' button in Visual Basic?

I use several forms in a program and the program keeps running in the background unless the user clicks my "EXIT" button to return to the main form to exit from there and clicks the 'X' button instead.

Dave
 
daniellr posted this code in thread222-750657

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
Cancel = True
End Sub

The X button is still there, it just doesn't work. The practical difference in the two options is appearance. With daniellr's code you still have the option of displaying an icon for your form in the form’s title bar and Windows taskbar. You can also put your custom exit button's code here giving your users a choice of either your button or the X-button.


________________________________________
Die lewe is te kort om te worry oor kak:)
 
>The X button is still there, it just doesn't work

And therefore breaks the interface...

Before I start on this, I should just point out that I'm will be slightkly getting into a philosophical area concering interface design, and not everyone will necessarily agree with the view I'm going to put forward.

OK. Here we go:

A decent user interface should not give the user options that don't work at all, or don't work as expected.
Common metaphors should be retained, and not changed just to suit the programmer.

(in other words, if you are going to disable the standard windows close button through code, you should also signal this in the interface either by removing the close button or by greying it out, which is the common metaphor in Windows for a disabled control)
 
You may find the disable Close API of use. This again leave's the X button visible But 'greyed ou't to indicate it's disabled state. I don't have the code to hand & I'm now leaving the Office for the weekend. I can post it next Monday If that's of help.

Everybody body is somebodys Nutter.
 
>A decent user interface should not give the user options that don't work at all, or don't work as expected.

I agree with you, strongm. I just found the graphical limitations of setting the controlbox to false to be to limiting. Didn't consider the after effects, though - like an irretated end-user...

Luckily we've got ClulessChris to the rescue for all of us that's even more clueless;) I'll be much oblidged if you can post that code ClulessChris.
 
strongm is very right in his statment and I fully agree with him. It is better to either remove, or disable the X button instead of having it there enabled but functionless.

The "Remove/Disable X Button" problem is one of the most popular questions asked on this forum atleast once a month and you may find many threads including thread222-662889 and thread222-523899 if you search this forum.

But don't visit these threads; let me post the solution once more.[smile]
___
[tt]
Option Explicit
Private Declare Function GetSystemMenu Lib "user32" (ByVal hwnd As Long, ByVal bRevert As Long) As Long
Private Declare Function RemoveMenu Lib "user32" (ByVal hMenu As Long, ByVal nPosition As Long, ByVal wFlags As Long) As Long
Private Const MF_BYPOSITION = &H400&
Private Sub Form_Load()
Dim hSysMenu As Long

'get a handle to the system menu.
hSysMenu = GetSystemMenu(hwnd, 0)

'remove the 6th menu item from the system menu
'which is the "Close" command.
'note that this index is zero-based.
RemoveMenu hSysMenu, 6, MF_BYPOSITION
'removing the Close command disables
'the 'X' on the title bar as well!

'remove the 5th menu item which is the seperator bar.
RemoveMenu hSysMenu, 5, MF_BYPOSITION
End Sub
[/tt]
 
Sorry for kinda taking over your thread davejazz. Hope you don't mind.

Thanks Hypetia.
 
Another Cool bit o code from Hypetia (*%$&~#, beat me to the punch). Hypetia's code is a tad different from mine though so take your pick.

As promised:

Code:
'The declarations:
Public Const SC_CLOSE       As Long = &HF060&

'SetMenuItemInfo fMask constants.
Public Const MIIM_STATE     As Long = &H1&
Public Const MIIM_ID        As Long = &H2&

'SetMenuItemInfo fState constants.
Public Const MFS_GRAYED     As Long = &H3&
Public Const MFS_CHECKED    As Long = &H8&

'SendMessage constants.
Public Const WM_NCACTIVATE  As Long = &H86

'User-defined Types.
Public 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

'Declarations.
Public Declare Function GetSystemMenu Lib "user32" ( _
    ByVal hwnd As Long, ByVal bRevert As Long) As Long

Public Declare Function GetMenuItemInfo Lib "user32" Alias _
    "GetMenuItemInfoA" (ByVal hMenu As Long, ByVal un As Long, _
    ByVal B As Boolean, lpMenuItemInfo As MENUITEMINFO) As Long

Public Declare Function SetMenuItemInfo Lib "user32" Alias _
    "SetMenuItemInfoA" (ByVal hMenu As Long, ByVal un As Long, _
    ByVal bool As Boolean, lpcMenuItemInfo As MENUITEMINFO) As Long

Public Declare Function SendMessage Lib "user32" Alias _
    "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, _
    ByVal wParam As Long, lParam As Any) As Long

'Application-specific constants and variables.
Public Const xSC_CLOSE  As Long = -10
Public Const SwapID     As Long = 1
Public Const ResetID    As Long = 2

Public hMenu  As Long
Public MII    As MENUITEMINFO

The Call:

Private Sub DisableClose()
    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)

    MII.fState = (MII.fState Or MFS_GRAYED)
    MII.fMask = MIIM_STATE
    Ret = SetMenuItemInfo(hMenu, MII.wID, False, MII)
End Sub


Everybody body is somebodys Nutter.
 
Heh! Might have saved some time if you'd just posted the reference to the knowledgebase article
 
Thanks to all who responded.

The original solution posted by DrJavaJoe worked best for me ... and that was to set the controlbox property to false.

That removed the Minimize, Maximize and 'X' buttons leaving just a form with my display boxes and my own 'Exit' button. When a user click my 'Exit' button I ensure that the form is properly shut down before returning to the main form.

Davejazz
 
Sorry, My last post was a little rushed (bit ‘pushed for time’ here at the ‘mo’). I have to say that I also agree with Strongm, if you give the user a button to ‘click’ they’ll do and expect things to happen. However in order to remove the ‘X’ button you must also remove the ‘max’ ‘min’ buttons thus reducing functionality of the form. I like the ‘Disable Close’ API as you may then retain the use of the ‘max’ ‘min’ buttons and although the ‘X’ is visible, it’s ‘greyed out’ providing a clear indicator of it’s disabled state.
But all that said it’s just a matter of preference.


Everybody body is somebodys Nutter.
 
“Heh! Might have saved some time if you'd just posted the reference to the knowledgebase article”

Do I detect a hint of derision here? I never state the code was my own, and although I regard myself as a ‘newbie’ this is a call that I’ve used for some time. I’d kind o forgotten the sorce (O but for the photographic memory some of you guys seem to have).
Sorry if this comes across a tad defensive however it’s not often that I (with my limited knowledge) get to make any useful input. And considering the amount of help I’ve had from users of this site (strongm, numbering among them) I do like to contribute when able.


Everybody body is somebodys Nutter.
 
Thanks again for everyone's help!

One thing I've learned with programming is that there's more than one way to skin a cat.

Speaking of skinning cats, I think I may have solved (cough, cough!) the DOB problem tonight. (Figuring a person's age without using DateDiff and it's drawbacks.)

One day I'm 62 ... tomorrow I'm 63. It works!

Will post soon after further tests.

Davejazz
 
No, no. Sorry, I assumed you knew it was a KB article and was just trying to suggest that you could therefore have posted the link on Friday rather than waiting until Monday to find and post your specific copy of the code, thus saving time.
 
Strongm,
Many thanks for the reply, No offence taken.

Everybody body is somebodys Nutter.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top