C# auto click and send key to another application window 10 - c#

I need to write an auto click C# application for Bluestack in background.
I tried using Autoit api and I can click or sendkey, but it does not support drag & drop.
I found a solution using "user32.dll" PostMessage on C#, but it doesn't seem to work in window 10 anymore.
Anyone have other solutions. Please help. Thanks a lot!
[DllImport("user32.dll", SetLastError = true)]
static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
PostMessage(handle, (uint)WMessages.WM_LBUTTONDOWN, 0, MAKELPARAM(400, 400));

Make Sure you are using correct window handle for sending click. It is with name BlueStacks Android PluginAndroid{X} {X=>instance of android running}
I tries sending message to that handle of window and it worked like charm on win10.
Win32.SendMessage(0x00060714, Win32.WM_LBUTTONDOWN, 0x00000001, 0x1E5025B);
Here is the winapi class I picked from here
public class Win32
{
// The WM_COMMAND message is sent when the user selects a command item from
// a menu, when a control sends a notification message to its parent window,
// or when an accelerator keystroke is translated.
public const int WM_KEYDOWN = 0x100;
public const int WM_KEYUP = 0x101;
public const int WM_COMMAND = 0x111;
public const int WM_LBUTTONDOWN = 0x201;
public const int WM_LBUTTONUP = 0x202;
public const int WM_LBUTTONDBLCLK = 0x203;
public const int WM_RBUTTONDOWN = 0x204;
public const int WM_RBUTTONUP = 0x205;
public const int WM_RBUTTONDBLCLK = 0x206;
// The FindWindow function retrieves a handle to the top-level window whose
// class name and window name match the specified strings.
// This function does not search child windows.
// This function does not perform a case-sensitive search.
[DllImport("User32.dll")]
public static extern int FindWindow(string strClassName, string strWindowName);
// The FindWindowEx function retrieves a handle to a window whose class name
// and window name match the specified strings.
// The function searches child windows, beginning with the one following the
// specified child window.
// This function does not perform a case-sensitive search.
[DllImport("User32.dll")]
public static extern int FindWindowEx(
int hwndParent,
int hwndChildAfter,
string strClassName,
string strWindowName);
// The SendMessage function sends the specified message to a window or windows.
// It calls the window procedure for the specified window and does not return
// until the window procedure has processed the message.
[DllImport("User32.dll")]
public static extern Int32 SendMessage(
int hWnd, // handle to destination window
int Msg, // message
int wParam, // first message parameter
[MarshalAs(UnmanagedType.LPStr)] string lParam); // second message parameter
[DllImport("User32.dll")]
public static extern Int32 SendMessage(
int hWnd, // handle to destination window
int Msg, // message
int wParam, // first message parameter
int lParam); // second message parameter
}

Related

ShowWindow is unable to show or minimize Task Manager

I need to show Task Manager app programatically, maximize it and minimize it as any other window but there is a problem and it simply doesn't respond to ShowWindow(int hWnd, int nCmdShow).
I am pretty sure I use the correct handle because I enumerated all of the windows with EnumWindows(PCallBack callback, int lParam) and the only window that didn't respond was the task manager window with title process.MainWindowTitle = "Task Manager", I even manually found its handle using spy++ but it still doesn't respond to SW_SHOWNORMAL or any other nCmdShow parameter. I tried running apps as administrator to see if it has something to do with the issue but they kept behaving like normal when proper handle was given to ShowWindow function;
private delegate bool PCallBack(int hWnd, int lParam);
private static void ShowWindows()
{
EnumWindows(new PCallBack(FindWindows), 0);
}
private bool FindWindows(int handle, int lparam)
{
Console.WriteLine("showing");
ShowWindow(handle, (int)SW.SHOWMINIMIZED);
ShowWindow(handle, (int)SW.SHOWNORMAL);
Thread.Sleep(3000);
return true;
}
static void Main(string[] args)
{
ShowWindows();
}
This code literally shows every window EnumWindows can find even if they are not visible and task manager was never shown which proved to me that the problem has nothing to do with wrong handle.
This is how I find it by the way.
// the correct handle of Task Manager window
var handle = (int)Process.GetProcessesByName("taskmgr").FirstOrDefault().MainWindowHandle;
Basically this is my problem. Need help.
it simply doesn't respond to ShowWindow(int hWnd, int nCmdShow).
I tested on Windows 10 and this works for me :
Manifest file with level="requireAdministrator"
Test :
IntPtr hWndTarget = FindWindow("TaskManagerWindow", null);
bool bRet = ShowWindow(hWndTarget, SW_SHOWMINIMIZED);
with declarations :
[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
public const int SW_HIDE = 0;
public const int SW_SHOWNORMAL = 1;
public const int SW_SHOWMINIMIZED = 2;
public const int SW_SHOWMAXIMIZED = 3;

Send Short cut command to other application in c#

Hi I am developing an application (A) in c# that will use other application (B) which is running in try mode in the background. I want to send some short cut commands to application (B) from Application (A) by pressing a button on Application (A) I have following code behind the button:
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
// public static extern IntPtr FindWindowEx(IntPtr handleParent, IntPtr handleChild, string className, string WindowName);
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
public const int WM_SYSCOMMAND = 0x0112;
public const int SC_CLOSE = 0xF060;
public const int WM_KEYDOWN = 0x0102;
public const int VK_SHIFT=10;
public const int VK_A = 0x41;
public void sendShortcutsToOneScreenConnect()
{
Process[] process1 = Process.GetProcessesByName("NameOfTheProcess");
process1[0].WaitForInputIdle();
IntPtr handler = FindWindow(null,"Tittle Of The Window ");
SendMessage(handler, WM_KEYDOWN, VK_A, VK_SHIFT);
}
I am getting "0" handler of this window . And can some body tell me is this right approach to this thing ? I don't want to bring Application (B) window to foreground .

How to send WM_APPCOMMAND message

I'm trying to send WM_APPCOMMAND message to foreground window, but it's not working.
Can someone explain to me how to do it correctly?
[DllImportAttribute("user32.dll")]
public static extern int SendMessage(int hWnd, int Msg, int wParam, int lParam);
[DllImport("user32.dll")]
public static extern int GetForegroundWindow();
public const int WM_APPCOMMAND = 0x319;
public const int APPCOMMAND_UNDO = 34;
SendMessage(GetForegroundWindow(), WM_APPCOMMAND, 0, WM_UNDO * 65536);
EDIT:
Hans Passant: Most AppCommands are mapped to dedicated keys on the keyboard and automatically triggered when you press such a key. Since very few keyboards actually have an Undo key, the odds that an app will respond to APPCOMMAND_UNDO are zilch.
Thank you Hans. This is the answer.

programmatically mouse click in another window

Is it possible to click programmatically a location in another window without moving the mouse to that location and even if the window is not on-top? I want to send a kind of message to another window to simulate a mouse click on a location.
I tried to accomplish this with PostMessage:
PostMessage(WindowHandle, 0x201, IntPtr.Zero, CreateLParam(300,300));
PostMessage(WindowHandle, 0x202, IntPtr.Zero, CreateLParam(300,300));
I made the CreateLParam function this way:
private static IntPtr CreateLParam(int LoWord, int HiWord)
{
return (IntPtr)((HiWord << 16) | (LoWord & 0xffff));
}
The problem is that the window gets locked on his location. I think that my application clicks on the (1,1) coordinate. Can some on help me with this problem?
Edit:
This is PostMessage:
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll")]
public static extern bool PostMessage(IntPtr WindowHandle, int Msg, IntPtr wParam, IntPtr lParam);
And 0x201 and 0x202 are WM_LBUTTONDOWN and WM_LBUTTONUP respectively.
You can't do that by sending messages, instead use SendInput Windows API.
Call method ClickOnPoint, this is an example from form click event, so this.handle is form handle, note that these are client coordinates on window witch handle is send, you can easily change this and send screen coordinates, and in that case you don't need handle or ClientToScreen call below.
ClickOnPoint(this.Handle, new Point(375, 340));
UPDATE: using SendInput now, tnx Tom.
btw. I used only declarations needed for this sample, for anything more there is a nice library : Windows Input Simulator (C# SendInput Wrapper - Simulate Keyboard and Mouse)
public class ClickOnPointTool
{
[DllImport("user32.dll")]
static extern bool ClientToScreen(IntPtr hWnd, ref Point lpPoint);
[DllImport("user32.dll")]
internal static extern uint SendInput(uint nInputs, [MarshalAs(UnmanagedType.LPArray), In] INPUT[] pInputs, int cbSize);
#pragma warning disable 649
internal struct INPUT
{
public UInt32 Type;
public MOUSEKEYBDHARDWAREINPUT Data;
}
[StructLayout(LayoutKind.Explicit)]
internal struct MOUSEKEYBDHARDWAREINPUT
{
[FieldOffset(0)]
public MOUSEINPUT Mouse;
}
internal struct MOUSEINPUT
{
public Int32 X;
public Int32 Y;
public UInt32 MouseData;
public UInt32 Flags;
public UInt32 Time;
public IntPtr ExtraInfo;
}
#pragma warning restore 649
public static void ClickOnPoint(IntPtr wndHandle , Point clientPoint)
{
var oldPos = Cursor.Position;
/// get screen coordinates
ClientToScreen(wndHandle, ref clientPoint);
/// set cursor on coords, and press mouse
Cursor.Position = new Point(clientPoint.X, clientPoint.Y);
var inputMouseDown = new INPUT();
inputMouseDown.Type = 0; /// input type mouse
inputMouseDown.Data.Mouse.Flags = 0x0002; /// left button down
var inputMouseUp = new INPUT();
inputMouseUp.Type = 0; /// input type mouse
inputMouseUp.Data.Mouse.Flags = 0x0004; /// left button up
var inputs = new INPUT[] { inputMouseDown, inputMouseUp };
SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(INPUT)));
/// return mouse
Cursor.Position = oldPos;
}
}
I found in the past, a way to send message to Windows Media Player
so I used that to simulate click in application I wanted!
Using this class (code below) to find the window and to send messages you want!
using System;
using System.Runtime.InteropServices;
namespace Mouse_Click_Simulator
{
/// <summary>
/// Summary description for Win32.
/// </summary>
public class Win32
{
// The WM_COMMAND message is sent when the user selects a command item from
// a menu, when a control sends a notification message to its parent window,
// or when an accelerator keystroke is translated.
public const int WM_KEYDOWN = 0x100;
public const int WM_KEYUP = 0x101;
public const int WM_COMMAND = 0x111;
public const int WM_LBUTTONDOWN = 0x201;
public const int WM_LBUTTONUP = 0x202;
public const int WM_LBUTTONDBLCLK = 0x203;
public const int WM_RBUTTONDOWN = 0x204;
public const int WM_RBUTTONUP = 0x205;
public const int WM_RBUTTONDBLCLK = 0x206;
// The FindWindow function retrieves a handle to the top-level window whose
// class name and window name match the specified strings.
// This function does not search child windows.
// This function does not perform a case-sensitive search.
[DllImport("User32.dll")]
public static extern int FindWindow(string strClassName, string strWindowName);
// The FindWindowEx function retrieves a handle to a window whose class name
// and window name match the specified strings.
// The function searches child windows, beginning with the one following the
// specified child window.
// This function does not perform a case-sensitive search.
[DllImport("User32.dll")]
public static extern int FindWindowEx(
int hwndParent,
int hwndChildAfter,
string strClassName,
string strWindowName);
// The SendMessage function sends the specified message to a window or windows.
// It calls the window procedure for the specified window and does not return
// until the window procedure has processed the message.
[DllImport("User32.dll")]
public static extern Int32 SendMessage(
int hWnd, // handle to destination window
int Msg, // message
int wParam, // first message parameter
[MarshalAs(UnmanagedType.LPStr)] string lParam); // second message parameter
[DllImport("User32.dll")]
public static extern Int32 SendMessage(
int hWnd, // handle to destination window
int Msg, // message
int wParam, // first message parameter
int lParam); // second message parameter
}
}
For Example:
Win32.SendMessage(iHandle, Win32.WM_LBUTTONDOWN, 0x00000001, 0x1E5025B);
Here's My Application Source Code that I Created to auto click in "BlueStacks" Application in a specific interval!
For FindWindow, wParam, lParam, etc. you can feel free to ask me how to do it! it's not too hard :) ;)
Hope it helped! :)
I can't add a comment :D
Work for me:
[DllImport("User32.dll")]
public static extern Int32 SendMessage(
int hWnd,
int Msg,
int wParam,
IntPtr lParam);
and combine coord in lParam like this:
private static IntPtr CreateLParam(int LoWord, int HiWord)
{
return (IntPtr)((HiWord << 16) | (LoWord & 0xffff));
}
and use:
Clicktoapp.SendMessage(0x00040156, Clicktoapp.WM_LBUTTONDOWN, 0x00000001, CreateLParam(150,150));
Clicktoapp.SendMessage(0x00040156, Clicktoapp.WM_LBUTTONUP, 0x00000000, CreateLParam(150, 150));
0x00040156 - Window Handle.
I was looking for a window handle using spy ++
Each time it is new, so it's better to use FindWindow.
P.S
Screenshot of the application window even if the window is not on top
https://stackoverflow.com/a/911225/12928587
i use this solution. work great.

How to simulate Keyboard Events in Code in not active window?

How do I use SendWait() to send key strokes to a window without using SetForegroundWindow() to make the target window active?
Here is the SendWait example on the MSDN site: http://msdn.microsoft.com/en-us/library/ms171548.aspx
See this thread. Basically given some handle to a window, you need to use p/invoke and call PostMessage with the WM_KEYDOWN message:
private const int VK_RETURN = 0x0D;
private const uint WM_KEYDOWN = 0x0100;
[DllImport("user32.dll", SetLastError = true)]
private static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
public void SendKeysToWindow(IntPtr hWnd)
{
PostMessage(hWnd, WM_KEYDOWN, new IntPtr(VK_RETURN), IntPtr.Zero);
}
Here's the list of Virtual Keys.

Categories