Obtain mouse click position relative to active window - c#

Having worked out how to obtain the mouse click position anywhere along the monitor boundaries using low level hooks I receive an X Y coordinate that will contain a value typically between x: -1680 to +1920 and y: 0 to 1200 in my pcs case. Easy enough!
Now the problem is that I now want to calculate the mouse position relative to a given window that I have so I use GetForegroundWindow() and GetWindowRect(HandleRef hWnd, out RECT lpRect) to obtain my active window coordinates.
Where I am stuck is I require the current active desktop (By active I mean which monitor the click occurred on) to calculate the coordinates of my mouse click relative to a window.
Unfortunately I have not been able to find an API call like GetActiveMonitor() or similar so hopefully someone can point me in the right direction?

[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
Call it as:
RECT rct = new RECT();
GetWindowRect(hWnd, ref rct);
after get your mouse position like this
int mouserelativepositionX = mousePosition.X - rct.Left;
int mouserelativepositionY = mousePosition.Y - rct.Top;

My guess is that you can know where your mouse is by using an if:
if(mousePosition.X > -1680 && mousePosition.X < 0)
//We are in monitor 1;
else
//Monitor 2;

Related

Hijacking another processes form

So, I have been asked to figure out a way to make a program containing sensitive data more secure since we have staff that go afk and put potentially put data at risk.
I have loaded up Visual Studio for C# and found a nice way to get process of the fore mentioned application. Then grab the main window and attach a panel of my very own. This panel will basically now be used like a blind covering the application when its not in use.
Now, I have a program running in system tray waiting for the sensitive data to come on screen and my little panel hijacks the entire window and now nothing can be seen.
My problem now is how ever, that whilst my panel is attacked the main window of the application i am trying to lock out seems to just crash. I am guessing that is because my panel and the application belong to different processes.
Anyway I could do with some advise here.
Here is my panels class.
class LockingPanel : System.Windows.Forms.Panel
{
private IntPtr prn;
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
public void SetParent(IntPtr parent)
{
prn = parent;
SetParent(this.Handle, prn);
}
public IntPtr GetParent() {
return prn;
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(IntPtr hWnd, ref RECT Rect);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left; // x position of upper-left corner
public int Top; // y position of upper-left corner
public int Right; // x position of lower-right corner
public int Bottom; // y position of lower-right corner
}
public void FillParent()
{
RECT rtc = new RECT();
GetWindowRect(prn, ref rtc);
this.Location = new System.Drawing.Point(0, 0);
this.Size = new System.Drawing.Size(rtc.Right, rtc.Bottom);
}
Anybody got a better idea on how I can go about this, or at least make it so that my panel inst going to crash the application.

C# Moving/Clicking Mouse Winforms

i want to make an application that will automatically move the mouse and click it with just a press of a button in the background.. I'm from Sales and Inventory / HTML Shop website programming and this is my first time making an application that involves control. please help me because i want to push my programming skills.
This is what i'm trying to do and my Idea.
*i will put an loop counter for the repetition of the moves
1.get the x/y of current cursor and save it to variable named (coordinate) (Point A)
2.Right click it and move lower right (Point B)
3.wait 2 seconds
4.Move back to the first position by using variable (coordinate)
5.End loop repeat.
that's my idea and my algorithm my problem is i don't have any idea how to move a mouse and make it stop.
In Window Form projects to move a cursor to a specific point on your screen, you can use this static method.
System.Windows.Forms.Cursor.Position = new Point (X,Y);
and to perform a click event you can use this method.
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);
public void DoMouseClick()
{
//Call the imported function with the cursor's current position
uint X = (uint)System.Windows.Forms.Cursor.Position.X;
uint Y = (uint)System.Windows.Forms.Cursor.Position.Y;
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, X, Y, 0, 0);
}
You can move mouse writing some function or code like this:
private void MoveCursor()
{
// Set the Current cursor, move the cursor's Position,
// and set its clipping rectangle to the form.
this.Cursor = new Cursor(Cursor.Current.Handle);
Cursor.Position = new Point(Cursor.Position.X - 50, Cursor.Position.Y - 50);
Cursor.Clip = new Rectangle(this.Location, this.Size);
}
How To Move mouse in C#
And to find location of any control on your Form you can use the following code
Point locationOnForm = control.FindForm().PointToClient(
control.Parent.PointToScreen(control.Location));
How to get controls location in Win Forms

Position a small console window to the bottom left of the screen?

As the title says, I want to position it to the bottom left corner of the screen. Here's the code I have so far:
Console.WindowWidth = 50
Console.WindowHeight = 3
Console.BufferWidth = 50
Console.BufferHeight = 3
Console.BackgroundColor = ConsoleColor.Black
Console.ForegroundColor = ConsoleColor.DarkMagenta
Console.Title = "My Title"
Console.WriteLine("")
Console.Write(" Press any key to close this window ...")
Console.ReadKey()
Note: Despite their names, setting Console.WindowLeft and Console.WindowTop of the System.Console class does not change the window's position on screen.
Instead, they position the visible part of the window relative to the (potentially larger) window buffer - you cannot use type System.Console to change the position of console windows on the screen - you need to use the Windows API for that.
The following is code for a complete console application that positions its own window in the lower left corner of the screen, respecting the location of the taskbar.
Note:
It should work with multi-monitor setups - positioning the window on the specific monitor (display, screen) it is (mostly) being displayed on - but I haven't personally verified it.
Only Windows API functions are used via P/Invoke declarations, avoiding the need for referencing the WinForms assembly (System.Windows.Forms), which is not normally needed in console applications.
You'll see that a good portion of the code is devoted to P/Invoke signatures (declaration) for interfacing with the native Windows APIs; these were gratefully adapted from pinvoke.net
The actual code in the Main() method is short by comparison.
If you compile the code below from a console-application project in Visual Studio and run the resulting executable from a cmd.exe console window (Command Prompt), that console window should shift to the lower left corner of the (containing screen).
To verify the functionality while running from Visual Studio, place a breakpoint at the closing } and, when execution pauses, Alt-Tab to the console window to verify its position.
using System;
using System.Runtime.InteropServices; // To enable P/Invoke signatures.
public static class PositionConsoleWindowDemo
{
// P/Invoke declarations.
[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
static extern IntPtr MonitorFromWindow(IntPtr hwnd, uint dwFlags);
const int MONITOR_DEFAULTTOPRIMARY = 1;
[DllImport("user32.dll")]
static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFO lpmi);
[StructLayout(LayoutKind.Sequential)]
struct MONITORINFO
{
public uint cbSize;
public RECT rcMonitor;
public RECT rcWork;
public uint dwFlags;
public static MONITORINFO Default
{
get { var inst= new MONITORINFO(); inst.cbSize = (uint)Marshal.SizeOf(inst); return inst; }
}
}
[StructLayout(LayoutKind.Sequential)]
struct RECT
{
public int Left, Top, Right, Bottom;
}
[StructLayout(LayoutKind.Sequential)]
struct POINT
{
public int x, y;
}
[DllImport("user32.dll", SetLastError = true)]
static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
[DllImport("user32.dll", SetLastError = true)]
static extern bool SetWindowPlacement(IntPtr hWnd, [In] ref WINDOWPLACEMENT lpwndpl);
const uint SW_RESTORE= 9;
[StructLayout(LayoutKind.Sequential)]
struct WINDOWPLACEMENT
{
public uint Length;
public uint Flags;
public uint ShowCmd;
public POINT MinPosition;
public POINT MaxPosition;
public RECT NormalPosition;
public static WINDOWPLACEMENT Default
{
get
{
var instance = new WINDOWPLACEMENT();
instance.Length = (uint) Marshal.SizeOf(instance);
return instance;
}
}
}
public static void Main()
{
// Get this console window's hWnd (window handle).
IntPtr hWnd = GetConsoleWindow();
// Get information about the monitor (display) that the window is (mostly) displayed on.
// The .rcWork field contains the monitor's work area, i.e., the usable space excluding
// the taskbar (and "application desktop toolbars" - see https://msdn.microsoft.com/en-us/library/windows/desktop/ms724947(v=vs.85).aspx)
var mi = MONITORINFO.Default;
GetMonitorInfo(MonitorFromWindow(hWnd, MONITOR_DEFAULTTOPRIMARY), ref mi);
// Get information about this window's current placement.
var wp = WINDOWPLACEMENT.Default;
GetWindowPlacement(hWnd, ref wp);
// Calculate the window's new position: lower left corner.
// !! Inexplicably, on W10, work-area coordinates (0,0) appear to be (7,7) pixels
// !! away from the true edge of the screen / taskbar.
int fudgeOffset = 7;
wp.NormalPosition = new RECT() {
Left = -fudgeOffset,
Top = mi.rcWork.Bottom - (wp.NormalPosition.Bottom - wp.NormalPosition.Top),
Right = (wp.NormalPosition.Right - wp.NormalPosition.Left),
Bottom = fudgeOffset + mi.rcWork.Bottom
};
// Place the window at the new position.
SetWindowPlacement(hWnd, ref wp);
}
}
You can use Console.WindowTop and Console.WindowWidth of the System.Console class to set the location of the console window.
Here is an example on MSDN
The BufferHeight and BufferWidth property gets/sets the number of rows and columns to be displayed.
WindowHeight and WindowWidth properties must always be less than BufferHeight and BufferWidth respectively.
WindowLeft must be less than BufferWidth - WindowWidth and WindowTop must be less than BufferHeight - WindowHeight.
WindowLeft and WindowTop are relative to the buffer.
To move the actual console window, this article has a good example.
I have used some of your code and code from the CodeProject sample. You can set window location and size both in a single function. No need to set Console.WindowHeight and Console.WindowWidth again. This is how my class looks:
class Program
{
const int SWP_NOZORDER = 0x4;
const int SWP_NOACTIVATE = 0x10;
[DllImport("kernel32")]
static extern IntPtr GetConsoleWindow();
[DllImport("user32")]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter,
int x, int y, int cx, int cy, int flags);
static void Main(string[] args)
{
Console.WindowWidth = 50;
Console.WindowHeight = 3;
Console.BufferWidth = 50;
Console.BufferHeight = 3;
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = ConsoleColor.DarkMagenta;
var screen = System.Windows.Forms.Screen.PrimaryScreen.Bounds;
var width = screen.Width;
var height = screen.Height;
SetWindowPosition(100, height - 300, 500, 100);
Console.Title = "My Title";
Console.WriteLine("");
Console.Write(" Press any key to close this window ...");
Console.ReadKey();
}
/// <summary>
/// Sets the console window location and size in pixels
/// </summary>
public static void SetWindowPosition(int x, int y, int width, int height)
{
SetWindowPos(Handle, IntPtr.Zero, x, y, width, height, SWP_NOZORDER | SWP_NOACTIVATE);
}
public static IntPtr Handle
{
get
{
//Initialize();
return GetConsoleWindow();
}
}
}
Run any console application
Click RMB on headline.
Choose properties option.
choose Position tab.
Uncheck box "Automatic choice"
Set console position as you want.

Get A Window's Bounds By Its Handle

I am trying to get the height and the width of the current active window.
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr hWnd, Rectangle rect);
Rectangle bonds = new Rectangle();
GetWindowRect(handle, bonds);
Bitmap bmp = new Bitmap(bonds.Width, bonds.Height);
This code doesn't work because I need to use RECT and I don't know how.
Things like this are easily answered by google (C# GetWindowRect); you should also know about pinvoke.net -- great resource for calling native APIs from C#.
http://www.pinvoke.net/default.aspx/user32/getwindowrect.html
I guess for completeness I should copy the answer here:
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(HandleRef hWnd, out RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left; // x position of upper-left corner
public int Top; // y position of upper-left corner
public int Right; // x position of lower-right corner
public int Bottom; // y position of lower-right corner
}
Rectangle myRect = new Rectangle();
private void button1_Click(object sender, System.EventArgs e)
{
RECT rct;
if(!GetWindowRect(new HandleRef(this, this.Handle), out rct ))
{
MessageBox.Show("ERROR");
return;
}
MessageBox.Show( rct.ToString() );
myRect.X = rct.Left;
myRect.Y = rct.Top;
myRect.Width = rct.Right - rct.Left;
myRect.Height = rct.Bottom - rct.Top;
}
Of course that code will not work. It has to be this way: GetWindowRect(handle, ref rect);. So, edit your GetWindowRect declaration. And Rectangle is just a wrapper of the native RECT. Rectangle and RECT has left, top, right and bottom fields that the Rectangle class changed to read-properties (Left, Top, Right, Bottom). Width is not equivalent to right and Height is not equivalent to bottom. Width is right-left and Height is bottom-top. Of course, RECT don't have these sort of properties. It's just a bare struct.
Creating RECT is an overkill. Rectangle is enough in .NET for native/unmanaged API that need it. You just have to pass it in the appropriate way.

Move a window on keypress + mouse (like linux ALT + mouse down)

Simple, i want to move a windows pressing ALT+MOUSE, like linux os (ALT+drag).
It's possible to pass a win32 api (move api) to the windows interested clicking on it?
I have a windows services that hook key pressed (ALT button in specific).
When ALT key is pressed and a mouse down event is verified, i want to move window clicking anywhere, not only on the title bar!
Currently i move my form windows in this way:
using System.Runtime.InteropServices;
[DllImport( "user32.dll", CharSet = CharSet.Auto, SetLastError = false )]
static extern IntPtr SendMessage( IntPtr hWnd, uint Msg, int wParam, int lParam );
[DllImportAttribute( "user32.dll", CharSet = CharSet.Auto, SetLastError = false )]
public static extern bool ReleaseCapture();
private void Form1_MouseDown( object sender, MouseEventArgs e )
{
ReleaseCapture();
SendMessage( this.Handle, 0xa1, 0x2, 0 );
}
How can I get windows handle of the specific windows by clicking and after call SendMessage() on it?
It's possible?
You can do this by trapping the WM_NCHITTEST message that Windows sends to see what area of the window got clicked. You can fool it by returning HTCAPTION and it will dutifully perform the mouse actions you'd normally get when clicking the caption of a window. Including moving the window. Paste this code into your form:
protected override void WndProc(ref Message m) {
base.WndProc(ref m);
// Trap WM_NCHITTEST when the ALT key is down
if (m.Msg == 0x84 && (Control.ModifierKeys == Keys.Alt)) {
// Translate HTCLIENT to HTCAPTION
if (m.Result == (IntPtr)1) m.Result = (IntPtr)2;
}
}
I worked this out my self, came up with something interesting of my own calculations, worked perfectly for me, for any window (any active foreground window). Kinda long, but really easy to understand if you follow along the comments, hope it helps :)
The way it works, is that you press a certain registered key-combo, like Ctrl+Alt+M
and the mouse will stick in the center of an active window, you move the mouse, the windows follows it, press the SAME combo again, to release, no need for mouse clicks or anything.
public void MoveWindow_AfterMouse()
{
// 1- get a handle to the foreground window (or any window that you want to move).
// 2- set the mouse pos to the window's center.
// 3- let the window move with the mouse in a loop, such that:
// win(x) = mouse(x) - win(width)/2
// win(y) = mouse(y) - win(height)/2
// This is because the origin (point of rendering) of the window, is at its top-left corner and NOT its center!
// 1-
IntPtr hWnd = WinAPIs.GetForegroundWindow();
// 2- Then:
// first we need to get the x, y to the center of the window.
// to do this, we have to know the width/height of the window.
// to do this, we could use GetWindowRect which will give us the coords of the bottom right and upper left corners of the window,
// with some math, we could deduce the width/height of the window.
// after we do that, we simply set the x, y coords of the mouse to that center.
RECT wndRect = new RECT();
WinAPIs.GetWindowRect(hWnd, out wndRect);
int wndWidth = wndRect.right - wndRect.left;
int wndHeight = wndRect.bottom - wndRect.top; // cuz the more you go down, the more y value increases.
Point wndCenter = new Point(wndWidth / 2, wndHeight / 2); // this is the center of the window relative to itself.
WinAPIs.ClientToScreen(hWnd, out wndCenter); // this will make its center relative to the screen coords.
WinAPIs.SetCursorPos(wndCenter.X, wndCenter.Y);
// 3- Moving :)))
while (true)
{
Point cursorPos = new Point();
WinAPIs.GetCursorPos(out cursorPos);
int xOffset = cursorPos.X - wndWidth / 2;
int yOffset = cursorPos.Y - wndHeight / 2;
WinAPIs.MoveWindow(hWnd, xOffset, yOffset, wndWidth, wndHeight, true);
Thread.Sleep(25);
}
}
And now:
int moveCommandToggle = 0;
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x0312)
{
int keyID = m.WParam.ToInt32();
if(keyID == some_key_combo_you_registered_for_the_moving)
{
if (moveCommandToggle++ % 2 == 0)
{
mover = new Thread(() => MoveWindow_AfterMouse());
mover.Start();
}
else mover.Abort();
}
}
}
If you're wondering about RECT:
public struct RECT
{
public int left; // xCoor of upper left corner.
public int top; // yCoor of upper left corner.
public int right; // xCoor of lower right corner.
public int bottom; // yCoor of lower right corner.
};
WinAPIs was just a static class that I did my DllImports in.

Categories