KeyDown ignored by several important controls

  • Thread starter Jared Miniman [MVP]
  • Start date
J

Jared Miniman [MVP]

I have a recursive function that snakes throughout a form and all of it's
sub-controls to set a KeyDown event (to listen for the 'ESC' key). However,
several important controls, like the combobox and even buttons do not seem
to properly listen for keydown events. Is this by design? If I want to
enable a given hardware key throughout a form, is there a better way to
achieve this?

--
_________________________________
Jared Miniman, MS-MVP Mobile Devices
Mobile Computer Consultant

ActiveSync problems?
http://www.microsoft.com/mobile/pocketpc/support/help/activesync.asp
Connection Mngr Q's?
http://www.microsoft.com/mobile/pocketpc/tutorials/connectionmanager
 
P

PeterB

Combobox and button do not support keypressing events in the current version
of compact framework. It was however supported in Service Pack 2, but that
SP was taken back by MS due to some errors, and we are all eagerly awaiting
it's return...

/ P
 
P

Paul G. Tobey [eMVP]

You could capture all keyboard input with a C-based hook routine and pass it
to a message window subclass in your .NET CF application. That gives you a
single point at which the ESC key will arrive. Maybe that's actually better
than setting a KeyDown event all over the place, too.

Paul T.
 
P

Paul G. Tobey [eMVP]

Here's my code to actually trap/untrap all keys. This code goes in the C
DLL:

static
HHOOK localHook = NULL;
static
HWND messageWindow = NULL;
static
UINT message = 0;

FOCUSHELPER_API int HookTabs( HWND msgWindow )
{
OutputDebugString( _T( "HookTabs: enter\r\n" ) );

// Save the messagewindow for use in the hook routine.
messageWindow = msgWindow;

// Set up a hook and send all of the keys to the indicated
// MessageWindow subclass.
// This works, but isn't really what we want. Ideally, we'd like
// to associate the key with the target window. Maybe we can figure
// out how to decide if we should notify the message window, though.
localHook = SetWindowsHookEx( WH_KEYBOARD_LL,
&TabHook,
(HINSTANCE)hMod,
0 /* Associate with current thread */ );

if ( localHook == NULL )
{
TCHAR syserrs[ 512 ];
DWORD err = GetLastError();

FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, err,
0, syserrs, sizeof( syserrs ) / sizeof( syserrs[ 0 ] ), 0 );

OutputDebugString( syserrs );

return err;
}

// Register the window message sent to the target message window when
// a tab is detected.
message = RegisterWindowMessage( _T( "KeyMessage" ) );

return 0;
}

FOCUSHELPER_API int UnhookTabs( HWND msgWindow )
{
OutputDebugString( _T( "UnhookTabs: enter\r\n" ) );

// Stop capturing the Tab keys (maybe the application is no longer
// in front or something).
UnhookWindowsHookEx( localHook );
localHook = NULL;

return 0;
}

Note that, in your case, you might want to unhook when your application is
no longer in front, etc. Or, you can set up your message window to do that
right thing in that case and just keep the hook installed for the life of
the application. You might also note that I'm registering my own message to
send.

Here's the actual hook routine:

LRESULT CALLBACK TabHook( int code, WPARAM wParam, LPARAM lParam )
{
if ( code < 0 )
{
DEBUGMSG( 1, (TEXT( "TabHook (%x): got a code less than zero\r\n" ),
GetCurrentThreadId() ) );

// Send the message to the next hook and return its return value.
return CallNextHookEx( localHook, code, wParam, lParam );
}

if ( code != HC_ACTION )
{
DEBUGMSG( 1, (TEXT( "TabHook (%x): got a code other than HC_ACTION\r\n" ),
GetCurrentThreadId() ) );
}

// Process the message ourselves.
KBDLLHOOKSTRUCT *msg = (KBDLLHOOKSTRUCT*)lParam;

// Check for tab and shift-tab.
if ( ( wParam == WM_KEYDOWN ) && ( msg->vkCode == VK_TAB ) )
{
LPARAM lp = 0;

if ( GetKeyState( VK_SHIFT ) )
lp |= SHIFT_DOWN;
if ( GetKeyState( VK_CONTROL ) )
lp |= CONTROL_DOWN;
if ( GetKeyState( VK_MENU ) )
lp |= ALT_DOWN;

// Trying to do this as fast as possible so that the hook doesn't
// violate any timing specifications. SendMessage might take too
// long, for example.
PostMessage( messageWindow, message, msg->vkCode, lp );
}
else if ( ( wParam == WM_KEYDOWN ) &&
( ( msg->vkCode == VK_UP ) || ( msg->vkCode == VK_DOWN ) || ( msg->vkCode
== VK_LEFT ) || ( msg->vkCode == VK_RIGHT ) ) )
{
LPARAM lp = 0;

if ( GetKeyState( VK_SHIFT ) )
lp |= SHIFT_DOWN;
if ( GetKeyState( VK_CONTROL ) )
lp |= CONTROL_DOWN;
if ( GetKeyState( VK_MENU ) )
lp |= ALT_DOWN;

// Trying to do this as fast as possible so that the hook doesn't
// violate any timing specifications. SendMessage might take too
// long, for example.
PostMessage( messageWindow, message, msg->vkCode, lp );
}
else if ( ( wParam == WM_SYSKEYDOWN ) &&
( msg->vkCode >= 'A' ) && ( msg->vkCode <= 'Z' ) )
{
// This might be an accelerator. Send it on.
LPARAM lp = 0;

if ( GetKeyState( VK_SHIFT ) )
lp |= SHIFT_DOWN;
if ( GetKeyState( VK_CONTROL ) )
lp |= CONTROL_DOWN;
if ( GetKeyState( VK_MENU ) )
lp |= ALT_DOWN;

// Trying to do this as fast as possible so that the hook doesn't
// violate any timing specifications. SendMessage might take too
// long, for example.
PostMessage( messageWindow, message, msg->vkCode, lp );
}

return CallNextHookEx( localHook, code, wParam, lParam );
}

Note that I'm only forwarding some keys and you may want to do that, also,
since the C code can handle those messages pretty quickly and the managed
code might be slower; you can decide.

Here's the message window code in C#:

public class KeysMessageWindow :
Microsoft.WindowsCE.Forms.MessageWindow
{
protected int message;

public KeysMessageWindow( )
{
// Register the window message which will be sent
// when the key is pressed. Note
// that this string must match the string used in
// the helper DLL.
message = RegisterWindowMessage( "KeyMessage" );
}

protected override void WndProc ( ref Microsoft.WindowsCE.Forms.Message
m )
// override
{
// Handle arrival of registered message.
if ( m.Msg == message )
{
// ???? do whatever you want to do with the message here.
}
}

/// <summary>
/// This external function found in coredll is used to
/// register a named message used to communicate between
/// the helper DLL and this MessageWindow.
/// </summary>
[DllImport("coredll.dll")]
protected static extern int RegisterWindowMessage( string lpString );
}
#endif

That's about it...

Paul T.
 
E

Elmer Miller

Could this code be modified to capture mousedown events instead?
I have an app that needs to respond to mousedown events on a treeview and
the treeview doesn't support mousedown.
I've never worked with C before. Am I correct in assuming you are refering
to Embedded Visual C++ to create the native DLL?


Paul G. Tobey said:
Here's my code to actually trap/untrap all keys. This code goes in the C
DLL:

static
HHOOK localHook = NULL;
static
HWND messageWindow = NULL;
static
UINT message = 0;

FOCUSHELPER_API int HookTabs( HWND msgWindow )
{
OutputDebugString( _T( "HookTabs: enter\r\n" ) );

// Save the messagewindow for use in the hook routine.
messageWindow = msgWindow;

// Set up a hook and send all of the keys to the indicated
// MessageWindow subclass.
// This works, but isn't really what we want. Ideally, we'd like
// to associate the key with the target window. Maybe we can figure
// out how to decide if we should notify the message window, though.
localHook = SetWindowsHookEx( WH_KEYBOARD_LL,
&TabHook,
(HINSTANCE)hMod,
0 /* Associate with current thread */ );

if ( localHook == NULL )
{
TCHAR syserrs[ 512 ];
DWORD err = GetLastError();

FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, err,
0, syserrs, sizeof( syserrs ) / sizeof( syserrs[ 0 ] ), 0 );

OutputDebugString( syserrs );

return err;
}

// Register the window message sent to the target message window when
// a tab is detected.
message = RegisterWindowMessage( _T( "KeyMessage" ) );

return 0;
}

FOCUSHELPER_API int UnhookTabs( HWND msgWindow )
{
OutputDebugString( _T( "UnhookTabs: enter\r\n" ) );

// Stop capturing the Tab keys (maybe the application is no longer
// in front or something).
UnhookWindowsHookEx( localHook );
localHook = NULL;

return 0;
}

Note that, in your case, you might want to unhook when your application is
no longer in front, etc. Or, you can set up your message window to do that
right thing in that case and just keep the hook installed for the life of
the application. You might also note that I'm registering my own message to
send.

Here's the actual hook routine:

LRESULT CALLBACK TabHook( int code, WPARAM wParam, LPARAM lParam )
{
if ( code < 0 )
{
DEBUGMSG( 1, (TEXT( "TabHook (%x): got a code less than zero\r\n" ),
GetCurrentThreadId() ) );

// Send the message to the next hook and return its return value.
return CallNextHookEx( localHook, code, wParam, lParam );
}

if ( code != HC_ACTION )
{
DEBUGMSG( 1, (TEXT( "TabHook (%x): got a code other than HC_ACTION\r\n" ),
GetCurrentThreadId() ) );
}

// Process the message ourselves.
KBDLLHOOKSTRUCT *msg = (KBDLLHOOKSTRUCT*)lParam;

// Check for tab and shift-tab.
if ( ( wParam == WM_KEYDOWN ) && ( msg->vkCode == VK_TAB ) )
{
LPARAM lp = 0;

if ( GetKeyState( VK_SHIFT ) )
lp |= SHIFT_DOWN;
if ( GetKeyState( VK_CONTROL ) )
lp |= CONTROL_DOWN;
if ( GetKeyState( VK_MENU ) )
lp |= ALT_DOWN;

// Trying to do this as fast as possible so that the hook doesn't
// violate any timing specifications. SendMessage might take too
// long, for example.
PostMessage( messageWindow, message, msg->vkCode, lp );
}
else if ( ( wParam == WM_KEYDOWN ) &&
( ( msg->vkCode == VK_UP ) || ( msg->vkCode == VK_DOWN ) || ( msg->vkCode
== VK_LEFT ) || ( msg->vkCode == VK_RIGHT ) ) )
{
LPARAM lp = 0;

if ( GetKeyState( VK_SHIFT ) )
lp |= SHIFT_DOWN;
if ( GetKeyState( VK_CONTROL ) )
lp |= CONTROL_DOWN;
if ( GetKeyState( VK_MENU ) )
lp |= ALT_DOWN;

// Trying to do this as fast as possible so that the hook doesn't
// violate any timing specifications. SendMessage might take too
// long, for example.
PostMessage( messageWindow, message, msg->vkCode, lp );
}
else if ( ( wParam == WM_SYSKEYDOWN ) &&
( msg->vkCode >= 'A' ) && ( msg->vkCode <= 'Z' ) )
{
// This might be an accelerator. Send it on.
LPARAM lp = 0;

if ( GetKeyState( VK_SHIFT ) )
lp |= SHIFT_DOWN;
if ( GetKeyState( VK_CONTROL ) )
lp |= CONTROL_DOWN;
if ( GetKeyState( VK_MENU ) )
lp |= ALT_DOWN;

// Trying to do this as fast as possible so that the hook doesn't
// violate any timing specifications. SendMessage might take too
// long, for example.
PostMessage( messageWindow, message, msg->vkCode, lp );
}

return CallNextHookEx( localHook, code, wParam, lParam );
}

Note that I'm only forwarding some keys and you may want to do that, also,
since the C code can handle those messages pretty quickly and the managed
code might be slower; you can decide.

Here's the message window code in C#:

public class KeysMessageWindow :
Microsoft.WindowsCE.Forms.MessageWindow
{
protected int message;

public KeysMessageWindow( )
{
// Register the window message which will be sent
// when the key is pressed. Note
// that this string must match the string used in
// the helper DLL.
message = RegisterWindowMessage( "KeyMessage" );
}

protected override void WndProc ( ref Microsoft.WindowsCE.Forms.Message
m )
// override
{
// Handle arrival of registered message.
if ( m.Msg == message )
{
// ???? do whatever you want to do with the message here.
}
}

/// <summary>
/// This external function found in coredll is used to
/// register a named message used to communicate between
/// the helper DLL and this MessageWindow.
/// </summary>
[DllImport("coredll.dll")]
protected static extern int RegisterWindowMessage( string lpString );
}
#endif

That's about it...

Paul T.


Jared Miniman said:
Can you possibly point me to an example that does something vaguely similar
to this? :)

--
_________________________________
Jared Miniman, MS-MVP Mobile Devices
Mobile Computer Consultant

ActiveSync problems?
http://www.microsoft.com/mobile/pocketpc/support/help/activesync.asp
Connection Mngr Q's?
http://www.microsoft.com/mobile/pocketpc/tutorials/connectionmanager

pass you not
seem
want
 
P

Paul G. Tobey [eMVP]

The mouse events are not sent to any hook routines in Windows CE that I can
find, no. You may, depending on whether the tree view is actually using the
underlying Windows API control, be able to subclass the control and do
something with that to send messages to your MessageWindow subclass. Yes,
you would use eVC++ to create the DLL.

You're going to have to learn C, I'm afraid. There are just too many things
that .NET CF can't do right now to live without the ability to understand
the Win32 API and be able to call it.

Paul T.

Elmer Miller said:
Could this code be modified to capture mousedown events instead?
I have an app that needs to respond to mousedown events on a treeview and
the treeview doesn't support mousedown.
I've never worked with C before. Am I correct in assuming you are refering
to Embedded Visual C++ to create the native DLL?


Paul G. Tobey said:
Here's my code to actually trap/untrap all keys. This code goes in the C
DLL:

static
HHOOK localHook = NULL;
static
HWND messageWindow = NULL;
static
UINT message = 0;

FOCUSHELPER_API int HookTabs( HWND msgWindow )
{
OutputDebugString( _T( "HookTabs: enter\r\n" ) );

// Save the messagewindow for use in the hook routine.
messageWindow = msgWindow;

// Set up a hook and send all of the keys to the indicated
// MessageWindow subclass.
// This works, but isn't really what we want. Ideally, we'd like
// to associate the key with the target window. Maybe we can figure
// out how to decide if we should notify the message window, though.
localHook = SetWindowsHookEx( WH_KEYBOARD_LL,
&TabHook,
(HINSTANCE)hMod,
0 /* Associate with current thread */ );

if ( localHook == NULL )
{
TCHAR syserrs[ 512 ];
DWORD err = GetLastError();

FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, err,
0, syserrs, sizeof( syserrs ) / sizeof( syserrs[ 0 ] ), 0 );

OutputDebugString( syserrs );

return err;
}

// Register the window message sent to the target message window when
// a tab is detected.
message = RegisterWindowMessage( _T( "KeyMessage" ) );

return 0;
}

FOCUSHELPER_API int UnhookTabs( HWND msgWindow )
{
OutputDebugString( _T( "UnhookTabs: enter\r\n" ) );

// Stop capturing the Tab keys (maybe the application is no longer
// in front or something).
UnhookWindowsHookEx( localHook );
localHook = NULL;

return 0;
}

Note that, in your case, you might want to unhook when your application is
no longer in front, etc. Or, you can set up your message window to do that
right thing in that case and just keep the hook installed for the life of
the application. You might also note that I'm registering my own
message
to
send.

Here's the actual hook routine:

LRESULT CALLBACK TabHook( int code, WPARAM wParam, LPARAM lParam )
{
if ( code < 0 )
{
DEBUGMSG( 1, (TEXT( "TabHook (%x): got a code less than zero\r\n" ),
GetCurrentThreadId() ) );

// Send the message to the next hook and return its return value.
return CallNextHookEx( localHook, code, wParam, lParam );
}

if ( code != HC_ACTION )
{
DEBUGMSG( 1, (TEXT( "TabHook (%x): got a code other than HC_ACTION\r\n" ),
GetCurrentThreadId() ) );
}

// Process the message ourselves.
KBDLLHOOKSTRUCT *msg = (KBDLLHOOKSTRUCT*)lParam;

// Check for tab and shift-tab.
if ( ( wParam == WM_KEYDOWN ) && ( msg->vkCode == VK_TAB ) )
{
LPARAM lp = 0;

if ( GetKeyState( VK_SHIFT ) )
lp |= SHIFT_DOWN;
if ( GetKeyState( VK_CONTROL ) )
lp |= CONTROL_DOWN;
if ( GetKeyState( VK_MENU ) )
lp |= ALT_DOWN;

// Trying to do this as fast as possible so that the hook doesn't
// violate any timing specifications. SendMessage might take too
// long, for example.
PostMessage( messageWindow, message, msg->vkCode, lp );
}
else if ( ( wParam == WM_KEYDOWN ) &&
( ( msg->vkCode == VK_UP ) || ( msg->vkCode == VK_DOWN ) || ( msg->vkCode
== VK_LEFT ) || ( msg->vkCode == VK_RIGHT ) ) )
{
LPARAM lp = 0;

if ( GetKeyState( VK_SHIFT ) )
lp |= SHIFT_DOWN;
if ( GetKeyState( VK_CONTROL ) )
lp |= CONTROL_DOWN;
if ( GetKeyState( VK_MENU ) )
lp |= ALT_DOWN;

// Trying to do this as fast as possible so that the hook doesn't
// violate any timing specifications. SendMessage might take too
// long, for example.
PostMessage( messageWindow, message, msg->vkCode, lp );
}
else if ( ( wParam == WM_SYSKEYDOWN ) &&
( msg->vkCode >= 'A' ) && ( msg->vkCode <= 'Z' ) )
{
// This might be an accelerator. Send it on.
LPARAM lp = 0;

if ( GetKeyState( VK_SHIFT ) )
lp |= SHIFT_DOWN;
if ( GetKeyState( VK_CONTROL ) )
lp |= CONTROL_DOWN;
if ( GetKeyState( VK_MENU ) )
lp |= ALT_DOWN;

// Trying to do this as fast as possible so that the hook doesn't
// violate any timing specifications. SendMessage might take too
// long, for example.
PostMessage( messageWindow, message, msg->vkCode, lp );
}

return CallNextHookEx( localHook, code, wParam, lParam );
}

Note that I'm only forwarding some keys and you may want to do that, also,
since the C code can handle those messages pretty quickly and the managed
code might be slower; you can decide.

Here's the message window code in C#:

public class KeysMessageWindow :
Microsoft.WindowsCE.Forms.MessageWindow
{
protected int message;

public KeysMessageWindow( )
{
// Register the window message which will be sent
// when the key is pressed. Note
// that this string must match the string used in
// the helper DLL.
message = RegisterWindowMessage( "KeyMessage" );
}

protected override void WndProc ( ref Microsoft.WindowsCE.Forms.Message
m )
// override
{
// Handle arrival of registered message.
if ( m.Msg == message )
{
// ???? do whatever you want to do with the message here.
}
}

/// <summary>
/// This external function found in coredll is used to
/// register a named message used to communicate between
/// the helper DLL and this MessageWindow.
/// </summary>
[DllImport("coredll.dll")]
protected static extern int RegisterWindowMessage( string lpString );
}
#endif

That's about it...

Paul T.


Jared Miniman said:
Can you possibly point me to an example that does something vaguely similar
to this? :)

--
_________________________________
Jared Miniman, MS-MVP Mobile Devices
Mobile Computer Consultant

ActiveSync problems?
http://www.microsoft.com/mobile/pocketpc/support/help/activesync.asp
Connection Mngr Q's?
http://www.microsoft.com/mobile/pocketpc/tutorials/connectionmanager

You could capture all keyboard input with a C-based hook routine and pass
it
to a message window subclass in your .NET CF application. That
gives
you
a
single point at which the ESC key will arrive. Maybe that's actually
better
than setting a KeyDown event all over the place, too.

Paul T.

I have a recursive function that snakes throughout a form and all of
it's
sub-controls to set a KeyDown event (to listen for the 'ESC' key).
However,
several important controls, like the combobox and even buttons do not
seem
to properly listen for keydown events. Is this by design? If I
want
to
enable a given hardware key throughout a form, is there a better
way
to
achieve this?

--
_________________________________
Jared Miniman, MS-MVP Mobile Devices
Mobile Computer Consultant

ActiveSync problems?
http://www.microsoft.com/mobile/pocketpc/support/help/activesync.asp
Connection Mngr Q's?
http://www.microsoft.com/mobile/pocketpc/tutorials/connectionmanager
 
E

Elmer Miller

I found an excellent article by Alex Feinman on subclassing using callbacks.
The code looks excellent, but so far I haven't been able to get it to work
form WM_LBUTTONDOWN. Maybe someone else will have better luck adapting this
code than me. Any tips would be appreciated. Thanks.
http://www.alexfeinman.com/Callbacks/Callbacks.htm

Paul G. Tobey said:
The mouse events are not sent to any hook routines in Windows CE that I can
find, no. You may, depending on whether the tree view is actually using the
underlying Windows API control, be able to subclass the control and do
something with that to send messages to your MessageWindow subclass. Yes,
you would use eVC++ to create the DLL.

You're going to have to learn C, I'm afraid. There are just too many things
that .NET CF can't do right now to live without the ability to understand
the Win32 API and be able to call it.

Paul T.

Elmer Miller said:
Could this code be modified to capture mousedown events instead?
I have an app that needs to respond to mousedown events on a treeview and
the treeview doesn't support mousedown.
I've never worked with C before. Am I correct in assuming you are refering
to Embedded Visual C++ to create the native DLL?
the
C
DLL:

static
HHOOK localHook = NULL;
static
HWND messageWindow = NULL;
static
UINT message = 0;

FOCUSHELPER_API int HookTabs( HWND msgWindow )
{
OutputDebugString( _T( "HookTabs: enter\r\n" ) );

// Save the messagewindow for use in the hook routine.
messageWindow = msgWindow;

// Set up a hook and send all of the keys to the indicated
// MessageWindow subclass.
// This works, but isn't really what we want. Ideally, we'd like
// to associate the key with the target window. Maybe we can figure
// out how to decide if we should notify the message window, though.
localHook = SetWindowsHookEx( WH_KEYBOARD_LL,
&TabHook,
(HINSTANCE)hMod,
0 /* Associate with current thread */ );

if ( localHook == NULL )
{
TCHAR syserrs[ 512 ];
DWORD err = GetLastError();

FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, err,
0, syserrs, sizeof( syserrs ) / sizeof( syserrs[ 0 ] ), 0 );

OutputDebugString( syserrs );

return err;
}

// Register the window message sent to the target message window when
// a tab is detected.
message = RegisterWindowMessage( _T( "KeyMessage" ) );

return 0;
}

FOCUSHELPER_API int UnhookTabs( HWND msgWindow )
{
OutputDebugString( _T( "UnhookTabs: enter\r\n" ) );

// Stop capturing the Tab keys (maybe the application is no longer
// in front or something).
UnhookWindowsHookEx( localHook );
localHook = NULL;

return 0;
}

Note that, in your case, you might want to unhook when your
application
is
no longer in front, etc. Or, you can set up your message window to do that
right thing in that case and just keep the hook installed for the life of
the application. You might also note that I'm registering my own
message
to
send.

Here's the actual hook routine:

LRESULT CALLBACK TabHook( int code, WPARAM wParam, LPARAM lParam )
{
if ( code < 0 )
{
DEBUGMSG( 1, (TEXT( "TabHook (%x): got a code less than zero\r\n" ),
GetCurrentThreadId() ) );

// Send the message to the next hook and return its return value.
return CallNextHookEx( localHook, code, wParam, lParam );
}

if ( code != HC_ACTION )
{
DEBUGMSG( 1, (TEXT( "TabHook (%x): got a code other than HC_ACTION\r\n" ),
GetCurrentThreadId() ) );
}

// Process the message ourselves.
KBDLLHOOKSTRUCT *msg = (KBDLLHOOKSTRUCT*)lParam;

// Check for tab and shift-tab.
if ( ( wParam == WM_KEYDOWN ) && ( msg->vkCode == VK_TAB ) )
{
LPARAM lp = 0;

if ( GetKeyState( VK_SHIFT ) )
lp |= SHIFT_DOWN;
if ( GetKeyState( VK_CONTROL ) )
lp |= CONTROL_DOWN;
if ( GetKeyState( VK_MENU ) )
lp |= ALT_DOWN;

// Trying to do this as fast as possible so that the hook doesn't
// violate any timing specifications. SendMessage might take too
// long, for example.
PostMessage( messageWindow, message, msg->vkCode, lp );
}
else if ( ( wParam == WM_KEYDOWN ) &&
( ( msg->vkCode == VK_UP ) || ( msg->vkCode == VK_DOWN ) || ( msg->vkCode
== VK_LEFT ) || ( msg->vkCode == VK_RIGHT ) ) )
{
LPARAM lp = 0;

if ( GetKeyState( VK_SHIFT ) )
lp |= SHIFT_DOWN;
if ( GetKeyState( VK_CONTROL ) )
lp |= CONTROL_DOWN;
if ( GetKeyState( VK_MENU ) )
lp |= ALT_DOWN;

// Trying to do this as fast as possible so that the hook doesn't
// violate any timing specifications. SendMessage might take too
// long, for example.
PostMessage( messageWindow, message, msg->vkCode, lp );
}
else if ( ( wParam == WM_SYSKEYDOWN ) &&
( msg->vkCode >= 'A' ) && ( msg->vkCode <= 'Z' ) )
{
// This might be an accelerator. Send it on.
LPARAM lp = 0;

if ( GetKeyState( VK_SHIFT ) )
lp |= SHIFT_DOWN;
if ( GetKeyState( VK_CONTROL ) )
lp |= CONTROL_DOWN;
if ( GetKeyState( VK_MENU ) )
lp |= ALT_DOWN;

// Trying to do this as fast as possible so that the hook doesn't
// violate any timing specifications. SendMessage might take too
// long, for example.
PostMessage( messageWindow, message, msg->vkCode, lp );
}

return CallNextHookEx( localHook, code, wParam, lParam );
}

Note that I'm only forwarding some keys and you may want to do that, also,
since the C code can handle those messages pretty quickly and the managed
code might be slower; you can decide.

Here's the message window code in C#:

public class KeysMessageWindow :
Microsoft.WindowsCE.Forms.MessageWindow
{
protected int message;

public KeysMessageWindow( )
{
// Register the window message which will be sent
// when the key is pressed. Note
// that this string must match the string used in
// the helper DLL.
message = RegisterWindowMessage( "KeyMessage" );
}

protected override void WndProc ( ref Microsoft.WindowsCE.Forms.Message
m )
// override
{
// Handle arrival of registered message.
if ( m.Msg == message )
{
// ???? do whatever you want to do with the message here.
}
}

/// <summary>
/// This external function found in coredll is used to
/// register a named message used to communicate between
/// the helper DLL and this MessageWindow.
/// </summary>
[DllImport("coredll.dll")]
protected static extern int RegisterWindowMessage( string lpString );
}
#endif

That's about it...

Paul T.


Can you possibly point me to an example that does something vaguely
similar
to this? :)

--
_________________________________
Jared Miniman, MS-MVP Mobile Devices
Mobile Computer Consultant

ActiveSync problems?
http://www.microsoft.com/mobile/pocketpc/support/help/activesync.asp
Connection Mngr Q's?
http://www.microsoft.com/mobile/pocketpc/tutorials/connectionmanager

You could capture all keyboard input with a C-based hook routine and
pass
it
to a message window subclass in your .NET CF application. That gives
you
a
single point at which the ESC key will arrive. Maybe that's actually
better
than setting a KeyDown event all over the place, too.

Paul T.

I have a recursive function that snakes throughout a form and
all
of do
not
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top