Printscreen in C#

Asked

Viewed 744 times

2

I want to make a program that takes printscreen of a window defined by me in C# So far I’ve made that code:

        private void btPrintScreenEcra_Click(object sender, EventArgs e)
    {
        //Definimos qual a dimensão do bitmap
        //A utilização do Bounds.Width irá permitir que o programa "saiba" onde começa a aplicação
        Bitmap printscreen = new Bitmap(this.Bounds.Width, this.Bounds.Height);

        //Definimos o bitmap como imagem
        Graphics graphics = Graphics.FromImage(printscreen);

        //O uso do this.Bounds é fundamental para que o printscreen apenas incida sobre a aplicação
        //O this.Bounds.Size determina automaticamente qual a dimensão da janela da aplicação
        graphics.CopyFromScreen(this.Bounds.X, this.Bounds.Y, 0, 0, this.Bounds.Size);

        //Por fim, basta apenas indicar o caminho, o nome da imagem, a extensão e o formato
        string caminho = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
        string nome = "PrintScreen Peopleware";
        printscreen.Save(caminho + "\\" + nome + ".jpg", ImageFormat.Jpeg);
    }

But the code in question only print out the window itself. Wanted one I could set type: Google Chrome And no matter what window was open on my computer, it would take a photo of Chrome. Does anyone have any idea how to do?

1 answer

3


I remember taking a code somewhere (probably in the OS itself) to do this (I used it to print the screen when I made a mistake, so email it to the development team).

Create a reference to a RECT:

[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
    private int _Left;
    private int _Top;
    private int _Right;
    private int _Bottom;

    public RECT(RECT Rectangle) : this(Rectangle.Left, Rectangle.Top, Rectangle.Right, Rectangle.Bottom)
    {
    }
    public RECT(int Left, int Top, int Right, int Bottom)
    {
        _Left = Left;
        _Top = Top;
        _Right = Right;
        _Bottom = Bottom;
    }

    public int X
    {
        get { return _Left; }
        set { _Left = value; }
    }
    public int Y
    {
        get { return _Top; }
        set { _Top = value; }
    }
    public int Left
    {
        get { return _Left; }
        set { _Left = value; }
    }
    public int Top
    {
        get { return _Top; }
        set { _Top = value; }
    }
    public int Right
    {
        get { return _Right; }
        set { _Right = value; }
    }
    public int Bottom
    {
        get { return _Bottom; }
        set { _Bottom = value; }
    }
    public int Height
    {
        get { return _Bottom - _Top; }
        set { _Bottom = value + _Top; }
    }
    public int Width
    {
        get { return _Right - _Left; }
        set { _Right = value + _Left; }
    }
    public Point Location
    {
        get { return new Point(Left, Top); }
        set
        {
            _Left = value.X;
            _Top = value.Y;
        }
    }
    public Size Size
    {
        get { return new Size(Width, Height); }
        set
        {
            _Right = value.Width + _Left;
            _Bottom = value.Height + _Top;
        }
    }

    public static implicit operator Rectangle(RECT Rectangle)
    {
        return new Rectangle(Rectangle.Left, Rectangle.Top, Rectangle.Width, Rectangle.Height);
    }
    public static implicit operator RECT(Rectangle Rectangle)
    {
        return new RECT(Rectangle.Left, Rectangle.Top, Rectangle.Right, Rectangle.Bottom);
    }
    public static bool operator ==(RECT Rectangle1, RECT Rectangle2)
    {
        return Rectangle1.Equals(Rectangle2);
    }
    public static bool operator !=(RECT Rectangle1, RECT Rectangle2)
    {
        return !Rectangle1.Equals(Rectangle2);
    }

    public override string ToString()
    {
        return "{Left: " + _Left + "; " + "Top: " + _Top + "; Right: " + _Right + "; Bottom: " + _Bottom + "}";
    }

    public override int GetHashCode()
    {
        return ToString().GetHashCode();
    }

    public bool Equals(RECT Rectangle)
    {
        return Rectangle.Left == _Left && Rectangle.Top == _Top && Rectangle.Right == _Right && Rectangle.Bottom == _Bottom;
    }

    public override bool Equals(object Object)
    {
        if (Object is RECT)
        {
            return Equals((RECT)Object);
        }
        else if (Object is Rectangle)
        {
            return Equals(new RECT((Rectangle)Object));
        }

        return false;
    }
}

Then add in some class (e.g., in a form) these two references to the methods of api Win32, and create this method PrintarAplicativo():

public partial class Form1 : Form
{

    [DllImport("user32.dll")]
    public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
    [DllImport("user32.dll")]
    public static extern bool PrintWindow(IntPtr hWnd, IntPtr hdcBlt, int nFlags);

    public static Bitmap PrintarAplicativo(IntPtr hwnd)
    {
        RECT rc;
        GetWindowRect(hwnd, out rc);

        Bitmap bmp = new Bitmap(rc.Width, rc.Height, PixelFormat.Format32bppArgb);
        Graphics gfxBmp = Graphics.FromImage(bmp);
        IntPtr hdcBitmap = gfxBmp.GetHdc();

        PrintWindow(hwnd, hdcBitmap, 0);

        gfxBmp.ReleaseHdc(hdcBitmap);
        gfxBmp.Dispose();

        return bmp;
    }

}

This method receives the handle of the process in which you want to take the print. Hence you use it like this, for example:

private void btPrintScreenEcra_Click(object sender, EventArgs e)
{
    // tirando um print de algum "notepad" aberto...
    var proc = Process.GetProcessesByName("notepad")[0];
    using (var bmp = PrintarAplicativo(proc.MainWindowHandle))
    {
        SaveFileDialog dialog = new SaveFileDialog();
        dialog.Filter = "Imagens(*.png, *.jpeg) | *.png; *.jpeg | Todos Arquivos(*.*) | *.* ";
        if (dialog.ShowDialog() == DialogResult.OK)
        {
            bmp.Save(dialog.FileName);
        }
    }
}

The first method Process.GetProcessesByName() takes the process name. If I had 3 notepads open, this method would return an array containing these 3 processes. I’m randomly taking the first open (note that this would be a mistake if I didn’t have at least one open Notepad).

Then we call the method PrintarAplicativo passing the Handle from the main screen of that process. An application can have several windows inside it, and each window has its own Handle (I remember that for having worked hard with Delphi, and there we used this concept to fire messages with Postmessage from one screen to another). In this case, the main window represents the entire screen of the application, so it would be possible to take the print of "subtelas" within that process.

This method returns the Bitmap ready, then in this example I open a dialog box for the user to choose where to save this file (but you wouldn’t even need to do it, just save directly to some directory without the user nor be bothered).


To the Chrome in particular, it is complicated because from what I know Chrome creates about 30 processes, note in my case:

Gerenciador de Tarefas

However, I did the test below, and of all these processes, only one has the main window Handle:

var processes = Process.GetProcessesByName("chrome");
// verificar se o processo tem interface gráfica
foreach (var proc in processes.Where(p => p.MainWindowHandle != IntPtr.Zero))
{
    using (var bmp = PrintarAplicativo(proc.MainWindowHandle))
    {
        bmp.Save(string.Format("C:\\Users\\Alisson\\Pictures\\chrome-{0}.png", proc.Id));
    }
}

Which resulted in the following image:

Chrome

  • 1

    Damn, man, you helped me, man, thank you so much!

  • @Fredericosampaio for nothing!!! D

Browser other questions tagged

You are not signed in. Login or sign up in order to post.