Link to home
Start Free TrialLog in
Avatar of kayhustle
kayhustle

asked on

Need help with setting hooks

I need to set a global hook that raises the callback function whenever a window is minimized,maximized or is set focus.  I tried using WH_CBT but this does not seem to work.  Is there another hook type I should use?  Can you please give sample code that works.
Avatar of jkr
jkr
Flag of Germany image

I'd suggest 'WH_GETMESSAGE', e.g.

#define __DLL

#ifndef _DEBUG
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>

#ifdef _DEBUG
#include <crtdbg.h>

#ifdef __DLL
#define __DYNLINK __declspec(dllexport)
#else
#define __DYNLINK __declspec(dllimport)
#endif

#define HOOL_EVENT_NAME "ElmerFudd"

#pragma warning(disable:4786)   // 'identifier truncated to 255 characters'

#pragma data_seg( ".shared")
HHOOK       g_hhk   =   NULL;
#pragma data_seg()

HINSTANCE   g_hThisDll;

LRESULT CALLBACK    HookProc    (   int     nCode,  
                                    WPARAM  wParam,
                                    LPARAM  lParam  
                                );

int APIENTRY    DllMain (   HINSTANCE   hInstance,
                            DWORD       dwReason,
                            LPVOID      lpReserved
                        )
{
    if  (   dwReason    ==  DLL_PROCESS_ATTACH)
        {
            g_hThisDll  =   hInstance;

            return  (   DisableThreadLibraryCalls   (   g_hThisDll));
        }


    return( TRUE);
}

LRESULT CALLBACK HookProc   (   int     nCode,  // hook code
                                WPARAM  wParam, // removal flag
                                LPARAM  lParam  // address of structure with message
                            )
{
    PMSG    pmsg    =   ( PMSG) lParam;

    if  (   0   >   nCode   ||  PM_NOREMOVE ==  wParam)
        {
            return  (   CallNextHookEx  (   g_hhk,
                                            nCode,
                                            wParam,
                                            lParam
                                        )
                    );
        }

    if  (       WM_KEYDOWN  ==  pmsg->message
            ||  WM_KEYUP    ==  pmsg->message  
        )
        {
            /* this one is for us, do whatever is desired */
        }

    return  (   CallNextHookEx  (   g_hhk,
                                    nCode,
                                    wParam,
                                    lParam
                                )
            );
}

LONG __DYNLINK HookInit ( void)
{
    HANDLE  hev;

    if  (   g_hhk)  return  (   ERROR_ALREADY_EXISTS);

    g_hhk   =   SetWindowsHookEx    (   WH_GETMESSAGE,
                                        ( HOOKPROC) HookProc,
                                        g_hThisDll,
                                        0
                                    );
#ifdef _DEBUG
    _ASSERT (   g_hhk);
#endif

    if  (   !(  hev =   CreateEvent (   NULL,  
                                        FALSE,  
                                        FALSE,  
                                        HOOK_EVENT_NAME
                                    )
            )
        )
        {
            if  (   ERROR_ALREADY_EXISTS    ==  GetLastError    ())
                {
                    if  (   !(  hev =   OpenEvent   (   EVENT_ALL_ACCESS,  
                                                        FALSE,  
                                                        HOOK_EVENT_NAME
                                                    )
                            )
                        )
                        {
                            return  (   -1);
                        }
                }
             else  
                {
                    return  (   -2);
                }
        }

    WaitForSingleObject (   hev,    INFINITE);

    Sleep   (   5000);

    return  (   0);
}

LONG __DYNLINK HookTerm ( void)
{
    HANDLE  hev;

    UnhookWindowsHookEx (   g_hhk);

    Sleep   (   5000);

    if  (   !(  hev =   OpenEvent   (   EVENT_ALL_ACCESS,  
                                        FALSE,  
                                        HOOK_EVENT_NAME
                                    )
            )
        )
        {  
            return  (   GetLastError    ());
        }

    PulseEvent  (   hev);

    return  (   0);
}

All you need to do is calling 'HookInit()' to set the hook and 'HookTerm()' to remove it.
Avatar of kayhustle
kayhustle

ASKER

Ok, I'm working in .net, when I set the WH_GETMESSAGE hook for some reason the callback function is never called, just like when I set the WH_CBT hook.  If I set the WH_MOUSE_LL hook, the callback is called maybe a hundred times before a null reference is raised.  This has been an ongoing problem if you can figure this out I will double the points.  If I have two of the same processes running then the WH_MOUSE_LL hook will be called maybe 2000 times before the null reference exception is raised.  If anybody can figure out why this behavior happens and explain it I'll give double points and even paypal you $20 bucks.  If you can just give me an example of how to get it working I'll give at least double the points.  Here is the code I have.  There is another form that I make a reference to this dll with and do HCallback h = new HCallback(); This class is stored in a dll called testcbthookproc.dll:
using System;
using WindowsFunctions;
using System.Text;
using System.Runtime.InteropServices;
namespace testcbthookproc
{
      /// <summary>
      /// Summary description for Class1.
      /// </summary>
      public class HCallback
      {
            public const int WH_CBT = 5;
            public const int WH_MOUSE = 7;      public const int WH_MOUSE_LL = 14;
            public const int WH_GETMESSAGE = 3;
            public const int WH_CALLWNDPROC = 4;
                        
            public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
            [DllImport("kernel32",CharSet=CharSet.Auto,
                   CallingConvention=CallingConvention.StdCall)]
            internal static extern int LoadLibrary(string lpLibFileName);
            
            [DllImport("user32.dll",CharSet=CharSet.Auto,
                   CallingConvention=CallingConvention.StdCall)]
            internal static extern int SetWindowsHookEx(int idHook, HookProc lpfn,
                  IntPtr hInstance, int threadId);
            
            [DllImport("user32.dll",CharSet=CharSet.Auto,
                   CallingConvention=CallingConvention.StdCall)]
            internal static extern int GetWindowText(int hWnd, StringBuilder lpString, int nMaxCount);
            [DllImport("user32.dll",CharSet=CharSet.Auto,
                   CallingConvention=CallingConvention.StdCall)]
            internal static extern int CallNextHookEx(int idHook, int nCode,IntPtr wParam, IntPtr lParam);
            public static int hHook;
            private bool cbt = false;
            public HCallback()
            {
                  int lib = LoadLibrary("testcbthookproc.dll");
                  int mess = WH_GETMESSAGE;
                  if(mess==WH_CBT)
                        cbt=true;
                  HCallback.hHook=SetWindowsHookEx(mess,new HookProc(CBTHookProc2),
                        (IntPtr)lib,0);
            
            }
            public int CBTHookProc2(int nCode, IntPtr wParam, IntPtr lParam)
            {
                  if(nCode>=0)
                  {
                        StringBuilder s = new StringBuilder(1000);      
                        GetWindowText((int)wParam,s,100);
                        if(cbt)
                        {
                              switch((HCBTType)nCode)
                              {
                                    case HCBTType.HCBT_SETFOCUS:
                                          Console.WriteLine(s);
                                          Console.WriteLine("Focus "+((int)wParam).ToString());//+","+((int)wh.LParam).ToString());
                                          break;
                                    case HCBTType.HCBT_CREATEWND:
                                          Console.WriteLine(s);
                                          Console.WriteLine("Created."+((int)wParam).ToString());
                                          break;
                                    case HCBTType.HCBT_MINMAX:
                                          Console.WriteLine(s);
                                          Console.WriteLine("Min max."+((int)wParam).ToString());
                                          break;
                              }
                        }
                  }
                  else
                  {
                        if(nCode==-1)
                              Console.WriteLine("Got -1 code");
                  }
                  return CallNextHookEx(hHook, nCode, wParam, lParam);            
            }
      }
}
oh, ignore the include WindowsFunctions, its just a dll with this enum specified:
public enum HCBTType
      {
            HCBT_MOVESIZE = 0,
            HCBT_MINMAX = 1,
            HCBT_QS = 2,
            HCBT_CREATEWND = 3,
            HCBT_DESTROYWND = 4,
            HCBT_ACTIVATE = 5,
            HCBT_CLICKSKIPPED = 6,
            HCBT_KEYSKIPPED = 7,
            HCBT_SYSCOMMAND = 8,
            HCBT_SETFOCUS = 9,
      }
ASKER CERTIFIED SOLUTION
Avatar of chandru_in
chandru_in

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
https://www.experts-exchange.com/questions/21529436/Mysterious-behavior-with-setting-hooks.html

Go there and leave the same answer so I can leave you double the points for telling me why it wasn't working.
Thanx for that.

I've done it.