I believe what I'm trying to do is fairly simple but have been stuck for hours googling already.
I have a windows Form with a button. When I press the button I want to perform a rightclick with my mouse on coordinate 50, 50. This is outside the form so I think it should be done with a windowhook.
Please help.
You should use not hook, but WinApi.
You need one of 2 methods from USER32.DLL (read about different in MSDN):
[DllImport("user32.dll")]
private static extern bool SendMessage(int hnd, Messages msg, int wParam, uint lParam);
[DllImport("user32.dll")]
private static extern bool PostMessage(int hWnd, Messages msg, int wParam, int lParam);
Messages is a enum, here it is:
enum Messages
{
WM_LBUTTONDOWN = 0x201,
WM_LBUTTONUP = 0x202,
WM_RBUTTONDOWN = 0x204,
WM_RBUTTONUP = 0x205
}
And with this methods you should send special messages to hWND equals to 0, which means sending messages to Desktop.
Here methods which will help you:
public static void MouseLeftClick(Point p)
{
int coordinates = p.X | (p.Y << 16);
PostMessage(0, Messages.WM_LBUTTONDOWN, 0x1, coordinates);
PostMessage(0, Messages.WM_LBUTTONUP, 0x1, coordinates);
}
public static void MouseRightClick(Point p)
{
int coordinates = p.X | (p.Y << 16);
PostMessage(0, Messages.WM_RBUTTONDOWN, 0x1, coordinates);
PostMessage(0, Messages.WM_RBUTTONUP, 0x1, coordinates);
}
By changing 0 to Handle of any Window you can press left or right button in any Window you want.
Related
How can I set the Delta parameter of the WM_MOUSEWHEEL message and send the message to a Windows using PostMessage?
My code:
[DllImport("user32.dll")]
static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
const uint WM_MOUSEWHEEL = 0x020A;
private int MAKELPARAM(int p, int p_2)
{
return ((p_2 << 16) | (p & 0xFFFF));
}
Now I'm using it like this:
IntPtr hwnd1;
hwnd1 = FindWindow(null, "NoxPlayer");
Point location = new Point(1205,411);
PostMessage(hwnd1, WM_MOUSEWHEEL, 0, MAKELPARAM(location.X, location.Y));
When I do it like that I have:
The Windows doesn't scroll because delta is 0.
The WHEEL_DELTA is the default value of a mouse wheel increment (for mouse controllers with no freely-rotating wheel). This value is returned by SystemInformation.MouseWheelScrollDelta.
It's usually set to 120, but it can be a different value.
When the Delta value is positive, it indicates that the mouse wheel is rotated forward, causing a Window to scroll upwards, the opposite when Delta is negative.
In the code sample, directionUp and directionDown determine this direction.
The Delta can be set to a fraction or a multiple of the base increment (can be used to fine-tune the scrolling). See the Docs about WM_MOUSEWHEEL for more information.
In the example, the wheel increment is divided in half (the float multiplier argument of the MAKEWPARAM macro is set to .5f).
The Window identified by [Handle] doesn't need to be activated (it doesn't need to be the Foreground Window).
The Cursor position represents Screen coordinates. The application should be DpiAware to handle Cursor positions and Screen coordinates correctly.
See the notes about the VirtualScreen and how DpiAwareness is involved here:
Using SetWindowPos with multiple monitors.
int directionUp = 1;
int directionDown = -1;
// Scrolls [Handle] down by 1/2 wheel rotation with Left Button pressed
IntPtr wParam = MAKEWPARAM(directionDown, .5f, WinMsgMouseKey.MK_LBUTTON);
IntPtr lParam = MAKELPARAM(Cursor.Position.X, Cursor.Position.Y);
PostMessage([Handle], WM_MOUSEWHEEL, wParam, lParam);
internal const uint WM_MOUSEWHEEL = 0x020A;
[Flags]
public enum WinMsgMouseKey : int
{
MK_NONE = 0x0000,
MK_LBUTTON = 0x0001,
MK_RBUTTON = 0x0002,
MK_SHIFT = 0x0004,
MK_CONTROL = 0x0008,
MK_MBUTTON = 0x0010,
MK_XBUTTON1 = 0x0020,
MK_XBUTTON2 = 0x0040
}
[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
internal static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
internal static IntPtr MAKEWPARAM(int direction, float multiplier, WinMsgMouseKey button)
{
int delta = (int)(SystemInformation.MouseWheelScrollDelta * multiplier);
return (IntPtr)(((delta << 16) * Math.Sign(direction) | (ushort)button));
}
internal static IntPtr MAKELPARAM(int low, int high)
{
return (IntPtr)((high << 16) | (low & 0xFFFF));
}
I know there are already a million threads about this, but I've spent countless hours trying to find a solution and i'm hoping I can find it here instead.
My goal is to create a 'Ghost mouse', meaning that I want to be able to simulate mouse clicks on a certain position in a minimized window, without moving my own cursor our mouse. I want to be able to browse the internet and click on other stuff, while the program does its own thing. This is a feature that many game bots have, but my intention is not to create a bot, but only to experience with.
So far i've managed to simulate mouse clicks, but with my actual mouse.
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);
private const int MOUSEEVENTF_LEFTDOWN = 0x02;
private const int MOUSEEVENTF_LEFTUP = 0x04;
public static void LeftClick()
{
int X = Cursor.Position.X;
int Y = Cursor.Position.Y;
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, X, Y, 0, 0);
}
static void Main(string[] args)
{
System.Threading.Thread.Sleep(5000);
Point pt = new Point(1259, 560);
Cursor.Position = pt;
LeftClick();
}
As far as I know, calling mouse_event will not click in minimized windows.
You have to use SendMessage WinApi for this.
First, acquire a handle for the process, either using OpenProcess or Process.GetProcessesByName(processName).First().MainWindowHandle, then you may use the following code:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
public const uint WM_LBUTTONDOWN = 0x0201;
public const uint WM_LBUTTONUP = 0x0202;
public static IntPtr makeLParam(int x, int y)
{
return (IntPtr)((y << 16) | x);
}
public static void sendMouseClick(IntPtr handle, int x, int y)
{
SendMessage(handle, WM_LBUTTONDOWN, (IntPtr)1, makeLParam(x, y));
SendMessage(handle, WM_LBUTTONUP, (IntPtr)1, makeLParam(x, y));
}
Please note that this code is a bit old and might not still work. Also, keep in mind the game protections prevents acquiring handles for the game process. In addition, some games might query the mouse position from the windows rather than using the ones provided with SendMessage
I am creating a winforms application in visual studio 2017, I am populating the list box using a List.
I set the multicolumn property to true. Since I have lots of strings in my list, there is a horizontal scrollbar appearing at the bottom of the box.
The application I am creating should be working on a tablet, so therefore the scroll bar is not easy to navigate using fingers.
My question is, is there a way to be able to control this scrollbar using a button ?
Yes, It is possible to control the behavior you are expecting with the help of Buttons.
To move from right to left -
private void btnLeft_Click(object sender, EventArgs e)
{
int visibleItemsInColumn = listBox1.ClientSize.Height / listBox1.ItemHeight; //No of items in each column. In this case - 5
listBox1.TopIndex = listBox1.TopIndex - visibleItemsInColumn;
}
To move from left to right -
private void btnRight_Click(object sender, EventArgs e)
{
int visibleItemsInColumn = listBox1.ClientSize.Height / listBox1.ItemHeight;
listBox1.TopIndex = listBox1.TopIndex + visibleItemsInColumn;
}
What it actually does is every time you click on button, It
increases/decreases the TopIndex by the total elements per columns. So
on each clicks, you move one column either left or right.
You can send WM_HSCROLL message to the ListBox to scroll it. To do so, you should first get the scroll position by calling GetScrollInfo methods.
The following code, scrolls the ListBox, 1 column to the right:
var info = new SCROLLINFO() { fMask = ScrollInfoMask.SIF_ALL };
GetScrollInfo(listBox1.Handle, SBOrientation.SB_HORZ, ref info);
var wparam = ((uint)(info.nPos + 1) << 16) | (SB_THUMBPOSITION & 0xffff);
SendMessage(listBox1.Handle, WM_HSCROLL, wparam, 0);
To scroll one column to the left, use info.nPos - 1.
Here are the declarations which you need:
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg,
uint wParam, uint lParam);
[StructLayout(LayoutKind.Sequential)]
struct SCROLLINFO {
public uint cbSize;
public ScrollInfoMask fMask;
public int nMin;
public int nMax;
public uint nPage;
public int nPos;
public int nTrackPos;
}
public enum ScrollInfoMask : uint {
SIF_RANGE = 0x1,
SIF_PAGE = 0x2,
SIF_POS = 0x4,
SIF_DISABLENOSCROLL = 0x8,
SIF_TRACKPOS = 0x10,
SIF_ALL = (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS),
}
[DllImport("user32.dll")]
private static extern bool GetScrollInfo(IntPtr hwnd,
SBOrientation fnBar, ref SCROLLINFO lpsi);
public enum SBOrientation : int {
SB_HORZ = 0x0,
SB_VERT = 0x1,
}
const uint WM_HSCROLL = 0x0114;
const uint SB_THUMBPOSITION = 4;
I want to simulate a mouseclick at a specific position inside a window that is hidden. So no maximizing the window or moving the mouse. I just want to send the right message.
Now I tried something like this
DllImport("user32.dll")]
public static extern int PostMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
static int WM_LBUTTONDOWN = 0x0201;
static int WM_LBUTTONUP = 0x0202;
private static IntPtr MakeLParam(int LoWord, int HiWord)
{
return (IntPtr)((HiWord << 16) | (LoWord & 0xffff));
}
public static void test()
{
int windowPtr = FindWindow(null, "Calculator");
Console.WriteLine("pointer: " + windowPtr);
int x = 260;
int y = 180;
IntPtr lParam = MakeLParam(x, y);
IntPtr windowPointer = new IntPtr(windowPtr);
PostMessage(windowPointer, WM_LBUTTONDOWN, IntPtr.Zero, lParam);
PostMessage(windowPointer, WM_LBUTTONUP, IntPtr.Zero, lParam);
}
I expected this program to click the 8 on the calculator ( if you set it to scientific ), but it doesn't do that.
How can I simulate that click? Please don't suggest finding the windows-control-element for the "8"-Button, this is not what I am trying to do here.
I want to simulate a left-click at the window (background) x/y coordinates.
I have searched and found a lot of stuff to simulate mouseclicks to other windows but it does not work 100% well.
My code:
private const int WM_LBUTTONDOWN = 0x201; //Left mousebutton down
private const int WM_LBUTTONUP = 0x202; //Left mousebutton up
[DllImport("user32.dll", EntryPoint = "PostMessageA", SetLastError = true)]
public static extern bool PostMessage(IntPtr hwnd, uint Msg, IntPtr wParam, IntPtr lParam);
public void SimulateMouseLeft(IntPtr hwnd, int x,int y)
{
int coordinates = x | (y << 16);
//PostMessage(hwnd, WM_LBUTTONDOWN, IntPtr.Zero, (IntPtr)coordinates);
//PostMessage(hwnd, WM_LBUTTONUP, IntPtr.Zero, (IntPtr)coordinates);
PostMessage(hwnd, WM_LBUTTONDOWN, (IntPtr)0x1, (IntPtr)coordinates);
PostMessage(hwnd, WM_LBUTTONUP, (IntPtr)0x1, (IntPtr)coordinates);
//send left button up
//PostMessage(hwnd, 0x202, (IntPtr)0x1, (IntPtr)coordinates);
}
If I start this code, and simulate a click to another window, then the other window gets a left click but not at x/y. The click is at the same position then my mouse is and after the click my mouse jumps to another position on the screen.
Thanks for your help!