Reputation: 29
I am trying to use global hooks to detect input events (a mouse click, keyboard keys) and use the detection to trigger another event, such as storing the mouse coordinates. The code I've found does work, but I cannot call on another method in the same form because the hookProc is set to static.
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("CTRL");
Form1 Trigger = new Form1(); // Supposed to allow calls to Form1, specifically textBox1
Trigger.textBox1.Text = "3"; // Will not change the Text value
}
return (IntPtr)1;
}
else
return CallNextHookEx(hhook, code, (int)wParam, lParam);
}
I know the code works because the CTRL MessageBox will show. I know textBox1.Text = "3"; because I can use the code elsewhere in an instance without issue. I searched and found I need to create a new instance of form1 in order to call on methods found outside the static hookProc. My code does not give me any build errors but does not do anything in regards to textBox1. Even if I wanted to call on another method when CTRL is detected, I cannot link to anything outside hookProc. Help?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace Demo
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
SetHook(); // Set the hook
}
private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
UnHook(); // Remove the hook
}
// 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("CTRL");
Form1 Trigger = new Form1(); // Allows called to Form1, specifically textBox3
Trigger.TriggeredEvent(); //Visual confirmation of CTRL has been detected
Trigger.textBox1.Text = "3";
}
return (IntPtr)1;
}
else
return CallNextHookEx(hhook, code, (int)wParam, lParam);
}
}
}
Upvotes: 0
Views: 228
Reputation: 18155
As you would have guessed, the issue is that you are creating a new instance of Form1 and attempting to update the TextBox Value in the new instance. What you require is the same instance which is currently open.
Assuming you have only a single instance of Form1, you can use Application.OpenForms
to get collection of all Open Forms and use Enumerable.OfType
to filter the Form1 Type.
For Example
var formInstance = Application.OpenForms.OfType<Form1>().Single();
formInstance.TriggeredEvent();
formInstance.textBox1.Text = "3";
Upvotes: 2