BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

[Remy] SendMessage() from a DLL to APP

 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (Native API)
View previous topic :: View next topic  
Author Message
Vladimir Stefanovic
Guest





PostPosted: Tue May 03, 2005 9:48 am    Post subject: [Remy] SendMessage() from a DLL to APP Reply with quote



Hi Remy,

I wanted to avoid getting HWND of some APP from my DLL
by FindWindow() because of some problems I reported before.

Then you suggested me to pass the APP HWND to a DLL directly,
and so avoid determining the APP HWND all the time by
FindWindow().

You also suggested me to store the HWND in the shared memory
because that every DLL instance can have a valid HWND, but in my
case the APP can have in fact only *one* instance, so I suppose that
is not necessary.

That concept works *almost* fine for me, but... The funy thing
is that if my APP is in tray - nothing happens, ie. my APP
KeyHook() function that should be triggered by DLL's:

// Send key information to the main window
SendMessage( hAppWnd, WM_KEYHOOK, 0, lParam );

.... simply is not executed. I placed a fake ShowMessage("?"),
but it's not reached if the APP is in tray.

If the app is on screen, it is triggered.

Whay I'm missing? Is there anything I can do to avoid FindWindow()
which indeed works if the APP is in tray?


--- DLL ---

// ...
HWND hAppWnd;
// ...
void __stdcall SetHook( HWND hWnd )
{
ghhookKB = SetWindowsHookEx( WH_KEYBOARD, (HOOKPROC)CheckKey, ghInst,
NULL );
hAppWnd = hWnd;
}
// ...
DWORD __stdcall CheckKey( int nCode, WORD wParam, LONG lParam )
{
if ( ( nCode < 0 ) || ( nCode == HC_NOREMOVE ) )
return CallNextHookEx( ghhookKB, nCode, wParam, lParam );

// Skip if it's a repeat
if ( lParam & 0x40000000 )
return CallNextHookEx( ghhookKB, nCode, wParam, lParam );

// Check if Alt is pressed
if ( !( lParam & ( 1<<29 ) ) )
return CallNextHookEx( ghhookKB, nCode, wParam, lParam );

// Send key information to the main window
SendMessage( hAppWnd, WM_KEYHOOK, 0, lParam );

return CallNextHookEx( ghhookKB, nCode, wParam, lParam );
}
/************************************************************/


--
Best regards,
Vladimir Stefanovic


Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Tue May 03, 2005 6:26 pm    Post subject: Re: [Remy] SendMessage() from a DLL to APP Reply with quote




"Vladimir Stefanovic" <antivari (AT) po (DOT) sbb.co.yu> wrote


Quote:
HWND hAppWnd;

You should always initialize your variables, especially when used globally:

HWND hAppWnd = NULL;;

Quote:
ghhookKB = SetWindowsHookEx( WH_KEYBOARD, (HOOKPROC)CheckKey, ghInst,
NULL)


You did not specify whether the HHOOK was in shared memory or not. It must
be. Otherwise, the hook will only work in your own application and not in
others. When you place your icon in the System Tray and hide your window,
your window won't be focused anymore, and won't be the window receiving
keyboard input. If you do not set up your hook properly to begin with, then
you will not be hooking the keyboard input of other applications properly.

Quote:
// Send key information to the main window
SendMessage( hAppWnd, WM_KEYHOOK, 0, lParam );

Check the HWND for NULL before calling SendMessage():

if( hAppWnd )
SendMessage( hAppWnd, WM_KEYHOOK, 0, lParam );


Gambit



Back to top
Vladimir Stefanovic
Guest





PostPosted: Wed May 04, 2005 11:37 am    Post subject: Re: [Remy] SendMessage() from a DLL to APP Reply with quote



Hi Remy,

Following your instructions I completely redesigned my DLL, and
now I have placed HWND in the shared memory, at least I think I did.

The code now works as I expect, and so far I haven't noticed crashes
of other VCL programs on their termination like it was the case when
I used FindWindow (from a DLL) to get the App HWND.

Anyway, can you please take a short look at the code and see if
I should make any (maybe code security) corrections to it.

Also, I have few questions:

1) Is there any sigifficant difference if I use SendMessage() or
PostMessage() from my DLL, in my case?

2) In the API CreateFileMapping(), I named a last argument "DiHook",
and I never used it after that. Is that OK? Should I use NULL?

3) Is that normal that I haven't any chages (because of shared memory
changes in y DLL) at my App side, except that I passed the HWND
argument to install a DLL?

--- DLL CODE ---

#include <vcl.h>
#include <windows.h>
#pragma hdrstop

#define WM_KEYHOOK (WM_USER + 1002)

HINSTANCE ghInst;

typedef struct _HookInfo
{
HHOOK ghhookKB;
HWND hAppWnd;

} HOOKINFO, *PHOOKINFO;

HANDLE hFileMapping = NULL;
PHOOKINFO pHookInfo = NULL;

#pragma argsused

//---------------------------------------------------------------------------
extern "C" __declspec(dllexport) __stdcall void SetHook(HWND);
extern "C" __declspec(dllexport) __stdcall void RemoveHook(void);
extern "C" __declspec(dllexport) __stdcall DWORD CheckKey(int, WORD,LONG);
//---------------------------------------------------------------------------

int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void
*lpReserved)
{
ghInst = hinst;

switch ( reason )
{
case DLL_PROCESS_ATTACH:
hFileMapping = CreateFileMapping( INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
sizeof(HOOKINFO),
"DiHook" );
if ( hFileMapping )
pHookInfo = (PHOOKINFO)MapViewOfFile( hFileMapping,
FILE_MAP_WRITE,
0,
0,
0 );
break;

case DLL_PROCESS_DETACH:
UnmapViewOfFile( pHookInfo );
pHookInfo = NULL;
CloseHandle( hFileMapping );
hFileMapping = NULL;
break;

}

return ( 1 );
}

void __stdcall SetHook( HWND hWnd )
{
if ( pHookInfo )
{
if( pHookInfo->ghhookKB == NULL )
pHookInfo->ghhookKB = SetWindowsHookEx( WH_KEYBOARD,
(HOOKPROC)CheckKey, ghInst, NULL );
pHookInfo->hAppWnd = hWnd;
}
}

void __stdcall RemoveHook( void )
{
if ( pHookInfo )
{
if ( pHookInfo->ghhookKB )
{
UnhookWindowsHookEx( pHookInfo->ghhookKB );
pHookInfo->ghhookKB = NULL;
}
}

}

DWORD __stdcall CheckKey( int nCode, WORD wParam, LONG lParam )
{
if ( ( nCode < 0 ) || ( nCode == HC_NOREMOVE ) )
return CallNextHookEx( pHookInfo->ghhookKB, nCode, wParam, lParam );

// Skip if it's a repeat
if ( lParam & 0x40000000 )
return CallNextHookEx( pHookInfo->ghhookKB, nCode, wParam, lParam );

// Check if Alt is pressed
if ( !( lParam & ( 1<<29 ) ) )
return CallNextHookEx( pHookInfo->ghhookKB, nCode, wParam, lParam );

// Send key information to the main window
if ( pHookInfo && pHookInfo->hAppWnd )
PostMessage( pHookInfo->hAppWnd, WM_KEYHOOK, 0, lParam );

return CallNextHookEx( pHookInfo->ghhookKB, nCode, wParam, lParam );
}






--
Best regards,
Vladimir Stefanovic
"Remy Lebeau (TeamB)" <no.spam (AT) no (DOT) spam.com> wrote

Quote:

"Vladimir Stefanovic" <antivari (AT) po (DOT) sbb.co.yu> wrote in message
news:427748eb (AT) newsgroups (DOT) borland.com...

HWND hAppWnd;

You should always initialize your variables, especially when used
globally:

HWND hAppWnd = NULL;;

ghhookKB = SetWindowsHookEx( WH_KEYBOARD, (HOOKPROC)CheckKey, ghInst,
NULL)

You did not specify whether the HHOOK was in shared memory or not. It
must
be. Otherwise, the hook will only work in your own application and not in
others. When you place your icon in the System Tray and hide your window,
your window won't be focused anymore, and won't be the window receiving
keyboard input. If you do not set up your hook properly to begin with,
then
you will not be hooking the keyboard input of other applications properly.

// Send key information to the main window
SendMessage( hAppWnd, WM_KEYHOOK, 0, lParam );

Check the HWND for NULL before calling SendMessage():

if( hAppWnd )
SendMessage( hAppWnd, WM_KEYHOOK, 0, lParam );


Gambit





Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Wed May 04, 2005 6:26 pm    Post subject: Re: [Remy] SendMessage() from a DLL to APP Reply with quote


"Vladimir Stefanovic" <antivari (AT) po (DOT) sbb.co.yu> wrote


Quote:
Anyway, can you please take a short look at the code and see if
I should make any (maybe code security) corrections to it.

1) Is there any sigifficant difference if I use SendMessage() or
PostMessage() from my DLL, in my case?

That entirely depends on your actual needs. SendMessage() waits for the
message to be processed. PostMessage() does not.

Quote:
2) In the API CreateFileMapping(), I named a last argument
"DiHook", and I never used it after that. Is that OK? Should I use
NULL?

No, do not use NULL, or else the memory won't be shared at all. The name is
what makes it sharable to begin with.

Quote:
3) Is that normal that I haven't any chages (because of shared memory
changes in y DLL) at my App side, except that I passed the HWND
argument to install a DLL?


Quote:
extern "C" __declspec(dllexport) __stdcall void SetHook(HWND);
extern "C" __declspec(dllexport) __stdcall void RemoveHook(void);

I would recommend adding return values to those functions so that the
application can know whether or not the hooking/unhooking actuall succeeds.

Quote:
if ( hFileMapping )
pHookInfo = (PHOOKINFO)MapViewOfFile( hFileMapping,
FILE_MAP_WRITE,
0,
0,
0 );

If either CreateFileMapping() or MapViewOfFile() fail, I prefer to release
the file mapping and make DllEntryPoint() return FALSE. That way, the
application knows that the DLL was unable to initialize itself, and thus the
hooks won't work properly.

Quote:
UnmapViewOfFile( pHookInfo );
pHookInfo = NULL;
CloseHandle( hFileMapping );
hFileMapping = NULL;
break;

Make sure to check for NULL pointers before calling the functions:

if( pHookInfo )
UnmapViewOfFile( pHookInfo );
if( hFileMapping )
CloseHandle( hFileMapping );

Quote:
DWORD __stdcall CheckKey( int nCode, WORD wParam, LONG lParam )

You can simplify that code to the following:

DWORD __stdcall CheckKey( int nCode, WORD wParam, LONG lParam )
{
if( pHookInfo )
{
if( ((nCode >= 0) && (nCode != HC_NOREMOVE))
&& ((lParam & 0x40000000) == 0) // Skip if it's a repeat
&& (lParam & 0x20000000) ) // Check if Alt is pressed
{
// Send key information to the main window
if( pHookInfo->hAppWnd )
PostMessage(pHookInfo->hAppWnd, WM_KEYHOOK, 0, lParam);
}
return CallNextHookEx(pHookInfo->ghhookKB, nCode, wParam,
lParam);
}
return 0;
}


Gambit



Back to top
Vladimir Stefanovic
Guest





PostPosted: Wed May 04, 2005 6:59 pm    Post subject: Re: [Remy] SendMessage() from a DLL to APP Reply with quote

Thanks,

I'll implement all that tomorrow...


--
Best regards,
Vladimir Stefanovic
"Remy Lebeau (TeamB)" <no.spam (AT) no (DOT) spam.com> wrote

Quote:

"Vladimir Stefanovic" <antivari (AT) po (DOT) sbb.co.yu> wrote in message
news:4278b3f0 (AT) newsgroups (DOT) borland.com...

Anyway, can you please take a short look at the code and see if
I should make any (maybe code security) corrections to it.

1) Is there any sigifficant difference if I use SendMessage() or
PostMessage() from my DLL, in my case?

That entirely depends on your actual needs. SendMessage() waits for the
message to be processed. PostMessage() does not.

2) In the API CreateFileMapping(), I named a last argument
"DiHook", and I never used it after that. Is that OK? Should I use
NULL?

No, do not use NULL, or else the memory won't be shared at all. The name
is
what makes it sharable to begin with.

3) Is that normal that I haven't any chages (because of shared memory
changes in y DLL) at my App side, except that I passed the HWND
argument to install a DLL?


extern "C" __declspec(dllexport) __stdcall void SetHook(HWND);
extern "C" __declspec(dllexport) __stdcall void RemoveHook(void);

I would recommend adding return values to those functions so that the
application can know whether or not the hooking/unhooking actuall
succeeds.

if ( hFileMapping )
pHookInfo = (PHOOKINFO)MapViewOfFile( hFileMapping,
FILE_MAP_WRITE,
0,
0,
0 );

If either CreateFileMapping() or MapViewOfFile() fail, I prefer to release
the file mapping and make DllEntryPoint() return FALSE. That way, the
application knows that the DLL was unable to initialize itself, and thus
the
hooks won't work properly.

UnmapViewOfFile( pHookInfo );
pHookInfo = NULL;
CloseHandle( hFileMapping );
hFileMapping = NULL;
break;

Make sure to check for NULL pointers before calling the functions:

if( pHookInfo )
UnmapViewOfFile( pHookInfo );
if( hFileMapping )
CloseHandle( hFileMapping );

DWORD __stdcall CheckKey( int nCode, WORD wParam, LONG lParam )

You can simplify that code to the following:

DWORD __stdcall CheckKey( int nCode, WORD wParam, LONG lParam )
{
if( pHookInfo )
{
if( ((nCode >= 0) && (nCode != HC_NOREMOVE))
&& ((lParam & 0x40000000) == 0) // Skip if it's a repeat
&& (lParam & 0x20000000) ) // Check if Alt is pressed
{
// Send key information to the main window
if( pHookInfo->hAppWnd )
PostMessage(pHookInfo->hAppWnd, WM_KEYHOOK, 0, lParam);
}
return CallNextHookEx(pHookInfo->ghhookKB, nCode, wParam,
lParam);
}
return 0;
}


Gambit





Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (Native API) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.