I’m trying to intercept mouse clicks from another program. I’m making a plugin for the program, that overlays a transparent form on the program and displays additional information. When I click on the transparent part of the form I can click on things in the main
program. I don’t want this to happen (at least not every time - there are some parts where you are allowed to click and some parts where you aren’t but this isn’t the problem).
The way I’m doing this now is by using WH_MOUSE_LL
, this is working fine and I can keep the mouse click from getting to the program by returning a non zero value (http://msdn.microsoft.com/en-gb/library/windows/desktop/ms644988(v=vs.85).aspx).
The problem is, this makes my main program lag, I don’t need to get notifications for all mouse movements, I only want to get a notification if the user actually clicked something. Is there any way I can limit the WH_MOUSE_LL
so it only fires on mouse clicks? (The lag isn’t because of calculations in the MouseHookProc
method - it’s currently doing nothing except for calling: CallNextHookEx(hHook, nCode, wParam, lParam)
.)
I’ve tried to fix this by using a global hook (http://www.codeproject.com/Articles/18638/Using-Window-Messages-to-Implement-Global-System-H) that hooks the WM_MOUSEACTIVATE
message. The idea was to only hook up the WH_MOUSE_LL
when I received a WM_MOUSEACTIVATE
notification. Unfortunately WH_MOUSE_LL
click notification gets sent before WM_MOUSEACTIVATE
so this doesn't work.
EDIT:
@Nanda here’s the proc code:
public int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
return WindowUtility.CallNextHookEx(hHook, nCode, wParam, lParam);
}
As you can see I’m not doing very much with it atm, but it already lags...
@Cody Gray I’ve made a very small test for the Form handling the messages:
public class Form1 : Form
{
private TrackBar m_Trackbar;
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
public Form1()
{
m_Trackbar = new System.Windows.Forms.TrackBar();
m_Trackbar.LargeChange = 1;
m_Trackbar.Location = new System.Drawing.Point(5, 10);
m_Trackbar.Maximum = 100;
m_Trackbar.Size = new System.Drawing.Size(280, 40);
m_Trackbar.Value = 100;
this.Controls.Add(m_Trackbar);
m_Trackbar.Scroll += new System.EventHandler(this.m_TrackbarScroll);
}
private void m_TrackbarScroll(object sender, System.EventArgs e)
{
this.Opacity = ((Convert.ToDouble(m_Trackbar.Value)) / 100);
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case 0x201: //WM_LBUTTONDOWN
Console.WriteLine("MouseButton Down!");
//I could copy the Message over to the MainProgram with this right?
//SendMessage(MainProgramHwnd, m.Msg, m.WParam, m.LParam);
//This will also only work on an opacity higher than 0.
break;
}
base.WndProc(ref m);
}
}
When you said: “return that it's transparent and let it be routed to the window underneath it?” Can I do this by using SendMessage and basically copying the message I receive in my WndProc method?
To make things more complicated I’m also using this form http://www.codeproject.com/Articles/1822/Per-Pixel-Alpha-Blend-in-C. To my understanding this enables me to draw bitmaps on the form who are Anti Aliasing against the background. With this form there seems to be no way to set the opacity, as it’s just transparent all the time. Is there a better way to draw bitmaps on a Form?
You may want to look into Easyhook (http://easyhook.codeplex.com/) which will allow you to hook Windows API calls from a single process rather than for all processes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With