3 Replies - 3344 Views - Last Post: 17 April 2008 - 02:59 PM Rate Topic: -----

#1 RodgerB  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 66
  • View blog
  • Posts: 2,284
  • Joined: 21-September 07

Confused as hell.. how the hell can this code work? :S

Posted 16 April 2008 - 03:34 AM

Recently I've been experimenting with Key Hooking, I have tried using GetAsyncKeyState, but I decided I'd rather use an API hook as running Timers are inefficient in comparison to API hooks (at least I'd hope).

I searching around MSDN for "Keyboard Hook", and came across a blog post by Stephen Toub on a Low Level Keyboard Hook in C# (click), exactly what I was looking for. I began converting the code to VB.NET, and this is what I have came up with.

Option Strict On
Imports System.Runtime.InteropServices

Public Class Form1

    Private Const WH_KEYBOARD_LL As Integer = 13
    Private Const WM_KEYDOWN As Integer = &H100
    Private Shared _proc As LowLevelKeyboardProc = HookCallback
    Private Shared _hookID As IntPtr = IntPtr.Zero

    Public Declare Auto Function SetWindowsHookEx Lib "user32.dll" ( _
        ByRef idHook As Integer, ByRef lpfn As LowLevelKeyboardProc, _
        ByRef hMod As IntPtr, ByRef dwThreadId As UInteger) As IntPtr

    Public Declare Auto Function UnhookWindowsHookEx _
    Lib "user32.dll" (ByRef hhk As IntPtr) As IntPtr

    Public Declare Auto Function CallNextHookEx _
    Lib "user32.dll" (ByRef hhk As IntPtr, ByRef nCode As Integer, _
                      ByRef wParam As IntPtr, ByRef lParam As IntPtr) As IntPtr

    Public Declare Auto Function GetModuleHandle Lib "kernel32.dll" ( _
    ByRef lpModuleName As String) As IntPtr


    Private Shared Function SetHook( _
        ByRef proc As LowLevelKeyboardProc) As IntPtr

        Dim curProcess As Process = Process.GetCurrentProcess()
        Dim curModule As ProcessModule = curProcess.MainModule

        Return SetWindowsHookEx(WH_KEYBOARD_LL, proc, _
                GetModuleHandle(curModule.ModuleName), 0)

    End Function

    Public Delegate Function LowLevelKeyboardProc( _
        ByRef nCode As Integer, ByRef wParam As IntPtr, _
        ByRef lParam As IntPtr) As IntPtr

    Public Shared Function HookCallback( _
        ByRef nCode As Integer, _
        ByRef wParam As IntPtr, ByRef lParam As IntPtr) As IntPtr

        If nCode >= 0 And wParam = CType(WM_KEYDOWN, IntPtr) Then
            Dim vkCode As Integer = Marshal.ReadInt32(lParam)
            Console.WriteLine(CType(vkCode, Keys))
        End If

        Return CallNextHookEx(_hookID, nCode, wParam, lParam)
    End Function

End Class



The problem I am recieving is when I assign the HookCallback function to the form level variable _proc.

This is the working code I have working with C# (pretty much copied and pasted from Stephen Toub's entry):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace InterceptKeys
{
    static class Program
    {
        private const int WH_KEYBOARD_LL = 13;
        private const int WM_KEYDOWN = 0x0100;
        private static LowLevelKeyboardProc _proc = HookCallback;
        private static IntPtr _hookID = IntPtr.Zero;

        private static IntPtr SetHook(LowLevelKeyboardProc proc)
        {
            using (Process curProcess = Process.GetCurrentProcess())
            using (ProcessModule curModule = curProcess.MainModule)
            {
                return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
                    GetModuleHandle(curModule.ModuleName), 0);
            }
        }

        private delegate IntPtr LowLevelKeyboardProc(
            int nCode, IntPtr wParam, IntPtr lParam);

        private static IntPtr HookCallback(
            int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
            {
                int vkCode = Marshal.ReadInt32(lParam);
                Console.WriteLine((Keys)vkCode);
            }
            return CallNextHookEx(_hookID, nCode, wParam, lParam);
        }

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx(int idHook,
            LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool UnhookWindowsHookEx(IntPtr hhk);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
            IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string lpModuleName);

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        public static void Main()
        {
            _hookID = SetHook(_proc);
            Application.Run();
            UnhookWindowsHookEx(_hookID);
        }
    }
}



The question I have is, well a) how can I get the above C# code to work in VB.NET, and the second question would be, how can C# just totally ignore 3 arguments in a function, and compile?

I am so confused. Thanks in advance homies. XD :D

This post has been edited by RodgerB: 16 April 2008 - 03:35 AM


Is This A Good Question/Topic? 0
  • +

Replies To: Confused as hell.. how the hell can this code work? :S

#2 Matthew1511  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 11-April 08

Re: Confused as hell.. how the hell can this code work? :S

Posted 17 April 2008 - 12:46 AM

I agree. ohh hey rodger i am in QLD how r u how is school. i didnt know how else to contact u. any way i defiantly agree with your point of view on this subject. ok cya.
Was This Post Helpful? 0
  • +
  • -

#3 orcasquall  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 12
  • View blog
  • Posts: 158
  • Joined: 14-September 07

Re: Confused as hell.. how the hell can this code work? :S

Posted 17 April 2008 - 04:30 AM

Actually, Stephen already answered your first question in one of his comments. Scroll down till you find his comment dated September 10, 2006 11:20 AM. It's something about delegate inference, so you're probably using Visual Studio 2003 (or at least compiling against the 1.x Framework).

I'll assume that you still want the code to work in VS2003. Your VB.NET port of the code seems ok. Try changing to this line
Private Shared _proc As LowLevelKeyboardProc = New LowLevelKeyboardProc(AddressOf HookCallback)



That should answer your first question.

As for your second question, I'm assuming you're referring to how you can compile without function parameters, when it seems like you should. Anyway, this should work for the C# version
private static LowLevelKeyboardProc _proc = new LowLevelKeyboardProc(HookCallback);



You know, if you think about it, both of your questions have the same answer...

If you're still stuck, maybe you can compile with the C# version, then use Lutz Roeder's Reflector to get the VB.NET version... just a thought...

This post has been edited by orcasquall: 17 April 2008 - 04:33 AM

Was This Post Helpful? 0
  • +
  • -

#4 RodgerB  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 66
  • View blog
  • Posts: 2,284
  • Joined: 21-September 07

Re: Confused as hell.. how the hell can this code work? :S

Posted 17 April 2008 - 02:59 PM

Thanks very much orcaquall, that was exactly the answer I needed. I did a quick google and came up with this quote from an MSDN article about new features to C# 2.0.

Quote

When you assign a method name to a delegate, the compiler first infers the delegate's type. Then the compiler verifies that there is a method by that name and that its signature matches that of the inferred delegate type. Finally, the compiler creates a new object of the inferred delegate type, wrapping the method and assigning it to the delegate.


I'm using 2005/2008, and afaik VB.NET doesn't have delegate inference, so I suppose that answers my problem also.
EDIT: I just found out VB.NET does support delegate inference at school today, however I had to add the keyword AddressOf. :)

Again, thanks, that is something I didn't know, and is handy to know! :D

@matt: I'm good thanks. Please don't reply to this topic, off-topic. I'm good, I hit a 360 layup at school, it was hardcore and stuff mkay. Cool. CYA :) :P

This post has been edited by RodgerB: 17 April 2008 - 11:02 PM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1