1

This shouldnt be a difficult question, but it is difficult to google the question and get the idea across.

The problem is simple: I have a windows form where the user presses a button, then, it will wait on the user to click another window. It stores that selected window information for manipulation later (specifically the dimensions).

How can I get the active window of the next user click after a button is pressed?

Thanks

Gaʀʀʏ
  • 4,372
  • 3
  • 39
  • 59
  • MDI? Are the forms in the same process? Are all the forms instantiated from a single app in the same app domain? – IAbstract Jul 17 '12 at 02:59
  • The idea is that my WinForm will let them click on any other application window. The intent is to take a screenshot of the dimensions of that window that is selected. – Gaʀʀʏ Jul 17 '12 at 03:01
  • I think an alternative that may be easier would be to have the user select an area on the screen with the mouse and store those dimensions. – Gaʀʀʏ Jul 17 '12 at 03:13

2 Answers2

1

You need to get the foreground window.

[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();

[DllImport("user32.dll", SetLastError = true)]
static extern bool GetWindowRect(IntPtr hWnd, out Rectangle lpRect); 


Rect rect = new Rect ();
GetWindowRect(GetForegroundWindow(), out rect);

//calculate width and height from rect

using (Bitmap bitmap = new Bitmap(width, height))
{
    using (Graphics g = Graphics.FromImage(bitmap))
    {
        Size size = new System.Drawing.Size(width, height);
        g.CopyFromScreen(new Point(rect.Left, rect.Top), Point.Empty, size);
    }
    bitmap.Save("C://test.jpg", ImageFormat.Jpeg);
}

[StructLayout(LayoutKind.Sequential)]
public struct Rect {
    public int Left;
    public int Top;
    public int Right;
    public int Bottom;
}

I found most of the code in these two answers on SO. Modifed it to suit your question

Capture window

Find window width and height

Community
  • 1
  • 1
nunespascal
  • 17,584
  • 2
  • 43
  • 46
0

Interested by your question i have created this small screen capture app.

It has strange workarounds:

  1. Timer used to capture mouse position outside winform is strange but was easier to implement than using Global System Hooks . You might try to use lib from link or implement it by yourself. You wouldn't need than to use Timer and what is more important you could drop this constant reactivation of form.
  2. I have found somewhere in SE info about overriding CreateParams but i can't find link to it anymore it allows you to click trough form (i think that not all of added params are neccessery but as i said i lost link :) ).
  3. Only visible part of window is captured + all windows overlapping it (probably sinc u got a windowHandle to it u might try to show/activate it somehow).
  4. For some windows it gets controls inside window.
  5. Provided app is probably very unprofessional and unsafe and might blow up your computer so beware ;P

    Used form is borderless with opacity set to 80%.

Used form

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowInfo { public partial class CurrentWindow : Form { Rectangle GDIrect = new Rectangle(0, 0, 100, 100); [DllImport("user32.dll")] public static extern IntPtr WindowFromPoint(Point lpPoint); [DllImport("user32.dll")] public static extern bool GetCursorPos(out Point lpPoint); [DllImport("user32.dll")] private static extern IntPtr GetWindowRect(IntPtr hWnd, ref Rect rect); [DllImport("user32.dll")] static extern IntPtr GetForegroundWindow(); [StructLayout(LayoutKind.Sequential)] public struct Rect { public int Left; public int Top; public int Right; public int Bottom; } public CurrentWindow() { InitializeComponent(); } protected override CreateParams CreateParams { get { CreateParams baseParams = base.CreateParams; baseParams.ExStyle |= (int)( 0x00080000 | 0x08000000 | 0x00000080 | 0x00000020 ); return baseParams; } } public static IntPtr GetWindowUnderCursor() { Point ptCursor = new Point(); GetCursorPos(out ptCursor); return WindowFromPoint(ptCursor); } public Bitmap CaptureScreen() { var result = new Bitmap(this.DisplayRectangle.Width, this.DisplayRectangle.Height); using (var g = Graphics.FromImage(result)) { g.CopyFromScreen(this.Location.X, this.Location.Y, 0, 0, this.DisplayRectangle.Size); } return result; } private void timer1_Tick(object sender, EventArgs e) { IntPtr windowHandle = GetWindowUnderCursor(); Rect rect = new Rect(); GetWindowRect(windowHandle, ref rect); GDIrect = new Rectangle(rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top);

this.Location = new Point(GDIrect.Left, GDIrect.Top); this.Size = GDIrect.Size; this.Activate(); } private void CurrentWindow_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == 'c') { this.Visible = false; Bitmap bmp = CaptureScreen(); bmp.Save(Application.StartupPath + "\\example.png"); this.Visible = true; } else if (e.KeyChar == 'x') { this.Close(); } } } }

U might add it to your app and run after button click, it should work but i have tested it only separately. Good luck :).

Archibald
  • 846
  • 10
  • 24