Laden...

Screenshot per SendInput()

Erstellt von Mazo vor 16 Jahren Letzter Beitrag vor 16 Jahren 2.881 Views
M
Mazo Themenstarter:in
255 Beiträge seit 2006
vor 16 Jahren
Screenshot per SendInput()

Hallo,
ich möchte wenn mein Programm startet ein Scrennshot vom Bildschirm automatisch machen, um diesen dann aus der Zwischnablage zu holen...
Nachdem ich es mit SendKeys versucht habe bin ich auf SendInput gekommen...
Leider funktioniert der folgende Code, es wird kein Screenshot erzeugt, was amch ich flasch?


private void Form1_Load(object sender, EventArgs e)
{
INPUT[] input = new INPUT[1];
input[0].type = 1;
input[0].ki.wVk = 0x2A; // Keycode für PRINT
input[0].ki.dwFlags = 0x00; // Keydown


SendInput((uint)input.Length, input, Marshal.SizeOf(input[0]));

pictureBox1.Size = this.Size;
if (Clipboard.ContainsImage())
{
pictureBox1.Image = (Image)Clipboard.GetDataObject().GetData(DataFormats.Bitmap);
}
}

[StructLayout(LayoutKind.Sequential)]
struct MOUSEINPUT
{
public int dx;
public int dy;
public int mouseData;
public int dwFlags;
public int time;
public IntPtr dwExtraInfo;
}

[StructLayout(LayoutKind.Sequential)]
struct KEYBDINPUT
{
public short wVk;
public short wScan;
public int dwFlags;
public int time;
public IntPtr dwExtraInfo;
}

[StructLayout(LayoutKind.Sequential)]
struct HARDWAREINPUT
{
public int uMsg;
public short wParamL;
public short wParamH;
}

[StructLayout(LayoutKind.Explicit)]
struct INPUT
{
[FieldOffset(0)]
public int type;
[FieldOffset(4)]
public MOUSEINPUT mi;
[FieldOffset(4)]
public KEYBDINPUT ki;
[FieldOffset(4)]
public HARDWAREINPUT hi;
}

[DllImport("user32.dll")]
static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);


3.511 Beiträge seit 2005
vor 16 Jahren

Warum so umständlich? 🙂


private void button1_Click(object sender, EventArgs e)
{
  Rectangle bounds = Screen.PrimaryScreen.Bounds;
  using (Bitmap screenshot = new Bitmap(bounds.Width, bounds.Height))
  {
    using (Graphics g = Graphics.FromImage(screenshot))
    {
      g.CopyFromScreen(bounds.Left, bounds.Top, 0, 0, bounds.Size);
      Clipboard.SetImage(screenshot);
    }
  }
}

Wenn du mehrere Bildschirme hast, muss dementsprechend die größe des Bitmaps angepasst werden.

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

M
Mazo Themenstarter:in
255 Beiträge seit 2006
vor 16 Jahren

also wenn das geht (was ich annehme) bekomm ich ja eine Auszeichnung für Intelligenz 😁
Danke 🙂

M
Mazo Themenstarter:in
255 Beiträge seit 2006
vor 16 Jahren

(was ich annehme)

Irgendwie geht es nicht :?Ich bekomm immer das als Bild:

915 Beiträge seit 2006
vor 16 Jahren

Hrm, habe das damals in C++ so gemacht:


HWND hWnd=FindWindow(NULL, "Hello World");
    HDC  hDC = GetDC(hWnd);
    HBITMAP hBIT = CreateCompatibleBitmap(hDC, 640,480);
    BitBlt("screenie.bmp",0,0,640,480,hBIT,0,0,PATINVERT);

Den Rest machst dann wie Khalid es geschrieben hat, die DLL Imports denke ich weist ja auf www.pinvoke.net 🙂

Statt FindWindow kannst auch gleich nur GetDesktopWindow() verwenden.

Wie vernichtet stand Andreas unter den flammenden Augen seiner Kunden.
Ihm war's, als stünde des Schicksals dunkle Wetterwolke über seinem Haupte X(

M
34 Beiträge seit 2005
vor 16 Jahren

Khalid's Code funktioniert perfekt, fehlt evtl. nur noch ein abschließendes pictureBox1.Image = Clipboard.GetImage(); außerhalb des ersten using-Blocks.

3.511 Beiträge seit 2005
vor 16 Jahren

Denke mal, michme hat da vollkommen recht.
Es fehlt noch irgendeine Zuweisung. Ich mach Screenshots immer auf diese Art und Weise und es hat bis jetzt immer funktioniert 🙂

[Edit] Zeig mal, wie du es implementier hast bitte.

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

M
Mazo Themenstarter:in
255 Beiträge seit 2006
vor 16 Jahren

Hallo,
ich hab esprobiert mit


Rectangle bounds = Screen.PrimaryScreen.Bounds;
pictureBox1.Size = this.Size;
using (Bitmap screenshot = new Bitmap(bounds.Width, bounds.Height))
{
using (Graphics g = Graphics.FromImage(screenshot))
{
g.CopyFromScreen(bounds.Left, bounds.Top, 0, 0, bounds.Size);
Clipboard.SetImage(screenshot);
}
}

if (Clipboard.ContainsImage())
{
pictureBox1.Image = (Image)Clipboard.GetImage();
}


und mit


Rectangle bounds = Screen.PrimaryScreen.Bounds;
pictureBox1.Size = this.Size;
using (Bitmap screenshot = new Bitmap(bounds.Width, bounds.Height))
{
using (Graphics g = Graphics.FromImage(screenshot))
{
g.CopyFromScreen(bounds.Left, bounds.Top, 0, 0, bounds.Size);
pictureBox1.Image = screenshot;

}
}

es muss was mit der Zeit zu tun haben hab grad mal gedebuggt und da geht es :?

//edit es geht ich bin doch rech trotlig heute 😁 ich starte das Programm in Vollbild mach nen screen von und wunder mich warum es nicht geht...


public Form1()
{
Rectangle bounds = Screen.PrimaryScreen.Bounds;
using (Bitmap screenshot = new Bitmap(bounds.Width, bounds.Height))
{
using (Graphics g = Graphics.FromImage(screenshot))
{
g.CopyFromScreen(bounds.Left, bounds.Top, 0, 0, bounds.Size);
Clipboard.SetImage(screenshot);
}
}
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
if (Clipboard.ContainsImage())
{
pictureBox1.Image = (Image)Clipboard.GetImage();
}

pictureBox1.Size = this.Size;
}


M
34 Beiträge seit 2005
vor 16 Jahren

Sieht ja man Chaotisch aus 🙂
Erstelle doch eine eigene Methode dafür die du dann nach InitializeComponent(); im ctor aufrufst. Dann benötigst du auch nicht mehr (hierfür) die FormLoad-Methode.

Hier pictureBox1.Image = (Image)Clipboard.GetImage(); brauchst du auch nicht nach Image zu casten.

Beispiel:


        public Form2()
        {
            InitializeComponent();
            ShowScreenShot();
        }

        private void ShowScreenShot()
        {
            Rectangle bounds = Screen.PrimaryScreen.Bounds;
            using (Bitmap screenshot = new Bitmap(bounds.Width, bounds.Height))
            {
                using (Graphics g = Graphics.FromImage(screenshot))
                {
                    g.CopyFromScreen(bounds.Left, bounds.Top, 0, 0, bounds.Size);
                    Clipboard.SetImage(screenshot);
                }
            }
            pictureBox1.Image = Clipboard.GetImage();
        }

M
Mazo Themenstarter:in
255 Beiträge seit 2006
vor 16 Jahren

Erstelle doch eine eigene Methode dafür die du dann nach InitializeComponent();

Das ist gerade das Problem wenn ich danach den Screen mache seh ich nur mein eigenes Programm 😉 und nicht das was ich Screenen wollte...Aber es geht ja jetzt...Nochmal dnake für deine HilfeMazo

2.760 Beiträge seit 2006
vor 16 Jahren

Dann minimier doch dein Programm nach InitializeComponent() und mach danach deinen Screenshot und dann kannst du es wieder maximieren.