title: C++ using SetWindowsHookEx only works with strange vcl code added to it. in BCB2009
body: <p>I have a strange situation using SetWindowsHookEx</p>
  
  <p>I have a bcb 2009 project with a form and a Memo on it.</p>
  
  <p>in the create we load the Dll and attach the function handler's  to both sides.</p>
  
  <p>The idea is that when the key board is hit a message appear in the memo box and when a mouse event happen an other text appears in the memo box.</p>
  
  <p>The strange this is that when I cleaned the code from debug information it stops working. That means the hook got triggered one time and than it was over. 
  In the debug I was using some VCL TStringList to log key stokes data to disk. Playing with that code I finally detected that by adding</p>
  
  <p>[code]</p>
  
  <pre><code>TList* lList = new TList();
  delete lList;
  </code></pre>
  
  <p>To every one of the hook functions (keyboard, mouse) the code is working again.</p>
  
  <p>What is wrong in my code that I have to do this?</p>
  
  <p>This is the first time in 15 years I make a dll. so it can be something real basic in creating a dll or exporting the functions.</p>
  
  <p>Every suggestion is welcome.</p>
  
  <p>regards</p>
  
  <p>JVDN</p>
  
  <p>Some new additional information:</p>
  
  <p>[solved]My target is win XP embedded. my application creates a error that closes the explorer by windows. And the hook is not working global in xp but only local. But it is working on my develop platform win 7 x64 global typing and mousing in notepad result in messages in the application.
  [solution] Modified the WH_KEYBOARD to WH_KEYBOARD_LL and the mouse from WH_MOUSE to WH_MOUSE_LL solves the receiving key and mouse on Windows XP embedded.</p>
  
  <p>Both the dll and the application have no runtime lib or packages.</p>
  
  <p>DLL Code</p>
  
  <p>[code]</p>
  
  <pre><code>//---------------------------------------------------------------------------
  
  #include &lt;vcl.h&gt;
  #include &lt;windows.h&gt;
  #pragma hdrstop
  //---------------------------------------------------------------------------
  //   Important note about DLL memory management when your DLL uses the
  //   static version of the RunTime Library:
  //
  //   If your DLL exports any functions that pass String objects (or structs/
  //   classes containing nested Strings) as parameter or function results,
  //   you will need to add the library MEMMGR.LIB to both the DLL project and
  //   any other projects that use the DLL.  You will also need to use MEMMGR.LIB
  //   if any other projects which use the DLL will be performing new or delete
  //   operations on any non-TObject-derived classes which are exported from the
  //   DLL. Adding MEMMGR.LIB to your project will change the DLL and its calling
  //   EXE's to use the BORLNDMM.DLL as their memory manager.  In these cases,
  //   the file BORLNDMM.DLL should be deployed along with your DLL.
  //
  //   To avoid using BORLNDMM.DLL, pass string information using "char *" or
  //   ShortString parameters.
  //
  //   If your DLL uses the dynamic version of the RTL, you do not need to
  //   explicitly add MEMMGR.LIB as this will be done implicitly for you
  //---------------------------------------------------------------------------
  
  typedef void __stdcall ( *typFn)(WPARAM,LPARAM);
  
  
  static typFn gGUIProcessingKeyboard = NULL;
  
  static HHOOK gGUIProcessingKeyboardHook = NULL;
  
  
  static typFn gGUIProcessingMouse = NULL;;
  
  static HHOOK gGUIProcessingMouseHook = NULL;
  
  
  #pragma argsused
  
  int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
  
  {
  
    return 1;
  
  }
  
  //---------------------------------------------------------------------------
  
  
  
  extern "C"
  
  { __declspec(dllexport) void SetGUIProcessingKeyboard(typFn aHandle);
  
   __declspec(dllexport) void ReleaseGUIProcessingKeyboard(typFn aHandle);
  
   __declspec(dllexport) LRESULT CALLBACK wireKeyboardProc(int code, WPARAM wParam,LPARAM lParam);
  
   __declspec(dllexport) void SetKeyboardHookHandle(HHOOK aHook );
  
  
   __declspec(dllexport) void SetGUIProcessingMouse(typFn aHandle);
  
   __declspec(dllexport) void ReleaseGUIProcessingMouse(typFn aHandle);
  
   __declspec(dllexport) void SetMouseHookHandle(HHOOK aHook );
  
   __declspec(dllexport) LRESULT CALLBACK wireMouseProc(int code, WPARAM wParam,LPARAM lParam);
  
  
  
  
   /**
    * Set the keyboard loop back handle
    */
  
  void SetGUIProcessingKeyboard(typFn aHandle)
  {
    if (aHandle != gGUIProcessingKeyboard)
    {
      gGUIProcessingKeyboard = aHandle;
    }
  }
  
  
   /**
    * Release the keyboard loop back handle
    */
  void ReleaseGUIProcessingKeyboard(typFn aHandle)
  {
    gGUIProcessingKeyboard = NULL;
  }
  
  /**
   * Set the handle used for tapping the Keyboard
   */
  void SetKeyboardHookHandle(HHOOK aHook )
  {
    gGUIProcessingKeyboardHook = aHook;
  }
  
  
   /**
    * Tapping the keyboard from the other applications
    */
  LRESULT CALLBACK wireKeyboardProc(int code, WPARAM wParam,LPARAM lParam)
  {
      TList* lList = new TList();
      delete lList;
      if (code &lt; 0) {
        return CallNextHookEx(gGUIProcessingKeyboardHook, code, wParam, lParam);
      }
      if (NULL != gGUIProcessingKeyboard)
      {
        gGUIProcessingKeyboard( wParam,lParam);
      }
      return CallNextHookEx(gGUIProcessingKeyboardHook, code, wParam, lParam);
  }
  
  
   /**
    * Set the mouse loop back handle
    */
  
  void SetGUIProcessingMouse(typFn aHandle)
  {
    if (aHandle != gGUIProcessingMouse)
    {
      gGUIProcessingMouse = aHandle;
    }
  }
  
  
   /**
    * Release the mouse loop back handle
    */
  
  void ReleaseGUIProcessingMouse(typFn aHandle)
  {
    gGUIProcessingMouse = NULL;
  }
  
  
  /**
   * Set the handle used for tapping the mouse
   */
  
  void SetMouseHookHandle(HHOOK aHook )
  {
    gGUIProcessingMouseHook = aHook;
  }
  
  
   /**
    * Tapping the mouse from the other applications
    */
  
  LRESULT CALLBACK wireMouseProc(int code, WPARAM wParam,LPARAM lParam)
  {
      TList* lList = new TList();
      delete lList;
  //  if (gGUIProcessingMouseHook != NULL)
  //  {
      if (code &lt; 0) {
        return CallNextHookEx(gGUIProcessingMouseHook, code, wParam, lParam);
      }
      if (NULL != gGUIProcessingMouse)
      {
        gGUIProcessingMouse( wParam,lParam);
      }
      return CallNextHookEx(gGUIProcessingMouseHook, code, wParam, lParam);
      //  }
      //  return 0;
  
      }
  
      } // extern C
  </code></pre>
  
  <p>And here is the application.</p>
  
  <p>[code cpp]</p>
  
  <pre><code>//---------------------------------------------------------------------------
  
  #include &lt;vcl.h&gt;
  #pragma hdrstop
  
  #include "MonitoringToolMain.h"
  //---------------------------------------------------------------------------
  #pragma package(smart_init)
  #pragma resource "*.dfm"
  
  typedef void __stdcall ( __closure *typFn)(WPARAM,LPARAM);
  
  TForm1 *Form1;
  HHOOK TForm1::mHook = NULL;
  typedef void __stdcall (*typSetHook)(HHOOK);
  typedef LRESULT CALLBACK (  *typHookFunc)(int,WPARAM,LPARAM);
  static HHOOK gMyGUIProcessingKeyboardHook = NULL;
  static HHOOK gMyGUIProcessingMouseHook = NULL;
  
  
  //---------------------------------------------------------------------------
  __fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
  {
  }
  
  void __stdcall TForm1::MyKeyboardProc(
    WPARAM wParam,
    LPARAM lParam
  )
  {
    if (Form1 != NULL)
    {
      Form1-&gt;Memo1-&gt;Lines-&gt;Add(L"GotA keyboard");
    }
  }
  void __stdcall TForm1::MyMouseProc(
    WPARAM wParam,
    LPARAM lParam
  )
  {
    if (Form1 != NULL)
    {
      Form1-&gt;Memo1-&gt;Lines-&gt;Add(L"Pip pip");
    }
  }
  
  //---------------------------------------------------------------------------
  void __fastcall TForm1::FormCreate(TObject *Sender)
  {
    if (NULL == mHinst)
    {
      mHinst = LoadLibrary("KeyboardMouseHookDLL.dll");
    }
  
    if (mHinst)
    {
      typedef void (*Install)(typFn);
  
      // the keyboard
  
      typSetHook SetHook = (typSetHook) GetProcAddress( mHinst, "_SetKeyboardHookHandle" );
      typHookFunc wireKeyboardProc = (typHookFunc)GetProcAddress(mHinst, "wireKeyboardProc" );
  
      Install install = (Install) GetProcAddress(mHinst, "_SetGUIProcessingKeyboard");
  
      if (install)
      {
         install(&amp;MyKeyboardProc);
      }
  
      if ((NULL != wireKeyboardProc) &amp;&amp;
          (NULL != SetHook) )
      {
        gMyGUIProcessingKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)wireKeyboardProc,mHinst,NULL);
        SetHook(gMyGUIProcessingKeyboardHook);
      }
  
      // The mouse
      typSetHook  SetMouseHook = (typSetHook) GetProcAddress(mHinst, "_SetMouseHookHandle");
      typHookFunc wireMouseProc = (typHookFunc)GetProcAddress(mHinst, "wireMouseProc");
  
      Install installMouse = (Install) GetProcAddress(mHinst, "_SetGUIProcessingMouse");
  
      if (installMouse)
      {
         installMouse(&amp;MyMouseProc);
      }
  
      if ((NULL != wireMouseProc) &amp;&amp;
          (NULL != SetMouseHook) )
      {
        gMyGUIProcessingMouseHook = SetWindowsHookEx(WH_MOUSE,(HOOKPROC)wireMouseProc,mHinst,NULL);
        SetMouseHook(gMyGUIProcessingMouseHook);
      }
    }
  }
  //---------------------------------------------------------------------------
  void __fastcall TForm1::FormDestroy(TObject *Sender)
  {
    if (NULL == mHinst)
    {
      mHinst = LoadLibrary("KeyboardMouseHookDLL.dll");
    }
  
    if (mHinst)
    {
  
      if (NULL != gMyGUIProcessingKeyboardHook )
      {
        UnhookWindowsHookEx(gMyGUIProcessingKeyboardHook);
        gMyGUIProcessingKeyboardHook = NULL;
      }
      typedef void (*Uninstall)(typFn);
  
      Uninstall uninstall = (Uninstall) GetProcAddress(mHinst, "_ReleaseGUIProcessingKeyboard");
  
      if (uninstall)
      {
        uninstall(&amp;MyKeyboardProc);
      }
  
      if (NULL != gMyGUIProcessingMouseHook )
      {
        UnhookWindowsHookEx(gMyGUIProcessingMouseHook);
        gMyGUIProcessingMouseHook = NULL;
      }
  
      Uninstall uninstallMouse = (Uninstall) GetProcAddress(mHinst, "_ReleaseGUIProcessingMouse");
  
      if (uninstallMouse)
      {
        uninstallMouse(&amp;MyMouseProc);
      }
  
      FreeLibrary(mHinst);
      mHinst = NULL;
    }
  }
  //---------------------------------------------------------------------------
  </code></pre>
  
  <p>And the form header</p>
  
  <p>[code]</p>
  
  <pre><code>//---------------------------------------------------------------------------
  
  #ifndef MonitoringToolMainH
  #define MonitoringToolMainH
  //---------------------------------------------------------------------------
  #include &lt;Classes.hpp&gt;
  #include &lt;Controls.hpp&gt;
  #include &lt;StdCtrls.hpp&gt;
  #include &lt;Forms.hpp&gt;
  //---------------------------------------------------------------------------
  class TForm1 : public TForm
  {
  __published:    // IDE-managed Components
    TMemo *Memo1;
    void __fastcall FormCreate(TObject *Sender);
    void __fastcall FormDestroy(TObject *Sender);
  private:    // User declarations
    int __stdcall lKeyBoard();
    void __stdcall MyKeyboardProc( WPARAM wParam, LPARAM lParam );
    void __stdcall MyMouseProc( WPARAM wParam, LPARAM lParam );
    HINSTANCE mHinst;
  static  HHOOK mHook;
  
  public:     // User declarations
    __fastcall TForm1(TComponent* Owner);
  };
  //---------------------------------------------------------------------------
  extern PACKAGE TForm1 *Form1;
  //---------------------------------------------------------------------------
  #endif
  </code></pre>