【问题标题】:How to prevent ALT+F4 of a WinForm but allow all other forms of closing a WinForm?如何防止 WinForm 的 ALT+F4 但允许关闭 WinForm 的所有其他形式?
【发布时间】:2017-08-04 06:07:33
【问题描述】:

我搜索了互联网和该资源的各个部分,其中提出了这个问题,并注意到我得到了以下代码:

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

按预期工作,这确实禁用了 ALT+F4 的使用。但是,作为此代码的意外副作用:通过控制框关闭窗口被禁用

此代码是否存在 disables ALT+F4 但仍允许通过其控制框或其他 UI 选项(例如关闭按钮和菜单中的关闭选项)关闭窗口的版本。

我知道有人会说检查e.CloseReason of the form,但是UserClosing 是我想做的唯一原因,但是......这仍然会禁用用户界面。除非有我忘记的代码。

【问题讨论】:

标签: vb.net winforms event-handling


【解决方案1】:

回答您的评论,处理来自单独类的KeyDown

文档:

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

现在您可以在每个表单的 Load 事件处理程序中执行以下操作:

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

正如 Olaf 所说,您还可以让所有表单都从基类继承。但是,这可能会变得有点复杂,因为您必须同时告诉 yourForm.vbyourForm.Designer.vb 文件您想从基本表单继承。

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

yourForm.vb:

Public Class yourForm
    Inherits BaseForm

    ...code...
End Class

yourForm.Designer.vb:

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

    ...code...
End Class

【讨论】:

  • 刚刚测试了响应的第一部分(水平规则之前的部分编辑)。这一切都检查出来了。 (不过,我必须启用“密钥预览”才能使其工作。不确定这是否是说明的一部分。)
  • @PaulWilliams :这不是我的指示的一部分,因为我假设您在测试 Olaf 的答案时已经这样做了。但是,是的,这是必需的。 ;)
  • @PaulWilliams :我编辑了答案以将其包含在代码中。
  • 现在更好了。谢谢。
【解决方案2】:

设置 KeyPreview = True 并处理 KeyDown 事件:

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

【讨论】:

  • 奇怪的问题,有没有办法在整个程序中全局执行此操作,还是我必须在每个单独的表单上使用它?
  • @PaulWilliams :您可以在一个单独的类中创建一个共享方法,您可以调用每个表单的Form.Load(将表单作为参数传递)。然后该方法将为您设置正确的属性并订阅事件处理程序。
  • 你会不会碰巧有它的代码,因为我在一般类中尝试它会给我错误。
  • 您可以在基类 MyNotF4ClosableForm 中处理它,并从该基类继承您应用中的所有其他表单。
  • Olaf,请原谅我,因为我正在尝试执行此操作,但尝试在新的自定义类中继承 Forms 类时遇到了错误……因为我做不到"Me.KeyDown" 不附加到某物上。
【解决方案3】:

您还应该使用RemoveMenu() 互操作调用从表单系统菜单中删除相应的关闭菜单项。这会禁用所有默认的窗口关闭选项。

当然,您可以在代码中调用Form.Close() 来关闭您的表单。这可以由自定义按钮、菜单项等的Click 事件处理程序触发。此外,您可以实现System.Windows.Forms.IMessageFilter 来处理自定义键序列(而不是 ALT+F4)以关闭表单,例如C+L+O+S+E。

【讨论】:

  • 等等等等……我觉得你没看错……我想保留菜单选项,保留控制框选项,但是禁用ALT+F4方法。
【解决方案4】:

简单:

在 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);
}

在 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

【讨论】:

    猜你喜欢
    • 2018-10-31
    • 2019-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-13
    • 1970-01-01
    • 2013-04-18
    相关资源
    最近更新 更多