Can a C# program that has focus artificially generate a key event that will be handled by another open application?
For those who are curious, this is why I'm asking:
I'm currently working on a demo/mockup for a design idea for a gesture based media player, using the Kinect as a primary input device. This is something I decided to do on as a favor, and it neither needs nor deserves a ton of my time as far as programming goes.
So to speed things along, I'm using the FAAST tool which you can use to easily bind key events to certain gestures. So, you turn on this program, tell it what key maps to what gesture, then when you make the gesture the key is registered as pressed by the current application.
What I would like to create is a go-between that will display a simple GUI that I'll display to the audience. At a certain point, the user will make the "select" gesture, and I want music to start playing in an open media player. So, I would check their place in the menu hierarchy, see that they've selected "music" based on some key I choose to arbitrarily mean select, then generate a key event with the MediaPlayPause key.
It requires a little p/invoke work to do from C# but it's not complicated. You'll use the FindWindow API to get an hWnd for the target program, then the PostMessage API to send key events:
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true)]
private static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
private const UInt32 WM_KEYDOWN = 0x0100;
private const UInt32 WM_KEYUP = 0x0101;
public static void SendSelect(IntPtr HWnd)
{
PostMessage(HWnd, WM_KEYDOWN, KeyInterop.VirtualKeyFromKey(System.Windows.Input.Key.Enter), 0);
}
I wanna send key stroke to a program even if it is running in background. But I can do this only for NOTEPAD like this,
[DllImport("user32.dll")]
protected static extern byte VkKeyScan(char ch);
[DllImport("user32.dll", SetLastError = true)]
protected static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("User32.Dll", EntryPoint = "PostMessageA")]
protected static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
char Key = // key value to send
IntPtr hWnd = FindWindowEx(_handle, IntPtr.Zero, "edit", null); // _handle is the windows handle of the program (here its notepad)
PostMessage(hWnd, WM_KEYDOWN, VkKeyScan(Key), 0);
But for all other applications I can't send keystrokes if its in background. Since I don't know the lpszClass of that program (I think this is the userControl name of the typing area in that program. For NotePad it is "edit". I found this surfing internet).
For all other applications what I'm doing is, get the application to foreground, then send the key, then again get my program foreground. I need my program to be run as foreground always.
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
SetForegroundWindow(_handle); // _handle is the windows handle of the program
System.Threading.Thread.Sleep(50); // Waiting few milliseconds till application coming to foreground.
wsh.SendKeys(Key.ToString(), ref wait); // wsh is WshShellClass wsh= new WshShellClass();
SetForegroundWindow(_mainHandle); // _mainHandle is the windows handle of my application
But this way is not working. some keys getting missed and the program foreground->background->foregound->background...... like its dancing...
How to send keys to other applications if its running in background.
or are there any way/source to find the lpszClass of a program ?
Sorry if I have missed any required information. this is a large application. I have posted only required parts here. If someone needs any additional information, pls ask.
I think you'll need to have the background program install a low-level keyboard hook via the win32 function SetWindowsHookEx().
Here's the MSDN documentation for SetWindowsHookEX()
http://msdn.microsoft.com/en-us/library/ms644990(v=vs.85).aspx
And here's the KB article on how to do it from C#
http://support.microsoft.com/kb/318804
This article goes into some detail, too: http://www.codeguru.com/columns/vb/article.php/c4829
I expect your app will get caught by various spyware/anti-virus software as a keyboard logger, though.
Good luck.
You may be able to figure out the lpszClass of the program using an inspection tool such as WinSpy++. It gives you a crosshair that you can drag and position over the desired control. This was able to easily provide me with the "edit" class name for notepad.
If things aren't working, click the "More>>" button in the lower right of WinSpy++, then click the "Locate" button to view the control hierarchy; you may need to post the WM_KEYDOWN message to one of the parent or child controls instead.
How can I programmatically create an event that would simulate a key being pressed on the keyboard?
The question is tagged WPF but the answers so far are specific WinForms and Win32.
To do this in WPF, simply construct a KeyEventArgs and call RaiseEvent on the target. For example, to send an Insert key KeyDown event to the currently focused element:
var key = Key.Insert; // Key to send
var target = Keyboard.FocusedElement; // Target element
var routedEvent = Keyboard.KeyDownEvent; // Event to send
target.RaiseEvent(
new KeyEventArgs(
Keyboard.PrimaryDevice,
PresentationSource.FromVisual(target),
0,
key)
{ RoutedEvent=routedEvent }
);
This solution doesn't rely on native calls or Windows internals and should be much more reliable than the others. It also allows you to simulate a keypress on a specific element.
Note that this code is only applicable to PreviewKeyDown, KeyDown, PreviewKeyUp, and KeyUp events. If you want to send TextInput events you'll do this instead:
var text = "Hello";
var target = Keyboard.FocusedElement;
var routedEvent = TextCompositionManager.TextInputEvent;
target.RaiseEvent(
new TextCompositionEventArgs(
InputManager.Current.PrimaryKeyboardDevice,
new TextComposition(InputManager.Current, target, text))
{ RoutedEvent = routedEvent }
);
Also note that:
Controls expect to receive Preview
events, for example PreviewKeyDown
should precede KeyDown
Using target.RaiseEvent(...) sends the event directly to the target
without meta-processing such as
accelerators, text composition and
IME. This is normally what you want.
On the other hand, if you really do
what to simulate actual keyboard keys
for some reason, you would use
InputManager.ProcessInput() instead.
To produce key events without Windows Forms Context,
We can use the following method,
[DllImport("user32.dll")]
public static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo);
sample code is given below:
const int VK_UP = 0x26; //up key
const int VK_DOWN = 0x28; //down key
const int VK_LEFT = 0x25;
const int VK_RIGHT = 0x27;
const uint KEYEVENTF_KEYUP = 0x0002;
const uint KEYEVENTF_EXTENDEDKEY = 0x0001;
int press()
{
//Press the key
keybd_event((byte)VK_UP, 0, KEYEVENTF_EXTENDEDKEY | 0, 0);
return 0;
}
List of Virtual Keys are defined here.
To get the complete picture, please use the below link,
http://tksinghal.blogspot.in/2011/04/how-to-press-and-hold-keyboard-key.html
I've not used it, but SendKeys may do what you want.
Use SendKeys to send keystrokes and
keystroke combinations to the active
application. This class cannot be
instantiated. To send a keystroke to a
class and immediately continue with
the flow of your program, use Send. To
wait for any processes started by the
keystroke, use SendWait.
System.Windows.Forms.SendKeys.Send("A");
System.Windows.Forms.SendKeys.Send("{ENTER}");
Microsoft has some more usage examples here.
Easily!
(because someone else already did the work for us...)
After spending a lot of time trying to this with the suggested answers I came across this codeplex project Windows Input Simulator which made it simple as can be to simulate a key press:
Install the package, can be done or from the NuGet package manager or from the package manager console like:
Install-Package InputSimulator
Use this 2 lines of code:
inputSimulator = new InputSimulator()
inputSimulator.Keyboard.KeyDown(VirtualKeyCode.RETURN)
And that's it!
-------EDIT--------
The project page on codeplex is flagged for some reason, this is the link to the NuGet gallery.
Windows SendMessage API with send WM_KEYDOWN.
Basically I want to simulate in code a user clicking on the windows key. I know there is SendKeys which allows me to send key presses to windows if I get a handle to them, but what I can't figure out is what I need to get a handle on in order to send Windows key commands. E.g. Windows key + L. Having read into this a bit it appears that CTRL-ESC should pop up the Start Menu also but not sure how to tell it to send the keys to Windows (if this is even possible). Any help would be much appreciated.
Cheers!
I don't think you can do this using SendKeys, you will need to p/invoke to an API function instead, probably keybd_event to send either CTRL+ESC or the Windows key.
Here is an example of opening the start menu this way in VB and here is keybd_event with its C# signature on pinvoke.net.
Some of the things that a user would do via a WinKey shortcut can be done programmatically in other ways. To take your WinKey+L example, you could instead just use the following statement:
Process.Start("rundll32.exe", "user32.dll,LockWorkStation");
If you could elaborate on what exactly you're trying to accomplish, maybe there's a better way than keybd_event (as Dale has suggested).
I've used the class provided here by user703016 and worked fine!
for ref:
using System.Runtime.InteropServices;
using System.Windows.Forms;
static class KeyboardSend
{
[DllImport("user32.dll")]
private static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
private const int KEYEVENTF_EXTENDEDKEY = 1;
private const int KEYEVENTF_KEYUP = 2;
public static void KeyDown(Keys vKey)
{
keybd_event((byte)vKey, 0, KEYEVENTF_EXTENDEDKEY, 0);
}
public static void KeyUp(Keys vKey)
{
keybd_event((byte)vKey, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
}
}
used in this way:
KeyboardSend.KeyDown(Keys.LWin);
KeyboardSend.KeyDown(Keys.D4);
KeyboardSend.KeyUp(Keys.LWin);
KeyboardSend.KeyUp(Keys.D4);
You need to use a global keyboard hook to hook into keyboards outside your application. There's an article on how to do it here.
I have a requirement that an application I am working on prevent the user from being able to easily capture the contents of the screen.
I have communicated that there is no feasible way to completely prevent this from happening, but I'm looking for methods to introduce some hurdles to the process.
I'm using C#/.NET 2.0 and WinForms
You can't.
The best you can do is render to a hardware accelerated device on an overlay, similar to what video players used to do. Basically, you paint your entire window blue, and render your graphics onto the video card, and internally the video card will replace the blue with the graphics. The downside to this is you have to give up using winforms controls, and I don't know of any way to do this with .NET easily. I think if you use DirectShow.NET, one of their samples is putting your own graphics into a stream.
Even after doing all of that, it's still possible to get a screenshot. Just take a picture of the screen with a digital camera.
From here:
A. Windows implements Print Screen using a registered hotkey. Windows
uses the predefined hotkeys IDHOT_SNAPDESKTOP and IDHOT_SNAPWINDOW to
handle Print Screen. These correspond to Print Screen, which captures
the entire screen, and Alt+Print Screen, which captures only the
active window. To disable these functions all you have to do is
register the hotkeys, which causes Windows to send your app a
WM_HOTKEY message when the user presses either hotkey. Your
implementation can ignore the message to bypass the default
screen-capture behavior. A good place to do it is in your mainframe
class.
FWIW, it is possible. Here's some code:
This would be a dll that you create, then call the HookKeyboard method from your application. I've tested it and it works. Granted, if someone takes a picture with a camera it can't help, but, point made. NYAH!
namespace KeyboardHook
{
public class Hooker
{
[StructLayout(LayoutKind.Sequential)]
public struct KBDLLHOOKSTRUCT
{
public int vkCode;
public int scanCode;
public int flags;
public int time
;
public int extraInfo;
}
public delegate int HookProc(int nCode, int wParam, IntPtr ptrKBDLLHOOKSTRUCT);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(int idHook, HookProc callBack, IntPtr hMod, int threadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern int CallNextHookEx(IntPtr hhk, int nCode, int wParam, IntPtr lParam);
private static IntPtr kbh_Handle;
private static HookProc kbh_HookProc;
private const int VK_SNAPSHOT = 0x2C;
private const int WM_KEYDOWN = 0x0100;
private const int WM_SYSKEYDOWN = 0x0104;
private const int WH_KEYBOARD_LL = 13;
private static int LowLevelKeyboardProc(int nCode, int wParam, IntPtr lParam)
{
if (nCode < 0)
{
CallNextHookEx(kbh_Handle, nCode, wParam, lParam);
return 0;
}
if (wParam == WM_KEYDOWN)
{
IntPtr kbdll = lParam;
KBDLLHOOKSTRUCT kbdllstruct = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(kbdll, typeof(KBDLLHOOKSTRUCT));
if (kbdllstruct.vkCode == VK_SNAPSHOT)
return -1;
}
return CallNextHookEx(kbh_Handle, nCode, wParam, lParam);
}
public static void HookKeyboard()
{
try
{
kbh_HookProc = LowLevelKeyboardProc;
kbh_Handle = SetWindowsHookEx(WH_KEYBOARD_LL, kbh_HookProc, Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0);
if (kbh_Handle != IntPtr.Zero)
System.Diagnostics.Debug.WriteLine(String.Format("It worked! HookHandle: {0}", kbh_Handle));
else
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(String.Format("ERROR: {0}", ex.Message));
}
}
}
}
You can try using IpcProtectWindow provided in msipc.dll.
[DllImport("msipc.dll", SetLastError = false, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
internal static extern int IpcProtectWindow([In] IntPtr hwnd);
Download the SDK from Microsoft
Call the function above and provide the handle of the form you would like to protect. (Form.Handle property)
You'll have two cases here that you need to worry about. One, when your window/application has focus, the other when it doesn't have focus.
When it doesn't have focus, there's not a whole lot you can do, i.e. if the user clicks off of your app and onto the desktop, keys aren't sent to your app so you'll never see them. In that case, you can minimize to the tray when your app loses focus (or, perhaps, place a "blank" panel over the form to prevent users from seeing anything on it which will also prevent a print-screen from being useful).
In the other case, when you have focus, capture keystrokes and examine them. If the Alt key is down and the PrintScreen key is down, reset the value so that a print-screen doesn't occur. (Come to think of it, that may not work. I'd need to test it to be sure.)
You could look into what movie players do. I believe they render directly to a hardware surface (via DirectX). I suspect that you'd need to do this.
This doesn't really answer the questions, but keep in mind that there exists tools to capture screen, and that a simple camera breaks everything.
I mean ok you "have to", but I would (but I'm young and still student, so I don't know much about what can be said) answer that this is just stupid.
Check out the new tech - sivizion.com, they prevent print screen all together - no way to bypass it. If anyone will figure out a way how to hack it, please post here, I couldn't. I think they also license their tech, not sure, check it out.
Well, you could try capturing the button, but I'm not sure how well that will work.
One thing that always annoyed me was that whenever I played a movie, it would never take screenshots of it. If you can render through a separate context, it would make it really annoying to take a picture of it. Perhaps you can send your screen output through something like that?
There are applications that can capture the screen from OpenGL and DirectX apps ! (depending (they are used for recording game movies)
ps. windows aero is DirectX
http://www.fraps.com/
i think thats the application
You can make any casual Print Screen useless using Visual Cryptography and taking advantage of retinal persistence (see this article for details, and bit.ly/vcrypto for a web demo).
The idea is to alternate at high frequency between two or more random noise images, that will combine through persistence of vision to reveal the content. A screen capture will only grab one image, with meaningless random noise.
This comes at the cost of flickering and inducing user headaches, can be defeated by a camera taking a picture of the screen, or by a less casual user that knows photoshop, but will defeat any kind of casual screen capture or frame grabbing.
Might occasionally be useful, in an academic meaning of the term!
It is too late but there is a quick work around,
Simply use it in MDI form
Set TopMost Property of form True, then write below event
private void frmMDI_Deactivate(object sender, EventArgs e){Clipboard.Clear();}
after taking print screen user have to minimize the application, the moment user minimize the app, we are clearing clipboard.
you can use this in logout function or when screen move or resize or any other form event as required :)
Snipping tool also can't copy screens by this if TopMost Property is true.
Yes we can't stop user from capturing screen from external device like phone or cam.
In windows form application, Use this code in form keyup event,
if (e.KeyCode == Keys.PrintScreen)
{
Clipboard.Clear();
}
Form keypreview should be TRUE
Microsoft has been developed an API named SetWindowDisplayAffinity to support the window content protection. This feature enables applications to protect application content from being captured or copied through a specific set of public operating system features and APIs
SetWindowDisplayAffinity(hWnd, WDA_MONITOR);
I solved it using a Timer object and Clipboard.Clear() method.
First add a Timer to your main form with Interval=1 (Very fast), then add the following code in its event:
Clipboard.Clear();