I want to handle mouse click in a native MFC application from a C# application.
To do so I'm trying to subclass the native application. I don't get any errors, but the wndproc are newer invoked.
private const int GwlWndProc = -4;
private delegate int Win32WndProc(IntPtr hWnd, int msg, int wParam, int lParam);
[DllImport("user32")]
private static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, Win32WndProc newProc);
Win32WndProc _newWndProc = MyWndProc;
SetLastError(0);
IntPtr oldWndProc = SetWindowLong(hWnd, GwlWndProc, _newWndProc);
if (oldWndProc == IntPtr.Zero)
{
int errorCode = Marshal.GetLastWin32Error();
if (errorCode != 0)
throw new Win32Exception(errorCode);
}
private int MyWndProc(IntPtr hWnd, int msg, int wParam, int lParam)
{
Debug.WriteLine("MyWndProc " + (WindowsMessage)msg);
if (msg == (int) WindowsMessage.LeftButtonDown)
{
MessageBox.Show("Clicked");
return 0;
}
else return CallWindowProc(_subclasses[hWnd], hWnd, msg, wParam, lParam);
}
Edit:
To get the hWnd I use GetForegroundWindow()
What I try to do is is to prevent the application to get the mouse click
I think you need to use hooking because SetWindowLong does not work across different processes: have a look here http://www.codeproject.com/Articles/5264/Cross-Process-Subclassing
Related
I am trying to capture the keypress event. Below is the code. If I press say for example 'F8' from anywhere, the method 'HookCallback' is being called. But If I do a key press from excel VBA window, it is not being called. I need to capture a keypress event in excel VBA. I don't know what I am missing here.
Edit:
The same code works in Excel 2010. It doesn't work with Excel 2016 and Excel 2022. So it should be a office 2016 and greater version problem.
#region Keyboard Event Handler
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private KeyBoardHookProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
private IntPtr SetHook(KeyBoardHookProc proc)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
0, 0);
}
private delegate IntPtr KeyBoardHookProc(
int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
....
}
I have a problem with posting a message to a process. When I send a key like A it is working great, but when I am sending a "special character" like Enter or F3 it is not working.
Here is my code :
[DllImport("user32.dll")]
private static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
public IntPtr SendKeystroke(IntPtr hWnd, Keys k)
{
return PostMessage(hWnd, 0x100, (IntPtr)k, (IntPtr)0);
}
And here is executing a method :
Process p = Process.GetProcessesByName("name")[0];
SendKeystroke(p.Handle, Keys.A);
SendKeystroke(p.Handle, Keys.Enter);
I am currently developing a program that will send a "key press" (the letter A or 0x41 in virtual key codes) to another program (notepad) every X seconds.
The problem is that for it to work I need the other program (notepad) to be in the FOREGROUND, example :
Process[] processes = Process.GetProcessesByName("notepad");
foreach (Process proc in processes) {
SetForegroundWindow(proc.MainWindowHandle);
// Do Whatever
}
Thread.Sleep(1000);
Is there a way to do that WITHOUT notepad having to be in the foreground ?
Like something that could run in the background ?
You could do it via winApi. Try to use SendMessage
According to this link you can do following:
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
public static void sendKeystroke(ushort k)
{
const uint WM_KEYDOWN = 0x100;
const uint WM_SYSCOMMAND = 0x018;
const uint SC_CLOSE = 0x053;
IntPtr WindowToFind = FindWindow(null, "Untitled1 - Notepad++");
IntPtr result3 = SendMessage(WindowToFind, WM_KEYDOWN, ((IntPtr)k), (IntPtr)0);
//IntPtr result3 = SendMessage(WindowToFind, WM_KEYUP, ((IntPtr)c), (IntPtr)0);
}
In C#, I write code to detect arrival/removal of device information from Serial Port.
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
const int WM_DEVICECHANGE = 0x0219;
// System detects a new device
const int DBT_DEVICEARRIVAL = 0x8000;
// The device has been succesfully removed from the system
const int DBT_DEVICEREMOVECOMPLETE = 0x8004;
if (msg == WM_DEVICECHANGE)
{
switch (wParam.ToInt32())
{
case DBT_DEVICEARRIVAL:
MessageBox.Show("New device added");
break;
case DBT_DEVICEREMOVECOMPLETE:
MessageBox.Show("An device has been removed from system");
break;
default:
break;
}
}
return IntPtr.Zero;
}
I searched on Google and I founded this article.
http://www.codeproject.com/Articles/60579/A-USB-Library-to-Detect-USB-Devices
It gives me exactly the code I need to write. But I have to provide to it a PID and VID.
So that, I need to combine my code with above code to make an program that automatically show information about arrival/removal of a device.
My problems is: From the WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled), how to extract the device's VID and PID?.
I want to simulate a mouseclick at a specific position inside a window that is hidden. So no maximizing the window or moving the mouse. I just want to send the right message.
Now I tried something like this
DllImport("user32.dll")]
public static extern int PostMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
static int WM_LBUTTONDOWN = 0x0201;
static int WM_LBUTTONUP = 0x0202;
private static IntPtr MakeLParam(int LoWord, int HiWord)
{
return (IntPtr)((HiWord << 16) | (LoWord & 0xffff));
}
public static void test()
{
int windowPtr = FindWindow(null, "Calculator");
Console.WriteLine("pointer: " + windowPtr);
int x = 260;
int y = 180;
IntPtr lParam = MakeLParam(x, y);
IntPtr windowPointer = new IntPtr(windowPtr);
PostMessage(windowPointer, WM_LBUTTONDOWN, IntPtr.Zero, lParam);
PostMessage(windowPointer, WM_LBUTTONUP, IntPtr.Zero, lParam);
}
I expected this program to click the 8 on the calculator ( if you set it to scientific ), but it doesn't do that.
How can I simulate that click? Please don't suggest finding the windows-control-element for the "8"-Button, this is not what I am trying to do here.