Results 1 to 10 of 10

Thread: hooking windows - please help! *resolved*

  1. #1

    Thread Starter
    Member
    Join Date
    Nov 2000
    Posts
    51

    hooking windows - please help! *resolved*

    I've tried to create a hooking-dll in VC++ for VB use.
    The dll should hook the MouseProc of every window of a certain thread. For testing purpose the dll is writing the hwnd of the Mousevent to the titlebar of my form every time the MouseProc fires. As long as I'm trying to hook VB-windows only, everything is fine. As soon as I'm trying to hook other windows (TaskBar e.g.), nothing works.

    Here is my VC++code:


    code:--------------------------------------------------------------------------------
    --- in the Hook.cpp ------
    #include <iostream>
    #include <windows.h>

    HHOOK hHook;
    HWND hWndSend;
    HINSTANCE hDll;

    void __stdcall StartHook(HWND hWndHook, HWND _hWndSend) {
    hWndSend = _hWndSend;
    hDll = LoadLibrary("Hook.dll");
    DWORD ThreadID = GetWindowThreadProcessId(hWndHook,NULL);
    HOOKPROC hProc = (HOOKPROC) GetProcAddress(hDll, "MouseProc");
    hHook = SetWindowsHookEx(WH_MOUSE, hProc, hDll, ThreadID);
    char str[100];
    sprintf(str, "%d", hHook);
    SetWindowText(hWndSend, str);
    }

    void __stdcall StopHook(void) {
    UnhookWindowsHookEx(hHook);
    FreeLibrary(hDll);
    }

    LRESULT __stdcall CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam) {
    if (nCode == HC_ACTION)
    {
    MOUSEHOOKSTRUCT mhs;
    memcpy(&mhs, (void*)lParam, sizeof(MOUSEHOOKSTRUCT));
    char str[100];
    sprintf( str, "%d", mhs.hwnd);
    SetWindowText(hWndSend,str);
    }
    return CallNextHookEx(hHook, nCode, wParam, lParam);
    }


    --- in the Hook.def ------
    LIBRARY "hook.dll"
    EXPORTS
    StartHook
    StopHook
    MouseProc
    --------------------------------------------------------------------------------


    The vb-Project looks like this:

    code:--------------------------------------------------------------------------------
    Private Declare Sub StartHook Lib "Hook.dll" (ByVal hWndHook As Long, ByVal hWndSend As Long)
    Private Declare Sub StopHook Lib "Hook.dll" ()
    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

    Private Sub Command1_Click()
    Dim hWndHook As Long
    hWndHook = FindWindow("Shell_TrayWnd", vbNullString)
    StartHook hWndHook, Me.hWnd
    End Sub

    Private Sub Form_Unload(Cancel As Integer)
    StopHook
    End Sub
    --------------------------------------------------------------------------------


    This doesn't work at all. When I'm putting hWndHook to Me.hwnd, it works perfectly.

    Any ideas?

    Thanks, Quixx.
    Last edited by Quix; May 29th, 2002 at 12:47 PM.

  2. #2
    Frenzied Member MerrionComputin's Avatar
    Join Date
    Apr 2001
    Location
    Dublin, Ireland
    Posts
    1,616
    When calling SetWindowsHookEx
    VB Code:
    1. Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long
    you need to specify the hMod for a global hook OR the dwThreadId for a process local hook. Because you are passing both the hook type is defaulting to a local hook so you can only hook the current process - which is VB.
    Try passing NULL for dwThreadId.

    Hope this helps,
    Duncan
    ----8<---------------------------------------
    NEW - The .NET printer queue monitor component
    ----8<---------------------------------------
    Now with Examples of use

  3. #3

    Thread Starter
    Member
    Join Date
    Nov 2000
    Posts
    51
    Thanks for your reply.
    I've tried to start the hook from a vb-app using this code
    Code:
    Private hDll As Long, _
    hHook As Long
    
    Private Sub Command1_Click()
    Dim hProc As Long, _
    idThread As Long
    
    hDll = LoadLibrary(App.Path + "\Hook.dll")
    hProc = GetProcAddress(hDll, "MouseProc")
    idThread = GetWindowThreadProcessId(FindWindow("Shell_TrayWnd", vbNullString), 0&)
    hHook = SetWindowsHookEx(WH_MOUSE, hProc, 0&, idThread)
    InitHook Me.hWnd
    End Sub
    
    Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
    UnhookWindowsHookEx hHook
    FreeLibrary hDll
    End Sub
    hDll, hProc and idThread are ok, but SetWindowsHookEx returns zero (=Error).

    I've tried
    Code:
    hHook = SetWindowsHookEx(WH_MOUSE, hProc, 0&, idThread)
    hHook = SetWindowsHookEx(WH_MOUSE, hProc, hDll, 0&)
    hHook = SetWindowsHookEx(WH_MOUSE, hProc, hDll, idThread)
    neither of them works. What am I doing wrong?

  4. #4
    Frenzied Member MerrionComputin's Avatar
    Join Date
    Apr 2001
    Location
    Dublin, Ireland
    Posts
    1,616
    Your best bet to find out what is going on is to get the Err.LastDllError after the call returns zero and translate it thus:

    VB Code:
    1. '\\ API Error decoding
    2. Private Declare Function FormatMessage Lib "kernel32" Alias "FormatMessageA" (ByVal dwFlags As Long, lpSource As Any, ByVal dwMessageId As Long, ByVal dwLanguageId As Long, ByVal lpBuffer As String, ByVal nSize As Long, Arguments As Long) As Long
    3.  
    4.  
    5. '\\ -- [ LastSystemError ]----------------------------------
    6. '\\ Returns the message from the system which describes the
    7. '\\ last dll error to occur, as
    8. '\\ held in Err.LastDllError. This function should be
    9. '\\ called as soon after the API call
    10. '\\ which might have errored, as this member can be reset
    11. '\\ to zero by subsequent API calls.
    12. '\\ --------------------------------------------------------
    13. '\\ (c) 2001 Merrion Computing Ltd
    14. Public Function LastSystemError() As String
    15.  
    16. Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000
    17. Dim sError As String * 500 '\ Preinitilise a string buffer to put any error message into
    18. Dim lErrNum As Long
    19. Dim lErrMsg As Long
    20.  
    21. lErrNum = Err.LastDllError
    22.  
    23. lErrMsg = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, ByVal 0&, lErrNum, 0, sError, Len(sError), 0)
    24.  
    25. LastSystemError = Trim(sError)
    26.  
    27. End Function

    Hope this helps,
    Duncan
    ----8<---------------------------------------
    NEW - The .NET printer queue monitor component
    ----8<---------------------------------------
    Now with Examples of use

  5. #5

    Thread Starter
    Member
    Join Date
    Nov 2000
    Posts
    51
    Thanks for your reply, Duncan.
    I've tried the following:
    VB Code:
    1. hHook = SetWindowsHookEx(WH_MOUSE, hProc, hDll, idThread)
    2. hHook = SetWindowsHookEx(WH_MOUSE, hProc, hDll, 0&)
    3. 'works both, but sets the hook to vb only, even if idThread is the
    4. 'id of a thread in a different process, like
    5. 'GetWindowThreadProcessId(FindWindow("Shell_TrayWnd", vbNullString), 0&) e.g.
    6.  
    7. hHook = SetWindowsHookEx(WH_MOUSE, hProc, 0&, idThread)
    8. hHook = SetWindowsHookEx(WH_MOUSE, hProc, 0&, 0&)
    9. 'both return the error "Non-locale hook can't be set without module-handle".
    But passing the ModuleHandle of the Hook.dll is reducing the hook to the vb-process! How do I set a GLOBAL hook?

  6. #6
    Frenzied Member MerrionComputin's Avatar
    Join Date
    Apr 2001
    Location
    Dublin, Ireland
    Posts
    1,616
    Only difference I can see is that where you have 0 I have vbNull i.e.:
    VB Code:
    1. hHook = SetWindowsHookEx(WH_MOUSE, hProc, vbNull, idThread)

    HTH,
    Duncan
    ----8<---------------------------------------
    NEW - The .NET printer queue monitor component
    ----8<---------------------------------------
    Now with Examples of use

  7. #7

    Thread Starter
    Member
    Join Date
    Nov 2000
    Posts
    51
    Hey, that works!!! Thanks!
    Didn't know, there's a difference between vbNull and 0&...

    Regards, Quix

  8. #8
    Hyperactive Member
    Join Date
    Jun 2001
    Posts
    297
    i'm trying to learn how to hook..and i'm starting at this code..i'm VERY newb to VC++ but i know vb pretty well...i'm wondering how to make a .def file so i can test out this global hook

  9. #9

    Thread Starter
    Member
    Join Date
    Nov 2000
    Posts
    51
    I'm new to VC++ too. That was my first C-program.
    For the *.def-file just add an ordinary textfile to your project and insert
    Code:
    LIBRARY "hook.dll"
    
    EXPORTS
       InitHook
       MouseProc
    where InitHook and MouseProc are the Procedures you want to export (and use from vb).

    Hope this helps,
    Quix

  10. #10

    Thread Starter
    Member
    Join Date
    Nov 2000
    Posts
    51
    BTW, that stuff with SetWindowText didn't work. To recognize when your hooking-Proc is called just add a Beep. I used this code:

    Code:
    LRESULT __stdcall CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam) { 
    if (nCode == HC_ACTION) 
    { 
    MOUSEHOOKSTRUCT mhs; 
    memcpy(&mhs, (void*)lParam, sizeof(MOUSEHOOKSTRUCT)); 
    Beep(440,50);
    } 
    return CallNextHookEx(hHook, nCode, wParam, lParam); 
    }
    use mhs.hWnd to get the handle of the window calling the MouseProc.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width