2013-11-13 6 views
-2

Я пытаюсь написать лучшую (я думаю, лучше) и многоразовую процедуру WndProc, , но приведенный ниже код не работает, потому что, когда я добавляю больше аргументов в подпрограмму, он говорит, что sub не принимает такое количество аргументов, конечно, это разумно.Попытка написать лучшую обработку WndProc

Но я знаю, что этот трюк можно сделать, потому что я видел тот же самый wndproc sub с множеством настраиваемых аргументов в некоторых классах третьей стороны, которые я не помню, где я не видел ни того, помните, как они сделали трюк.

Тогда кто-то может помочь мне исправить этот код и улучшить его, если у него что-то не так?

Кроме того, есть что сказать о производительности, выполняющей такую ​​модификацию? действительно, я не знаю, может ли что-то подобное повлиять на производительность в некотором роде.

''' <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 

UPDATE:

Я нашел один из исходных кодов, которые я буду на перепечатку управлять сообщения проще.

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 

UPDATE 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 
+1

Вы не можете переопределить базовый метод, если не будете соответствовать параметрам. В конце концов, вы не тот, кто вызывает WndProc, окна есть. Как Windows знает, как предоставить дополнительные параметры? – LarsTech

+0

@LarsTech Я еще раз повторю, что знаю, что это можно сделать, я видел это раньше в рабочем коде, проблема в том, что я не знаю, как воспроизвести его, потому что у меня нет исходного кода. конечно, у вас есть причина, что способ не переопределяет суб, но я не знаю, как это сделать правильно. Я написал глупый код. Извините – ElektroStudios

+3

. Класс Control имеет это: 'protected virtual void WndProc (ref Message m)'. Один параметр. Это все, что вы можете назвать, и это все, что вы можете отменить. – LarsTech

ответ

5

Почему? ... зачем вы это делаете?

Вы просто открываете себя для совершения ошибок. Старая школа VB6-программа будет использовать этот тип API из-за простого факта, что язык не обеспечил встроенный способ его выполнения. Если вам нужно было идти на низкий уровень, это было одним из способов сделать это.

VB.Net дает вам это бесплатно, однако, позволяя вам переопределить WndProc().

Этот API не облегчает управление сообщениями. Все эти «лишние» параметры, которые вы пытаетесь получить доступ с помощью этого API являются там уже в параметре сообщения называется «м» в консервированном WndProc() процедура:

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

Посмотрите на свойствах включен в список Message:

enter image description here

Эти значения все там. Вы можете сделать хороший Оператор 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 

... и вы можете получить доступ к другим PARAMS таким же образом. Вы можете установить свойство Result(), чтобы изменить способ обработки сообщения. Вы даже можете изменить сообщение и т. Д. Если вам нужна дружественная версия String сообщения, используйте m.ToString().

Это все, что есть мой друг ...использование API не дает вам ничего, чего у вас еще нет, это просто создает больше работы с вашей стороны.

+0

спасибо, может быть, этот вопрос о том, что вы сказали, может вас заинтересовать: http://stackoverflow.com/questions/19961694/what-means-the-result-propertie-of-a-windows-message-and-when- и как-потребительной его – ElektroStudios