调整此类中的Windows消息 [英] Adapt windows messages in this class

查看:135
本文介绍了调整此类中的Windows消息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道这个代码是否适合在正常类(例如:Form1 Class)中使用,以便不需要对控件进行子类化。



代码来自 BlueMonkMN 这里捕获用户在Windows默认上下文菜单中选择的选项?

 类MyTextBox:Inherits TextBox 
公开枚举ContextCommands
WM_CUT =& H300
WM_COPY =& H301
WM_PASTE =& H302
结束枚举

公共类ContextCommandEventArgs
继承EventArgs
公共属性命令作为ContextCommands
结束类

事件OnCut(发件人作为对象,e作为ContextCommandEventArgs)
事件OnCopy(发件人作为对象,e作为ContextCommandEventArgs)
事件OnPaste(发件人作为对象,e作为ContextCommandEventArgs)

受保护的Ove Rides Sub WndProc(ByRef m As Message)
MyBase.WndProc(m)
选择案例m.Msg
案例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
结束类

为了更好地了解我的问题,我会告诉你我已经尝试改编:



公共类Form1

公开枚举ContextCommands
WM_CUT =& H300
WM_COPY =& H301
WM_PASTE = & H302
结束枚举

公共类ContextCommandEventArgs
继承E publicArc
公共属性命令作为ContextCommands
结束类

事件OnCut(TextBox1 As Object,e As ContextCommandEventArgs)
事件OnCopy(TextBox1 As Object,e As ContextCommandEventArgs)
事件OnPaste(TextBox1 As Object,e As ContextCommandEventArgs)

受保护的覆盖Sub WndProc(ByRef m As Message)
MyBase.WndProc(m)
选择案例m .Msg
Case ContextCommands.WM_CUT
RaiseEvent OnCut(TextBox1,New ContextCommandEventArgs()With {.Command = ContextCommands.WM_CUT})
Case ContextCommands.WM_COPY
RaiseEvent OnCopy(TextBox1,新的ContextCommandEventArgs()与{.Command = ContextCommands.WM_COPY})
案例ContextCommands.WM_PASTE
RaiseEvent OnPaste(TextBox1,新的ContextCommandEventArgs()与{.Command = ContextCommands.WM_PASTE})
结束选择
End Sub

私人S ub TextBox1_OnTextCommand()处理TextBox1.TextChanged
如果WM_CUT然后...
Elseif WM_COPY然后...
Elseif WM_Paste然后...
如果
结束Sub结束

私有Sub TextBox1_OnTextCommand()处理Me.OnPaste,Me.OnCopy,Me.OnCut
MsgBox(Activated)
End Sub

结束class


解决方案

这不是VB开发人员的简单任务,但我希望这有帮助。代码不再与特定的文本框相关联,但您应该可以通过将 cwp.hWnd TextBox.Handle进行比较来识别哪个文本框导致事件。 值,如果你需要。 EditMenuHook.Enable 应该在应用程序开始时只能调用一次,以打开挂钩,最后一次将其关闭。

  Imports System.Runtime.InteropServices 

公共类Form1
受保护的覆盖Sub OnLoad(e As EventArgs)
MyBase.OnLoad(e)
EditMenuHook.Enable(True)
End Sub

受保护的覆盖Sub OnClosed(e As EventArgs)
EditMenuHook.Enable(False )
MyBase.OnClosed(e)
End Sub
结束类

朋友类EditMenuHook
公共结构CWPSTRUCT
公共lParam作为IntPtr
public wParam As IntPtr
公共消息作为UInt32
公共hWnd作为IntPtr
结束结构

公共委托函数CallBack(_
ByVal nCode As整数,_
ByVal wParam As IntPtr,_
ByVal lParam As IntPtr)As Integer

共享hHook As Intege r = 0

'为SetWindowsHookEx函数导入。
< DllImport(User32.dll,CharSet:= CharSet.Auto,CallingConvention:= CallingConvention.StdCall)> _
公共重载共享函数SetWindowsHookEx _
(ByVal idHook As Integer,ByVal HookProc As CallBack,_
ByVal hInstance As IntPtr,ByVal wParam As Integer)As Integer
End Function

'为CallNextHookEx函数导入。
< DllImport(User32.dll,CharSet:= CharSet.Auto,CallingConvention:= CallingConvention.StdCall)> _
公共重载共享函数CallNextHookEx _
(ByVal idHook As Integer,ByVal nCode As Integer,_
ByVal wParam As IntPtr,ByVal lParam As IntPtr)As Integer
End Function

'为UnhookWindowsHookEx函数导入。
< DllImport(User32.dll,CharSet:= CharSet.Auto,CallingConvention:= CallingConvention.StdCall)> _
公共重载共享函数UnhookWindowsHookEx _
(ByVal idHook As Integer)As Boolean
结束函数

Private Const WH_CALLWNDPROC = 4

Public Enum TextCommandMessage
WM_CUT =& H300
WM_COPY =& H301
WM_PASTE =& H302
End Enum

'保留引用,以便代表不是垃圾回收。
私有共享hookproc As CallBack

共享子启用(启用为布尔值)
如果hHook = 0 AndAlso enable = True然后
hookproc = AddressOf EditCommandHook
hHook = SetWindowsHookEx(WH_CALLWNDPROC,_
hookproc,_
IntPtr.Zero,_
AppDomain.GetCurrentThreadId())
如果hHook.Equals(0)然后
MsgBox (SetWindowsHookEx Failed)
返回
结束If
ElseIf hHook<> 0 AndAlso enable = False然后
Dim ret As Boolean = UnhookWindowsHookEx(hHook)

如果ret.Equals(False)然后
MsgBox(UnhookWindowsHookEx Failed)
返回
Else
hHook = 0
End If
End If
End Sub

公共共享函数EditCommandHook(_
ByVal nCode As Integer,_
ByVal wParam As IntPtr,_
ByVal lParam As IntPtr)As Integer

如果nCode < 0然后
返回CallNextHookEx(hHook,nCode,wParam,lParam)
End If

Dim cwp = DirectCast(System.Runtime.InteropServices.Marshal.PtrToStructure(lParam,GetType CWPSTRUCT)),

选择案例cwp.message
案例TextCommandMessage.WM_CUT
System.Diagnostics.Debug.WriteLine(String.Format(Cut {0}, cwp.hWnd))
案例TextCommandMessage.WM_COPY
System.Diagnostics.Debug.WriteLine(String.Format(Copy {0},cwp.hWnd))
案例TextCommandMessage.WM_PASTE
System.Diagnostics.Debug.WriteLine(String.Format(Paste {0},cwp.hWnd))
结束选择

返回CallNextHookEx(hHook,nCode,wParam, lParam)
结束函数
结束类


I would like to know if this code can be adapted to use it inside a normal class (Example: Form1 Class) to don't need subclassing a Control.

Code is from BlueMonkMN here Capture the option selected by the user in a windows default contextmenu?

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

To understand better my problem, I'll show you what I've tried to adapt it:

Public Class Form1

    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(TextBox1 As Object, e As ContextCommandEventArgs)
    Event OnCopy(TextBox1 As Object, e As ContextCommandEventArgs)
    Event OnPaste(TextBox1 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(TextBox1, New ContextCommandEventArgs() With {.Command = ContextCommands.WM_CUT})
            Case ContextCommands.WM_COPY
                RaiseEvent OnCopy(TextBox1, New ContextCommandEventArgs() With {.Command = ContextCommands.WM_COPY})
            Case ContextCommands.WM_PASTE
                RaiseEvent OnPaste(TextBox1, New ContextCommandEventArgs() With {.Command = ContextCommands.WM_PASTE})
        End Select
    End Sub

Private Sub TextBox1_OnTextCommand() Handles TextBox1.TextChanged
    If WM_CUT then...
    Elseif WM_COPY then...
    Elseif WM_Paste then...
    End if
End Sub

Private Sub TextBox1_OnTextCommand() Handles Me.OnPaste, Me.OnCopy, Me.OnCut
    MsgBox("Activated")
End Sub

End Class

解决方案

This is not a simple task for a VB developer, but I hope this helps. The code no longer relates to a specific textbox, but you should be able to identify which textbox caused the event by comparing cwp.hWnd with TextBox.Handle values if you need to. EditMenuHook.Enable should probably only be called once at the beginning of your application to turn on the hook, and once at the end to turn it off.

Imports System.Runtime.InteropServices

Public Class Form1
   Protected Overrides Sub OnLoad(e As EventArgs)
      MyBase.OnLoad(e)
      EditMenuHook.Enable(True)
   End Sub

   Protected Overrides Sub OnClosed(e As EventArgs)
      EditMenuHook.Enable(False)
      MyBase.OnClosed(e)
   End Sub
End Class

Friend Class EditMenuHook
   Public Structure CWPSTRUCT
      Public lParam As IntPtr
      Public wParam As IntPtr
      Public message As UInt32
      Public hWnd As IntPtr
   End Structure

   Public Delegate Function CallBack( _
       ByVal nCode As Integer, _
       ByVal wParam As IntPtr, _
       ByVal lParam As IntPtr) As Integer

   Shared hHook As Integer = 0

   'Import for the SetWindowsHookEx function.
   <DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _
   Public Overloads Shared Function SetWindowsHookEx _
          (ByVal idHook As Integer, ByVal HookProc As CallBack, _
           ByVal hInstance As IntPtr, ByVal wParam As Integer) As Integer
   End Function

   'Import for the CallNextHookEx function.
   <DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _
   Public Overloads Shared Function CallNextHookEx _
          (ByVal idHook As Integer, ByVal nCode As Integer, _
           ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
   End Function

   'Import for the UnhookWindowsHookEx function.
   <DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _
   Public Overloads Shared Function UnhookWindowsHookEx _
              (ByVal idHook As Integer) As Boolean
   End Function

   Private Const WH_CALLWNDPROC = 4

   Public Enum TextCommandMessage
      WM_CUT = &H300
      WM_COPY = &H301
      WM_PASTE = &H302
   End Enum

   'Keep the reference so that the delegate is not garbage collected.
   Private Shared hookproc As CallBack

   Shared Sub Enable(enable As Boolean)
      If hHook = 0 AndAlso enable = True Then
         hookproc = AddressOf EditCommandHook
         hHook = SetWindowsHookEx(WH_CALLWNDPROC, _
                                  hookproc, _
                                  IntPtr.Zero, _
                                  AppDomain.GetCurrentThreadId())
         If hHook.Equals(0) Then
            MsgBox("SetWindowsHookEx Failed")
            Return
         End If
      ElseIf hHook <> 0 AndAlso enable = False Then
         Dim ret As Boolean = UnhookWindowsHookEx(hHook)

         If ret.Equals(False) Then
            MsgBox("UnhookWindowsHookEx Failed")
            Return
         Else
            hHook = 0
         End If
      End If
   End Sub

   Public Shared Function EditCommandHook( _
      ByVal nCode As Integer, _
      ByVal wParam As IntPtr, _
      ByVal lParam As IntPtr) As Integer

      If nCode < 0 Then
         Return CallNextHookEx(hHook, nCode, wParam, lParam)
      End If

      Dim cwp = DirectCast(System.Runtime.InteropServices.Marshal.PtrToStructure(lParam, GetType(CWPSTRUCT)), CWPSTRUCT)

      Select Case cwp.message
         Case TextCommandMessage.WM_CUT
            System.Diagnostics.Debug.WriteLine(String.Format("Cut {0}", cwp.hWnd))
         Case TextCommandMessage.WM_COPY
            System.Diagnostics.Debug.WriteLine(String.Format("Copy {0}", cwp.hWnd))
         Case TextCommandMessage.WM_PASTE
            System.Diagnostics.Debug.WriteLine(String.Format("Paste {0}", cwp.hWnd))
      End Select

      Return CallNextHookEx(hHook, nCode, wParam, lParam)
   End Function
End Class

这篇关于调整此类中的Windows消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆