el***********@gmail.com wrote:
>Thanks for your help so far. This is the most frustrating thing ever. I
switched to using mouse_event, which should be exactly like SendInput.
(Is that the wrapper?)
Doh! Read the MSDN docs of functions that are mentioned to you but you
don't yet know! mouse_event is deprecated in favour of SendInput.
>Anyways, I am receiving the WM_LBUTTONDOWN and WM_LBUTTONDOWN as seen
on Spy++. However, nothing is getting clicked
The following (complete) program works, in that I programmatically
synthesize a click on the button and the button's OnClick event does
indeed get called. You might use this as a starting point for your
further explorations.
Like you, I created a button within my own C# application and spoofed
a click on that. What you will probably find is that (1) C# and .net
applications might respond different to mouse events from other
applications, and (2) response by a button INSIDE your own process
will be different from response by a button OUTSIDE. The reason for my
conjecture (1) is that I wouldn't expect the .net authors to follow
the win32 mouse model slavishly. The reason for my conjecture number
(2) is that an external process will have its own asynchronous
message-loop.
Things that I discovered: I couldn't send both MOUSEEVENTF_LBUTTONDOWN
and MOUSEEVENTF_LBUTTONUP both within a single call to SendInput. What
I did in this code was to space them out with a timer. My reasons for
doing this is my experience that lots of people write code which
depends on the message-queue being cleared after the first event
before later stuff happens. (I coded my MOUSEINPUT structure to allow
up to two events. But, following this discovery, my code only uses the
first event.)
I also discovered about how my .net button responded to mouse events.
When it received the MOUSEEVENTF_LBUTTONDOWN, it seemed to ignore the
mouse coordinate parameters of the MOUSEINPUT structure. Instead it
queried the cursor position. I suspect that regular win32 controls
will behave differently here.
Note: I put my code in response to a timer. Partly because I
anticipated problems like the first one I discovered. Partly because
of my conjecture (2): I thought that if I put my code in response to a
mouseclick of mine, then it would end up in a confused state when it
gets another mouseclick immediately.
I've spent five long paragraphs explaining these things. That's
because, as I said, controlling applications through synthesized
mouse-clicks requires a lot of experience with how windows deals with
mice and messages, and a lot of experiments. It also means that no one
will be able to help you "in abstract". They'll only be able to help
when you give very concrete details of the application you're trying
to control, and maybe not even then.
Note: it's because of all these irritations that I suggested using
SendMessage(WM_COMMAND) instead. That reliably bypasses all the
irritations. It works great for sending many kinds of notifications of
button-clicks or slideybar-drags and so on.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace WindowsApplication4
{
public partial class Form1:Form
{
[System.Runtime.InteropServices.StructLayout(System .Runtime.InteropServices.LayoutKind.Sequential)]
public struct MOUSEINPUT
{ public static MOUSEINPUT Zero()
{ MOUSEINPUT mi;
mi.type1=INPUT_MOUSE;mi.dx1=0;mi.dy1=0;mi.mouseDat a1=0;mi.dwFlags1=0;mi.time1=0;mi.dwExtraInfo1=IntP tr.Zero;
mi.type2=INPUT_MOUSE;mi.dx2=0;mi.dy2=0;mi.mouseDat a2=0;mi.dwFlags2=0;mi.time2=0;mi.dwExtraInfo2=IntP tr.Zero;
return mi;
}
public int Size() {return (int)Count()*28;}
public UInt32 Count() {if (dwFlags2!=0) return 2; else if
(dwFlags1!=0) return 1; else return 0;}
public Int32 type1, dx1,dy1, mouseData1, dwFlags1, time1; public
IntPtr dwExtraInfo1;
public Int32 type2, dx2,dy2, mouseData2, dwFlags2, time2; public
IntPtr dwExtraInfo2;
}
const Int32 INPUT_MOUSE=0;
const Int32 MOUSEEVENTF_LEFTDOWN=0x0002;
const Int32 MOUSEEVENTF_LEFTUP = 0x0004;
const Int32 MOUSEEVENTF_ABSOLUTE = 0x8000;
[System.Runtime.InteropServices.DllImport("user32.d ll")]
public static extern UInt32 SendInput(UInt32 nInputs, ref MOUSEINPUT
pInputs, Int32 cbSize);
public Form1()
{ InitializeComponent();
}
private void button2_Click(object sender,EventArgs e)
{ MessageBox.Show("click2");
}
int state=1;
private void button1_Click(object sender,EventArgs e)
{ state=1;
}
private void timer1_Tick(object sender,EventArgs e)
{ if (state==0) return;
MOUSEINPUT mi = MOUSEINPUT.Zero();
if (state==1)
{ Point pt=new Point(button2.Width/2,button2.Height/2),
oldpos=Cursor.Position;
Cursor.Position = button2.PointToScreen(pt);
mi.dwFlags1=MOUSEEVENTF_LEFTDOWN;
uint r=SendInput(mi.Count(), ref mi, mi.Size());
if (r==mi.Count()) Console.Beep();
state=3; return;
}
if (state==3)
{ mi.dx1=0; mi.dy1=0; mi.dwFlags1=MOUSEEVENTF_LEFTUP; uint
r=SendInput(1,ref mi, mi.Size());
if (r==1) Console.Beep();
state=0; return;
}
}
}
}
--
Lucian