Using Remote Control Input Outside of Windows Media Center C# - c#

I would like to make a very simple C# windows form application (or WPF) that can be controlled by the Media Center Remote Control that came with the computer.
It's a very simple app that has an event listener that receives messages from the remote and calls the appropriate function.
I found this article that explains how to do it yet I was not able to follow up:
http://msdn.microsoft.com/en-us/library/windows/desktop/bb417079.aspx
I've read the article many times yet I have no clue how execute it.
I'm novice when it comes to HID programing,
so please try to be as clear and detailed as possible.
A full example would be appreciated.
Thank You
Thank You Corey your answer was very helpfull, I mixed it with another code I found:
http://discuss.mediacentersandbox.com/forums/thread/8549.aspx
and it worked

I don't have a Media Center Remote to test with, but from what I can find...
Pressing buttons on the MC remote will result in one of three types messages being sent to your application: WM_APPCOMMAND, WM_KEYDOWN or WM_INPUT. The first two are fairly simple - just synthetic keyboard interactions. The third is the difficult one.
First, you need to call RegisterRawInputDevices with an array of RAWINPUTDEVICE structures that indicate the data your application is interested in. In this case you'll need at least Page 0x000C Collection 0x01 and Page 0xFFBC Collection 0x88 to get the majority of the buttons. If you want to handle the Standyby button you also need Page 0x0001 Collection 0x80.
After that call you will get WM_INPUT messages for each button. This is as far as I can go at the moment, since I haven't found a decent explanation of the content of the HIDRAW structure beyond the fact that it can contain data for multiple events. I'd suggest dumping it out and seeing if you can locate the appropriate codes - from the Button Usage ID column.
Edit: processing the messages
In order to process the WM_APPCOMMAND messages you'll need to override the WndProc method of your form:
// Some of the named constants:
const int WM_APPCOMMAND = 0x0319;
const int APPCOMMAND_BROWSER_BACK = 1;
const int APPCOMMAND_MEDIA_CHANNEL_DOWN = 52;
const int APPCOMMAND_MEDIA_CHANNEL_UP = 51;
const int APPCOMMAND_MEDIA_FAST_FORWARD = 49;
const int APPCOMMAND_VOLUME_MUTE = 8;
const int APPCOMMAND_MEDIA_PAUSE = 14;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_APPCOMMAND)
{
int lParam = unchecked ((int)m.LParam);
int cmd = unchecked ((short)((uint)lParam>>16));
switch (cmd)
{
case APPCOMMAND_BROWSER_BACK:
// process 'back' button
break;
case APPCOMMAND_MEDIA_CHANNEL_DOWN:
// process 'channel down' command
break;
}
}
base.WndProc(ref m);
}
There are more, but that's the gist of it. You'll need to find the values for the various named constants.

Related

C# Detect Keystrokes and Send to Background Windows

I've looked around for six hours today in search of a method to complete the task I'm looking to accomplish. However with little luck every method I've tried has come out not working.
So the program I'm working on is a multiboxing application for video games. Essentially I want to have my created application running in the background. The user will check on checkbox's to state which keys they want to be captured, so not every key is being captured. Then while they are playing the main game, the application will send the keys that are checked to the games running in the background.
I've tried global hotkeys however never could get more than one key working. I've also tried to hook keys but for some reason, couldn't get that functional. I also dabbled into sendmessage with little luck there either.
Was just curious if anyone else had some ideas for going about doing this. To give an example of another program that does this same thing would be HotKeyNet, KeyClone, and ISboxer. I know there are more out there but that gives you an idea of what I'm trying to do with my application.
Alright, after quite a bit of research into different methods for sending keystrokes and reading keystrokes. I finally was able to splice to different types of coding together to provide the results I was looking for.
I'm posting up the answer, so anyone that is looking for the answer to this question later down the road has it available to them.
My two references for splicing this code together are the following:
http://www.codeproject.com/Articles/19004/A-Simple-C-Global-Low-Level-Keyboard-Hook
Send combination of keystrokes to background window
I used the global low level hook and postmessage for sending keystrokes to the background application.
So first you will need to follow the instructions from the first
link, to get the starting code working.
Download the working source code from link one, and use the
globalKeyboardHook.cs in your application.
Then in references place the following:
using System.Runtime.InteropServices; //Grabs for your DLLs
using Utilities; //Grabs from the file you added to your application.
Now you will want to place the following code in your class:
globalKeyboardHook gkh = new globalKeyboardHook();
[DllImport("user32.dll")] //Used for sending keystrokes to new window.
public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", EntryPoint = "FindWindow", CharSet = CharSet.Ansi)] //Used to find the window to send keystrokes to.
public static extern IntPtr FindWindow(string className, string windowName);
Now go ahead place your keystrokes you want to be grabbed this I
found is best in Form1_Loaded:
gkh.HookedKeys.Add(Keys.A);//This collects the A Key.
gkh.HookedKeys.Add(Keys.B);//This collects the B Key.
gkh.HookedKeys.Add(Keys.C);//This collects the C Key.
gkh.KeyDown += new KeyEventHandler(gkh_KeyDown); //Event for pressing the key down.
gkh.KeyUp += new KeyEventHandler(gkh_KeyUp); //Event for the release of key.
After that you will want to go ahead and place in the following in
your code as well:
void gkh_KeyUp(object sender, KeyEventArgs e) //What happens on key release.
{
lstLog.Items.Add("Up\t" + e.KeyCode.ToString());
e.Handled = false; //Setting this to true will cause the global hotkeys to block all outgoing keystrokes.
}
void gkh_KeyDown(object sender, KeyEventArgs e) //What happens on key press.
{
lstLog.Items.Add("Down\t" + e.KeyCode.ToString());
e.Handled = false;
}
Once that is in place just put this little bit in the gkh_KeyDown to
get your keystrokes to send to another window of your choosing:
const uint WM_KEYDOWN = 0x100;
IntPtr hWnd = FindWindow(null, "Example1"); //Find window Example1 for application.
switch (e.KeyCode)
{
case Keys.A: //Makes it so it only sends that key when it's pressed and no other keys.
if(chkA.Checked == true)
{
PostMessage(hWnd, WM_KEYDOWN, (IntPtr)(Keys.A), IntPtr.Zero); //Sends to key A to new window assigned hWnd which equals Example1.
}
break;
}
}
The code that I have provided is setup so people can use checkbox's to tell the program which keys they want to send over to the second application.
If you have any questions regarding to this post just let me know, and I will do my best to walk you through the process. Hope this helps someone out later down the road.
My suggestion is to go with "mapped memory" (in operating system concepts: shared memory)
First process creates (may be your check state program) creates a mapped memory and writes values to it.
All other game process reads the value from memory map created by first process.
Here is a very nice example regarding how to do it.
https://msdn.microsoft.com/en-us/library/dd267552(v=vs.110).aspx

Clipboard Monitor

I have a problem. I am trying to use the ClipboardMonitor for my C# Application. The goal is to monitor every change in the clipboard.
To start monitoring:
AddClipboardFormatListener(this.Handle);
To stop the listener:
RemoveClipboardFormatListener(this.Handle);
And the override WndProc() method:
const int WM_DRAWCLIPBOARD = 0x308;
const int WM_CHANGECBCHAIN = 0x030D;
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_DRAWCLIPBOARD:
IDataObject iData = Clipboard.GetDataObject();
if (iData.GetDataPresent(DataFormats.Text))
{
ClipboardMonitor_OnClipboardChange((string)iData.GetData(DataFormats.Text));
}
break;
default:
base.WndProc(ref m);
break;
}
}
And of course the DLL import:
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool AddClipboardFormatListener(IntPtr hwnd);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool RemoveClipboardFormatListener(IntPtr hwnd);
But when putting a breakpoint at the method call ClipboardMonitor_OnClipboardChange and changing the clipboard, I never get the method called.
How can I change my code so that I receive a WM_ message notifying me that the clipboard has changed?
The problem is that you're handling the wrong window message. Quoting the documentation for AddClipboardFormatListener:
When a window has been added to the clipboard format listener list, it is posted a WM_CLIPBOARDUPDATE message whenever the contents of the clipboard have changed.
With that knowledge, change the code to:
const int WM_CLIPBOARDUPDATE = 0x031D;
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_CLIPBOARDUPDATE:
IDataObject iData = Clipboard.GetDataObject();
if (iData.GetDataPresent(DataFormats.Text))
{
string data = (string)iData.GetData(DataFormats.Text);
}
break;
default:
base.WndProc(ref m);
break;
}
}
SharpClipboard as a library could be of more benefit as it encapsulates the same features into one fine component library. You can then access its ClipboardChanged event and detect various data-formats when they're cut/copied.
You can choose the various data-formats you want to monitor:
var clipboard = new SharpClipboard();
clipboard.ObservableFormats.Texts = true;
clipboard.ObservableFormats.Files = true;
clipboard.ObservableFormats.Images = true;
clipboard.ObservableFormats.Others = true;
Here's an example using its ClipboardChanged event:
private void ClipboardChanged(Object sender, ClipboardChangedEventArgs e)
{
// Is the content copied of text type?
if (e.ContentType == SharpClipboard.ContentTypes.Text)
{
// Get the cut/copied text.
Debug.WriteLine(clipboard.ClipboardText);
}
// Is the content copied of image type?
else if (e.ContentType == SharpClipboard.ContentTypes.Image)
{
// Get the cut/copied image.
Image img = clipboard.ClipboardImage;
}
// Is the content copied of file type?
else if (e.ContentType == SharpClipboard.ContentTypes.Files)
{
// Get the cut/copied file/files.
Debug.WriteLine(clipboard.ClipboardFiles.ToArray());
// ...or use 'ClipboardFile' to get a single copied file.
Debug.WriteLine(clipboard.ClipboardFile);
}
// If the cut/copied content is complex, use 'Other'.
else if (e.ContentType == SharpClipboard.ContentTypes.Other)
{
// Do something with 'e.Content' here...
}
}
You can also find out the application that the cut/copy event occurred on together with its details:
private void ClipboardChanged(Object sender, SharpClipboard.ClipboardChangedEventArgs e)
{
// Gets the application's executable name.
Debug.WriteLine(e.SourceApplication.Name);
// Gets the application's window title.
Debug.WriteLine(e.SourceApplication.Title);
// Gets the application's process ID.
Debug.WriteLine(e.SourceApplication.ID.ToString());
// Gets the application's executable path.
Debug.WriteLine(e.SourceApplication.Path);
}
There are also other events such as the MonitorChanged event which listens whenever clipboard-monitoring is disabled, meaning that you can enable or disable monitoring the clipboard at runtime.
In addition to all this, since it's a component, you can use it in Designer View by dragging-and-dropping it to a Windows Form, making it super easy for anyone to customize its options and work with its inbuilt events.
SharpClipboard seems to be the very best option for clipboard-monitoring scenarios in .NET.
Just to add to theB's excellent answer ...
The WM_DRAWCLIPBOARD message is an older message used after setting up a "Clipboard Viewer Window." This dates back at least to Windows 95. Starting with Windows Vista and Windows Server 2008, the "Clipboard Format Listener" API was added.
The old Clipboard Viewer Window required more work:
Add your window into the chain of objects receiving clipboard messages by calling the SetClipboardViewer() API.
You receive a WM_CHANGECBCHAIN message when another window in the chain adds or removes itself from the chain, and you are required to process that message by passing it on to the next window in the chain with the SendMessage() API.
When you receive the WM_DRAWCLIPBOARD message, you also needed to pass the message along to the next object (hwnd) in the chain, using the SendMessage() API. Then you could process the changed contents of the Clipboard.
When you close your program, you needed to remove it from the chain, using the ChangeClipboardChain() API.
The newer Clipboard Format Listener only requires:
Start monitoring the clipboard by calling the AddClipboardFormatListener() API.
Wait for the WM_CLIPBOARDUPDATE message to notify you of changed clipboard contents.
Before closing your program, stop the monitoring by calling RemoveClipboardFormatListener().
All issues relating to the chain of notification are handled automatically by Windows.
Another key difference: WM_DRAWCLIPBOARD is a sent (non-queued) message, which will have to be processed by your program immediately. WM_CLIPBOARDUPDATE is a posted (queued) message, which will be added to a queue, where it will be handled after your program is finished executing its current process.
This means that when the WM_DRAWCLIPBOARD message comes through, your program will have to process it immediately, even if you are in the middle executing code. For example, let's say you've created a clipboard monitor that allows you to save and retrieve past clips, and load those past clips to the clipboard. You've decided to use the older SetClipboardViewer() API, which will trigger the WM_DRAWCLIPBOARD message when the clipboard changes. When you execute the code to load the old clip back into the clipboard, you have just changed the clipboard contents, which will trigger the message. If you are stepping through your C# code line by line in Visual Studio, the Clipboard.SetText() method will trigger the message and you will be taken immediately back to your WndProc() method, starting that whole process all over again. When the WndProc() method is finished, you will continue on to the next line of code after Clipboard.SetText().
If instead, you use the newer AddClipboardFormatListener() API, you can use the Clipboard.SetText() method also, but it won't trigger an immediate message. The WM_CLIPBOARDUPDATE message is added to a queue, and it won't be processed by your program until your code is finished executing. If you are stepping through the code line by line, you can execute the Clipboard.SetText() method and simply move on to the next line. When your program finishes whatever it is doing, you will then be taken back to the WndProc() method to deal with the WM message. Here is some Microsoft documentation about message queuing and routing:
Windows Message Routing
There will be times when our program will need to treat WM messages in different ways, depending on what has triggered the message. If the end user copies a new clip into the clipboard, we will want to process that WM message. If the end user uses our program to load a saved old clip back into the clipboard, we will want our program to ignore the WM message that results from that. One way to ignore a WM message is to create a public class integer property called "Ignore". Every time our code changes the clipboard contents (instead of the user copying something new), we FIRST increment (increase) the Class.Ignore property. We add an If statement in the WndProc() method to only process a WM clipboard message if the ignore property is zero. If Class.Ignore is greater than zero, WndProc() will ignore the message. Every time it ignores a message, it also decrements (decreases) the Class.Ignore integer. That is how the program can know if the WM_ message was generated from copying a new clip, or from an old clip being re-loaded into the clipboard.
Just remember that the newer AddClipboardFormatListener() API requires Windows Vista (Client machine) or Windows Server 2008 (server machine) or later. But according to this article in August, 2021, only about 0.5% or less of Windows users are still on XP or older.
Here is a writeup for implementing the Clipboard Format Listener in C#:
Monitor for clipboard changes using AddClipboardFormatListener
And here is the Microsoft Documentation (in C++) for anyone interested:
Microsoft Documentation on monitoring the clipboard
Best of luck to everyone in their coding.

Send Windows key keypress into application [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to detect the currently pressed key?
(EDIT: For what it's worth, this is not a duplicate... not sure why it was voted as such)
I have a small timer application that we use in the office to track the hours spent on a project. There is a start and stop button, and a project and task fields. When we go on break and to lunch and other things, we stop the timer for that project, then restart it. This is a repetitive task that generally involves digging the window out from behind several other Windows, then the same after the break.
What I want to do is assign WindowKey+W to the work timer application and have it not only bring the timer application to the front and focus it, but also have it toggle the Start/Stop.
I have tried a number of searches, but I can't seem to narrow down the examples to what I want. I do know that you can open the properties of a Windows shortcut and assign a shortcut key to launch a program, and (I guess?) if you have that app already open and it is set to allow only one instance of the program that it will bring that program to the front??? maybe..
Anyway.. but that method will not accept the WindowsKey as a valid key combo. And I don't know if it can somehow pass that key combo in to the program.
I appreciate any help or direction here!!
EDIT - Answer Update
Thank you #huadianz for your answer! I converted your code to VB:
Public Const MOD_WIN As Integer = &H8
Public Const KEY_W As Integer = &H57
<DllImport("user32.dll")> _
Public Shared Function RegisterHotKey(hWnd As IntPtr, id As Integer, fsModifiers As Integer, vlc As Integer) As Boolean
End Function
<DllImport("user32.dll")> _
Public Shared Function UnregisterHotKey(hWnd As IntPtr, id As Integer) As Boolean
End Function
Public Sub RegisterKeys()
RegisterHotKey(Me.Handle, 1, MOD_WIN, KEY_W)
End Sub
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
MyBase.WndProc(m)
If (m.Msg = &H312) Then
Me.TopMost = True
Me.PlayPauseTimer()
Me.TopMost = False
End If
End Sub
On an interesting note, Me.BringToFront() would not actually bring the application to the front in this scenario in Win7, nor did Me.Focus(). However, Me.TopMost = True worked, but it has the secondary effect of making the window always on top. Setting it to True, toggling the timer, then setting it back to False works great!
If you want full operating system intergration, you can hook into the kernel input functions by using PInvoke.
What you are looking for is the explorer.exe Windows API function, described in detail here:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646309%28v=vs.85%29.aspx
Using PInvoke, you can invoke this C++ function
[DllImport("user32.dll")]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc);
[DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
public const int MOD_WIN = 0x00000008;
public const int KEY_W = 0x00000057
public static void RegisterKeys()
{
RegisterHotKey((IntPtr)this.Handle, 1, MOD_WIN, KEY_W);
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == 0x0312)
this.Visible = !this.Visible;
}
I would also suggest looking at Auto Hotkey: http://www.autohotkey.com/. If all you're after is sending a window to front on key-press then you may find it faster to learn AHK and write a script to do so (be only 1 or 2 lines) than writing something in C# or VB.
*edit*As regards pressing a button automatically, if it's set as the default button then you can just send the enter keystroke to it. Otherwise you may need to send a mouse click even to the window. Neither is particularly difficult once you have the first part done.
#W::MsgBox "This is a message box. You just need to use something like send to send keystrokes and other commands to the window you want to control, instead of the this message box."
You can use Windows SendKeys. If you look at that link it shows the codes and syntax for applying a ctrl, alt or shift key. I imagine you can send these keys to your application to simulate a shortcut press.

C# For how long was user inactive

Some background:
I am writing a application with several forms, etc. Users have to log in in order to use most of the features, and this worked fine until now. However, now, client has requested that the user would be logged out after a certain amount of inactive time. The problem is that the user can still be active on the computer, just not in my application,. To be clear, I have to log the user out when he is inactive in my application, even if he is still interacting with the desktop.
First I thought this would be fairly simple. Just remember the time of the last action, compare it continually in a timer with current time and log out the user if the time passed is greater than the allowed time. However I have realised that finding out the last action time may not be so simple...
Of course I could copy paste something like
Program.LastActionTime = DateTime.Now;
in every OnChange, OnClick, etc, event ... However not only that this would be a great amount of work because of the size of the application ... It would also be a very bad practice and I'm sure it would be forgot at least once, making the whole thing unreliable (And appear broken, the bug would be almost impossible to reproduce!)
So, is there a better way?
One approach that I've used in the past, create a MessageFilter on your application form and check for certain types of events that indicate user activity:
public class UserActivityFilter : IMessageFilter
{
// Define WinAPI window message values (see pinvoke.net)
private int WM_LBUTTONDOWN = 0x0201;
private int WM_MBUTTONDOWN = 0x0207;
private int WM_RBUTTONDOWN = 0x0204;
private int WM_MOUSEWHEEL = 0x020A;
private int WM_MOUSEMOVE = 0x0200;
private int WM_KEYDOWN = 0x0100;
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == WM_LBUTTONDOWN || m.Msg == WM_MBUTTONDOWN || m.Msg == WM_RBUTTONDOWN || m.Msg == WM_MOUSEWHEEL || m.Msg == WM_MOUSEMOVE || m.Msg == WM_KEYDOWN)
{
//User activity has occurred
// Reset a flag / timer etc.
}
return false;
}
}
Then in the Main() method of the form, BEFORE the call to Run():
Application.AddMessageFilter(new UserActivityFilter());
One caveat, adding a complex message filter or adding multiple separate filters can slow down the responsiveness of your application.
In your Program.CS file, you can handle the Application.Idle event and reset your timer there. See:
http://msdn.microsoft.com/en-us/library/system.windows.forms.application.idle.aspx
You can override WndProc, update Program.LastActionTime on each relevant Keyboard/Mouse event message.
Hook an event handler on the MouseMove and KeyPressed events, and then check for focus inside that event?
In general it would be the best idea to derive this information from your application logic instead of raw user input, but I assume you have no flexible infrastructure (maybe using the command pattern) that could provide this information.
So I suggest just to register handlers with your main form - if you receive clicks or key events (enable Form.KeyPreview for this), your user is active and you can reset the inactivity time.
You could create a base class that all your window forms inherits from. In the base class you check and reset your timeout on every KeyPress or Click.

c# SendKey to a hidden window

I have a window which is hidden and I would like to send a keypress to it. An example of what I'm trying to achieve is an app that will send the key F5 to a web browser which wasn't the active window. The web browser would know to refresh the current page when the F5 keystroke is received.
I would also like to send a combination of keys to an application, e.g. Ctrl+S. One example of this usage could be a timed auto-save feature to use with applications which don't have autosave. This would spare me having to remember to save every 5 mins.
C# is my technology, does this sound realistic?
This CodeProject article shows how to send keystrokes to an external application (with C# source code).
You can use WinApi for this purpose. SendMessage or PostMessage method to send desired message to your application.
Here's C# definition of SendMessage
[DllImport("user32.dll")]
public static extern int SendMessage(
int hWnd, // handle to destination window
uint Msg, // message
long wParam, // first message parameter
long lParam // second message parameter
);
and define the message that you want to send like:
public const uint %WM_MESSAGE_HERE% = %value%;
Check PInvoke - great resource containing WinApi method definitions for .NET
This should be possible, look at www.pinvoke.net and search for sendinput, that page should tell you everything you need to know, also how to find the window (look for findwindow)

Categories