4

I've searched around the interwebs and various parts of this resource where this question was asked and noticed I got the following bits of code:

Protected Overrides ReadOnly Property CreateParams() As CreateParams
    Get
        Dim cp As CreateParams = MyBase.CreateParams
        Const CS_NOCLOSE As Integer = &H200
        cp.ClassStyle = cp.ClassStyle Or CS_NOCLOSE
        Return cp
    End Get
End Property

Which works as intended, this does disable ALT+F4 from being used. However, as an unintended side effect of this code: closing the window via the Control Box is disabled:

Closing "X" is disabled

Is there a version of this code that disables ALT+F4 BUT still allows for the closing of the window via its control box or other UI options (such as a close button and a Close option in a menu.)

I know someone will say to check the e.CloseReason of the form, however UserClosing is the only reason the resembles what I would like to do, however... that still disables the UI from being used. Unless there is a code that I forgot about.

Paul Williams
  • 1,554
  • 7
  • 40
  • 75
  • 2
    Maybe this question will help you: https://stackoverflow.com/questions/5805335/how-to-handle-a-form-close-event-in-vb-net – muffi Aug 04 '17 at 06:18

4 Answers4

2

Set KeyPreview = True and handle the KeyDown event:

Private Sub Form1_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
    If e.Alt AndAlso e.KeyCode = Keys.F4 Then
        e.Handled = True
    End If
End Sub
Olaf
  • 76
  • 3
  • Weird question, is there a way to do this globally throughout a program or do I have to use this on each individual form? – Paul Williams Aug 04 '17 at 08:31
  • 1
    @PaulWilliams : You could create a shared method in a separate class that you call upon `Form.Load` of every form (passing the form as a parameter). Then that method will set the right properties and subscribe to the event handler for you. – Visual Vincent Aug 04 '17 at 08:34
  • Would you happen to have the code for it, because me trying it in a general Class is giving me errors. – Paul Williams Aug 04 '17 at 08:57
  • 1
    Your can handle it in a base class MyNotF4ClosableForm and inherit every other form in your app from this base class. – Olaf Aug 04 '17 at 09:11
  • Olaf, forgive me as I'm trying to do this but I'm running into errors trying to either inherit the `Forms` class in the new custom class... as I can't do "Me.KeyDown" without attaching it to something. – Paul Williams Aug 04 '17 at 12:15
  • @PaulWilliams : _"is giving me errors"_ isn't a very good problem description... See my answer below. – Visual Vincent Aug 04 '17 at 18:15
1

Answer to your comment, handling KeyDown from a separate class.

Documentation:

Public NotInheritable Class MainInterface
    Private Sub New() 'No constructor.
    End Sub

    Public Shared Sub DisableAltF4(ByVal TargetForm As Form)
        TargetForm.KeyPreview = True
        AddHandler TargetForm.KeyDown, AddressOf Form_KeyDown
    End Sub

    Private Shared Sub Form_KeyDown(sender As Object, e As KeyEventArgs)
        e.Handled = (e.Alt AndAlso e.KeyCode = Keys.F4)
    End Sub
End Class

Now in every form's Load event handler you can do:

Private Sub yourForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    MainInterface.DisableAltF4(Me)
End Sub

As Olaf said you can also make all forms inherit from a base class. However this might get a little bit more complicated as you have to tell both the yourForm.vb and the yourForm.Designer.vb file that you want to inherit from the base form.

Public Class BaseForm
    Inherits Form

    Protected Overrides Sub OnLoad(e As System.EventArgs)
        MyBase.OnLoad(e)
        Me.KeyPreview = True
    End Sub

    Protected Overrides Sub OnKeyDown(e As System.Windows.Forms.KeyEventArgs)
        MyBase.OnKeyDown(e)
        e.Handled = e.Handled OrElse (e.Alt AndAlso e.KeyCode = Keys.F4)
    End Sub
End Class

In yourForm.vb:

Public Class yourForm
    Inherits BaseForm

    ...code...
End Class

In yourForm.Designer.vb:

<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class yourForm
    Inherits yourNamespace.BaseForm

    ...code...
End Class
Visual Vincent
  • 18,045
  • 5
  • 28
  • 75
0

You should also remove the corresponding CLOSE menu item from the forms system menu using a RemoveMenu() interop call. This disables all default window close options.

Of course you can call Form.Close() in your code to close your form. That can be triggered by a Click event handler of a custom button, menu item etc. Additionally, you can implement an System.Windows.Forms.IMessageFilter to handle a custom key sequence (instead of ALT+F4) to close your form, e.g. C+L+O+S+E.

KBO
  • 653
  • 7
  • 17
  • Wait wait... I don't think you read it right... I want to keep the menu option, keep the control box option, but disable the ALT+F4 method. – Paul Williams Aug 04 '17 at 06:53
0

Easy:

In C#

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    if (keyData == (Keys.Alt | Keys.F4))
    {
        return true;  // The key is manually processed
    }
    else
        return base.ProcessCmdKey(ref msg, keyData);
}

In VB.Net

Protected Overrides Function ProcessCmdKey(ByRef msg As Message, ByVal keyData As Keys) As Boolean
    If keyData = (Keys.Alt Or Keys.F4) Then
        Return True
    Else
        Return MyBase.ProcessCmdKey(msg, keyData)
    End If
End Function
Luiz
  • 198
  • 2
  • 13