This program is supposed to move to a button and click on it. When the button is clicked, it changes text.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);
private const int MOUSEEVENTF_LEFTDOWN = 0x02;
private const int MOUSEEVENTF_LEFTUP = 0x04;
private const int MOUSEEVENTF_RIGHTDOWN = 0x08;
private const int MOUSEEVENTF_RIGHTUP = 0x10;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//My button is about 150 units away from the top left corner
Cursor.Position = new Point(this.Location.X + 150, this.Location.Y + 150);
DoMouseClick();
}
public void DoMouseClick()
{
//Call the imported function with the cursor's current position
int X = Cursor.Position.X;
int Y = Cursor.Position.Y;
mouse_event(MOUSEEVENTF_LEFTDOWN, X, Y, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, X, Y, 0, 0);
}
It moves till the button but it does not click on it. I don't know if something's wrong with the code or if I'm being blocked by some feature of Windows 7. Thank you for your help.
HanneSThEGreaT
November 23rd, 2009, 01:16 AM
Why are you going through all that trouble ¿
If this was a button on a separate program, yes, I could then understand that you use the mouse_event or even the SendMessage APIs to perform a click.
To automatically click a button on your form, you only need to use this :
button1.PerformClick();
So, if you modify your program to look like this :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace WindowsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void DoMouseClick()
{
button1.PerformClick();
Or :
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace WindowsApplication1
{
public partial class Form1 : Form
{
Thank you for your help, but I need to generate a click outside my application. I had initially written my program for clicking on the start button, but since that didn't work I wanted to verify if I could use that code to click inside my own application first. I don't know why the API call isn't working.
HanneSThEGreaT
December 4th, 2009, 12:56 AM
Thanks for telling us that you're dealing with a separate window, upfront ;)
OK, if this is a separate window, you still do not need the mouse_event APIs :)
You need to obtain a proper handle to the particular button. You do this the following way :
Use FindWindow API to get a handle of the main window
Use FindWindoEx API to get the handle of the button - you would need a program such as Spy++ which can identify all the subwindows within a window
Use SendMEssage to click that button.
gregorian
December 4th, 2009, 10:49 AM
Thank you very much for the quick response! I'll be sure to try it out soon but I'm looking for a way to generate a click at a particular co-ordinate on the screen independent of what applications might be there. This is the reason I'm using the mouse APIs.
Also, could you tell me how to debug programs that use APIs like this? I don't know if something's blocking this or if I'm not using the API correctly. The code I posted in the original post seems very simple and compiles without a hitch. It doesn't crash when I run the program so I don't really know what's wrong.
Arjay
December 4th, 2009, 12:23 PM
Use the SendInput api.
gregorian
December 4th, 2009, 09:00 PM
Thanks for the response. I checked out MSDN for information regarding the SendInput API and this is what I found :
Return Value
The function returns the number of events that it successfully inserted into the keyboard or mouse input stream. If the function returns zero, the input was already blocked by another thread. To get extended error information, call GetLastError.
Microsoft Windows Vista. This function fails when it is blocked by User Interface Privilege Isolation (UIPI). Note that neither GetLastError nor the return value will indicate the failure was caused by UIPI blocking.
If this is the case, what can I do? How do I know that UIPI is blocking it?
I've managed to write code in C++ that moves the mouse to a corner and right click.
I'll be creating a new thread in the C++ and API subforum since it's almost done.
But it won't work for left click, even when I make the program sleep for sometime between the DOWN and UP. Very strange.
Arjay
December 6th, 2009, 12:02 AM
The mouse input structures don't look correct. They should resemble the following to left click at a specified position:
In addition, with the absolute flag set, you need to convert from pixels to normalized coordinates (between 0 and 65,535). For example, I specified the x and y coordinates to be 100px and 100px which converts to 4552.
gregorian
December 6th, 2009, 03:25 AM
I got it to work. I use Autohide on my taskbar so I actually clicked before the taskbar showed up. Problem resolved.
Thank you for your help Arjay, but it doesn't seem like the clicking operations make use of the co-ordinates data so there's no need to repeat the structures.
Arjay
December 6th, 2009, 12:17 PM
I got it to work. I use Autohide on my taskbar so I actually clicked before the taskbar showed up. Problem resolved.
Thank you for your help Arjay, but it doesn't seem like the clicking operations make use of the co-ordinates data so there's no need to repeat the structures.If you are referring to the 'extra' mouse move operation of input #2, I agree. This 'extra' mouse move entry is an artifact of an input generator tool that I have.
With the tool, you can build nested input statements with a combination of keys and mouse click (like CTRL SHIFT, click at x,y and then type 'xyz'). Because of the nesting levels, the mouse is always moved prior to a mouse click (whether it's an up click or a down click).
If you can't get the mouse to move in your code, then you have a bug because the mouse input structure is definitely able to move the mouse. The bug in your code is probably because you aren't coverting pixels to normalized coordinates.
gregorian
December 6th, 2009, 09:31 PM
There isn't a bug in the code since I got it to work.
When I said extra information, I was referring to the fact that you were providing co-ordinate data for the mouse click events (up and down). I assume Windows ignores the data since it doesn't need it. As a result, am I correct in understanding that you don't need to set it?
Apart from this, I'm now interested in simulating keystrokes.
Use FindWindow API to get a handle of the main window
Use FindWindoEx API to get the handle of the button - you would need a program such as Spy++ which can identify all the subwindows within a window
Use SendMEssage to click that button.
This information was very useful, but I'd like to send keys to the application having an active cursor. Could you tell me how to find it?
Arjay
December 6th, 2009, 09:49 PM
We seem to be having a bit of a disconnect. The following code won't work:
Unless you want to click in the lower right corner of the screen.
For keystrokes, see http://www.codeguru.com/forum/showthread.php?t=377393
gregorian
December 6th, 2009, 11:03 PM
I wanted to click on the Show Desktop button which is at the lower right corner in Windows 7.
Thank you for the link and the help you provided. It's been great!
Arjay
December 7th, 2009, 04:52 AM
In that case, you'll probably want to move to using the Active Accessibility interfaces. These will allow you to find the Show Desktop icon no matter where the taskbar is docked or whether it's set to autohide.
HanneSThEGreaT
December 7th, 2009, 05:28 AM
I wanted to click on the Show Desktop button which is at the lower right corner in Windows 7.
If you have said this, in the first place, this thread would most probably have been resolved a long time ago.
There are some APIs and techniques as described in this thread :
For "clicking" the Show Desktop button programmatically. See if it works, as I haven't tested it on Windows 7 yet, but works on Vista downwards
I mentioned it once, but I guess I didn't make it clear enough. Allow me to clear any misunderstandings - I just wanted to simulate a click and the Show Desktop button was simply a test, not a goal.
I went ahead and tested your program on Windows 7. Runs perfectly. :)
I would like to change prefix the title of the thread with RESOLVED, but editing the title of the first post doesn't help. Could you tell me how to do it?
HanneSThEGreaT
December 7th, 2009, 06:22 AM
Just above your First Post, there is a menu bar. Click Thread Tools, and select Mark Thread Resolved.
Thanx for testing! That is good news :)
PS: You have a good understanding of how forums work, unfortunately, most newbies don't. :)
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.