-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

アップデート:

メッセージを簡単に管理するために再現する元のコードの 1 つを見つけました。

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 を使用します。低レベルにする必要がある場合は、それが 1 つの方法でした。

ただし、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 に答える