-1

我正在尝试编写一个更好(我认为更好)且可重用的 WndProc 过程,但是下面的代码不起作用,因为当我向子公司添加更多参数时,它说子不接受那么多参数,当然这是合理的。

但是我知道这个技巧是可以做到的,因为我之前在一些第三方类中看到过带有很多自定义参数的同一个 wndproc 子程序,我不记得我在哪里见过我不记得他们是怎么做的诀窍。

那么,如果它有问题,有人可以帮助我修复这段代码并改进它吗?

另外,这样修改的性能有什么要注意的吗?真的我不知道这样的事情是否会以某种方式影响性能。

''' <summary>
''' Windows Message Identifiers.
''' </summary>
Private Enum Messages As Integer
    ''' <summary>
    ''' Message is sent when the user chooses a command from the system menu,
    ''' or when the user chooses the "maximize", "minimize", "restore", or "close" buttons.
    ''' </summary>
    WM_SYSCOMMAND = &H112
End Enum

''' <summary>
''' Intercepts Windows messages for this Window.
''' </summary>
''' <param name="MsgInt32">
''' Message Identifier as Integer.
''' </param>
''' <param name="MsgWin32">
''' Message Identifier as Win32Hex format.
''' </param>
''' <param name="MsgHex">
''' Message Identifier as Hexadecimal format.
''' </param>
''' <param name="HWnd">
''' Window Handle.
''' </param>
''' <param name="LParam">
''' LParan message argument.
''' </param>
''' <param name="WParam">
''' WParam message argument.
''' </param>
''' <param name="Result">
''' Specifies the value that is returned to window in response to handling the message.
''' </param>
Protected Overrides Sub WndProc(ByRef m as Message,
                                ByRef MsgInt32 As Integer
                                ByRef MsgWin32 As String,
                                ByRef MsgHex As String,
                                ByRef HWnd As IntPtr,
                                ByRef LParam As IntPtr,
                                ByRef WParam As IntPtr,
                                ByRef Result As IntPtr)

    Select Case MsgInt32

        Case Messages.WM_SYSCOMMAND

            MsgBox(MsgWin32)
            MsgBox(LParam)
            MsgBox(WParam)

    End Select

    ' Return control to base message handler.
    MyBase.WndProc(m, CInt(m.Msg), "&H" & Hex(m.Msg), Hex(m.Msg), m.HWnd, m.LParam, m.WParam, m.Result)

End Sub

更新:

我找到了我将复制的原始代码之一,以便更轻松地管理消息。

Public Declare Function CallWindowProc Lib "user32.dll" Alias "CallWindowProcA" (ByVal _
    lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam _
    As Long, ByVal lParam As Long) As Long

Public Delegate Function ipWindowProc(ByVal hwnd As Integer, ByVal uMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer

Dim ip As ipWindowProc = AddressOf Me.WindowProc

' The following function acts as Form1's window procedure to process messages.
Public Function WindowProc(ByVal hwnd As Integer, ByVal uMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
    Dim bTopMost As Boolean = Me.TopMost
    Dim hMenu As Integer = 0
    Dim iRet As Integer = 0
    Dim mii As MENUITEMINFO
Select Case uMsg
    Case WM_INITMENU
        hMenu = GetSystemMenu(hwnd, 0)
        mii.cbSize = Len(mii)
        mii.fMask = MIIM_STATE
        If bTopMost = True Then
            mii.fState = MFS_ENABLED Or MFS_CHECKED
        Else
            mii.fState = MFS_ENABLED Or 0
        End If
        iRet = SetMenuItemInfo(hMenu, 1, 0, mii)
        WindowProc = 0
    Case WM_SYSCOMMAND
        If wParam = 1 Then
            mii.cbSize = Len(mii)
            mii.fMask = MIIM_STATE
            If bTopMost = True Then
                mii.fState = MFS_ENABLED Or 0
                iRet = SetMenuItemInfo(hMenu, 1, 0, mii)
                Me.TopMost = False
            Else
                mii.fState = MFS_ENABLED Or MFS_CHECKED
                iRet = SetMenuItemInfo(hMenu, 1, 0, mii)
                Me.TopMost = True
            End If
            WindowProc = 0
        Else
            WindowProc = CallWindowProc(ioProc, hwnd, uMsg, wParam, lParam)
        End If
    Case Else
        WindowProc = CallWindowProc(ioProc, hwnd, uMsg, wParam, lParam)
End Select
End Function

更新 2

好吧,我已经从上面的代码中翻译了这个,现在我需要添加什么来使它像上面的代码一样作为 wndproc 替换工作?

public class form1

<System.Runtime.InteropServices.
DllImport("user32.dll")>
Private Shared Function CallWindowProc(
        ByVal lpPrevWndFunc As WndProcDelegate,
        ByVal hWnd As IntPtr,
        ByVal Msg As UInteger,
        ByVal wParam As IntPtr,
        ByVal lParam As IntPtr
) As IntPtr
End Function

Delegate Function WndProcDelegate(
         ByVal hWnd As IntPtr,
         ByVal msg As UInteger,
         ByVal wParam As IntPtr,
         ByVal lParam As IntPtr
) As IntPtr

''' <summary>
''' Process Windows messages.
''' This function acts as wndproc.
''' </summary>
Public Function WindowProc(ByVal hwnd As IntPtr,
                           ByVal uMsg As UInteger,
                           ByVal wParam As IntPtr,
                           ByVal lParam As IntPtr) As Integer

    Select Case uMsg

        Case &H112

            MsgBox("Message intercepted!")

    End Select

End Function

End class
4

1 回答 1

5

为什么?...你为什么要这样做?

你只是敞开心扉去犯错误。一个老式的 VB6 程序会使用这种类型的 API,因为简单的事实是该语言没有提供内置的方法。如果您需要降低水平,那么这是一种方法。

不过,VB.Net 允许您重写 WndProc(),从而免费为您提供此功能。

该 API 并没有使管理消息变得更容易。您尝试使用此 API 访问的所有这些“额外”参数已经存在于标准 WndProc() 过程中名为“m”的 Message 参数中:

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
    MyBase.WndProc(m)
End Sub

查看为Message列出的属性:

在此处输入图像描述

这些价值观都在那里。您可以使用以下方法制作一个不错的 Select Case 语句m.Msg

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
    Select Case m.Msg
        Case WM_LBUTTONDOWN

        Case WM_RBUTTONDOWN

    End Select
    MyBase.WndProc(m)
End Sub

...并且您可以以相同的方式访问其他参数。您可以设置 Result() 属性来更改处理消息的方式。您甚至可以更改消息等。如果您想要消息的友好字符串版本,请使用m.ToString().

我的朋友,这一切都在那里……使用 API 不会给你任何你还没有的东西,它只会为你创造更多的工作。

于 2013-11-13T18:10:24.870 回答