[gelöst] Screenshot, mehrere Bildschirme (MultiMonitor)

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
TerribleCode
Beiträge: 38
Registriert: Di 18. Nov 2014, 22:50
OS, Lazarus, FPC: Windows 7 [x64]; Lazarus 1.6.4 [i386-win32]; FPC 3.0.2 [win32 i386]
CPU-Target: 64Bit

[gelöst] Screenshot, mehrere Bildschirme (MultiMonitor)

Beitrag von TerribleCode »

Hallo.

Im Wiki habe ich folgenden Quellcode gefunden, mit dem man einen Screenshot erstellen kann:

Code: Alles auswählen

var
  MyBitmap: TBitmap
  ScreenDC: HDC;
begin
  MyBitmap := TBitmap.Create;
  ScreenDC := GetDC(0);
  MyBitmap.LoadFromDevice(ScreenDC);
  ReleaseDC(ScreenDC);
...

Jetzt habe ich aber zwei Monitore... Mit diesem Code wird aber nur der Primäre Bildschirm "fotografiert", ich möchte aber den gesamten sichtbaren Bereich speichern.

Kann mir da jemand weiterhelfen :?:

Danke und liebe Grüße.
Zuletzt geändert von TerribleCode am Mi 7. Sep 2016, 22:46, insgesamt 1-mal geändert.

wp_xyz
Beiträge: 4892
Registriert: Fr 8. Apr 2011, 09:01

Re: Screenshot bei bei mehr als einem Bildschirm (MultiMonit

Beitrag von wp_xyz »

https://stackoverflow.com/questions/661 ... -in-delphi, etwas weiter unten, etwa in der Mitte. Auszug davon (nicht getestet):

Code: Alles auswählen

var
  w,h: integer;
  DC: HDC;
  hWin: Cardinal;
  tmpBmp: TBitmap;
begin
  //ENTIRE desktop (all monitors)
  hWin := 0;
  DC := GetDC(GetDesktopWindow);
  w := Screen.DesktopWidth;
  h := Screen.DesktopHeight;
  tmpBmp := TBitmap.Create;
  try
    tmpBmp.Width := w;
    tmpBmp.Height := h;
    BitBlt(tmpBmp.Canvas.Handle,0,0,tmpBmp.Width,
      tmpBmp.Height,DC,0,0,SRCCOPY);
  finally
    ReleaseDC(hWin,DC);
  end//try-finally   

TerribleCode
Beiträge: 38
Registriert: Di 18. Nov 2014, 22:50
OS, Lazarus, FPC: Windows 7 [x64]; Lazarus 1.6.4 [i386-win32]; FPC 3.0.2 [win32 i386]
CPU-Target: 64Bit

Anordnung der Monitore + Bitmap speichern geht nicht

Beitrag von TerribleCode »

Zuerst einmal danke für deine Hilfe!

Der Code ist zwar funktionsfähig, hat aber eine Schwäche:
Wenn der primärer Monitor nicht ganz links angeordnet ist, dann können Left Werte negativ sein.
Dies hat zur folge, dass man nur den Bildbereich vom primären Monitor und alles von da aus gesehen sich rechts befindliche speichert.

Der folgende Code umschifft dieses Problem. Damit sollte wirklich alles was auf den Bildschirmen sichtbar ist, kopiert werden.

Code: Alles auswählen

procedure TForm1.Button1Click(Sender:TObject);
var
  ScreenBitmap: Graphics.TBitmap;
  ScreenDC: HDC;
begin
  ScreenBitmap:=Graphics.TBitmap.Create;
  ScreenBitmap.Width:=Screen.DesktopWidth;
  ScreenBitmap.Height:=Screen.DesktopHeight;
  ScreenDC:=GetDC(GetDesktopWindow);
  BitBlt(ScreenBitmap.Canvas.Handle, 0, 0, ScreenBitmap.Width, ScreenBitmap.Height, ScreenDC, Screen.DesktopLeft, Screen.DesktopTop, SRCCOPY);
  // Screen.DesktopLeft und Screen.DesktopTop anstatt 0
  ReleaseDC(0, ScreenDC);
  ScreenBitmap.SaveToFile('TEST-IMAGE'+ExtensionSeparator+ScreenBitmap.GetFileExtensions); // Fehler?
  Image1.Picture.Bitmap:=ScreenBitmap; // Bild wird korrekt dargestellt!
  ScreenBitmap.Free;
end;

Nun habe ich aber noch das Problem, dass wenn ich die Bitmap speichere, dass dann nur ein schwarzes Bild gespeichert wird.
Das Problem besteht auch dann, wenn ich das Bild aus Image1 speichere...
Wo liegt da das Problem?

wp_xyz
Beiträge: 4892
Registriert: Fr 8. Apr 2011, 09:01

Re: [gelöst] Screenshot, mehrere Bildschirme (MultiMonitor)

Beitrag von wp_xyz »

Wenn ich die BitBlt-Anweisung durch "ScreenBitmap.LoadFromDevice(ScreenDC);" ersetze, ist die Datei in Ordnung (nur mit 1 Monitor getestet).

In welcher Unit ist eigentlich die Funktion "GetDesktopWindow()"? Ich habe sie nur in "windows" gefunden. Wenn das alles ist, wäre die Lösung unschön, weil sie nur unter Windows funktioniert.

TerribleCode
Beiträge: 38
Registriert: Di 18. Nov 2014, 22:50
OS, Lazarus, FPC: Windows 7 [x64]; Lazarus 1.6.4 [i386-win32]; FPC 3.0.2 [win32 i386]
CPU-Target: 64Bit

Re: [gelöst] Screenshot, mehrere Bildschirme (MultiMonitor)

Beitrag von TerribleCode »

wp_xyz hat geschrieben:Wenn ich die BitBlt-Anweisung durch "ScreenBitmap.LoadFromDevice(ScreenDC);" ersetze, ist die Datei in Ordnung (nur mit 1 Monitor getestet).

Dann funktioniert es auch bei mir, aber ich habe wieder nur den Inhalt des primären Bildschirms...
Merkwürdig... Hast du noch eine Idee?

wp_xyz hat geschrieben:In welcher Unit ist eigentlich die Funktion "GetDesktopWindow()"? Ich habe sie nur in "windows" gefunden. Wenn das alles ist, wäre die Lösung unschön, weil sie nur unter Windows funktioniert.

Ich finde sie auch nur dort, aber Plattform Unabhängigkeit ist für mich (zur Zeit noch) nicht von Interesse.

wp_xyz
Beiträge: 4892
Registriert: Fr 8. Apr 2011, 09:01

Re: [gelöst] Screenshot, mehrere Bildschirme (MultiMonitor)

Beitrag von wp_xyz »

Ich fülle jetzt das Bitmap nach dem Setzen der Größe zunächst mit weißer Farbe. Da scheint's auch mit dem BitBlt zu funktionieren:

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var
  ScreenBitmap: Graphics.TBitmap;
  ScreenDC: HDC;
  bmp: Graphics.TBitmap;
begin
  ScreenBitmap:=Graphics.TBitmap.Create;
 
  ScreenBitmap.Width:=Screen.DesktopWidth;
  ScreenBitmap.Height:=Screen.DesktopHeight;
 
  ScreenBitmap.Canvas.Brush.Color := clWhite;
  ScreenBitmap.Canvas.FillRect(0, 0, Screenbitmap.Width, Screenbitmap.Height);
 
  ScreenDC:=GetDC(GetDesktopWindow);
 
  //ScreenBitmap.LoadFromDevice(ScreenDC);
 
  BitBlt(ScreenBitmap.Canvas.Handle, 0, 0, ScreenBitmap.Width, ScreenBitmap.Height,
    ScreenDC, Screen.DesktopLeft, Screen.DesktopTop, SRCCOPY);
 
  // Screen.DesktopLeft und Screen.DesktopTop anstatt 0
  ReleaseDC(0, ScreenDC);
 
  ScreenBitmap.SaveToFile('d:\TEST-IMAGE'+ExtensionSeparator+ScreenBitmap.GetFileExtensions); // Fehler?
  Image1.Picture.Bitmap:=ScreenBitmap; // Bild wird korrekt dargestellt!
 
  ScreenBitmap.Free;
end

TerribleCode
Beiträge: 38
Registriert: Di 18. Nov 2014, 22:50
OS, Lazarus, FPC: Windows 7 [x64]; Lazarus 1.6.4 [i386-win32]; FPC 3.0.2 [win32 i386]
CPU-Target: 64Bit

Re: [gelöst] Screenshot, mehrere Bildschirme (MultiMonitor)

Beitrag von TerribleCode »

wp_xyz hat geschrieben:Ich fülle jetzt das Bitmap nach dem Setzen der Größe zunächst mit weißer Farbe. Da scheint's auch mit dem BitBlt zu funktionieren.

Tatsache! Vielen lieben Dank.
Bleibt nur die Frage, warum es nicht auf direktem Wege geht...

Antworten