Distinguish mice devices from a LowLevel mouse hook - c#

I have a virtual mouse driver and an actual mouse on my computer.
I'm using LowLevelMouseProc to capture events windows wide and I would like to not process events from the virtual mouse.
I cannot use RawInput as I need to process message of another process.
Is there any way to know which device has sent the message ?
Forcing the dwExtraInfo also on a real mouse device may help me if possible.
private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
MSLLHOOKSTRUCT hookStruct;
if (nCode < 0)
{
return CallNextHookEx(_hookId, nCode, wParam, lParam);
}
hookStruct = (MSLLHOOKSTRUCT) Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
// I'd like to know from here which mouse has sent the message.
return CallNextHookEx(_hookId, nCode, wParam, lParam);
}

There is nothing exposed from the .NET Windows API to distinguish between different mice. There was a Microsoft SDK for multiple inputs at one time but it was dropped before Windows 10 so it likely doesn't work anymore.
rawinput-sharp shows how to do it but it uses raw input, as the name suggests, which I know you said you don't want to do. This limitation you have put on yourself has gotten you stuck. It's like saying "how do I see the screen with my eyes closed?"
Perhaps you could correlate the two events somehow to get the filter you are looking for. Or maybe you could filter out all events from the LowLevelMouseProc and pass the raw input from just one device into the LowLevelMouseProc.
There is a related discussion from the GameDev SE site.

Related

Changing keyboard events with global hook doesn't work

I am trying to make a little program that installs a global hook and catches keyboard input.
For now, I am trying to make every input changed to 'X' for example.
So if i write anywhere "hello" it will actually write "XXXXX".
I succeeded with hooking and even stopping any input from passing my hook but I can't figure out how to change the input.
The relevant method:
IntPtr HookCallBack(int nCode, IntPtr wParam, IntPtr lParam)
{
// Trying to change the input.
Marshal.WriteInt32(lParam, 88);
// Locked down
if (isKeyboardLockedDown)
return new IntPtr(1); // A non-zero return value blocks additional processing of key strokes.
// Not locked down.
else
return NativeMethods.CallNextHookEx(hookId, nCode, wParam, lParam);
}
As written above - if I understand right - lParam is the address where the input key is stored.
Therefor I overwrite it with "X".
That method doesn't work for some reason.
Any suggestions?
If the input is X:
Invoke CallNextHookEx()
Otherwise
Do not invoke CallNextHookEx(). Instead, call SendInput to post an X.
SendInput
Synthesizes keystrokes, mouse motions, and button clicks.
Note: In general it is unwise not to invoke CallNextHookEx(). Then again, it is in general not wise to replace all input with X :-)
iv'e done a similar project in C. Instead of changing the data i generated input. It works smoothly and not slowing the typing process down.
I used a global flag. True for input i generate and false for input from the user.
This is pretty much how it looked:
HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if(flag){
flag = FALSE;
return CallNextHookEx(NULL, nCode, wParam, lParam);}
else{
flag = TRUE;
keybd_event(what ever you want);
return 0;}
}

Control.ModifierKeys returns NONE

I am using a class i got from this blog:
http://blogs.msdn.com/b/toub/archive/2006/05/03/589423.aspx
private static IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
Console.WriteLine((Keys)vkCode);
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
This function get the key code for a single key, i wanted to alter it so i can catch ctrl+C so i altered the above function as follows:
private static IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
if ((Keys)(vkCode) == Keys.C && (Control.ModifierKeys == Keys.Control))
{
int vkCode = Marshal.ReadInt32(lParam);
Console.WriteLine((Keys)vkCode);
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
The problem is Control.ModifierKeys always returns NONE, i googled too much with any results, i want to note that i am using this code in class in a separate module in the solution. What am i doing here, please provide a solution.
Yes, this will go wrong in general but especially when your program does itself not have a GUI or uses a hidden window. Windows maintains keyboard state for each individual process, it is updated when a program receives a keyboard message. This is necessary because key strokes are stored in the message queue and get retrieved by the program later, sometimes much later. The problem with a keyboard hook is that it was another process that got the message, not yours. You've still got the stale keyboard state.
To make it truly reliable, you'll need to know the keyboard state of the other process. But that's not something you can get to, the GetKeyboardState() function only allows permitting retrieving your own state. This in general makes translating key strokes to typing keys very difficult. A WH_KEYBOARD hook is a much better solution but you cannot write such a hook in C#.
A workaround is to track the state of the Control key yourself. Or by pinvoking GetAsyncKeyState() to check the actual unbuffered state of the Control key.
That won't work for you!
The implementation of Control.ModifierKeys just calls the Windows API function GetKeyState() three times, with parameters 0x10, 0x11 and 0x12 in turn, and ors the results appropriately.
But the state is tied to which message from the message queue is being processed.
I think you need to use PInvoke to call the Windows API function GetAsyncKeyState() instead.

Send message taken from Spy++

I am trying to send a message to a game (to automate text commands), the problem is that I can't figure out how to use the information from spy++ to write a C# sendmessage function.
I was able to use spy++ to get
00220540 S WM_SETCURSOR hwnd:0024052C nHittest:HTCLIENT wMouseMsg:WM_MOUSEMOVE
Could anyone provide a breakdown of what this means, and how to send the message to the game in c#?
EDIT:
I found out that I was looking at the wrong process. Instead of looking at the javaw.exe, I was looking at the actual game.
Here is the code for pressing t:
<00919> 0038062A WM_INPUT nInputCode:RIM_INPUT hRawInput:189E0973
<00920> 0024052 P WM_KEYUP nVirtKey:'T' cRepeat:1 ScanCode:14fExtended:0fAltDown:0fRepeat:1fUp:1
So lets start with the signature for SendMessage, from Pinvoke.net:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
It taks a window handle, hWnd, a message ID, Msg, and two generic parameters wParam and lParam which change meaing based on the message ID.
What spy++ is showing you is the parameters that were sent to SendMessage. As you can see it doesn't show you wParam and lParam, but hwnd, nHittest, and wMouseMsg. That's because Spy++ knows what the wParam and lParam parameters actually mean for a WM_SETCURSOR message and is decoding them for you.
So decoding each piece of the what Spy++ has sent:
00220540 - the window handle receiving the message - the hWnd parameter.
S - It means it was sent via
SendMessage() and not posted via
PostMessage(). See http://msdn.microsoft.com/en-us/library/aa265147(v=vs.60).aspx
WM_SETCURSOR - The message ID - the
Msg parameter.
hwnd:0024052C - handle of the Window
containing the cursor - the wParam
parameter.
nHittest:HTCLIENT - the hit test
code - the low word of the lParam
parameter.
wMouseMsg:WM_MOUSEMOVE - the mouse
message - the high word of the
lParam parameter.
The way you would go about sending the message to a window is:
enum WindowMessages {
WM_SETCURSOR = 0x0020,
WM_MOUSEMOVE = 0x0200,
....
}
enum HitTestCodes {
HTCLIENT = 1,
....
}
....
IntPtr hWnd = [get your window handle some how]
int lParam = ((int)WindowMessages.WM_MOUSEMOVE) << 16 + (int)HitTestCodes.HTCLIENT;
SendMessage(hWnd, (uint)WindowMessages.WM_SETCURSOR, hWnd, (IntPtr)lParam);
For understanding what other messages mean you can do a search on Msdn.com for the messsage in the Windows documentation.
So after answering all of that I don't think this will have anything to do with sending keys to the game you are trying to control. WM_SETCURSOR doesn't have anything to do with keyboard input.

Repeat windows messages in Winforms

I want repeat sent windows messages to my winforms application.
Now, I have class implementing "IMessageFilter" which saves the selected messages (WM _KEYDOWN, WM _LBUTTONDOWN, etc...) to the list.
On key "Pause/Break" I copy the list of messages, clear original list, and resend the messages.
In my test project is only one form with one menuitem, one tab and one richtextbox. The hWnd of controls are same during saving and repeating messages.
All works fine, but the sending messages has not efect :/.
Sample code:
[System.Runtime.InteropServices.DllImport( "user32" )]
public static extern int SendMessage( IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam );
// ... in some method ...
SendMessage( msg.HWnd, msg.Msg, msg.WParam, msg.LParam );
It looks too easy, but don't know where can be problem.
Do you still have the message filter applied? Would that not interfere with sending the messages? Other possibility could be that the message in question should not be sent, but posted. Or, you may have to send the message from the correct thread for the target window.

How do I prevent print screen

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();

Categories

Resources