Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Fun With Hooks 1

Status
Not open for further replies.

yumbelie

Programmer
Dec 31, 2002
96
GB
Hi, got a problem getting my hooking procedure to work and I'd be grateful for some pointers. Basically I want to send a custom message to another window, but currently, the hooking procedure (which is initializing and terminating fine) is not picking up any message(s) from the child window - The code is below:

Code:
'Module

Option Explicit

Public Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long



Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, _
                                                    ByVal nIndex As Long) As Long

Public Declare Function GetCurrentThreadId Lib "kernel32" () As Long


Public Declare Function SetWindowsHookEx Lib "user32" _
       Alias "SetWindowsHookExA" (ByVal idHook As Integer, _
                                  ByVal myProcAddy As Long, _
                                  ByVal WindowInstance As Long, _
                                  ByVal dwThreadId As Long) As Long


Public Declare Function SendMessage Lib "user32" _
                        Alias "SendMessageA" (ByVal hWnd As Long, _
                                              ByVal Message As Long, _
                                              ByVal wParam As Long, _
                                              ByVal lParam As Long) As Long
   
Public Declare Function PostMessage Lib "user32" _
                        Alias "PostMessageA" (ByVal hWnd As Long, _
                                              ByVal Message As Long, _
                                              ByVal wParam As Long, _
                                              ByVal lParam As Long) As Long
   
'Public Declare Function RegisterWindowMessage Lib "user32.dll" Alias "RegisterWindowMessageA" ( _
'     ByVal lpString As String) As Long

Public Const WH_CALLWNDPROCRET = 12
Private Const GWL_HINSTANCE = (-6)
Const WM_MOUSEMOVE As Long = &H200
Public Const WH_CBT = 5
Public Const HWND_BROADCAST = 65535
Public Const WH_GETMESSAGE As Long = 3
Public Const WH_SYSMSGFILTER = 6
Public Const WH_FOREGROUNDIDLE = 11


Public ghookId As Long
Public Const CUSTOMMSG As Long = &H400
Public gCallingHwnd As Long

Public Function MyProc(ByVal uMsg As Long, _
                       ByVal lParam As Long, _
                       ByVal wParam As Long) As Long

    'Debug.Print uMsg & " - " & wParam & "  -  " & lParam
    
    If uMsg = WM_MOUSEMOVE Then
        Debug.Print "MouseMove Detected"
    End If
    
    If uMsg = CUSTOMMSG Then
        Debug.Print "Custom Message Detected"
        Call UnHookMe
    End If
    MyProc = False
End Function


Public Function HookMe(ByVal hWnd As Long) As Boolean

    Dim hInstance As Long
    Dim lThreadID As Long
    
    lThreadID = GetCurrentThreadId()
    hInstance = GetWindowLong(hWnd, GWL_HINSTANCE)
  
    'ghookId = SetWindowsHookEx(WH_CALLWNDPROCRET, AddressOf MyProc, hInstance, lThreadID)
    ghookId = SetWindowsHookEx(WH_GETMESSAGE, AddressOf MyProc, hInstance, lThreadID)
    'Temporary until can figure better way to get Hwnd
    gCallingHwnd = hWnd
    'Call UnHookMe
    HookMe = True
End Function

Public Function UnHookMe() As Boolean
    Dim myReturn As Long
    myReturn = UnhookWindowsHookEx(ghookId)
    'Temporary
    ghookId = 0
    UnHookMe = True
End Function


'Form frmParent
Private Sub cmdOpenChild_Click()

    HookMe (Me.hWnd)
    
    'Show my child
    frmChild.Show 1


End Sub


Private Sub Form_Terminate()

    'Temporary - Unload hook if not already done.
    If ghookId <> 0 Then
        Call UnHookMe
    End If

End Sub


'Form frmChild

Private Sub cmdSendMessage_Click()
    
    Dim myReturn As Boolean

    myReturn = PostMessage(frmParent.hWnd, CUSTOMMSG, 666&, 666&)
    
    'MsgBox myReturn
    
End Sub

Private Sub Form_Unload(Cancel As Integer)
    
    'Dim myReturn As Long

    'myReturn = SendMessage(gCallingHwnd, WM_CUSTOMMSG, 0&, 0&)

End Sub

- If I run the above, even when I move the mouse nothing happens - and frankly - I'm stumped. The lParam and wParam seem to contain stuff, but uMsg is always 0.

Any help greatly appericated - my first forray into Win32APi is meeting some resistance ;)

Thanks

Yum
 
Maybe I doesnt get the other app hwnd rite.
Try using apispy from to see if your hwnd ist the same of the apispy app.
I got a similar problem long ago and that was it.
 
Is the target window owned by the VB application that is doing the hooking? I ask because most of the hook methods that you can invoke through SetWindowHookEx cannot be used globally (i.e on other threads) by VB, because the hook function needs to run in the context of the hooked process and you can't achieve that in VB
 
In this instance, yes, the parent and child are running in the same thread. The code above is just a test to try and get hooking with a custom message working. I finally intend to apply it to an MDI Window where numerous children are spawned, and I need to be able to invoke operations on some child windows by sending messages from others. But currently, the simple example above just fails to work - It *should* technically cause the custom message to be intercepted by the hook, and invoke a debug.print message - but it's just not showing up -If anyone wants to compile it and have a go at solving my problem... ;))

I'm wondering if the hook type is incorrect - any ideas which I should be using? or any help at all :))

Thanks

Yum
 
To be honest, if it is just a simple VB MDI application I'm not quite sure why you need to send custom (API)messages between child windows. Can you not just add public subs/functions to the forms that can be called directly by other forms?

Having said that, let's look at what is going on here...........ah. OK. You need to carefully check out GetMsgProc (your MyProc function) to see what each of the passed parameters actually represents. They *don't* represent what your actual code in that function thinks they are passing...
 
Could you be a little more specific? As I understand it the MyProc function serves to hook the messages, which only accept three parameters - the message id, and l+w param's. I can't really see whats missing?

Thanks
 
Hi, thanks for that - I see what you mean, I've applied the changes - MyProc now uses copymemory to stuff any message into the MSG structure:

Code:
Public Function MyProc(ByVal uMsg As Long, _
                       ByVal wParam As Long, _
                       ByVal lParam As Long) As Long
                       
    Dim myMsg As MSG

    'Copy msg spec'd by lParam into MSG Structure
    
    If lParam <> 0 Then
        CopyMemory myMsg, ByVal lParam, Len(myMsg)
    End If
        

    If myMsg.lParam = 666& Or myMsg.wParam = 666& Then
                       
        Debug.Print "My Message: " & myMsg.message
                       
    End If

    MyProc = CallNextHookEx(-1, uMsg, wParam, lParam)


End Function

but it still doesn't work. frmChild (below) is sending a message to frmParent:

Code:
Private Sub cmdSendMessage_Click()
    
    Dim myReturn As Long
    
    myReturn = PostMessage(frmParent.hwnd, CUSTOMMSG, 666&, 666&) 'Returns Boolean
    
End Sub

I've defined the CUSTOMMSG constant as:

Code:
Public Const CUSTOMMSG As Long = &H400

I've stuck the project on : if you want to have a look.

Thanks for all the help so far - Any new help appericated.

Thanks

yum.
 
Right, got it working now :) Finally. Thanks for all your help. The trick was to fix the MyProc facility as specified above, but also to alter the hook type in SetWindowsHookEx to: WH_GETMESSAGE - It's hooking it's little heart out now ;))

Thanks again!

Yum.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top