Set mouse position in WPF? - c#

I have a two dimensional array with coordinates and i want to make the mouse move with the specific pattern those coordinates create in a WPF application. Can you help me? I've tried the Cursor class but it will not work. Obviously I am doing something wrong.
private void SetPosition( int a, int b)
{
this.Cursor = new Cursor(Cursor.Current.Handle);
Cursor.Position = new Point(a, b);
}
This is the method i use the a and b are from the array. thanks in advance!
PS that method is inside an event that fires 20 times a second.

I'm not entirely sure if there is a better way to do it in WPF (It seems the code you are using is targeted at WinForms), but using Platform Invoke on SetCursorPos seems to do the trick:
private void SetPosition(int a, int b)
{
SetCursorPos(a, b);
}
[DllImport("User32.dll")]
private static extern bool SetCursorPos(int X, int Y);

You have to use SendInput
http://inputsimulator.codeplex.com/ makes it somewhat easy

Related

WPF Mouse Position not retrieved properly

Disclosure: This is my first WPF app. Please be accepting of my ignorance.
In my WPF application, I have a ControlTemplate with a Grid and various children beneath that. In the code-behind, I am dynamically adding a custom ContentControl element using the ControlTemplate.
When the new Control is created, it is intended to capture the mouse and allow dragging capabilities. The code for the dragging calculations is fine if the Grid has already been loaded on the window and I have the start Point set to MouseButtonEventArgs.GetPosition(window). But when the event is fired when the Grid is initially loaded, the Point is equal to the inverse position of the window. E.g. if my window is at (350,250), my start Point is (-350,-250).
private void GridLoaded(object sender, EventArgs e) { // fires MouseLeftButtonDown event for grid}
private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
...
m_start = e.GetPosition(this); // 'this' is the current window; returns the inverse coordinates of 'this'
...
}
Is there a more appropriate method to get the x,y coordinates of my mouse position. I could work with screen coordinates if necessary, but all code I've found uses what would be PointToScreen(m_start). This is useless as m_start is incorrect.
Any help is greatly appreciated.
Can you try, I snagged this some time ago and it worked well for me:
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
public static implicit operator Point(POINT point)
{
return new Point(point.X, point.Y);
}
}
[DllImport("user32.dll")]
public static extern bool GetCursorPos(out POINT lpPoint);
public static Point GetCursorPosition()
{
POINT lpPoint;
GetCursorPos(out lpPoint);
//bool success = User32.GetCursorPos(out lpPoint);
// if (!success)
return lpPoint;
}

How can I position a Win32 floating window inside a user control in my WPF application?

Using a class derived from HwndHost and some voodoo code:
protected override HandleRef BuildWindowCore(HandleRef hwndHost)
{
CheckGuestValidity();
var guestHwnd = new HandleRef(GuestHwnd, _guestHwnd);
Win32.SetWindowStyle(guestHwnd.Handle, WindowStyles.WS_CHILD | Win32.GetWindowStyle(guestHwnd.Handle));
WindowsFormsHost.EnableWindowsFormsInterop();
System.Windows.Forms.Application.EnableVisualStyles();
Win32.SetParent(guestHwnd.Handle, hwndHost.Handle);
Win32.SetWindowStyle(_guestHwnd, Win32.GetWindowStyle(_guestHwnd) & ~WindowStyles.WS_CAPTION);
return guestHwnd;
}
I have managed to get an otherwise parentless (except for Windows' main window) window from a Delphi COM server to adopt my WPF application window as it's parent window. Problem is it is located under all the other user controls etc. at the very bottom of my WPF window. I would like to size and position it to fit inside a rectangle on a tab in a TabControl. How can I go about this? I realise it will take a few resize and position Win32 API calls and maybe even a few low level Windows messages, but I'm up for it.
First I found a handy little class to convert between coordinate systems. It is #Lu55's answer , not the accepted one, to the question How do I convert a WPF size to physical pixels?
Then, my WindowHostView XAML looks like this:
<Grid x:Name="WindowContainer" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Coral" >
<delphi:Win32WindowHost x:Name="Host" />
</Grid>
The Win32WindowHost class is what contains the code included in my question.
Now I have a neat little routine inside WindowHostView to fit the guest window into the the host's boundarys.
private void PositionGuestWindow(IntPtr hWnd)
{
var rect = WindowContainer.GetAbsoltutePlacement();
var winLeft = Win32Calc.PointsToPixels(rect.Left, Win32Calc.Dimension.Width);
var winTop = Win32Calc.PointsToPixels(rect.Top, Win32Calc.Dimension.Height);
var winWidth = Win32Calc.PointsToPixels(rect.Width, Win32Calc.Dimension.Width);
var winHeight = Win32Calc.PointsToPixels(this.ActualHeight - 20, Win32Calc.Dimension.Height);
Win32Api.MoveWindow(Host.GuestHwnd, (int)winLeft, (int)winTop, (int)winWidth + 1, (int)winHeight, true);
}
And Win32Api.MoveWindow is plain old:
[DllImport("user32.dll", SetLastError = true)]
public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);

Move mouse to specified point

I'd like to make a c# app that moves the mouse to a specified x,y position on the screen. I've tried a few codes I found online but none seem to work.
Try this:
System.Windows.Forms.Cursor.Position = new Point { X = xxx, Y = yyy };
Or try to use the native WinAPI for XP (or earlier):
[DllImport("user32.dll")]
public static extern long SetCursorPos(int x, int y);
public void SetCursorPosition(Point p)
{
SetCursorPos(p.X, p.Y);
}

How to programmatically (C# or Java) launch an app in Windows and invoke click in it's window?

There is a simple application that works in Windows. It has very simple interface: squre window with buttons in fixed coordinates.
I need to write a program that makes use of this application: to launch it and to click one of buttons (let's say invoke a click at (150,200)).
Is there any way to do it in Java or .NET?
The Java based solution is to launch the app. in a Process and use the Robot to interact with it.
The best solution on this thread was by #HFoE but deleted by a moderator. For reference, it basically came down to..
If you want to control another Windows application, use a tool that was built specifically for this such as AutoIt V3.
Since "Don't do it" seems to be considered a valid answer when an alternative is supplied (by general opinion on Meta), I cannot understand why the answer was deleted.
As Hovercraft Full Of Eels if you can - use autoit - it's much easier. If AutoIt is not an option then you will need to use winAPI functions in order to do it.
For example to call mouseclick at coordinates:
[DllImport("user32.dll")]
static extern bool SetCursorPos(int x, int y);
[DllImport("user32.dll")]
static extern bool GetCursorPos(ref Point lpPoint);
[DllImport("user32.dll")]
public static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);
public void LeftMouseClick(int xpos, int ypos) //Make a click at specified coords and return mouse back
{
Point retPoint = new Point();
GetCursorPos(ref retPoint); // set retPoint as mouse current coords
SetCursorPos(xpos, ypos); //set mouse cursor position
mouse_event(MOUSEEVENTF_LEFTDOWN, xpos, ypos, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, xpos, ypos, 0, 0); //click made
SetCursorPos(retPoint.X, retPoint.Y); //return mouse position to coords
}
But be aware, that to make click inside a window it needs to be at front of you - you cannot click to a minimized app for example.
If you want to try - you can find all needed functions(how to run a programm, get needed window by hwnd and so on) at PInvoke
For .Net you can pretty much use AutomationElement which I prefer. There's a bit of learning time, but it shouldn't take much. You can start your app with ProcessStartInfo.
If you have VS2010 Pro or Ultimate you can use the CodedUITests to generate a couple of button pushes.
As #Hovercraft Full Of Eels suggested - Autoit, Python could do the same
Yes - in C#...
Use the Process class to start the process (there are plenty of resources on the web on how to do this.
Wait until the process has started (either just wait for a fixed amount of time which is probably going to be long enough, or you could try and do something fancy like IPC or monitoring for a window being created)
To simulate the click take a look at How to simulate Mouse Click in C#? which uses a P/Invoke call to the mouse_event function.
However note that there are several things that can go wrong with this
Someone might move the window, or place another window on top of that window in the time it takes to launch the application
On a slower PC it may take longer to load the application (this risk can be mitigated by doing things like monitoring open windows and waiting for the expected application window to appear)
In .net you can Process.Start from System.Diagnostics to launch an application, you can even pass parameters, and to simulate mouse events you can use P/Invoke there is already an answer to that on SO here
Here is my working test app to play with clicking in windows.
We just start some app and hope to click it in right place)
It would be nice to have some solution for capturing windows this way =)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
namespace ConsoleApplication8
{
class Program
{
static void Main(string[] args)
{
var startInfo = new ProcessStartInfo(#"C:\Users\Bodia\Documents\visual studio 2010\Projects\ConsoleApplication8\WindowsFormsApplication1\bin\Debug\WindowsFormsApplication1.exe");
startInfo.WindowStyle = ProcessWindowStyle.Maximized;
Console.WriteLine(1);
var process = Process.Start(startInfo);
Console.WriteLine(2);
Thread.Sleep(400);
Console.WriteLine(3);
LeftMouseClick(1000, 200);
Console.WriteLine(4);
}
static void CursorFun()
{
Point cursorPos = new Point();
GetCursorPos(ref cursorPos);
cursorPos.X += 100;
Thread.Sleep(1000);
SetCursorPos(cursorPos.X, cursorPos.Y);
cursorPos.X += 100;
Thread.Sleep(1000);
SetCursorPos(cursorPos.X, cursorPos.Y);
cursorPos.X += 100;
Thread.Sleep(1000);
SetCursorPos(cursorPos.X, cursorPos.Y);
cursorPos.X += 100;
Thread.Sleep(1000);
SetCursorPos(cursorPos.X, cursorPos.Y);
}
[DllImport("user32.dll")]
static extern bool SetCursorPos(int x, int y);
[DllImport("user32.dll")]
static extern bool GetCursorPos(ref Point lpPoint);
[DllImport("user32.dll")]
public static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);
public static void LeftMouseClick(int xpos, int ypos) //Make a click at specified coords and return mouse back
{
Point retPoint = new Point();
GetCursorPos(ref retPoint); // set retPoint as mouse current coords
SetCursorPos(xpos, ypos); //set mouse cursor position
mouse_event(MOUSEEVENTF_LEFTDOWN, xpos, ypos, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, xpos, ypos, 0, 0); //click made
SetCursorPos(retPoint.X, retPoint.Y); //return mouse position to coords
}
struct Point
{
public int X;
public int Y;
}
private const int MOUSEEVENTF_LEFTDOWN = 0x02;
private const int MOUSEEVENTF_LEFTUP = 0x04;
private const int MOUSEEVENTF_RIGHTDOWN = 0x08;
private const int MOUSEEVENTF_RIGHTUP = 0x10;
}
}

How to get mouse position related to desktop in WPF?

Problem
When you search for such question using google you get a lot of hits but all solutions assume you have at least one window.
But my question is just like I phrased it -- not assumptions at all. I can have a window, but I could have zero windows (because I didn't even show one or I just closed the last one). So in short the solution cannot rely on any widget or window -- the only thing is known, is there is a desktop (and app running, but it does not have any windows).
So the question is -- how to get the mouse position?
Background
I would like to show windows centered to mouse position. There is no such mode in WPF (there are only center to owner, or center to screen) so I have to do it manually. The missing piece is mouse position.
Edits
Thank you all, so now I have the first part of the solution -- raw position. Now there is a problem how to convert the data for WPF. I found such topic:
WPF Pixels to desktop pixels
but again, it assumes having some window.
Then I googled more and I found solution:
http://jerryclin.wordpress.com/2007/11/13/creating-non-rectangular-windows-with-interop/
the code includes class for scaling up/down coordinates relying only on info about desktop. So joining those two pieces, I finally get the solution :-). Thanks again.
Getting the Screen Coordinates:
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetCursorPos(out POINT lpPoint);
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
public POINT(int x, int y)
{
this.X = x;
this.Y = y;
}
}
private void WritePoint(object sender, RoutedEventArgs e)
{
POINT p;
if (GetCursorPos(out p))
{
System.Console.WriteLine(Convert.ToString(p.X) + ";" + Convert.ToString(p.Y));
}
}
Converting Pixels to WPF Units:
[DllImport("User32.dll")]
static extern IntPtr GetDC(IntPtr hwnd);
[DllImport("gdi32.dll")]
static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
[DllImport("user32.dll")]
static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC);
private Point ConvertPixelsToUnits(int x, int y)
{
// get the system DPI
IntPtr dDC = GetDC(IntPtr.Zero); // Get desktop DC
int dpi = GetDeviceCaps(dDC, 88);
bool rv = ReleaseDC(IntPtr.Zero, dDC);
// WPF's physical unit size is calculated by taking the
// "Device-Independant Unit Size" (always 1/96)
// and scaling it by the system DPI
double physicalUnitSize = (1d / 96d) * (double)dpi;
Point wpfUnits = new Point(physicalUnitSize * (double)x,
physicalUnitSize * (double)y);
return wpfUnits;
}
Putting both together:
private void WriteMouseCoordinatesInWPFUnits()
{
POINT p;
if (GetCursorPos(out p))
{
Point wpfPoint = ConvertPixelsToUnits(p.X, p.Y);
System.Console.WriteLine(Convert.ToString(wpfPoint.X) + ";" + Convert.ToString(wpfPoint.Y));
}
}
Two options:
Use System.Windows.Forms.Control.MousePosition, or p/invoke
[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
public static extern bool GetCursorPos([In, Out] NativeMethods.POINT pt);
The first option already does the p/invoke for you. I'm not entirely sure it requires you have some UI splashed up, but I don't think so. Yes, its winforms and not wpf, but it really doesn't have anything to do with where its located at.
If you want to skip any dependencies on system.windows.forms.dll then check out more information about the second on pinvoke.net.
I stumbled over that thread while looking for a solution for the same problem. In the meantime, I found PointToScreen, which does not require any P/Invoke. The method is available on any Visual starting .NET 3.0 (and thus UIElement, Control, etc.) and an implementation would look like this:
protected void OnMouseLeave(object Sender, MouseEventArgs e) {
var relativePosition = e.GetPosition(this);
var screenPosition = this.PointToScreen(relativePosition);
}

Categories