Is there any way to recognize combination ctrl+c via Marshal? - c#

I try to detect ctrl+c stroke in background process. I can detect any key which has a keycode like PrintScreen but I have problem with ctrl+c combination.
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) {
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN) {
int vkCode = Marshal.ReadInt32(lParam);
if (((Keys)vkCode).Equals(Keys.PrintScreen)) {
//HOW_TO_DETECT_CTRL+C
}
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
How to detect ctrl+c? Is there any way besides remembering last pressed key in a field?

Related

Simulate mouse click using PostMessage

More recently, simulating a click using PostMessage has begun to activate the window. Previously, this was not and the click was performed in an inactive window without focus.
int coords = (y << 16) + x;
IntPtr lParam = new IntPtr(coords);
PostMessage(hwnd, WM_LBUTTONDOWN, IntPtr.Zero, lParam);
PostMessage(hwnd, WM_LBUTTONUP, IntPtr.Zero, lParam);
[DllImport("user32.dll", SetLastError = true)]
static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
const Int32 WM_LBUTTONDOWN = 0x201;
const Int32 WM_LBUTTONUP = 0x202;

C# Checking if more than one key is pressed (Global Keyboard Hook )

I'm making a C# form app that runs in the background and checking if you pressed CTRL + A + S. So I was checking forums on the internet and I already setup that the app runs in the background and now I'am trying to setup keyboard hook. I found a global keyboard hook code on the internet.
Here is this code:
// GLOBAL HOOK
[DllImport("user32.dll")]
static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc callback, IntPtr hInstance, uint threadId);
[DllImport("user32.dll")]
static extern bool UnhookWindowsHookEx(IntPtr hInstance);
[DllImport("user32.dll")]
static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, int wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
static extern IntPtr LoadLibrary(string lpFileName);
private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
const int WH_KEYBOARD_LL = 13; // Number of global LowLevel- hook on the keyboard
const int WM_KEYDOWN = 0x100; // Messages pressing
private LowLevelKeyboardProc _proc = hookProc;
private static IntPtr hhook = IntPtr.Zero;
public void SetHook()
{
IntPtr hInstance = LoadLibrary("User32");
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, _proc, hInstance, 0);
}
public static void UnHook()
{
UnhookWindowsHookEx(hhook);
}
public static IntPtr hookProc(int code, IntPtr wParam, IntPtr lParam)
{
if (code >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
if (vkCode.ToString() == "162") //162 is ASCI CTRL
{
MessageBox.Show("You pressed a CTRL");
}
return (IntPtr)1;
}
else
return CallNextHookEx(hhook, code, (int)wParam, lParam);
}
private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
// Remove the hook
UnHook();
}
private void Form1_Load(object sender, EventArgs e)
{
// Set the hook
SetHook();
}
}
My problem is that this hook is setup for 1 key and I can't figure it out how to check if 3 keys are pressed (CTRL + A + S).
I already tried this but didn't work.
if (vkCode.ToString() == "162" && vkCode.ToString() == "65" && vkCode.ToString() == "83") //162 is CTRL, 65 is A, 83 is S, ASCII CODE
{
MessageBox.Show("You pressed a CTRL + A + S");
}
So my question is what I need to do that the program or this hook will allows me to checking 3 pressed keys (CTRL + A + S).
I believe you'd have to detect CTRL, A, and S separately, using flags to keep track of whether CTRL and A were the last keypresses, like so:
static bool ctrlPressed = false;
static bool ctrlAPressed = false;
public static IntPtr hookProc(int code, IntPtr wParam, IntPtr lParam)
{
if (code >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
if (vkCode == 162 || vkCode == 163) //162 is Left Ctrl, 163 is Right Ctrl
{
ctrlPressed = true;
}
else if (vkCode == 65 && ctrlPressed == true) // "A"
{
ctrlPressed = false;
ctrlAPressed = true;
}
else if (vkCode == 83 && ctrlAPressed == true) // "S"
{
ctrlPressed = false;
ctrlAPressed = false;
MessageBox.Show("Bingo!");
}
else
{
ctrlPressed = false;
ctrlAPressed = false;
}
// return (IntPtr)1; // note: this will interfere with keyboard processing for other apps
}
// else // don't interfere , always return callnexthookex
return CallNextHookEx(hhook, code, (int)wParam, lParam);
}
If you want to make sure that all are pressed at the same time the logic is similar, you just have to add checks for whether the keypress was down or up. You might also come up with a more clever way of doing this using some kind of list or queue or something for the key presses.

Handling WM_NCACTIVATE in startup window blocks all other windows

I am trying to keep one particular WPF window in focus, meaning that it should not change the window style when losing focus (e.g. like the standard Windows Taskbar). To achieve this, I hook into the WndProc to check whether the WM_NCACTIVATE or WM_ACTIVATE is set on false ( wParam == 0 ) and then mark the message as handled = true; to block the Window from being inactive. Here is some example code:
void Window_Loaded(object sender, RoutedEventArgs e)
{
var source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
if (source != null) source.AddHook(WndProc);
}
private const uint WM_NCACTIVATE = 0x0086;
private const int WM_ACTIVATE = 0x0006;
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == WM_NCACTIVATE)
{
if (wParam == new IntPtr(0))
handled = true;
}
if (msg == WM_ACTIVATE)
{
if (wParam == new IntPtr(0))
handled = true;
}
return IntPtr.Zero;
}
However, by doing this, all other WPF windows that are created from within this main window
var f = new Window();
f.ShowDialog();
never receive focus and although they are visible, the window does not react to user input both in the client area but also for the Windows minimize, maximize and close button. I am obviously doing something wrong, so any advice or pointers on how to do this the right way?
The solution to keeping the visual style of a WPF window to active even if the window loses focus is to handle the WM_NCACTIVATE like this:
private const uint WM_NCACTIVATE = 0x0086;
private IntPtr WndProc(IntPtr hwnd, int msg,
IntPtr wParam, IntPtr lParam, ref bool handled)
{
var returnvalue = IntPtr.Zero;
if (msg == WM_NCACTIVATE)
{
//replace the wParam (true/false) which indicates
//active/inactive with always true
returnvalue = DefWindowProc(hwnd, WM_NCACTIVATE,
new IntPtr(1), new IntPtr(-1));
handled = true;
}
}
[DllImport("user32.dll")]
static extern IntPtr DefWindowProc(IntPtr hWnd, WindowsMessages uMsg, IntPtr wParam, IntPtr lParam);

WH_JOURNALPLAYBACK hook in C#

I am trying to create a callback for "WH_JOURNALPLAYBACK" hook in C#. This is the code
private delegate IntPtr JournalPlaybackProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr JournalPlaybackCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (HC_GETNEXT == nCode && curr < EventMsgs.Count)
{
EVENTMSG hookStruct = (EVENTMSG)Marshal.PtrToStructure(lParam, typeof(EVENTMSG));
EVENTMSG currentMsg = EventMsgs[curr];
hookStruct.message = currentMsg.message;
hookStruct.paramL = currentMsg.paramL;
hookStruct.paramH = currentMsg.paramH;
hookStruct.hwnd = currentMsg.hwnd;
hookStruct.time = currentMsg.time;
}
if (HC_SKIP == nCode)
{
curr++;
}
if (curr == EventMsgs.Count)
{
UnhookWindowsHookEx(_journalPlaybackProcHookID);
_journalPlaybackProcHookID = IntPtr.Zero;
}
return CallNextHookEx(_journalPlaybackProcHookID, nCode, wParam, lParam);
}
I get the callback correctly, i suppose i need to modify the value of lParam with my data to playback the events. How do i do this?
I assume you need to
Marshal.StructureToPtr(hookStruct,lParam,true);
To write it back at some point. When I run it just hangs though.

Button click in sendmessage API

How can I simulate a button click in the sendmessage API in C#?
C code:
#include <Windows.h>
//...
SendMessage(hWndButton, BM_CLICK, 0, 0);
C# code:
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
...
Button myButton = ...;
const int BM_CLICK = 0x00F5;
SendMessage(myButton.Handle, BM_CLICK, IntPtr.Zero, IntPtr.Zero);
But be aware that, in C#, you can just as easily do:
myButton.PerformClick();

Categories