toannds
asked on
System-wide hook works well in Win16 but doesn't work in Win32
Hi,
I have a system-wide hook function in DLL (Win16-based). That function sends all WM_CHAR messages to the main window of my .EXE program (Win16-based too). It works well. It sends WM_CHAR whenever I type in any application.
Yesterday, I want it supports taskbar icon notification so I change my project target (both .DLL and .EXE) to Win32 and they didn't work as before. The hook function didn't receive message when my window lost focus. In another word, it seems that hook associates only to one task (my .EXE).
For simple, I change my system-wide hook function to:
//------------------------ ---------- ---------- ---------- ---------- ---------- ----
LRESULT CALLBACK __export HookProc( int nCode, WPARAM Param, LPARAM lParam )
{
if ( nCode >= 0 ){
msg = * ( MSG far * ) lParam;
if( ((MSG far *)lParam)->message == WM_CHAR )
MessageBox( 0, "WM_CHAR", "Receive", MB_OK );
}
return CallNextHookEx( hhook, nCode, wParam, lParam);
}
but I couldn't receive any message box when I type in other application.
Please help me. Thanks.
I have only 30 points and many questions now, please understand me! :-)
I have a system-wide hook function in DLL (Win16-based). That function sends all WM_CHAR messages to the main window of my .EXE program (Win16-based too). It works well. It sends WM_CHAR whenever I type in any application.
Yesterday, I want it supports taskbar icon notification so I change my project target (both .DLL and .EXE) to Win32 and they didn't work as before. The hook function didn't receive message when my window lost focus. In another word, it seems that hook associates only to one task (my .EXE).
For simple, I change my system-wide hook function to:
//------------------------
LRESULT CALLBACK __export HookProc( int nCode, WPARAM Param, LPARAM lParam )
{
if ( nCode >= 0 ){
msg = * ( MSG far * ) lParam;
if( ((MSG far *)lParam)->message == WM_CHAR )
MessageBox( 0, "WM_CHAR", "Receive", MB_OK );
}
return CallNextHookEx( hhook, nCode, wParam, lParam);
}
but I couldn't receive any message box when I type in other application.
Please help me. Thanks.
I have only 30 points and many questions now, please understand me! :-)
ASKER
Edited text of question
Do you use SetWindowsHook ? If it`s true just call SetWindowsHookEx instead.
set DWORD dwThreadID parameter to the 0 to set system wide hook.
set DWORD dwThreadID parameter to the 0 to set system wide hook.
ASKER
I already used
HHOOK SetWindowsHookEx(idHook, hkprc, hinst, htask) in my program with htask = 0.
I didn't tell you another strange:
The Win32.hlp said that we don't need to use MakeProcInstance in Win32 version, we can pass directly function address to hkprc.
But if I do what it said, SetWindowsHookEx return NULL (an error) and of course, I don't receive any message at all. By the way, can you show me which function I can use to get error in this case?
HHOOK SetWindowsHookEx(idHook, hkprc, hinst, htask) in my program with htask = 0.
I didn't tell you another strange:
The Win32.hlp said that we don't need to use MakeProcInstance in Win32 version, we can pass directly function address to hkprc.
But if I do what it said, SetWindowsHookEx return NULL (an error) and of course, I don't receive any message at all. By the way, can you show me which function I can use to get error in this case?
GetLastError
toannds, a systemwide hook in win32 MUST reside in a DLL.
ASKER
That's what I did: my system-wide hook resides in my DLL, it posts message to my main window.
OK, we have progress... :-)
I have answered several hook-related questions in the past. Here are URLs to two of them. Please read the whole discussion (including the comments) and look at the sample code.
https://www.experts-exchange.com/Q.10063288 (5 points)
https://www.experts-exchange.com/Q.10069661 (4 points)
I have answered several hook-related questions in the past. Here are URLs to two of them. Please read the whole discussion (including the comments) and look at the sample code.
https://www.experts-exchange.com/Q.10063288 (5 points)
https://www.experts-exchange.com/Q.10069661 (4 points)
ASKER
My already used SetWindowHooksEx in my DLL.
ASKER
I'm so sorry. I wasn't intend to post previous message. That was a mistake. I'm reading alexo's answers in the past...
ASKER
alexo, thank you for your answers (and I lost 9 points :-) ). Now I know hhook must be the shared data for difference tasks. I use Borland C++ 4.5 so there're some differences from your answers. My DLL project includes 3 files:
sysdata.cpp
syshook.cpp
syshook.def
The sysdata.cpp contains variables in shared data segment.
The syshook.cpp set up system-wide hook and contains hook proc.
//------------------------ ---------- ---------- ---------- --------
// sysdata.cpp
// All variables in this file are in another shared data segment besides the default DLL segment.
//------------------------ ---------- ---------- ---------- --------
#pragma option -zRSHAREDATA // Sets the name of the initialized data segment.
#pragma option -zSSHAREGROUP // Sets the name of the initialized data segment group.
#pragma option -zTSHARECLASS // Sets the name of the initialized data segment class.
#include <windows.h>
HHOOK hhook = 0;
HWND __export hwndHookReport = 0;
UINT __export wm_hookreport = 0;
MSG __export msg = {0};
//------------------------ ---------- ---------- ---------- --------
// syshook.cpp
//------------------------ ---------- ---------- ---------- --------
#include <windows.h>
HINSTANCE hInstance;
// these variables are in the shared segment
extern HHOOK hhook;
extern HWND hwndHookReport;
extern UINT wm_hookreport;
//------------------------ ---------- ---------- ---------- ---------- ---------- ----
LRESULT CALLBACK __export HookProc( int nCode, WPARAM Param, LPARAM lParam )
{
if ( nCode >= 0 ){
if( ((MSG far *)lParam)->message == WM_CHAR )
MessageBox( 0, "WM_CHAR", "Receive", MB_OK );
}
return CallNextHookEx( hhook, nCode, wParam, lParam);
}
//------------------------ ---------- ---------- ---------- ---------- ---------- ----
int far __export InstallSystemHook( HWND hwnd, UINT wm_report, int idHook )
//
// hwnd: The window that receive wm_report every time HookProc get a message
//
{
FARPROC lpFunc;
hwndHookReport = hwnd;
wm_hookreport = wm_report;
lpFunc = MakeProcInstance( (FARPROC) HookProc, hInstance );
hhook = SetWindowsHookEx( idHook, (HOOKPROC) lpFunc, hInstance, 0 );
return (int) hhook;
}
//------------------------ ---------- ---------- ---------- ---------- ---------- ----
int far __export UninstallSystemHook()
{
return UnhookWindowsHookEx( hhook );
}
//------------------------ ---------- ---------- ---------- ---------- ---------- ----
int CALLBACK LibMain( HINSTANCE hinst, WORD wDataSeg, WORD cbHeap, LPSTR lpszCmdLine )
{
hInstance = hinst;
return 1;
}
//------------------------ ---------- ---------- ---------- --------
// syshook.dll
//------------------------ ---------- ---------- ---------- --------
LIBRARY SYSHOOK
DATA MULTIPLE NONSHARED
SEGMENTS SHAREDATA CLASS 'SHARECLASS' SHARED
//------------------------ ---------- ---------- ---------- --------
This .DLL is used only by one .EXE at a time. After sharing hhook and some other variables I couldn't resolve anything. You see: I write the line MessageBox(..) immediately after HookProc recieves WM_CHAR but the message box is showed only when the main window of my .EXE (that uses DLL) yields focus. It's likely not a system-wide hook manner but thread hook although the last parameter of SetWIndowsHookEx is NULL.
Ok, I'll try more research...
sysdata.cpp
syshook.cpp
syshook.def
The sysdata.cpp contains variables in shared data segment.
The syshook.cpp set up system-wide hook and contains hook proc.
//------------------------
// sysdata.cpp
// All variables in this file are in another shared data segment besides the default DLL segment.
//------------------------
#pragma option -zRSHAREDATA // Sets the name of the initialized data segment.
#pragma option -zSSHAREGROUP // Sets the name of the initialized data segment group.
#pragma option -zTSHARECLASS // Sets the name of the initialized data segment class.
#include <windows.h>
HHOOK hhook = 0;
HWND __export hwndHookReport = 0;
UINT __export wm_hookreport = 0;
MSG __export msg = {0};
//------------------------
// syshook.cpp
//------------------------
#include <windows.h>
HINSTANCE hInstance;
// these variables are in the shared segment
extern HHOOK hhook;
extern HWND hwndHookReport;
extern UINT wm_hookreport;
//------------------------
LRESULT CALLBACK __export HookProc( int nCode, WPARAM Param, LPARAM lParam )
{
if ( nCode >= 0 ){
if( ((MSG far *)lParam)->message == WM_CHAR )
MessageBox( 0, "WM_CHAR", "Receive", MB_OK );
}
return CallNextHookEx( hhook, nCode, wParam, lParam);
}
//------------------------
int far __export InstallSystemHook( HWND hwnd, UINT wm_report, int idHook )
//
// hwnd: The window that receive wm_report every time HookProc get a message
//
{
FARPROC lpFunc;
hwndHookReport = hwnd;
wm_hookreport = wm_report;
lpFunc = MakeProcInstance( (FARPROC) HookProc, hInstance );
hhook = SetWindowsHookEx( idHook, (HOOKPROC) lpFunc, hInstance, 0 );
return (int) hhook;
}
//------------------------
int far __export UninstallSystemHook()
{
return UnhookWindowsHookEx( hhook );
}
//------------------------
int CALLBACK LibMain( HINSTANCE hinst, WORD wDataSeg, WORD cbHeap, LPSTR lpszCmdLine )
{
hInstance = hinst;
return 1;
}
//------------------------
// syshook.dll
//------------------------
LIBRARY SYSHOOK
DATA MULTIPLE NONSHARED
SEGMENTS SHAREDATA CLASS 'SHARECLASS' SHARED
//------------------------
This .DLL is used only by one .EXE at a time. After sharing hhook and some other variables I couldn't resolve anything. You see: I write the line MessageBox(..) immediately after HookProc recieves WM_CHAR but the message box is showed only when the main window of my .EXE (that uses DLL) yields focus. It's likely not a system-wide hook manner but thread hook although the last parameter of SetWIndowsHookEx is NULL.
Ok, I'll try more research...
ASKER
Alexo,
Thank you very much. I change to VC++ 5 and work well. However I need to change your code. I couldn't understand why I need to export functions & definition of share data section in .DEF, otherwise (use dllexport at function prototype) my hook function didn't work! Do you have any idea?
I want to give you points, please post your answer instead of comment :-) ...
Thank you very much. I change to VC++ 5 and work well. However I need to change your code. I couldn't understand why I need to export functions & definition of share data section in .DEF, otherwise (use dllexport at function prototype) my hook function didn't work! Do you have any idea?
I want to give you points, please post your answer instead of comment :-) ...
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Alexo, you're right! Now my DLL catch any WM_CHAR.
I want to ask you more :-)
I declare a variable of MSG type in shared section and export it in EXPORTS section of .DEF of my .DLL. Every time when my hook function receives a message it copies message to this shared variable and informs my .EXE by SendMessage(). My .EXE receive message and check the share variable. However my .EXE always receives correct wParam, lParam but not *(MSG far *)lParam.
I want to ask you more :-)
I declare a variable of MSG type in shared section and export it in EXPORTS section of .DEF of my .DLL. Every time when my hook function receives a message it copies message to this shared variable and informs my .EXE by SendMessage(). My .EXE receive message and check the share variable. However my .EXE always receives correct wParam, lParam but not *(MSG far *)lParam.
ASKER
Alexo, you're right! Now my DLL catch any WM_CHAR.
I want to ask you more :-)
I declare a variable of MSG type in shared section and export it in EXPORTS section of .DEF of my .DLL. Every time when my hook function receives a message it copies message to this shared variable and informs my .EXE by SendMessage(). My .EXE receive message and check the share variable. However my .EXE always receives correct wParam, lParam but not *(MSG far *)lParam.
I want to ask you more :-)
I declare a variable of MSG type in shared section and export it in EXPORTS section of .DEF of my .DLL. Every time when my hook function receives a message it copies message to this shared variable and informs my .EXE by SendMessage(). My .EXE receive message and check the share variable. However my .EXE always receives correct wParam, lParam but not *(MSG far *)lParam.
>> my .EXE always receives correct wParam, lParam but not *(MSG far *)lParam.
Huh???
Huh???
ASKER