So I'm trying to simulate the left mouse click and the left mouse release to do some automated dragging and dropping.
It's currently in a C# Winforms (Yes, winforms :|) and is being a bit of a goose.
Basically, once a Click is sent, I want it to update the cursor position based upon the Kinect input. The Kinect side of things is fine but i'm not sure how to find if the button is still pressed or not.
here's the code i'm currently using + some psuedocode to help better explain myself (the do while).
class MouseImpersonator
{
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);
private const int leftDown = 0x02;
private const int leftUp = 0x04;
public static void Grab(int xPos, int yPos)
{
Cursor.Position = new Point(xPos + 25, yPos + 25);
mouse_event(leftDown, (uint) xPos, (uint) yPos, 0, 0);
//do
//{
//Cursor.Position = new Point(KinectSettings.movement.LeftHandX, KinectSettings.movement.LeftHandY);
//} while (the left mouse button is still clicked);
}
public static void Release(int xPos, int yPos)
{
Cursor.Position = new Point(xPos + 25, yPos + 25);
mouse_event(leftUp, (uint) xPos, (uint) yPos, 0, 0);
}
}
I've had a hunt of the google and can't find anything for what I need except for a WPF equivalent: http://msdn.microsoft.com/en-us/library/system.windows.input.mouse.aspx
I'm a bit out of my depth, but any help is greatly appreciated.
Lucas.
-
The Easiest answer was infact to use a bool and just check to see what's going on.
I started it on a new thread so it didn't break everything else.
Idealy you'd tidy this up a little bit.
public static void Grab(int xPos, int yPos)
{
_dragging = true;
Cursor.Position = new Point(xPos, yPos + offSet);
mouse_event(leftDown, (uint) xPos, (uint) yPos, 0, 0);
var t = new Thread(CheckMouseStatus);
t.Start();
}
public static void Release(int xPos, int yPos)
{
_dragging = false;
Cursor.Position = new Point(xPos, yPos + offSet);
mouse_event(leftUp, (uint) xPos, (uint) yPos, 0, 0);
}
private static void CheckMouseStatus()
{
do
{
Cursor.Position = new Point(KinectSettings.movement.HandX, KinectSettings.movement.HandY + offSet);
}
while (_dragging);
}
The following code should return true if the left mouse button is down, false if it is up, Control being System.Windows.Forms.Control:
Control.MouseButtons.HasFlag(MouseButtons.Left)
p.s. documentation for this can be found on MSDN here.
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern void mouse_event(uint dwFlags, int dx, int dy, uint cButtons, uint dwExtraInfo);
[DllImport("user32.dll")]
static extern bool SetCursorPos(int X, int Y);
const uint MOUSEEVENTF_LEFTDOWN = 0x0002;
const uint MOUSEEVENTF_LEFTUP = 0x0004;
const uint MOUSEEVENTF_MOVE = 0x0001;
static void Drag(int startX,int startY,int endX,int endY)
{
endX = endX - startX;
endY = endY - startY;
SetCursorPos(startX, startY);
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
mouse_event(MOUSEEVENTF_MOVE, endX, endY, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
}
Related
I have a function that triggers a click when passing coordinates to it. How can I get the coordinates of the selected text after doing a search with CTRL + F?
I am launching it with a console application.
EDIT: Code added.
[DllImport("user32.dll")]
static extern bool SetCursorPos(int x, int y);
[DllImport("user32.dll")]
private static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);
public const int MOUSEEVENTF_LEFTDOWN = 0x02;
public const int MOUSEEVENTF_LEFTUP = 0x04;
public const int MOUSEEVENTF_RIGHTDOWN = 0x08;
public const int MOUSEEVENTF_RIGHTUP = 0x10;
// LEFT CLICK
public static void SimularClickIzq(int xpos, int ypos)
{
SetCursorPos(xpos, ypos);
mouse_event(MOUSEEVENTF_LEFTDOWN, xpos, ypos, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, xpos, ypos, 0, 0);
}
// RIGHT CLICK
public static void SimularClickDer(int xpos, int ypos)
{
SetCursorPos(xpos, ypos);
mouse_event(MOUSEEVENTF_RIGHTDOWN, xpos, ypos, 0, 0);
mouse_event(MOUSEEVENTF_RIGHTUP, xpos, ypos, 0, 0);
}
#### FOCUS ON TEXT ####
SendKeys.SendWait("^f");
Thread.Sleep(2000);
SendKeys.SendWait("Estado de la Solicitud");
Thread.Sleep(2000);
SendKeys.SendWait("{ESC}");
Thread.Sleep(2000);
MISSING COORDINATES HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#### WINDOWS FORM ####
lbl_coordinates.Text = Cursor.Position.ToString();
I'm trying to learn a few things, but I'm kinda stuck and I don't know where to go from here. I'm either blind or just confused.
I've been looking at some scripts from here: Answers.Unity
Right now, I got the background transparency working on my main screen, but I'm wondering what I should do to make this happen on my second monitor too. Or third, if I had one. As of right now the other screens turn black. This is the code:
[SerializeField]
private Material m_Material;
[SerializeField]
private Camera mainCamera;
private bool clickThrough = true;
private bool prevClickThrough = true;
private struct MARGINS
{
public int cxLeftWidth;
public int cxRightWidth;
public int cyTopHeight;
public int cyBottomHeight;
}
[DllImport("user32.dll")]
private static extern IntPtr GetActiveWindow();
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);
[DllImport("user32.dll")]
static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll", EntryPoint = "SetLayeredWindowAttributes")]
static extern int SetLayeredWindowAttributes(IntPtr hwnd, int crKey, byte bAlpha, int dwFlags);
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
private static extern int SetWindowPos(IntPtr hwnd, int hwndInsertAfter, int x, int y, int cx, int cy, int uFlags);
[DllImport("Dwmapi.dll")]
private static extern uint DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS margins);
const int GWL_STYLE = -16;
const uint WS_POPUP = 0x80000000;
const uint WS_VISIBLE = 0x10000000;
const int HWND_TOPMOST = -1;
int fWidth;
int fHeight;
IntPtr hwnd;
MARGINS margins;
public bool OverUI()
{ //Use sparingly
//Set up the new Pointer Event
PointerEventData m_PointerEventData = new PointerEventData(EventSystem.current);
m_PointerEventData.position = Input.mousePosition;
List<RaycastResult> results = new List<RaycastResult>();
EventSystem.current.RaycastAll(m_PointerEventData, results);
if (results.Count > 0) return true;
return false;
}
void Start()
{
fWidth = Screen.width;
fHeight = Screen.height;
margins = new MARGINS() { cxLeftWidth = -1 };
hwnd = GetActiveWindow();
SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, fWidth, fHeight, 32 | 64); //SWP_FRAMECHANGED = 0x0020 (32); //SWP_SHOWWINDOW = 0x0040 (64)
DwmExtendFrameIntoClientArea(hwnd, ref margins);
Application.runInBackground = true;
}
void Update()
{
// If our mouse is overlapping an object
RaycastHit hit = new RaycastHit();
clickThrough = !Physics.Raycast(mainCamera.ScreenPointToRay(Input.mousePosition).origin,
mainCamera.ScreenPointToRay(Input.mousePosition).direction, out hit, 100,
Physics.DefaultRaycastLayers) && !OverUI();
if (clickThrough != prevClickThrough)
{
if (clickThrough)
{
SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
SetWindowLong (hwnd, -20, (uint)524288 | (uint)32);//GWL_EXSTYLE=-20; WS_EX_LAYERED=524288=&h80000, WS_EX_TRANSPARENT=32=0x00000020L
SetLayeredWindowAttributes (hwnd, 0, 255, 2);// Transparency=51=20%, LWA_ALPHA=2
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, fWidth, fHeight, 32 | 64); //SWP_FRAMECHANGED = 0x0020 (32); //SWP_SHOWWINDOW = 0x0040 (64)
}
else
{
SetWindowLong (hwnd, -20, ~(((uint)524288) | ((uint)32)));//GWL_EXSTYLE=-20; WS_EX_LAYERED=524288=&h80000, WS_EX_TRANSPARENT=32=0x00000020L
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, fWidth, fHeight, 32 | 64); //SWP_FRAMECHANGED = 0x0020 (32); //SWP_SHOWWINDOW = 0x0040 (64)
}
prevClickThrough = clickThrough;
}
}
void OnRenderImage(RenderTexture from, RenderTexture to)
{
Graphics.Blit(from, to, m_Material);
}
Could anyone guide me a little bit so that I can figure this out?
Edit: I've figured out a little bit.. I think.
When Unity opens, (with multiple displays), it creates two windows in the task bar. I'm guessing I need to find that other window, set it as active and then run something similar to this code again. But I'm guessing I would need to fix the pos and margins before doing so.
It's beyond my understanding of WinApi right now, but I hope someone knows a bit more about this than me.
I needed to simulate mouse left click in some scenario in the code (c# .net).
this simulation must be done but it must be invisible for users. so when left click is going to occur I save cursor position. After doing left click I should set cursor position to the save value.
there is a problem.
int save_cursur_x = Cursor.Position.X;
int save_cursur_y = Cursor.Position.Y;
int current_node_x = newGraphEditor.getCurrentNodeGlobalPosition_x();
int current_node_y = newGraphEditor.getCurrentNodeGlobalPosition_y();
LeftMouseClick(current_node_x, current_node_y);
Cursor.Position = new Point(save_cursur_x, save_cursur_y);
When the last line ( Cursor.Position = new Point(save_cursur_x, save_cursur_y)) is removed left click happen correctly on the target position. But when I add that line, left click happen on a unknown position (or maybe left click doesn't happen)
This is LeftMouseClick method :
//This is a replacement for Cursor.Position in WinForms
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern bool SetCursorPos(int x, int y);
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);
public const int MOUSEEVENTF_LEFTDOWN = 0x02;
public const int MOUSEEVENTF_LEFTUP = 0x04;
//This simulates a left mouse click
public static void LeftMouseClick(int xpos, int ypos)
{
SetCursorPos(xpos, ypos);
mouse_event(MOUSEEVENTF_LEFTDOWN, xpos, ypos, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, xpos, ypos, 0, 0);
}
Update:
There is a selection delegate where target position set. this delegate should run exactly when you click on target. I think problem is here . After left click on target this delegate isn't run . After setting Cursor position to previous value delegate is run. so target position doesn't set correctly because now cursor isn't on target.(Its position has changed)
ItemEventHandler<IModelItem> selectionDelegate =
delegate (object source, ItemEventArgs<IModelItem> args)
{
var tag = ((INode)(args.Item)).Tag;
if (tag is HostInnerNodeTag)
{
currentNodeGlobalPosition_x = Cursor.Position.X;
currentNodeGlobalPosition_y = Cursor.Position.Y;
}
}
You can use SendMessage instead.
[DllImport("user32.dll")]
public static extern int SendMessage(
IntPtr hWnd, // handle to destination window
uint Msg, // message
IntPtr wParam, // first message parameter
IntPtr lParam // second message parameter
);
public const uint WM_LBUTTONDOWN = 0x0201;
public const uint WM_LBUTTONUP = 0x0202;
//This simulates a left mouse click
public static void LeftMouseClick(IntPtr hwnd, uint xpos, uint ypos)
{
SendMessage(hwnd, WM_LBUTTONDOWN, new IntPtr(xpos), new IntPtr(ypos));
SendMessage(hwnd, WM_LBUTTONUP, new IntPtr(xpos), new IntPtr(ypos));
}
private void send()
{
LeftMouseClick(newGraphEditor.Handle, 10, 10);
}
Please let me elaborate what I am doing.
I am creating a screen share application. Where there are 2 apps first is a windows application (whose screen is getting shared) and the other is a browser web app (On which the user is watching the screen). The browser web app is sending client x and y coordinates of the mouse to the windows app. The windows app is using the x and y coordinates to move the mouse using the given below code.
[DllImport("user32.dll")]
static extern bool SetCursorPos(int X, int Y);
public static void MoveCursorToPoint(int x, int y)
{
SetCursorPos(x, y);
}
The browser app is also sending mouse clicks and the windows app is performing the clicks using the given below code.
[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 static void DoMouseClick()
{
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
}
Problem/Challenge
The problem or a challenge here is to perform the drag operation. For an example how will I drag the window of any application from one place to the another place from C# code.
Many thanks for your attention.
Finally, here is the code that will do all the system mouse events. In order to perform the drag and drop operation, you will need to First Send MouseDown(Mouse Click) and keep it Clicked While Changing the Mouse Position than Send MouseUp(Release Click) something like this.
MouseHelper mh = new MouseHelper();
mh.sendMouseDown();
Cursor.Position = new Point(30, 30);
mh.sendMouseUp();
Here is the whole helper file
public class MouseHelper
{
[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);
public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);
private const uint MOUSEEVENTF_LEFTDOWN = 0x02;
private const uint MOUSEEVENTF_LEFTUP = 0x04;
private const uint MOUSEEVENTF_RIGHTDOWN = 0x08;
private const uint MOUSEEVENTF_RIGHTUP = 0x10;
public void sendMouseRightclick(Point p)
{
mouse_event((uint)MOUSEEVENTF_RIGHTDOWN | (uint)MOUSEEVENTF_RIGHTUP, (uint)p.X, (uint)p.Y, (uint)0, (uint)0);
}
public void sendMouseDoubleClick(Point p)
{
mouse_event((uint)MOUSEEVENTF_LEFTDOWN | (uint)MOUSEEVENTF_LEFTUP, (uint)p.X, (uint)p.Y, (uint)0, (uint)0);
Thread.Sleep(150);
mouse_event((uint)MOUSEEVENTF_LEFTDOWN | (uint)MOUSEEVENTF_LEFTUP, (uint)p.X, (uint)p.Y, 0, 0);
}
public void sendMouseRightDoubleClick(Point p)
{
mouse_event((uint)MOUSEEVENTF_RIGHTDOWN | (uint)MOUSEEVENTF_RIGHTUP, (uint)p.X, (uint)p.Y, 0, 0);
Thread.Sleep(150);
mouse_event((uint)MOUSEEVENTF_RIGHTDOWN | (uint)MOUSEEVENTF_RIGHTUP, (uint)p.X, (uint)p.Y, 0, 0);
}
public void sendMouseDown()
{
mouse_event(MOUSEEVENTF_LEFTDOWN, 50, 50, 0, 0);
}
public void sendMouseUp()
{
mouse_event(MOUSEEVENTF_LEFTUP, 50, 50, 0, 0);
}
}
Source The given code at this source link will give an error
Additional Information: A call to PInvoke function 'KinectHandTrackmyApping!myApp.MainWindow::mouse_event' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.
In order resolve the error I have changed
public static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);
to this
public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);
The error was usage of long because long gives an exception because it's a 64-bit, uint works because it's 32-bit -- but it won't work for negative coordinates (which is a common monitor setup in Windows).
I tried
[DllImport("user32.dll")]
static extern bool SetCursorPos(int X, int Y);
and it works pretty fine to move the cursor to the desired point. I have never tried such kind of a DLL import before but it works :). However I want more what else can I extract?
Mainly I want to make double click, click or use wheel options without any mouse input, just the code how can I do that? and how can I check what else is included in user32dll?
Thanx
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, UIntPtr dwExtraInfo);
private const uint MOUSEEVENTF_LEFTDOWN = 0x02;
private const uint MOUSEEVENTF_LEFTUP = 0x04;
private const uint MOUSEEVENTF_RIGHTDOWN = 0x08;
private const uint MOUSEEVENTF_RIGHTUP = 0x10;
You should Import and Define these Constant's to work with Mouse using Win32API
Use method's below to do Mouse Operation's
void sendMouseRightclick(Point p)
{
mouse_event(MOUSEEVENTF_RIGHTDOWN | MOUSEEVENTF_RIGHTUP, p.X, p.Y, 0, 0);
}
void sendMouseDoubleClick(Point p)
{
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, p.X, p.Y, 0, 0);
Thread.Sleep(150);
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, p.X, p.Y, 0, 0);
}
void sendMouseRightDoubleClick(Point p)
{
mouse_event(MOUSEEVENTF_RIGHTDOWN | MOUSEEVENTF_RIGHTUP, p.X, p.Y, 0, 0);
Thread.Sleep(150);
mouse_event(MOUSEEVENTF_RIGHTDOWN | MOUSEEVENTF_RIGHTUP, p.X, p.Y, 0, 0);
}
void sendMouseDown()
{
mouse_event(MOUSEEVENTF_LEFTDOWN, 50, 50, 0, 0);
}
void sendMouseUp()
{
mouse_event(MOUSEEVENTF_LEFTUP, 50, 50, 0, 0);
}
If you want to do a Mouse Drag you should First Send MouseDown(Mouse Click) and keep it Clicked While Changing the Mouse Position than Send MouseUp(Release Click) something like this .
sendMouseDown();
Cursor.Position = new Point(30,30);
sendMouseUp();
Using long type raises an "PInvoke" error.
We should use int type:
[DllImport("user32.dll")]
static extern void mouse_event(int dwFlags, int dx, int dy,
int dwData, int dwExtraInfo);
[Flags]
public enum MouseEventFlags
{
LEFTDOWN = 0x00000002,
LEFTUP = 0x00000004,
MIDDLEDOWN = 0x00000020,
MIDDLEUP = 0x00000040,
MOVE = 0x00000001,
ABSOLUTE = 0x00008000,
RIGHTDOWN = 0x00000008,
RIGHTUP = 0x00000010
}
public static void LeftClick(int x, int y)
{
Cursor.Position = new System.Drawing.Point(x, y);
mouse_event((int)(MouseEventFlags.LEFTDOWN), 0, 0, 0, 0);
mouse_event((int)(MouseEventFlags.LEFTUP), 0, 0, 0, 0);
}
source: http://www.pinvoke.net/default.aspx/user32.mouse_event
Take a look at pinvoke.net for a listing of the available APIs. Code examples and the import statements are included. You can also expand the selection on the left to see the available APIs for each DLL.