|
|
A C# form test prog to see what the remote control is doing
Last post 11-04-2008, 10:05 PM by davidtjudd. 22 replies.
-
04-09-2007, 9:15 AM |
-
Gordon Moore
-
-
-
Joined on 03-13-2007
-
-
Posts 214
-
-
|
A C# form test prog to see what the remote control is doing
Edit: Please go towards the end of the thread if you're looking for a working bit of code for use in a background app. The first few posts are basically describing my experiments and search for a solution and aren't necessary (and aren't what you want probably) :) Gordon I have no idea if this will be useful to anyone, but using a test C# forms program I can "listen" to the basic windows messages that are generated with a remote control (possibly other messages.) It just produces a beep (or rather a stream of beeps/clicks) in response to remote control keys. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; using Microsoft.Win32; namespace Test { public partial class Form1 : Form { public Form1() { InitializeComponent(); } [StructLayout(LayoutKind.Sequential)] internal struct RAWINPUTDEVICE { [MarshalAs(UnmanagedType.U2)] public ushort usUsagePage; [MarshalAs(UnmanagedType.U2)] public ushort usUsage; [MarshalAs(UnmanagedType.U4)] public int dwFlags; public IntPtr hwndTarget; } RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[1]; [DllImport("User32.dll")] extern static bool RegisterRawInputDevices(RAWINPUTDEVICE[] pRawInputDevice, uint uiNumDevices, uint cbSize); [DllImport("Kernel32.dll")] //for beep public static extern bool Beep(UInt32 frequency, UInt32 duration); private void Form1_Load(object sender, EventArgs e) { //Register a raw input device - the remote control rid[0].usUsagePage = 0xFFBC; rid[0].usUsage = 0x88; rid[0].dwFlags = 0; //rid[0].hwndTarget = hwnd; RegisterRawInputDevices(rid, (uint)rid.Length, (uint)Marshal.SizeOf(rid[0])); } //override the WndProc so that we can look at the device messages, incl remote control protected override void WndProc(ref Message message) { Beep(200, 10); base.WndProc(ref message); } } } I used the following references to help me get this far http://www.codeproject.com/cs/system/rawinput.asphttp://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/rawinput/aboutrawinput.asphttp://msdn2.microsoft.com/en-us/library/aa468212.aspxThe stephen Toub article also contains much info http://blogs.msdn.com/toub/archive/2005/04/19/409845.aspxand updated for vmc http://blogs.msdn.com/toub/archive/2007/01/03/position-changer-add-in-updated-for-windows-vista.aspxI shall update as my experiments help me understand this stuff! :) edit: of course a beep isn't of much use so, except on mce to test that something is happening so replace it with Console.WriteLine(message.WParam.ToString()); and open an output window to see what is going on. You might try if (message.Msg == WM_KEYDOWN) { Console.WriteLine(message.WParam.ToString()); } where WM_KEYDOWN is defined as private const int WM_KEYDOWN = 0x0100; This reveal codes for quite a few keys although unfortunately for me the teletext buttons, though providing a message, do not seem to have any definition attached to them - anyone know anything?
Gordon: Has reached the end!
|
|
-
04-09-2007, 12:41 PM |
-
Gordon Moore
-
-
-
Joined on 03-13-2007
-
-
Posts 214
-
-
|
Re: A C# form test prog to see what the remote control is doing
Why do I bother?
I was trying to transfer the basic routines above to my background app, but I can't reference the WndProc. No matter what namespaces i use or checking that they are referenced, I can't seem to find one that works. i thought it was in System.Windows.Forms???
However, in doing more research, I have discovered that this method aint going to work anyway.
sugar!!!
Looks like I really am going to have to hack the keyboard hooks...
Gordon: Has reached the end!
|
|
-
04-09-2007, 1:01 PM |
-
AndyC
-
-
-
Joined on 06-14-2006
-
UK
-
Posts 1,858
-
-
|
Re: A C# form test prog to see what the remote control is doing
Boy you really like the difficult stuff don't you!!!
The issue with doing anything like this is that you're going to have to write your own handlers for keyboard input, as the KeyHandler and ShortcutHandler elements are much more restrictive than the raw input API.
Some of the keys on the remote pass back an APP_COMMAND message rather than a WM_INPUT message, so you'll need to process them differently. There's an MSDN article on the remote control and what messages you get for each key - search for "Remote Control" or similar on MSDN and you should find it.
Cheers, Andrew
|
|
-
04-09-2007, 2:48 PM |
-
Gordon Moore
-
-
-
Joined on 03-13-2007
-
-
Posts 214
-
-
|
Re: A C# form test prog to see what the remote control is doing
Yeah, that's where I found the code for the remote Control, but I think it's out of date for Vista. One of the posters here in a thread on the remote control pointed out in Toub's update vista app that this method wouldn't work - because of security I think, the ui just blocks it all (if I understood it?)
As I said I can't egt the reference to wndproc to be recognised, otherwise since all I wanted to do was recognise one key (i.e. the hash key) then it would have been sweet. But nothing is ever that simple.
Anyway, after investigating keyboard hooks and trying to find some simple code and failing, I've managed to hack Stephen's code to extract the stuff needed to display the basic keys.
Here it is: Please note folks that this is Stephen's code and really you should acknowledge that in any apps (is permission needed in commercial apps?)
using System; using System.Timers; using System.Collections; using System.Collections.Generic; using System.Threading; using Microsoft.MediaCenter; using Microsoft.MediaCenter.Hosting; using Microsoft.MediaCenter.UI; using System.Runtime.InteropServices; using System.Windows.Forms; using System.Diagnostics; using System.ComponentModel; using System.IO; using System.Runtime.ConstrainedExecution; using System.Security; using System.Security.Permissions; using Microsoft.Win32.SafeHandles;
namespace VMCMusicList { public class VMCMusicList : IAddInModule, IAddInEntryPoint {
private AddInHost _host; private ManualResetEvent vmcWaitForExit; private Process _ehshellProcess;
// Initialize (IAddInModule) public void Initialize(Dictionary<string, object> appInfo, Dictionary<string, object> entryPointInfo) { }
// Uninitialize (IAddInModule) public void Uninitialize() { }
// Launch (IAddInModule) public void Launch(AddInHost host) { try { _host = host; //so that host is available globally in the code
using (vmcWaitForExit = new ManualResetEvent(false)) //Keep app alive till vmc exit { using (_ehshellProcess = GetEhShellProcess()) // Get the ehshell process using (new KeyboardHook(_ehshellProcess.Id, hook_KeyDown)) {
vmcWaitForExit.WaitOne(); //this should just sit here until vmc is closed } } _host = null; //host is invalid once Launch returns... make sure we don't use it after this } catch (Exception exc) { host.MediaCenterEnvironment.Dialog("Unable to launch. " + exc.ToString(), "VMCMusicList", Microsoft.MediaCenter.DialogButtons.Ok, 0, true); throw; } }
//*******This is the "key" bit - ahem *********** private void hook_KeyDown(object sender, KeyEventArgs e) //handle the key { //Let's see what we have _host.MediaCenterEnvironment.Dialog(e.KeyCode.ToString(), "", Microsoft.MediaCenter.DialogButtons.Ok, 0, true); }
/// <summary>Gets a reference to the Process instance for the running ehshell.exe</summary> private Process GetEhShellProcess() { // Get the current terminal services session ID int currentSessionId; using (Process currentProcess = Process.GetCurrentProcess()) currentSessionId = currentProcess.SessionId;
// Get all ehome processes on the machine, and find the one in the current session Process[] procs = Process.GetProcessesByName("ehshell"); Process ehshell = null; for (int i = 0; i < procs.Length; i++) { if (ehshell == null && procs[i].SessionId == currentSessionId) ehshell = procs[i]; else procs[i].Dispose(); } return ehshell; }
/// <summary>StephenToub's Simple implementation of a keyboard hook for key down events on the GUI thread of an application.</summary> public sealed class KeyboardHook : IDisposable { /// <summary>Low-level keyboard hook id.</summary> private const int WH_KEYBOARD_LL = 13; /// <summary>Posted to the window with the keyboard focus when a nonsystem key is pressed.</summary> private const int WM_KEYDOWN = 0x0100; /// <summary>OS handle for the registered keyboard hook.</summary> private SafeWindowsHookHandle _hookHandle = null; /// <summary>Hook callback when a WH_KEYBOARD event occurs.</summary> private LowLevelKeyboardProc _hookProc; /// <summary>Delegate called when a key is pressed down.</summary> private KeyEventHandler _keyDown; /// <summary>Target process ID.</summary> private int _pid;
/// <summary>Initializes the keyboard hook.</summary> /// <param name="keyDown">The delegate to be called when a key down event occurs.</param> public KeyboardHook(int targetProcessID, KeyEventHandler keyDown) { if (keyDown == null) throw new ArgumentNullException("keyDown");
// Store the user's KeyDown delegate _keyDown = keyDown; _pid = targetProcessID;
// Create the callback and make sure it doesn't get GC'd, // since it'll be called from unmanaged code _hookProc = new LowLevelKeyboardProc(HookCallback);
// Set the hook for just the GUI thread using (Process curProcess = Process.GetCurrentProcess()) using (ProcessModule curModule = curProcess.MainModule) { _hookHandle = SafeWindowsHookHandle.SetWindowsHookEx( WH_KEYBOARD_LL, _hookProc, GetModuleHandle(curModule.ModuleName), 0); } if (_hookHandle.IsInvalid) { Exception exc = new Win32Exception(); Dispose(); throw exc; } }
/// <summary>Dispose the KeyboardHook.</summary> public void Dispose() { if (_hookHandle != null) { _hookHandle.Dispose(); _hookHandle = null; } }
/// <summary>Event raised when an exception is encountered from a callback.</summary> public ErrorEventHandler Error = delegate { };
/// <summary>HookCallback data.</summary> private struct KBDLLHOOKSTRUCT { #pragma warning disable 0649 public uint vkCode; public uint scanCode; public uint flags; public uint time; public IntPtr dwExtraInfo; #pragma warning restore 0649 }
/// <summary>Callback from the installed hook.</summary> ///</returns> private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) { bool handled = false; try { // Only respond to key down events when the shift key isn't pressed if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN) { uint pid; GetWindowThreadProcessId(GetForegroundWindow(), out pid); if (pid == _pid) { KBDLLHOOKSTRUCT hookParam = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT)); Keys key = (Keys)hookParam.vkCode; if (key == Keys.Packet) key = (Keys)hookParam.scanCode;
KeyEventArgs e = new KeyEventArgs(key | ModifierKeys); _keyDown(this, e); handled = e.Handled | e.SuppressKeyPress; } }
// If the event has not been handled/eaten by the user, relegate to the next hook in line. return handled ? new IntPtr(1) : SafeWindowsHookHandle.CallNextHookEx(_hookHandle, nCode, wParam, lParam); } catch (Exception exc) { Error(this, new ErrorEventArgs(exc)); } return new IntPtr(1); }
/// <summary>Gets the modifier keys currently in use.</summary> private static Keys ModifierKeys { get { Keys modifiers = Keys.None; if (GetKeyState(VK_SHIFT) < 0) modifiers |= Keys.Shift; if (GetKeyState(VK_CONTROL) < 0) modifiers |= Keys.Control; if (GetKeyState(VK_ALT) < 0) modifiers |= Keys.Alt; return modifiers; } }
/// <summary> /// The GetWindowThreadProcessId function retrieves the identifier of the thread that created the specified window /// and, optionally, the identifier of the process that created the window. /// </summary> /// <param name="hWnd">Handle to the window.</param> /// <param name="lpdwProcessId">Pointer to a variable that receives the process identifier.</param> /// <returns>The return value is the identifier of the thread that created the window.</returns> [DllImport("user32.dll", SetLastError = true)] private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
/// <summary>Returns a handle to the foreground window (the window with which the user is currently working).</summary> /// <returns>A handle to the foreground window.</returns> [DllImport("user32.dll", SetLastError = true)] private static extern IntPtr GetForegroundWindow();
/// <summary>Virtual key value for shift.</summary> private const uint VK_SHIFT = 0x10; private const uint VK_CONTROL = 0x11; private const uint VK_ALT = 0x12;
/// <summary>The GetKeyState function retrieves the status of the specified virtual key.</summary> /// <param name="nVirtKey">Specifies a virtual key.</param> /// <returns>The return value specifies the status of the specified virtual key.</returns> [DllImport("user32.dll", SetLastError = true)] private static extern short GetKeyState(uint nVirtKey);
/// <summary>Retrieves a module handle for the specified module. The module must have been loaded by the calling process</summary> /// <param name="lpModuleName">The name of the loaded module (either a .dll or .exe file).</param> /// <returns> /// If the function succeeds, the return value is a handle to the specified module. /// If the function fails, the return value is NULL. /// </returns> [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr GetModuleHandle(string lpModuleName); }
/// <summary>LowLevelKeyboardProc for callbacks from the OS.</summary> internal delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
/// <summary>A SafeHandle for windows hook handles.</summary> [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)] internal sealed class SafeWindowsHookHandle : SafeHandleZeroOrMinusOneIsInvalid { /// <summary>Initializes the SafeWindowsHookHandle.</summary> private SafeWindowsHookHandle() : base(true) { }
/// <summary>Releases the handle.</summary> /// <returns>true on success; false, otherwise.</returns> protected override bool ReleaseHandle() { return UnhookWindowsHookEx(handle); }
/// <summary>The UnhookWindowsHookEx function removes a hook procedure installed in a hook chain by the SetWindowsHookEx function.</summary> /// <param name="hhk">Handle to the hook procedure</param> /// <returns>true on success; otherwise, false.</returns> [SuppressUnmanagedCodeSecurity] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [DllImport("user32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool UnhookWindowsHookEx(IntPtr hhk);
/// <summary>The SetWindowsHookEx function installs an application-defined hook procedure into a hook chain.</summary> /// <param name="idHook">Specifies the type of hook procedure to be installed.</param> /// <param name="lpfn">Pointer to the hook procedure.</param> /// <param name="hMod">Handle to the DLL containing the hook procedure pointed to by the lpfn parameter.</param> /// <param name="dwThreadId">Specifies the identifier of the thread with which the hook procedure is to be associated.</param> /// <returns>If the function succeeds, the return value is the handle to the hook procedure; otherwise, 0.</returns> [DllImport("user32.dll", SetLastError = true)] public static extern SafeWindowsHookHandle SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
/// <summary>The CallNextHookEx function passes the hook information to the next hook procedure in the current hook chain.</summary> /// <param name="hhk">Handle to the current hook.</param> /// <param name="nCode">Specifies the hook code passed to the current hook procedure.</param> /// <param name="wParam">Specifies the wParam value passed to the current hook procedure.</param> /// <param name="lParam">Specifies the lParam value passed to the current hook procedure.</param> /// <returns>This value is returned by the next hook procedure in the chain.</returns> [DllImport("user32.dll", SetLastError = true)] public static extern IntPtr CallNextHookEx(SafeWindowsHookHandle hhk, int nCode, IntPtr wParam, IntPtr lParam); }
} }
Gordon: Has reached the end!
|
|
-
04-09-2007, 2:55 PM |
-
Gordon Moore
-
-
-
Joined on 03-13-2007
-
-
Posts 214
-
-
|
Re: A C# form test prog to see what the remote control is doing
If anyone cares to reduce this to the bare minimum as there's lot's of stuff here that i'm not sure is totally necessary for the prupose of understanding - I don't :(
Gordon: Has reached the end!
|
|
-
04-09-2007, 4:42 PM |
-
Gordon Moore
-
-
-
Joined on 03-13-2007
-
-
Posts 214
-
-
|
Re: A C# form test prog to see what the remote control is doing
The problem with the code above is that yet again it is completely beyond me, so I have no idea how I can adapt it, simplify it, alter it to allow me to look at other controls. Can anyone explain it? apart from Stephen Toub I decided to have another look at my first wndproc override idea that seems a lot simpler. Then I spotted this thread http://discuss.mediacentersandbox.com/forums/post/1656.aspx where AndyC says that because MS changed things, it is not possible to basically link into the main window, so you can't use wndproc. So, apart from these keyboard hooks, is there any other simple way of seeing what messages are going on? If not, then could someone show how a basic and simple global keyboard/remote/mouse hook works, please. Is anything simple in this media center world????
Gordon: Has reached the end!
|
|
-
04-09-2007, 11:15 PM |
-
AndyC
-
-
-
Joined on 06-14-2006
-
UK
-
Posts 1,858
-
-
|
Re: A C# form test prog to see what the remote control is doing
Gordon,
What exactly is it that you're trying to do?
The reason I ask is that you are taking the most imaginably complex way about getting a key press out of Media Center, as you are trying to do something that the platform isn't designed to do - that's why it's difficult.
If you are trying to intercept the # key while (for example) watching TV, then yes it is possible in Vista. There is an update to Stephens article that works with a global, low-level keyboard hook which intercepts ALL keypresses regardless of whether they are destined for Media Center or Wordpad, Outlook, etc. A simple example (or at least as simple as this topic gets) is here: http://blogs.msdn.com/toub/archive/2006/05/03/589423.aspx
The method that works with MCE2005 Update Rollup 2 also works in Vista - the UR2 version of Stephens add-in is here: http://blogs.msdn.com/toub/archive/2005/10/14/481082.aspx
If you just want to get a keypress from within an interactive add-in (i.e. one that is in "More Programs" and shows a UI before requiring a keypress), have a look at KeyHandler and ShortcutHandler in the MCE SDK.
Cheers, Andrew
|
|
-
04-10-2007, 2:53 AM |
-
Gordon Moore
-
-
-
Joined on 03-13-2007
-
-
Posts 214
-
-
|
Re: A C# form test prog to see what the remote control is doing
Thanks Andy.
All I'm trying to achieve is to do something like
launch Addin(..) { //whilst waiting for vmc to end
SetUpAnEventForWhenARemoteKeyIsPresed( EventForRemoteKeyPressed) //is this what delegates do?
//sit here unit vmc exits }
EventForRemoteKeyPressed (or mouse or any device) { //Check what key pressed DoMyProcessing() }
domyprocessing() { }
This is how windows forms work? event driven architecture. I assumed that it would be how vmc would work?
I saw the article on low level kbd hooks and thought that's it, but being thick, I couldn't see how to utilise it. I assume that something is returning the keystrokes to the console that's opened by Application.Run, but I just don't know how to utilise it. As you may have seen there is no explanation of how it works (okay, well Stephen's |time travel explains things granted). As I said I realise I don't have a very good understanding of .Net really. :( - I've got loads of books though :)
I didn't realise I was being complex in what I was trying to do. it seemed to me naively that intercepting the messages that the remote sends to media center (which is a net app?) and hijacking it by overriding wndproc seemed eminently sensible and simple. I accept that there are performance issues to this, and that there are more sophisticetd ways - keyboard hooks, but if the sdk would just add an event for the remote button pressed, we could do what we want.
In fact Stephen warns about using keyboard hooks as they may not work in future, so once again we are left with no safe mechanism for doing something that should be trivial.
I asuume that media center itself is a collection of apps, they must read the remote, so how do they do it, and why can't they simply open up the interface?
Anyway if you know how I can utilise the Toub low level hooks I'd be very grateful.
[Thanks my friend for all your interest and involvement. It is deeply appreciated by me and I'm sure by many others - Thankyou. I owe you a few pints that's for sure.]
Edit: I'm reading the second article now (I must have missed the explanations? of what changed or didn't understand it at the time) and the kb article it refers to, so hopefully I may understand better soon.
Gordon: Has reached the end!
|
|
-
04-10-2007, 4:05 AM |
-
AndyC
-
-
-
Joined on 06-14-2006
-
UK
-
Posts 1,858
-
-
|
Re: A C# form test prog to see what the remote control is doing
Is your addin a background addin or a foreground addin?
|
|
-
04-10-2007, 4:39 AM |
-
Gordon Moore
-
-
-
Joined on 03-13-2007
-
-
Posts 214
-
-
|
Re: A C# form test prog to see what the remote control is doing
It's a background app.
I think I've found what I was looking for.
There is a Console.Writeline in the HookCallback method which returns the keys to the console. Application.console just starts up the console, I think.
If I change this to call my processing procedure and just make sure I grab the proper process, I think I should be in with a shout.
Gordon: Has reached the end!
|
|
-
04-10-2007, 5:51 AM |
-
Gordon Moore
-
-
-
Joined on 03-13-2007
-
-
Posts 214
-
-
|
Re: A C# form test prog to see what the remote control is doing
So after a bit of tweaking of S. Toub's low level keyboard hook, mentioned in AndyC's reply which in particular involved setting my user method to be static, and also vmcHost to be also static I got this:
using System; using System.Collections.Generic; using System.Threading; using Microsoft.MediaCenter; using Microsoft.MediaCenter.Hosting; using Microsoft.MediaCenter.UI; using System.Runtime.InteropServices; using System.Diagnostics;
namespace VMCMusicList { public class VMCMusicList : IAddInModule, IAddInEntryPoint { private static AddInHost vmcHost; private ManualResetEvent vmcWaitForExit;
// Initialize (IAddInModule) public void Initialize(Dictionary<string, object> appInfo, Dictionary<string, object> entryPointInfo) { }
// Uninitialize (IAddInModule) public void Uninitialize() { }
// Launch (IAddInModule) public void Launch(AddInHost host) { try { vmcHost = host; //so that host is available globally in the code
using (vmcWaitForExit = new ManualResetEvent(false)) //Keep app alive till vmc exit { _hookID = SetHook(_proc);
vmcWaitForExit.WaitOne(); //this should just sit here until vmc is closed UnhookWindowsHookEx(_hookID); }
vmcHost = null; //host is invalid once Launch returns... make sure we don't use it after this } catch (Exception exc) { host.MediaCenterEnvironment.Dialog("Unable to launch. " + exc.ToString(), "VMCMusicList", Microsoft.MediaCenter.DialogButtons.Ok, 0, true); throw; } }
private static void HandleRemoteControlKeys(int vkCode) //this is where I intend to handle my app, I'm not sure I understand the static keyword though. I assume it's because I will only ever have the one instance. Anyway Toub's routines can't access it if its not static. { vmcHost.MediaCenterEnvironment.Dialog(vkCode.ToString(), "", Microsoft.MediaCenter.DialogButtons.Ok, 0, true); }
//S Toub's Low level Keyboard Hook http://blogs.msdn.com/toub/archive/2006/05/03/589423.aspx private const int WH_KEYBOARD_LL = 13; private const int WM_KEYDOWN = 0x0100; private static LowLevelKeyboardProc _proc = HookCallback; private static IntPtr _hookID = IntPtr.Zero;
private static IntPtr SetHook(LowLevelKeyboardProc proc) { using (Process curProcess = Process.GetCurrentProcess()) using (ProcessModule curModule = curProcess.MainModule) { return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0); } }
private delegate IntPtr LowLevelKeyboardProc( int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback( int nCode, IntPtr wParam, IntPtr lParam) { if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN) { int vkCode = Marshal.ReadInt32(lParam);
HandleRemoteControlKeys(vkCode); } return CallNextHookEx(_hookID, nCode, wParam, lParam); }
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr GetModuleHandle(string lpModuleName);
} }
It justs shows the keycodes in a dialogbox. Again you have to wait about ten seconds before its active!
Okay there are a couple of things that I'm wondering about.
1) I've placed the UnhookWindowsHookEx(_hookID); after the vmcWaitForExit.WaitOne(); routine. I assume this is okay?
2) In Toub's main article and the code for vista (also in one of the above posts, he has a much more sophisticated GetEhShellprocess routine. Should this be incorporated into the app and if so how? Is it just a matter of replacing the using (Process curProcess = Process.GetCurrentProcess()) in the SetHook routine with using (Process curProcess = Process.GetEhShellprocess()) If required, what is it's point?
Gordon: Has reached the end!
|
|
-
04-10-2007, 6:41 AM |
-
AndyC
-
-
-
Joined on 06-14-2006
-
UK
-
Posts 1,858
-
-
|
Re: A C# form test prog to see what the remote control is doing
1) You could put the Unhook... in a finally clause so that it definitely gets called, exception or not.
2) Yes that should be okay - the more complicated one is to ensure you get the right EhShell when running on a system with more than one copy running (e.g. when using extenders)
Cheers, Andrew
|
|
-
04-10-2007, 8:21 AM |
-
Gordon Moore
-
-
-
Joined on 03-13-2007
-
-
Posts 214
-
-
|
Re: A C# form test prog to see what the remote control is doing
Excellent.
Whe hey, onto the next battle,
blood is dripping from his vorpal blade, but no manxome foe does he fear. Beware jabberwock!!!
-apologies to the Rev Charles Dodgson (deceased)
Gordon: Has reached the end!
|
|
-
10-30-2008, 9:23 AM |
-
tronic
-
-
-
Joined on 06-18-2008
-
-
Posts 47
-
-
|
Re: A C# form test prog to see what the remote control is doing
Hey People. I will bring back this Thread up to the top :). I have test your Background app. Works fine. Now I have adapt the Code to a separate Class (see appendix) In my app I want to use it like this VMCRemoteControl rc = new VMCRemoteControl(); and in the HandleRemoteControlKeys(int vkCode) Method I want to handle with a switch block the Keys. VMCRemoteControl.csDebbugging shows me, that the rc-Object is built, but he never breaks at the HandleRemoteControlKeys or HookCallBack Method. Why not? Is it generally possible to hook Keys like numeric 0 inside of my Addin-Code with this LowLevelKeyBoardHook? Saw and test Projects like VMCControl and others. But they only can send Input. I want to receive from RemoteControl inside Media Center :) For a form it is easy. best regards, tronic
|
|
-
10-30-2008, 9:31 AM |
-
AndyC
-
-
-
Joined on 06-14-2006
-
UK
-
Posts 1,858
-
-
|
Re: A C# form test prog to see what the remote control is doing
tronic,
What is it that you are trying to do? The same applies here as to Gordon - this is a very complex way of getting a keypress from Media Center that you shouldn't use unless you really have to.
Cheers, Andrew
|
|
Page 1 of 2 (23 items)
1
|
|