I have a scenario, i need to send click events to an independent application. I started that application with the following code.
private Process app;
app = new Process();
app.StartInfo.FileName = app_path;
app.StartInfo.WorkingDirectory = dir_path;
app.Start();
Now i want to send Mouse click message to that applicaiton, I have specific coordinates in relative to application window. How can i do it using Windows Messaging or any other technique.
I used
[DllImport("user32.dll")]
private static extern void mouse_event(UInt32 dwFlags, UInt32 dx, UInt32 dy, UInt32 dwData, IntPtr dwExtraInfo);
It works well but cause the pointer to move as well. So not fit for my need.
Then i use.
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
It works well for minimize maximize, but do not work for mouse events.
The codes for mousevents i am using are,
WM_LBUTTONDOWN = 0x201, //Left mousebutton down
WM_LBUTTONUP = 0x202, //Left mousebutton up
WM_LBUTTONDBLCLK = 0x203, //Left mousebutton doubleclick
WM_RBUTTONDOWN = 0x204, //Right mousebutton down
WM_RBUTTONUP = 0x205, //Right mousebutton up
WM_RBUTTONDBLCLK = 0x206, //Right mousebutton do
Thanks for the help in advance, and waiting for feedback.
For a single click you should send two mouse event at the same time for an exact mouse click event.
SendMessage(nChildHandle, 0x201, 0, 0); //Mouse left down
SendMessage(nChildHandle, 0x202, 0, 0); //Mouse left up
It is working in my project.
Save the cursor position, use mouse_event and move the cursor back. mouse_event is really the best way to do this.
Related
Essentially cannot find and answer to this question, or if it is even possible.
I have a game I am creating for a class, and it simply looks better when forced full screen and when the zoom is set to a particular size. I was wonder if I could recreate this without the player being necessary to change it themselves.
ALT + ENTER Full screen
And
CTRL + Scroll wheel zoom
For a literal answer to your question on how to:
Send keys to go Fullscreen, and
Send a Ctrl+MouseWheel
You want some help from the Win32 interop to send keyboard & mouse messages to your console window.
using System.Runtime.InteropServices;
public class Win32
{
public const int VK_F11 = 0x7A;
public const int SW_MAXIMIZE = 3;
public const uint WM_KEYDOWN = 0x100;
public const uint WM_MOUSEWHEEL = 0x20A;
public const uint WHEEL_DELTA = 120;
public const uint MK_CONTROL = 0x00008 << 16;
[DllImport("kernel32.dll")]
public static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
}
As reference the magic numbers are from:
Virtual Keys (VK_*)
Window input messages (WM_*)
Mousewheel params (WHEEL_DELTA & MK_*)
and the ShowWindow params (SW_*)
You could then simply send your keypress and mousewheel like so:
using static Win32;
// Get window handle of the console
var hwnd = GetConsoleWindow();
// Go fullscreen by sending the F11 keydown message.
PostMessage(hwnd, WM_KEYDOWN, (IntPtr)VK_F11, IntPtr.Zero);
// Or maximize the window instead. Your users may not know how to get out of fullscreen...
/// ShowWindow(hwnd, SW_MAXIMIZE);
// Send mouse wheel message.
// MK_CONTROL: Holds the Ctrl key. WHEEL_DELTA: Positive=Up, Negative=Down.
PostMessage(hwnd, WM_MOUSEWHEEL, (IntPtr)(MK_CONTROL | WHEEL_DELTA), IntPtr.Zero);
Alternatively, as #JeremyLakerman mentioned in a comment to your question, you could set the console font to a larger size; which is a lot better, but also a bit more involved than sending Ctrl+MouseWheel.
Well, first off, what I'm trying to do is click a specific point inside a flash object, inside of a webbrowser control. I'm not sure why it isn't working, but I cannot seem to click any window, be it notepad, or the actual program.
Here is my code that I'm using.
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, IntPtr windowTitle);
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(String sClassName, String sAppName);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImport("user32.dll", SetLastError = true)]
static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
public IntPtr find()
{
return this.Handle;//FindWindow("", "Form1");
}
public enum WMessages : int
{
WM_LBUTTONDOWN = 0x201, //Left mousebutton down
WM_LBUTTONUP = 0x202, //Left mousebutton up
WM_LBUTTONDBLCLK = 0x203, //Left mousebutton doubleclick
WM_RBUTTONDOWN = 0x204, //Right mousebutton down
WM_RBUTTONUP = 0x205, //Right mousebutton up
WM_RBUTTONDBLCLK = 0x206, //Right mousebutton do
}
private int MAKELPARAM(int p, int p_2)
{
return ((p_2 << 16) | (p & 0xFFFF));
}
/** This is the non-working code **/
public void DoMouseLeftClick(IntPtr handle, Point x)
{
SendMessage(handle, (int)WMessages.WM_LBUTTONDOWN, 0, MAKELPARAM(x.X, x.Y));
SendMessage(handle, (int)WMessages.WM_LBUTTONUP, 0, MAKELPARAM(x.X, x.Y));
return;
//I have tried PostMessage, and SendMessage, and both of them at the same time, and neither works.
PostMessage(handle, (uint)WMessages.WM_LBUTTONDOWN, 0, MAKELPARAM(x.X, x.Y));
PostMessage(handle, (uint)WMessages.WM_LBUTTONUP, 0, MAKELPARAM(x.X, x.Y));
}
private void timer2_Tick(object sender, EventArgs e)
{
//I try hovering my mouse over a button I added to the form, and nothing happens.
DoMouseLeftClick(find(), Cursor.Position);
}
So, I have tried using PostMessage, and SendMessage, and neither of those seem to work.
All I need it to do is to click on a specific point.
Also, I need to mention that I can't use mouse_event, because from what I know, the window needs to be active, plus the cursor needs to be over the point you are clicking. I am making a bot that automatically does a process in a flash object, so that's why I can't use mouse_event.
Thanks for your help guys.
I had the same problem.
I tried to draw something in the MS Paint. It turned out that I was clicking on the main window but it turned out that MS Paint (and most of the applications) consist of many child windows and you actually want to click on the child. So I had to change my code from:
IntPtr handle = FindWindow(null, "Untitled - Paint");
PostMessage(handle, (uint)MOUSE_BUTTONS.LEFT_DOWN, 0, lparam);
to
IntPtr handle = FindWindow(null, "Untitled - Paint");
handle = FindWindowEx(handle, IntPtr.Zero, "MSPaintView", null);
canvasHandle = FindWindowEx(handle, IntPtr.Zero, "Afx:00007FF676DD0000:8", null);
PostMessage(canvasHandle, (uint)MOUSE_BUTTONS.LEFT_DOWN, 0, lparam);
You need to use tools like Spy++ for Windows that comes with C++ Visual Studio package if you want to debug these kind of things (even if you program in C#)
Hope it helps someone.
For the WM_LBUTTONDOWN, you may need to specify which button. Take reference for: https://msdn.microsoft.com/en-us/library/windows/desktop/ms645607(v=vs.85).aspx
I used:
SendMessage(hWnd, (int)WMessages.WM_RBUTTONDOWN, (int)KeyDownMessage.MK_LBUTTON, MAKELPARAM(x, y));
Winforms App. .Net 3.5.
I need to set the focus from my C# application to the user's desktop (almost like simulating a mouse click on the desktop).
Can someone please show me how to do this with C#? I just want to set focus on the desktop so the focus is no longer on my application but I want to do this from within my application.
Edit: An answer below works by setting the focus to the desktop, but it minimizes all the open windows on the user's desktop.
Is there a way I can maybe set the focus to the next open window on the desktop instead? I just want to get the focus off of my application (without minimizing my application or hiding it). I just want to move focus to somewhere else. Maybe the desktop was not the best choice if it will minimize all the user's open windows/applications.
This should do it for you.
using System;
using System.Runtime.InteropServices;
namespace ConsoleApplication1 {
class Program {
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", EntryPoint = "SendMessage", SetLastError = true)]
static extern IntPtr SendMessage(IntPtr hWnd, Int32 Msg, IntPtr wParam, IntPtr lParam);
const int WM_COMMAND = 0x111;
const int MIN_ALL = 419;
const int MIN_ALL_UNDO = 416;
static void Main(string[] args) {
IntPtr lHwnd = FindWindow("Shell_TrayWnd", null);
SendMessage(lHwnd, WM_COMMAND, (IntPtr)MIN_ALL, IntPtr.Zero);
System.Threading.Thread.Sleep(2000);
SendMessage(lHwnd, WM_COMMAND, (IntPtr)MIN_ALL_UNDO, IntPtr.Zero);
}
}
}
Get Next Window
I don't have a code example ready for these two but I'm going to give you the links to both. The first think you need to do is call GetWindow. After doing that you'll want to call SwitchToThisWindow passing in the pointer you received from GetWindow.
You can add this COM object in your project:
Microsoft Shell Controls And Automation
And then just call:
Shell32.ShellClass shell = new Shell32.ShellClass();
shell.MinimizeAll();
This will minimize all the windows and then focus the desktop. Otherwise, if you have your window non-full screen then you can simulate the mouse click using:
//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);
}
You can calculate coordinates by looking at your window startup location plus height/width and select a available space (that will be the desktop indeed).
I have created a small Window without border by WinApi functions in C#. I want to move this window when right mouse button is pressed. I am trying to catch a mouse offset by anylizing WM_MOUSEMOVE event. It seems to work and i can move my window holding Right Mouse Button.
But I am loosing control of the window when i move my mouse too fast. That's because my Window is too small and if mouse leaves window very quick it doesn'n recieve WM_MOUSEMOVE messages anymore and i can't calculate a MouseOffset to move my Window.
So, How I can fix that?
You need to call SetCapture to tell Windows that your hwnd wants all the events even when the mouse isn't physically over the window. http://msdn.microsoft.com/en-us/library/windows/desktop/ms646262(v=vs.85).aspx
You can tell Windows that the user actually moused down on the title bar and it will handle the rest automatically for you.
[DllImport("user32.dll", CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool ReleaseCapture();
[DllImport("user32.dll", CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
internal const uint WM_NCLBUTTONDOWN = 0xA1;
internal const int HTCAPTION = 2; // Window captions
internal const int HTBOTTOMRIGHT = 17; // Bottom right corner
/// <summary>
/// Simulates a Windows drag on the window border or title.
/// </summary>
/// <param name="handle">The window handle to drag.</param>
/// <param name="dragType">A HT* constant to determine which part to drag.</param>
internal static void DragWindow(IntPtr handle, int dragType) {
User32.ReleaseCapture();
User32.PostMessage(handle, User32.WM_NCLBUTTONDOWN, new IntPtr(dragType), IntPtr.Zero);
}
I am trying to generate an click event in a third party application. As a start I tried to simulate a click in calculator. Here's the code"
IntPtr hwnd = IntPtr.Zero;
IntPtr hwndChild = IntPtr.Zero;
//Get a handle for the Calculator Application main window
hwnd = FindWindow(null, "Calculator");
hwndChild = FindWindowEx(hwnd, IntPtr.Zero, "Button", "1");
//send BN_CLICKED message
SendMessage(hwndChild, BM_CLICK, IntPtr.Zero, IntPtr.Zero);
But using this code I am not getting the handle of the button. Could someone help please. Is there any other way to simulate a button click on third party application?
Thanks.
Your general approach is correct, but there are two potential problems with your code:
FindWindowEx only finds direct children of the specified window. It's possible that the calculator buttons are laid out in a container window which is a child of the main window, so the button wouldn't be a direct child of the main window.
The documentation for BM_CLICK says that it simulates a click by sending mouse down and up messages and hence you may have to activate the parent window before sending this message.
It started to work when I replaced
public const uint BM_CLICK = 0x00F5;
with
public const uint WM_LBUTTONDOWN = 0x0201;
public const uint WM_LBUTTONUP = 0x0202;
and used
SendMessage(buttonHandle, WM_LBUTTONDOWN, IntPtr.Zero, IntPtr.Zero);
SendMessage(buttonHandle, WM_LBUTTONUP, IntPtr.Zero, IntPtr.Zero);
First use SPY++ to find that is a button having Handle.
In some cases the controls that looks like Button can be graphic control.
The difference is the graphic control will not have Handle, but the Windows control will have handle.
If that control has valid Handle.Then use FindWindowEx
Also give Parent window Handle (I think first parameter, May be you have to use GetWindow() using the caption)
Then send click message.
If you haven't the handle of the button, you can emulate mouse clicking on coordinates:
class User32
{
[Flags]
public enum MouseEventFlags
{
LEFTDOWN = 0x00000002,
LEFTUP = 0x00000004,
MIDDLEDOWN = 0x00000020,
MIDDLEUP = 0x00000040,
MOVE = 0x00000001,
ABSOLUTE = 0x00008000,
RIGHTDOWN = 0x00000008,
RIGHTUP = 0x00000010
}
[DllImport("user32.dll")]
public static extern bool SetCursorPos(int X, int Y);
[DllImport("user32.dll")]
public static extern void mouse_event(uint dwFlags,
uint dx,
uint dy,
uint dwData,
int dwExtraInfo);
[DllImport("user32.dll")]
public static extern void mouse_event(uint dwFlags,
uint dx,
uint dy,
uint dwData,
UIntPtr dwExtraInfo);
}
class Program
{
static void Main()
{
User32.SetCursorPos(25, 153);
User32.mouse_event((uint)User32.MouseEventFlags.LEFTDOWN, 25, 153, 0, 0);
User32.mouse_event((uint)User32.MouseEventFlags.LEFTUP, 25, 153, 0, 0);
}
}
But, function SetCursorPos set cursor position in global coordinates of screen, so fist you shoud get the possition of a third party application's window.