Capture keypress sequence in Windows Mobile device - c#

I need to capture a keypress sequence from a Windows Mobile device to trigger a duress event. If my application was the only thing running I would use a base form event handler to check the keypress BUT... as the application could launch a browser and also uses SOTI, it must also work outside of the main application.
Is it possible to create a TSR application on a Windows Mobile device that can send web service messages (whilst in comms)?

I have written several keyboard hook 'applications' that invoke different functions. You can also use that to do socket or webservice calls: http://www.hjgode.de/wp/?s=hook and http://www.hjgode.de/wp/?s=keytoggle
// The command below tells the OS that this EXE has an export function so we can use the global hook without a DLL
__declspec(dllexport) LRESULT CALLBACK g_LLKeyboardHookCallback(
int nCode, // The hook code
WPARAM wParam, // The window message (WM_KEYUP, WM_KEYDOWN, etc.)
LPARAM lParam // A pointer to a struct with information about the pressed key
)
{
/* typedef struct {
DWORD vkCode;
DWORD scanCode;
DWORD flags;
DWORD time;
ULONG_PTR dwExtraInfo;
} KBDLLHOOKSTRUCT, *PKBDLLHOOKSTRUCT;*/
// Get out of hooks ASAP; no modal dialogs or CPU-intensive processes!
// UI code really should be elsewhere, but this is just a test/prototype app
// In my limited testing, HC_ACTION is the only value nCode is ever set to in CE
static int iActOn = HC_ACTION;
static bool isShifted=false;
#ifdef DEBUG
static TCHAR str[MAX_PATH];
#endif
PKBDLLHOOKSTRUCT pkbhData = (PKBDLLHOOKSTRUCT)lParam;
//DWORD vKey;
if (nCode == iActOn)
{
//only process unflagged keys
if (pkbhData->flags != 0x00)
return CallNextHookEx(g_hInstalledLLKBDhook, nCode, wParam, lParam);
//check vkCode against forbidden key list
if(pForbiddenKeyList!=NULL)
{
BOOL bForbidden=false;
int j=0;
do{
if(pForbiddenKeyList[j]==(BYTE)pkbhData->vkCode)
{
bForbidden=true;
DEBUGMSG(1, (L"suppressing forbidden key: 0x%0x\n",pkbhData->vkCode));
continue;
}
j++;
}while(!bForbidden && pForbiddenKeyList[j]!=0x00);
if(bForbidden){
return true;
}
}
SHORT sShifted = GetAsyncKeyState(VK_SHIFT);
if((sShifted & 0x800) == 0x800)
isShifted = true;
else
isShifted = false;
//check and toggle for Shft Key
//do not process shift key
if (pkbhData->vkCode == VK_SHIFT){
DEBUGMSG(1, (L"Ignoring VK_SHIFT\n"));
return CallNextHookEx(g_hInstalledLLKBDhook, nCode, wParam, lParam);
}
//################################################################
//check if the actual key is a match key including the shift state
if ((byte)pkbhData->vkCode == (byte)szVKeySeq[iMatched]){
DEBUGMSG(1 , (L"==== char match\n"));
if (bCharShiftSeq[iMatched] == isShifted){
DEBUGMSG(1 , (L"==== shift match\n"));
}
else{
DEBUGMSG(1 , (L"==== shift not match\n"));
}
}
if( wParam == WM_KEYUP ){
DEBUGMSG(1, (L"---> szVKeySeq[iMatched] = 0x%02x\n", (byte)szVKeySeq[iMatched]));
if ( ((byte)pkbhData->vkCode == (byte)szVKeySeq[iMatched]) && (isShifted == bCharShiftSeq[iMatched]) ) {
//the first match?
if(iMatched==0){
//start the timer and lit the LED
LedOn(LEDid,1);
tID=SetTimer(NULL, 0, matchTimeout, (TIMERPROC)Timer2Proc);
}
iMatched++;
DEBUGMSG(1, (L"iMatched is now=%i\n", iMatched));
//are all keys matched
if (iMatched == iKeyCount){
//show modeless dialog
DEBUGMSG(1, (L"FULL MATCH, starting ...\n"));
PostMessage(g_hWnd, WM_SHOWMYDIALOG, 0, 0);
//reset match pos and stop timer
DEBUGMSG(1, (L"FULL MATCH: Reset matching\n"));
LedOn(LEDid,0);
iMatched=0; //reset match pos
KillTimer(NULL, tID);
//return CallNextHookEx(g_hInstalledLLKBDhook, nCode, wParam, lParam);
}
//return -1; //do not forward key?
}
else
{
KillTimer(NULL, tID);
LedOn(LEDid,0);
iMatched=0; //reset match pos
DEBUGMSG(1, (L"FULL MATCH missed. Reseting matching\n"));
}
} //if wParam == WM_KEY..
}
return CallNextHookEx(g_hInstalledLLKBDhook, nCode, wParam, lParam);
}
Looking for a hook example that looks for a key sequence: http://code.google.com/p/keytoggleboot/source/browse/trunk/KeyToggleBoot/ReadMe.txt?spec=svn14&r=14
There are also articles and posts about keyboard hooks in the internet (ie at codeproject).

I recently needed to get a key code from a handheld device and I just created an empty project with 1 textbox, included the following file and add this bit of code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
HookKeys x = new HookKeys();
x.Start();
x.HookEvent += new HookKeys.HookEventHandler(HookEvent);
}
private void HookEvent(HookEventArgs e, KeyBoardInfo keyBoardInfo)
{
textBox1.Text = "vkCode = " + keyBoardInfo.vkCode + Environment.NewLine + textBox1.Text;
}
}
Worked for a windows mobile 6.5 professional

Related

'GetProcessIdOfThread' always return zero

I am trying to do something like the question asked in this post in win10 with C# SendInput to minimized window while you're working on other windows.
I followed the best answer to do and I find it didn't work as "GetProcessIdOfThread" always return 0.
Here is the code:
public MainWindow()
{
InitializeComponent();
IntPtr NotepadHandle = FindWindow("Notepad", "Untitled - Notepad");
if (NotepadHandle == IntPtr.Zero)
{
MessageBox.Show("Notepad is not running.");
return;
}
uint noteid = GetProcessIdOfThread(NotepadHandle);
uint selfid = GetCurrentThreadId();
bool attach = AttachThreadInput(selfid, noteid, true);
if (attach == false)
{
MessageBox.Show("attach fail");
return;
}
}
Did I misunderstood anything?
Thank you!
MSDN about GetProcessIdOfThread:
Retrieves the process identifier of the process associated with the
specified thread.
You are passing handle of a window (HWND) instead of handle of a thread to the function. That's why it returns zero. You need to get handle of the thread first or you can directly call the GetWindowThreadProcessId function to get process id from HWND.
IntPtr notepadHandle = FindWindow("Notepad", "Untitled - Notepad");
if (notepadHandle == IntPtr.Zero) {
MessageBox.Show("Notepad is not running.");
return;
}
uint noteId;
uint threadId = GetWindowThreadProcessId(notepadHandle , out noteId);
if (threadId != 0) {
// Succeed
}
...

word add-in, KeyDown handling on combobox in customui

Blockquote
Need some help with CustomUI in Word add-in.
I have a
<combobox />
in my custom ui.
How can I handle Enter pressing by user ?
I need to perform some actions when user presses Enter in that ComboBox.
Can I add KeyDown event somehow or maybe cast IRibbonControl to something useful?
UPDATE :
Made decision not to include that functionality. But still interested in solution for that problem.
Even WindowSelectionChange event wont help you. It works for other Key press but not for Enter and Backspace (As I am aware of).
You have to use low level keyboard hook
EDITED**
There is a callback when any of the key been pressed it will be called.
private static IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr) WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
//Check if the enter key is pressed
if (vkCode == (int) Keys.Enter )
// Do here whatever you need
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}

Multiple character inputs for single physical press

I am attempting to process the windows messages for keyboard events and pass them into an awesomium webview. The webview has native handling for windows events, but the host program must capture them, and send them on.
I am using .net and the com interop to capture and send on the messages. The key events are passed on to the best of my knowledge, but the input is variable. For example, there are varying numbers of characters being entered in a text box for a single press.
Here is a sample of the code I am using (credit to Sekhat on the awesomium site) :
private void CreateHook()
{
uint threadId = Win32.GetWindowThreadProcessId(hWnd, IntPtr.Zero);
//hHook = Win32.SetWindowsHookEx(Win32.HookType.WH_CALLWNDPROC, wndProcDelegate, IntPtr.Zero, threadId);
hHook = Win32.SetWindowsHookEx(Win32.HookType.WH_GETMESSAGE, wndProcDelegate, IntPtr.Zero, threadId);
}
private int WndProcHook(int nCode, IntPtr wParam, ref Win32.Message lParam)
{
if (nCode >= 0)
{
Win32.TranslateMessage(ref lParam);
WndProc(ref lParam);
}
return Win32.CallNextHookEx(hHook, nCode, wParam, ref lParam);
}
wndProcDelegate = WndProcHook;
Am I handling the events wrong, leading to the variable number of inputs? I beleive the relevant parts are above, but can post the rest if needed.
On a side note, when I use WH_KEYBOARD instead of WH_GETMESSAGE an AccessViolationException is thrown. Is the KEYBOARD event the right one to use? Thank you for any assistance.
EDIT: I have done some further investigation and discovered that multiple messages of type 0x102 (WM_CHAR) are being passed to my program. The number passed matches the number of characters that awesomium is then outputting. Should I limit this to only the first message? While this may work, I would still like to know why this is happening.
I have managed to devise a working fix:
if (message.msg == 256)
{
accept = true;
}
if (accept && message.msg == 258)
{
view.InjectKeyboardEventWin((int)message.msg, (int)message.wparam, (int)message.lparam);
accept = false;
}
if (message.msg != 258)
{
view.InjectKeyboardEventWin((int)message.msg, (int)message.wparam, (int)message.lparam);
}
This code checks for a key down, and if found, set accept to true. The char message is only processed if a key down has been received since the last one. This allows text entry, while preserving other messages. I am still interested in discovering the root cause however.

C# Write text when key held down

I've got a C# console application with some pieces of text that represent buttons so for example it looks like this [ D ][ E ][ F ][ G ]
When the user presses the button I want the button to be highlighted which is no problem as what im currently doing is rewriting over the button with Console.BackgroundColor set.
What I want to do is that they key be constantly highlighted while the key is held down but as soon as the key is lifted again the highlighting to be removed, if possible i'd also like multiple keys to be pressed at the same time. This is what I can't figure out how to do?
Hope that makes sense :)
Any help?
Thanks
If you are willing to add a reference to Windows.Forms, call Application.Run() to run a message queue, and call external Windows DLLs, you can do it using this code: http://blogs.msdn.com/b/toub/archive/2006/05/03/589423.aspx
That page will show you how to hook the low-level key-down keyboard event.
To also hook key-up keyboard events, you'll need to add a WM_KEYUP constant:
private const int WM_KEYDOWN = 0x0100;
private const int WM_KEYUP = 0x0101;
And then modify the HookCallback method:
private static IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
Console.WriteLine("Down:" + (Keys)vkCode);
}
else if (nCode >= 0 && wParam == (IntPtr)WM_KEYUP)
{
int vkCode = Marshal.ReadInt32(lParam);
Console.WriteLine("Up:" + (Keys)vkCode);
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
That will give you "Up" and "Down" messages for every key press. From there you should be able to incorporate it into your app.
Good luck!
Sorry but Console App only has Keyboard event (that too not actually an event unless you are in a loop and check for keypress) No KeyDown. keyPress or KeyUp events. It has no events of the GUI world.
I'm afraid AFAIK that a Console app can't detect multiple simultaneous key presses (that aren't modifier keys such as shift, or ctrl) so that isn't going to work.
With regard to highlighting a key as long as it is pressed you need to have your Console.ReadKey in a loop. Something like the following (you need to implement RemoveHighlight and HighlightKey methods yourself):
ConsoleKeyInfo currentKeyPressed;
ConsoleKeyInfo lastKeyPressed;
do
{
currentKeyPressed = Console.ReadKey();
if (lastKeyPressed.Key == currentKeyPressed.Key)
continue;
RemoveHighlight();
HighlightKey(keyPressed.Key);
lastKeyPressed = currentKeyPressed;
} while ((keyPressed.Key & ConsoleKey.Escape) != ConsoleKey.Escape);

XNA - Keyboard text input

Okay, so basically I want to be able to retrieve keyboard text. Like entering text into a text field or something. I'm only writing my game for windows.
I've disregarded using Guide.BeginShowKeyboardInput because it breaks the feel of a self contained game, and the fact that the Guide always shows XBOX buttons doesn't seem right to me either. Yes it's the easiest way, but I don't like it.
Next I tried using System.Windows.Forms.NativeWindow. I created a class that inherited from it, and passed it the Games window handle, implemented the WndProc function to catch WM_CHAR (or WM_KEYDOWN) though the WndProc got called for other messages, WM_CHAR and WM_KEYDOWN never did. So I had to abandon that idea, and besides, I was also referencing the whole of Windows forms, which meant unnecessary memory footprint bloat.
So my last idea was to create a Thread level, low level keyboard hook. This has been the most successful so far. I get WM_KEYDOWN message, (not tried WM_CHAR yet) translate the virtual keycode with Win32 funcation MapVirtualKey to a char. And I get my text! (I'm just printing with Debug.Write at the moment)
A couple problems though. It's as if I have caps lock on, and an unresponsive shift key. (Of course it's not however, it's just that there is only one Virtual Key Code per key, so translating it only has one output) and it adds overhead as it attaches itself to the Windows Hook List and isn't as fast as I'd like it to be, but the slowness could be more due to Debug.Write.
Has anyone else approached this and solved it, without having to resort to an on screen keyboard? or does anyone have further ideas for me to try?
thanks in advance.
Question asked by Jimmy
Maybe I'm not understanding the question, but why can't you use the XNA Keyboard and KeyboardState classes?
My comment:
It's because though you can read keystates, you can't get access to typed text as and how it is typed by the user.
So let me further clarify. I want to implement being able to read text input from the user as if they are typing into textbox is windows. The keyboard and KeyboardState class get states of all keys, but I'd have to map each key and combination to it's character representation. This falls over when the user doesn't use the same keyboard language as I do especially with symbols (my double quotes is shift + 2, while american keyboards have theirs somewhere near the return key).
it seems my window hook was the way to go, just the reason I wasn't getting WM_CHAR is because the XNA message pump doesn't do translate message.
Adding TranslateMessage in whenever I received a WM_KEYDOWN message meant I got my WM_CHAR message, I then used this to fire a character typed event in my MessageHook class which my KeyboardBuffer class had subscribed to, which then buffers that to a text buffer :D (or StringBuilder, but the result is the same)
So I have it all working as I want.
Many thanks to Jimmy for a link to a very informative thread.
For adding a windows hook in XNA
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Reflection;
/* Author: Sekhat
*
* License: Public Domain.
*
* Usage:
*
* Inherit from this class, and override the WndProc function in your derived class,
* in which you handle your windows messages.
*
* To start recieving the message, create an instance of your derived class, passing in the
* window handle of the window you want to listen for messages for.
*
* in XNA: this would be the Game.Window.Handle property
* in Winforms Form.Handle property
*/
namespace WindowsHookExample
{
public abstract class WindowsHook : IDisposable
{
IntPtr hHook;
IntPtr hWnd;
// Stored here to stop it from getting garbage collected
Win32.WndProcDelegate wndProcDelegate;
public WindowsHook(IntPtr hWnd)
{
this.hWnd = hWnd;
wndProcDelegate = WndProcHook;
CreateHook();
}
~WindowsHook()
{
Dispose(false);
}
private void CreateHook()
{
uint threadId = Win32.GetWindowThreadProcessId(hWnd, IntPtr.Zero);
hHook = Win32.SetWindowsHookEx(Win32.HookType.WH_CALLWNDPROC, wndProcDelegate, IntPtr.Zero, threadId);
}
private int WndProcHook(int nCode, IntPtr wParam, ref Win32.Message lParam)
{
if (nCode >= 0)
{
Win32.TranslateMessage(ref lParam); // You may want to remove this line, if you find your not quite getting the right messages through. This is here so that WM_CHAR is correctly called when a key is pressed.
WndProc(ref lParam);
}
return Win32.CallNextHookEx(hHook, nCode, wParam, ref lParam);
}
protected abstract void WndProc(ref Win32.Message message);
#region Interop Stuff
// I say thankya to P/Invoke.net.
// Contains all the Win32 functions I need to deal with
protected static class Win32
{
public enum HookType : int
{
WH_JOURNALRECORD = 0,
WH_JOURNALPLAYBACK = 1,
WH_KEYBOARD = 2,
WH_GETMESSAGE = 3,
WH_CALLWNDPROC = 4,
WH_CBT = 5,
WH_SYSMSGFILTER = 6,
WH_MOUSE = 7,
WH_HARDWARE = 8,
WH_DEBUG = 9,
WH_SHELL = 10,
WH_FOREGROUNDIDLE = 11,
WH_CALLWNDPROCRET = 12,
WH_KEYBOARD_LL = 13,
WH_MOUSE_LL = 14
}
public struct Message
{
public IntPtr lparam;
public IntPtr wparam;
public uint msg;
public IntPtr hWnd;
}
/// <summary>
/// Defines the windows proc delegate to pass into the windows hook
/// </summary>
public delegate int WndProcDelegate(int nCode, IntPtr wParam, ref Message m);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SetWindowsHookEx(HookType hook, WndProcDelegate callback,
IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, ref Message m);
[DllImport("coredll.dll", SetLastError = true)]
public static extern IntPtr GetModuleHandle(string module);
[DllImport("user32.dll", EntryPoint = "TranslateMessage")]
public extern static bool TranslateMessage(ref Message m);
[DllImport("user32.dll")]
public extern static uint GetWindowThreadProcessId(IntPtr window, IntPtr module);
}
#endregion
#region IDisposable Members
public void Dispose()
{
Dispose(true);
}
private void Dispose(bool disposing)
{
if (disposing)
{
// Free managed resources here
}
// Free unmanaged resources here
if (hHook != IntPtr.Zero)
{
Win32.UnhookWindowsHookEx(hHook);
}
}
#endregion
}
}
I used the solution from this gamedev.net post and it works great :)
Here's a simple way, IMO, to have the space, back, A-Z and then the special chars !,#,#,$,%,^,&,*,(,). (Note, you need to import System.Linq) Here are the fields:
Keys[] keys;
bool[] IskeyUp;
string[] SC = { ")" , "!", "#", "#", "$", "%", "^", "&", "*", "("};//special characters
Constructor:
keys = new Keys[38];
Keys[] tempkeys;
tempkeys = Enum.GetValues(typeof(Keys)).Cast<Keys>().ToArray<Keys>();
int j = 0;
for (int i = 0; i < tempkeys.Length; i++)
{
if (i == 1 || i == 11 || (i > 26 && i < 63))//get the keys listed above as well as A-Z
{
keys[j] = tempkeys[i];//fill our key array
j++;
}
}
IskeyUp = new bool[keys.Length]; //boolean for each key to make the user have to release the key before adding to the string
for (int i = 0; i < keys.Length; i++)
IskeyUp[i] = true;
And Finally, the update method:
string result = "";
public override void Update(GameTime gameTime)
{
KeyboardState state = Keyboard.GetState();
int i = 0;
foreach (Keys key in keys)
{
if (state.IsKeyDown(key))
{
if (IskeyUp[i])
{
if (key == Keys.Back && result != "") result = result.Remove(result.Length - 1);
if (key == Keys.Space) result += " ";
if (i > 1 && i < 12)
{
if (state.IsKeyDown(Keys.RightShift) || state.IsKeyDown(Keys.LeftShift))
result += SC[i - 2];//if shift is down, and a number is pressed, using the special key
else result += key.ToString()[1];
}
if (i > 11 && i < 38)
{
if (state.IsKeyDown(Keys.RightShift) || state.IsKeyDown(Keys.LeftShift))
result += key.ToString();
else result += key.ToString().ToLower(); //return the lowercase char is shift is up.
}
}
IskeyUp[i] = false; //make sure we know the key is pressed
}
else if (state.IsKeyUp(key)) IskeyUp[i] = true;
i++;
}
base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
}
Hopefull this well help. I personally thought it was easier to use than the hooks, and this also can easily be modified for special results (such as shuffling the keys).
Maybe I'm not understanding the question, but why can't you use the XNA Keyboard and KeyboardState classes?
This page is on top of google result about WM_CHAR interception in xna, so i leave here some note. Maybe this will be useful for other (if they will be able to understand my English =)) ).
I try code with windowshook from Sekhat, but seems there should be WH_GETMESSAGE passed to SetWindowsHookEx instead Win32.HookType.WH_CALLWNDPROC (only with WH_GETMESSAGE code lparaw will point to Win32.Message ).
Also there is sometime duplicated messages (with wparam 0).
(look here - http://msdn.microsoft.com/en-us/library/ms644981%28v=VS.85%29.aspx
something about PM_NOREMOVE/PM_REMOVE in WPARAM )
When i add something like this
if (nCode >= 0 && wParam == 1)
{
Win32.TranslateMessage(ref lParam);
WndProc(ref lParam);
}
wm_keypress wm_char duplication stopped (i supose 1 is PM_NOREMOVE or PM_REMOVE).
P.S.
nuclex variant now show 404 page, but can be viewed with webarchive.
nuclex variant works, but it cause broken mouseWheel processing from native XNA MouseState (on XNA 3.1) =(

Categories

Resources