Get A Window's Bounds By Its Handle - c#

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.

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.

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.

Screenshot of active window outside borders

I recently found a code to make a screenshot of the active window. It's actually working however the image is a little bit too big, it goes a little bit outside the borders of the current window.
This is the screenshot taken with my program:
This is the screenshot taken with alt+printscreen:
This is my class:
public static class Screenshotter
{
[DllImport("user32.dll")]
static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32.dll")]
private static extern bool PrintWindow(IntPtr hwnd, IntPtr hdcBlt, uint nFlags);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[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 static void MakeScreenshot()
{
var foregroundWindowsHandle = GetForegroundWindow();
var rect = new RECT();
GetWindowRect(foregroundWindowsHandle, out rect);
Rectangle bounds = new Rectangle(rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top);
Bitmap bmp = new Bitmap(bounds.Width, bounds.Height);
using (Graphics g = Graphics.FromImage(bmp))
{
g.CopyFromScreen(new Point(bounds.Left, bounds.Top), Point.Empty, bounds.Size);
}
bmp.Save("test.png", ImageFormat.Png);
}
}
I just want it screenshots the active window and not a little bit outside the window. I hope somebody can help me :)
I ran into a problem with the symptoms you have described. In my case, it was due to delay between the moments when a window is registered in system as "foreground" and when it actually fully shown on the screen in front of other windows. You probably observe the same. When you do g.CopyFromScreen(...), you get the pixels from a screen's region that may be still in transition from previous foreground window to the current.
In the first saved image, you can see a screen shot of foreground window (command prompt) made in 150 milliseconds after my image capturing program start:
As you can see, it is a mixture of previous foreground window's pixels (Visual Studio) and new one.
It took another 150 ms to fully update the screen:
So, it is not your screenshot has wrong size - it's the new foreground window has not "inflated" yet to its final boundaries.
A simple (and ugly) solution is: insert Thread.Sleep(...) before your call g.CopyFromScreen(...) to give the system enough time to fully replace the pixels on the screen.

Getting the color of a pixel drawn by DWM in C#

I want to get Screenshots of a possible hidden Window of another application that is using drawing via direct3d or opengl. I tryed a lot of ways to receive this windows content but only got black or transparent pictures. The closest i got was by using a DWM sample here
http://bartdesmet.net/blogs/bart/archive/2006/10/05/4495.aspx
this paints the window onto my c# form but i cant get the pixelcolors. If ill do a form.drawtobitmap the pixels drawn by dwm are missing.
So is their any way to use DWM to recive the capture into a image
or to get the image drawn onto my form?
To answer your question:
You can use GetPixel() Win32 function. But it's overkill in this situation.
Pinvoke GetPixel
MSDN GetPixel
The right way, is to get the device context and bit blit the content.
EDIT:
I've thrown together some code, by using PrintWindow. Seems to work quite well, even with media players. Note that GetWindowRect returns invalid rectangle for minimized Windows. But it's a decent start.
[StructLayout(LayoutKind.Sequential)]
public struct Rect
{
internal Rect(int left, int top, int right, int bottom)
{
Left = left;
Top = top;
Right = right;
Bottom = bottom;
}
public int Left;
public int Top;
public int Right;
public int Bottom;
}
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool PrintWindow(IntPtr hwnd, IntPtr hDC, uint nFlags);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowRect(IntPtr hwnd, out Rect lpRect);
public void DumpWindow(IntPtr hwndSource, string filename)
{
Rect rc;
GetWindowRect(hwndSource, out rc);
var bmp = new Bitmap(rc.Right - rc.Left, rc.Bottom - rc.Top, PixelFormat.Format32bppArgb);
using (Graphics gBmp = Graphics.FromImage(bmp))
{
IntPtr hdcBmp = gBmp.GetHdc();
PrintWindow(hwndSource, hdcBmp, 0);
gBmp.ReleaseHdc(hdcBmp);
}
bmp.Save(filename);
}
Edit2:
And if you add a second button to DWM demo form, insert this:
private void button1_Click(object sender, EventArgs e)
{
var w = (Window)lstWindows.SelectedItem;
DumpWindow(w.Handle, "test.bmp");
Process.Start("test.bmp");
}
It still shows an empty image?

Obtain mouse click position relative to active window

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;

Categories