Application of HOOK in VB.NET (2)
Second, then what kind of change is made on the call of API and HOOK implementation in VB.NET?
We look at a problem with a question:
1. Create a new module, write a declaration of the API:
Declare function setWindowshookex lib "user32" alias "setwindowshookexa" (byval) (Byval LPFN AS HookProc, Byval HMOD AS INTEGER, BYVAL DWTHREADID AS INTEGER) AS Integer
Declare Function UnHookWindowsHookex Lib "User32" (Byval HHOOK AS INTEGER) AS INTEGER
Declare function callnexthookex lib "user32" (byval hHOOK AS INTEGER, BYVAL WPARAM AS INTEGER, BYVAL LPARAM AS INTEGER) AS INTEGER
And the statement in VB6 above, what did you find? Is it a change in the data type? Integer instead of Long. This is a good understanding, because Integer in VB.NET is defined as an integer of 32-bit (4 bytes), the range is -231 to 231 (first bit is a symbol bit), which is consistent with the definition of long in VB6, therefore, We must do this conversion.
Wait, there is a change, that is, the type of setWindowshookex's parameter lpfn becomes hookproc, then ... that means. Hey, wait, I will make a statement first:
Public Delegate Function HookProc (Byval Ncode As INTEGER, BYVAL WPARAM AS INTEGER, BYVAL LPARAM AS INTEGER)
What did you see? HookProc is actually a function declaration, but there is a delegate in front of it? Why can't I use Integer in VB.NET to represent the type of lpfn? Let's look back at the sentence of VB6 to call the API:
HNEXTHOKPROC = SETWINDOWSHOKEX (Wh_Keyboard, Addressof _
Mykbhfunc, app.hinstance, 0)
LPFN is represented here as addressof mykbhfunc, that is, when the HOOK is functioning, the called substruction is mykbhfunc. That is to say, the LPFN is indicated by the address of the function or process. Use the long type in VB6 to record the address of the function or process.
In VB.NET, there is a small change, and the AddRessof operator creates a subtraction to the specified substruction. When the specified subsector is an instance method, the subcruit delegates simultaneously reference instances and methods to call the specified method of the specified instance when calling the subcrocess. The AddressOf operator can be used as an operand that the delegate constructor, or can be used in the context of the translator to determine the delegate type.
So, it is precisely because addressof is no longer just a simple function pointer, but a subsidiary! Bring your first, what is a delegation? (^? ^) Explain that the event is the message sent by the object, with the occurrence of signal notification operation. The operation may be caused by a user interaction (such as a mouse click), or it may be triggered by some other program logic. The object that causes (trigger) event is called an event sender. Capture the event and respond to the object of the event recipient. In the event communication, the event sending party class does not know which object or method will receive (handle) the event it ranked. What is needed is that there is a medium (or the mechanism of the similar pointer) between the source and the reception. The .NET framework defines a special type (DELEGATE), which provides functions of the function pointer. Look, here mention the .NET framework, so the language in the vs.net of C # can have this type.
The entrusted is an object that can be used to call other object methods. Unlike other classes, the delegate class has a signature, and it can only be referenced to the method that matches its signature. In this way, the commission is equivalent to a type of security function pointer or a callback. Because they are similar to the function pointers used in other programming languages. But unlike the function pointer, Visual Basic.Net delegate is a reference type based on the System.Delegate class, which can reference the sharing method - the method that is not required to be called. (For details, please go to the MSDN or wait for my follow-up]
Take it back to summarize, that is, Addressof is DelegateType (delegated type). Instead of simple subscar pointers, it is not a LONG of the address type, but a delegate type representation with the call schedule. Therefore, I defined a delegation function hookProc with mykbhfunc declaration to represent the type of LPFN.
(Call, one sweat, I don't know how to say it clearly. Hope is clear ...)
Continue, I will then declare an API:
Declare function getcurrentthreadid lib "kernel32" alias "getcurrentthreadid" () AS integer
Function Description: This function is used to get a unique thread identifier for the current thread. Return Value: The current thread identifier. What is the use of this, I will say it again, anyway, it is a simple question, it is better to sell a car, haha ... (don't smash me)
2. The defined constant is:
Public HNEXTHOOKPROC AS Long
Public const wh_keyboard = 2 'This is the type of hook is the keyboard HOOK
Public const pm_key_space = & h20 'space bar
Or, in fact, I have changed on the second sentence in the program, and there is nothing, just pay more, give friends:
Public Enum HookType
Wh_keyboard = 2
END ENUM
Defined into an enumeration. In fact, Hook's type is really much, such as: wh_callwndproc, wh_callwndprocret, wh_cbt, wh_debug, wh_getimentage, and more. So you may wish to write an enumeration to achieve the goal of life.
3. Code segment
Module Module1
Public frM1 as new form1 () 'This role, finally says the declare function getcurrentthreadid lib "kernel32" Alias "getcurrentthreadidID" () AS INTEGER
Declare function setWindowshookex lib "user32" alias _
"Setwindowshookexa" (Byval IDHOOK AS INTEGER, BYVAL LPFN AS HOOKPROC, _
BYVAL HMOD AS INTEGER, BYVAL DWTHREADID AS INTEGER AS INTEGER
Declare function unhookwindowshookex lib "user32" _
(Byval HHOOK AS INTEGER) AS INTEGER
Declare function callnexthookex lib "user32" (Byval HHOOK AS INTEGER, _
BYVAL NCODE AS INTEGER, BYVAL WPARAM AS INTEGER, BYVAL LPARAM AS INTEGER AS INTEGER
Public Delegate Function HookProc (Byval Ncode As INTEGER, BYVAL WPARAM AS INTEGER, BYVAL LPARAM AS INTEGER)
Public HNEXTHOKPROC AS INTEGER
Public const pm_key_space = & h20
Public Enum HookType
Wh_keyboard = 2
END ENUM
Public Sub UnHook () 'Solution HOOK
IF HNEXTHOOKPROC <> 0 THEN
UnHookWindowsHookex (HNEXTHOOKPROC)
HNEXTHOOKPROC = 0
END IF
End Sub
Public Function setHook () Set HOOK
IF HNEXTHOOKPROC <> 0 THEN
EXIT FUNCTION
END IF
HNEXTHOKPROC = setWindowshookex (hooktype.wh_keyboard, addressof mykeyboardproc, 0, getcurrentthreadid ())
I set the third parameter to 0 (ie null), indicating that this Hook code is in this process. The fourth parameter uses an API to remove the identifier of the thread associated with the Hook substruction. (See the previous API statement)
END FUNCTION
Public Function MyKeyboardProc (Byval Ncode As INTEGER, BYVAL LPARAM AS INTEGER) AS Integer
MyKeyboardProc = 0
IF ncode <0 THEN
MyKeyboardProc = CallNexthookex (HNEXTHOKPROC, NCODE, WPARAM, LPARAM)
EXIT FUNCTION
END IF
IF wparam = pm_key_space then
MyKeyboardProc = 1
'Write your own code
frm1.textBox1.text = "Hook success!"
END IF
END FUNCTION
Sub main () application.run (frm1)
End Sub
End module
Also please:
Solution Manager -> WindowsApplication1.sln -> Right Mouse -> Properties -> Universal Properties -> General -> Start Object -> Change to Module1
4. Code in Form1:
Private Sub Form1_Load (Byval E AS System.Object, Byval E AS System.Eventargs) Handles MyBase.LOAD
Call setook ()
End Sub
No form_unload event in VB.NET, but use closing
Private Sub Form1_Closing (Byval e as system.componentmodel.canceleventargs) Handles mybase.closing
Call unhook ()
End Sub
Finally, I briefly explained why I used Public FRM1 AS New Form1 () in Module1, and launching objects -> Change to Module1. This is because VB.Net is already OO, if you are a frequent visitor of VB.NET version on 9cbs, you will be familiar with this problem, we have discussed N times. I have also returned how much posts will explain this problem. Due to the definition of this paper, you don't understand this question, please take a look at:
http://www.9cbs.net/expert/topic/965/965919.xml
Get some concept. I will introduce more detailed and systematic introductions in subsequent articles (in fact it is also one of the problems I want to write by I am).
Conclusion: About the call of the API, this article only involves one corner of the iceberg. About specific call changes, I will explain the relevant article according to the specific circumstances of the VB.NET version.
Yes, add a little, VB.NET no longer recognizes the any type, so it is necessary to declare the type you want to use when declaring.
By Henry
2002.9.21 (Mid-Autumn Night)
If you have seen this article, the debugger has a problem, you want to get the source code of VB.Net Hook, you can contact me (but in fact, I have written the code all above)
E-mail: ruigeren@sina.com
QQ: 18349592
---- Declaration: The right to copyright and interpretation of this article belongs to Han Rui, if you need to reprint, please keep your full content and this statement.