【问题标题】:Capture the option selected by the user in a windows default contextmenu?在 Windows 默认上下文菜单中捕获用户选择的选项?
【发布时间】:2013-10-21 06:34:45
【问题描述】:

当右键单击具有默认 Windows 上下文菜单的文本框时,我想知道用户是否选择了 copy cutpaste 选项,以便在用户选择特定的上下文菜单选项时执行辅助操作。

我没有代码,因为我不知道从哪里开始尝试识别用户在上下文菜单中选择了哪个选项,以及如何捕获左键单击,因为我试图捕获默认的上下文菜单 mouseleft单击文本框MouseDown/Mouseclick 事件没有成功,我知道这没有多大意义,因为它是上下文菜单鼠标单击,而不是文本框鼠标单击,但是...我不知道如何管理该外部上下文菜单。

【问题讨论】:

  • 由于您想提供自己的操作,因此您应该替换默认的 ContextMenu - 即使这些操作是“次要的”。可能比尝试连接或搭载 Win/Net 的代码更少,也更容易。
  • @Plutonix 这就是我一直以来的处理方式。然后您可以手动将内容添加到剪贴板,也可以直接调用快捷键SendKeys.SendWait("[CTRL]+C")
  • 只是一个例子:假设我只想在用户在默认上下文菜单中选择“复制”或“粘贴”选项时抛出一个 MsgBox,这就是我所要求的。感谢阅读!
  • @Plutonix 我不想在此应用程序中将默认上下文菜单替换为自定义上下文菜单,Probably less code and easier than... 取决于它是简单的 cm 还是完全替换,默认 cm 有多个IME 选项,您确实需要大量代码来重现所有这些选项,例如 Unicode 控制选项......否则只需使用复制/剪切/粘贴选项制作上下文菜单我不喜欢它,但是只需要很少代码行,但似乎不是很专业(对于文本框)。我在这个应用程序中不需要它。
  • 对不起,我没有冒犯任何人的意思,只是对我来说,我认为这似乎并不专业,我认为任何其他类型控制的自定义 CM 都很好,但不适用于TextBox 控件,我总是在所有应用程序上看到 TextBox 的默认 CM,但我们的不同之处在于,无论如何我无法想象一个人可以将哪些自定义选项添加到文本框自定义 CM,因为 Windows 默认 Textbox CM 具有所有需要的选项! ,谢谢你的评论。

标签: .net vb.net winforms textbox contextmenu


【解决方案1】:

您可以将这样的类添加到您的项目中:

Class MyTextBox : Inherits TextBox
  Public Enum ContextCommands
     WM_CUT = &H300
     WM_COPY = &H301
     WM_PASTE = &H302
  End Enum

  Public Class ContextCommandEventArgs
     Inherits EventArgs
     Public Property Command As ContextCommands
  End Class

  Event OnCut(sender As Object, e As ContextCommandEventArgs)
  Event OnCopy(sender As Object, e As ContextCommandEventArgs)
  Event OnPaste(sender As Object, e As ContextCommandEventArgs)

  Protected Overrides Sub WndProc(ByRef m As Message)
     MyBase.WndProc(m)
     Select Case m.Msg
        Case ContextCommands.WM_CUT
           RaiseEvent OnCut(Me, New ContextCommandEventArgs() With {.Command = ContextCommands.WM_CUT})
        Case ContextCommands.WM_COPY
           RaiseEvent OnCopy(Me, New ContextCommandEventArgs() With {.Command = ContextCommands.WM_COPY})
        Case ContextCommands.WM_PASTE
           RaiseEvent OnPaste(Me, New ContextCommandEventArgs() With {.Command = ContextCommands.WM_PASTE})
     End Select
  End Sub
End Class

然后,您可以将 Designer.vb 文件中所有出现的“TextBox”替换为“MyTextBox”。然后,您将可以访问 3 个用于剪切、复制和粘贴的新事件。你可以这样处理它们:

Private Sub TextBox1_OnTextCommand(sender As Object, e As MyTextBox.ContextCommandEventArgs) _
    Handles TextBox1.OnCut, TextBox1.OnPaste, TextBox1.OnCopy
    MessageBox.Show("Activated " & e.Command.ToString())
End Sub

请注意,在这种情况下,我如何选择在一个函数中处理所有 3 个事件,但您也可以在单独的函数中处理它们。我注意到 cut 命令似乎也会导致复制命令事件,但我现在假设您可以处理这种轻微的复杂情况。

【讨论】:

  • 很好的解决方案,非常感谢!当我单击“剪切”CMT 选项时,WM_COPY 消息与 WM_CUT 一起发送,这可以修复吗?,我问这个是因为我需要同时管理 WM_COPY 和 WM_CUT,当我单击时这会给我一个 WM_COPY 误报“剪切”选项。
  • 是的,我已经在回复中提到了这种行为。你能忽略 wm_copy 吗?你为什么关心捕获 wm_copy?我不知道如何“修复”它,但我不确定它是否真的错了。剪切实际上是一种复制,然后是剪切/删除。所以我不知道为什么你的代码在乎。如果用户刚刚选择了副本,您的代码需要做什么?
  • 这很难解释,但无论如何我认为我可以使用计时器来测量 wm_copy + wm_delete 之间的时间以识别用户何时点击“剪切”
  • 也许你可以告诉我 wm_delete 的常量来满足我的需求?我在 MSDN 中找不到它,感谢您的宝贵时间
  • 发现:WM_CLEAR = &H303,但不幸的是,您的类在继承第 3 方文本框(例如:氪文本框)时将无法工作,如果可以,请在此处查看新问题:stackoverflow.com/questions/19560844/…
【解决方案2】:

如果有人需要这个,这是对@BlueMonkMN 代码的修改,以便与 CUT 选项一起正常工作,还添加了 DELETE 选项。

Class MyTextBox : Inherits TextBox

Private Last_Command As ContextCommands = Nothing

Private WithEvents CopyOrCut_Timer As New Timer _
        With {.Interval = 5, .Enabled = False}

Public Enum ContextCommands
    WM_CUT = &H300
    WM_COPY = &H301
    WM_PASTE = &H302
    WM_DELETE = &H303
End Enum

Public Class ContextCommandEventArgs
    Inherits EventArgs
    Public Property Command As ContextCommands
End Class

Event OnCut(sender As Object, e As ContextCommandEventArgs)
Event OnCopy(sender As Object, e As ContextCommandEventArgs)
Event OnPaste(sender As Object, e As ContextCommandEventArgs)
Event OnDelete(sender As Object, e As ContextCommandEventArgs)

Protected Overrides Sub WndProc(ByRef m As Message)

    MyBase.WndProc(m)

    Select Case m.Msg

        Case ContextCommands.WM_COPY
            Last_Command = ContextCommands.WM_COPY
            CopyOrCut_Timer.Enabled = True

        Case ContextCommands.WM_CUT
            Last_Command = ContextCommands.WM_CUT

        Case ContextCommands.WM_PASTE
            RaiseEvent OnPaste(Me, New ContextCommandEventArgs() _
                                   With {.Command = ContextCommands.WM_PASTE})

        Case ContextCommands.WM_DELETE
            RaiseEvent OnDelete(Me, New ContextCommandEventArgs() _
                                    With {.Command = ContextCommands.WM_DELETE})

    End Select

End Sub

Private Sub Cut_Timer_Tick(sender As Object, e As EventArgs) _
Handles CopyOrCut_Timer.Tick

    sender.enabled = False

    Select Case Last_Command

        Case ContextCommands.WM_COPY
            RaiseEvent OnCopy(Me, New ContextCommandEventArgs() _
                                  With {.Command = ContextCommands.WM_COPY})

        Case ContextCommands.WM_CUT
            RaiseEvent OnCut(Me, New ContextCommandEventArgs() _
                                 With {.Command = ContextCommands.WM_CUT})

    End Select

    Last_Command = Nothing

End Sub

End Class

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-14
    • 1970-01-01
    • 2020-10-18
    • 1970-01-01
    • 1970-01-01
    • 2022-01-10
    相关资源
    最近更新 更多