Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Screenshot vom Clientbereich der Mainform machen (https://www.delphipraxis.net/167485-screenshot-vom-clientbereich-der-mainform-machen.html)

Helmi 1. Apr 2012 15:06

Screenshot vom Clientbereich der Mainform machen
 
Hallo,

ich nutze folgenden Code um von meiner MainForm einen ScreenShot zu erstellen:

Delphi-Quellcode:
procedure ScreenShot_erstellen(Pfad: String);
var
  Bitmap   : TBitmap;
  Canvas   : TCanvas;
  WindowRect: TRect;
  BitmapRect: TRect;

begin
  //Bitmap erzeugen
  Bitmap := TBitmap.Create;

  //Canvas erzeugen
  Canvas := TCanvas.Create;

  //Handle für Canvas angeben
  Canvas.Handle := GetWindowDC(GetDesktopWindow);

  //Rect von MainForm holen
  GetWindowRect(Application.MainForm.Handle, WindowRect);

  try
    BitmapRect := Rect(0, 0, WindowRect.Right - WindowRect.Left, WindowRect.Bottom - WindowRect.Top);

    //Bitmap-Größe angeben
    Bitmap.Width := WindowRect.Right - WindowRect.Left;
    Bitmap.Height := WindowRect.Bottom - WindowRect.Top;

    Bitmap.Canvas.CopyRect(BitmapRect, Canvas, WindowRect);

    //nur für den Thread - eigentlich steht zum Speichern noch etwas mehr Code dahinter
    Bitmap.SaveToFile(Pfad + 'Bild.jpg');
  finally
    //Bitmap löschen und freigeben
    FreeAndNil(Bitmap);

    //Canvas löschen und freigeben
    ReleaseDC(0, Canvas.Handle);
    FreeAndNil(Canvas);
  end;
end;
Nur würde ich gerne nur einen ScreenShot vom Client-Bereich zu machen. Also alles innerhalb der Ränder/Taskleiste.

Ich vermute ich muss die Nullen bei:
Delphi-Quellcode:
    BitmapRect := Rect(0, 0, WindowRect.Right - WindowRect.Left, WindowRect.Bottom - WindowRect.Top);
durch Startwerte ersetzen, die innerhalb des Fensters sind.
Nur weiss ich nicht wie ich an "ClientLeft" und "ClientTop" komme.
(Es gibt ja nur ClientWidth und ClientHeight)

Oder gibt es den Clientbereich als Rect?

Helmi 1. Apr 2012 15:18

AW: Screenshot vom Clientbereich der Mainform machen
 
Wieso fallen mir nur immer die Lösungen ein, nachdem ich gepostet hab ... :gruebel:

Delphi-Quellcode:
procedure ScreenShot_erstellen(Pfad: String);
var
  Bitmap   : TBitmap;
  Jpg      : TJpegImage;
  BitmapRect: TRect;

  i_Width  : Integer;
  i_Height : Integer;

begin
  //Bitmap erzeugen
  Bitmap := TBitmap.Create;

  i_Width := Application.MainForm.ClientWidth;
  i_Height := Application.MainForm.ClientHeight;

  try
    //Rect des Clientbereiches definieren
    BitmapRect := Rect(0, 0, i_Width, i_Height);

    //Bitmap-Größe angeben
    Bitmap.Width := i_Width;
    Bitmap.Height := i_Height;

    Bitmap.Canvas.CopyRect(BitmapRect, Application.MainForm.Canvas, BitmapRect);

    //nur für den Thread - eigentlich steht zum Speichern noch etwas mehr Code dahinter
    Bitmap.SaveToFile(Pfad + 'Bild.jpg');
   finally
     //Bitmap löschen und freigeben
     FreeAndNil(Bitmap);
   end;
 end;

sx2008 1. Apr 2012 16:47

AW: Screenshot vom Clientbereich der Mainform machen
 
Wenn du das Formular der Funktion übergeben würdest wär's gleich doppelt so nützlich:
Delphi-Quellcode:
procedure ScreenShot_erstellen(form:TCustomForm; const bitmapfilename: String);

Namenloser 1. Apr 2012 17:12

AW: Screenshot vom Clientbereich der Mainform machen
 
TForm hat übrigens bereits eine Methode um den Client-Bereich als Bitmap zurückzuliefern: Delphi-Referenz durchsuchenTForm.GetFormImage

Helmi 1. Apr 2012 17:29

AW: Screenshot vom Clientbereich der Mainform machen
 
Zitat:

Zitat von NamenLozer (Beitrag 1159710)
TForm hat übrigens bereits eine Methode um den Client-Bereich als Bitmap zurückzuliefern: Delphi-Referenz durchsuchenTForm.GetFormImage

Hallo,

nach so was hab ich gesucht :-)

Nur dummerweise scheint das was nicht richtig freigegeben zu werden.

Ich erhalte von FastMM folgende Fehlermeldung am Ende vom Programm:
Zitat:

---------------------------
Project1.exe: Speicherleck entdeckt
---------------------------
Diese Anwendung hat Speicher-Lecks. Die kleineren Speicher-Lecks sind (ausschließlich von Zeigern registrierte Lecks):



21 - 28 bytes: TBrush x 1

29 - 36 bytes: TPen x 1, Unbekannt x 2

37 - 44 bytes: TFont x 1

61 - 68 bytes: TBitmap x 1

101 - 108 bytes: TBitmapCanvas x 1

117 - 124 bytes: TBitmapImage x 1

157 - 172 bytes: Unbekannt x 1



Hinweis: Um eine Protokolldatei zu erhalten, die Details über Speicherlecks enthält, aktivieren Sie die "{$ FullDebugMode}" und "{$ LogMemoryLeakDetailToFile}" Definitionen. Um die Speicherleckprüfung zu deaktivieren, deaktivieren sie die "{$ EnableMemoryLeakReporting} -Option".


---------------------------
OK
---------------------------
bei diesem Test-Code:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  Jpg: TJPEGImage;

begin
  Jpg := TJPEGImage.Create;

  Jpg.Assign(Form1.GetFormImage);

  Jpg.CompressionQuality := 100;
  Jpg.ProgressiveEncoding := false;
  Jpg.SaveToFile('D:\test.jpg');

  FreeAndNil(Jpg);
end;
(ja ich weiss, da fehlt ein try/finally-Block! - ist nur Test)

Bummi 1. Apr 2012 17:33

AW: Screenshot vom Clientbereich der Mainform machen
 
In GetFormImage wird ein Bitmap erzeugt (der Rückgabewert)
Delphi-Quellcode:
var
  Jpg: TJPEGImage;
  BMP:TBitmap;
begin
  Jpg := TJPEGImage.Create;
  BMP:=Form1.GetFormImage;
  Jpg.Assign(BMP);
  BMP.Free;
  ......
  ......

Helmi 1. Apr 2012 17:42

AW: Screenshot vom Clientbereich der Mainform machen
 
Mann häts sich halt mal den Quellcode anschauen sollen :wall: - Danke, Bummi!

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  Jpg: TJPEGImage;
  BMP:TBitmap;
begin
  Jpg := TJPEGImage.Create;

  try
    BMP:=Form1.GetFormImage;
    Jpg.Assign(BMP);

    Jpg.SaveToFile('D:\test.jpg');
  finally
    BMP.Free;
    Jpg.Free;
  end;
end;

DeddyH 1. Apr 2012 19:06

AW: Screenshot vom Clientbereich der Mainform machen
 
Und so etwas ist genau der Grund, weshalb man in Funktionen keine Objekte zurückgeben sollte, die man innerhalb der Funktion erstellt.

Helmi 1. Apr 2012 19:07

AW: Screenshot vom Clientbereich der Mainform machen
 
Zitat:

Zitat von DeddyH (Beitrag 1159723)
Und so etwas ist genau der Grund, weshalb man in Funktionen keine Objekte zurückgeben sollte, die man innerhalb der Funktion erstellt.

Stimmt!
Ich nutz für so was die out Variablen

mkinzler 1. Apr 2012 19:14

AW: Screenshot vom Clientbereich der Mainform machen
 
Es ist aber egal ob Rückgabewert oder Out-Parameter

DeddyH 1. Apr 2012 19:15

AW: Screenshot vom Clientbereich der Mainform machen
 
Out ist für Objektinstanzen aber auch nicht die erste Wahl. Einfach By Value oder als Konstante entgegennehmen, geht beides.

sx2008 1. Apr 2012 22:35

AW: Screenshot vom Clientbereich der Mainform machen
 
Bitte nicht das JPeg Format für Screenshots verwenden!
Durch die verlustbehaftete Komprimierung werden Schriften und Kanten verwaschen.
Siehe: http://www.r1ch.net/img-formats/
Gif und PNG sind für Screenshots besser geeignet.

himitsu 1. Apr 2012 23:07

AW: Screenshot vom Clientbereich der Mainform machen
 
GIF ist für die Anzahl der Farbwerte (kunterbunte GUIs, Farbverläufe, Schriftglättung und Co.) auch nicht unbedingt gut geeignet.

Man kann beim JPEG aber auch die Komprimierungsqualität entsprechend einstellen, dann wird die Datei zwar größer, aber diese Verfälschungen minimieren sich.

sx2008 1. Apr 2012 23:32

AW: Screenshot vom Clientbereich der Mainform machen
 
Zitat:

Zitat von himitsu (Beitrag 1159758)
GIF ist für die Anzahl der Farbwerte (kunterbunte GUIs, Farbverläufe, Schriftglättung und Co.) auch nicht unbedingt gut geeignet.
Man kann beim JPEG aber auch die Komprimierungsqualität entsprechend einstellen, dann wird die Datei zwar größer, aber diese Verfälschungen minimieren sich.

Normale Delphi VCL Programme haben in der Regel nie mehr als 100 versch. Farben.
Sollte ein Farbverlauf in der Titelleiste als Gif-Bild etwas stufig aussehen ist das weit weniger tragisch als der Verlust an Schärfe bei einem JPEG-Bild.
Und wenn man aus dem JPEG Screenshot mit einer Bildverarbeitung einen Ausschnitt wieder im JPEG Format speichert wird das Problem noch schlimmer.
Aber im oben angegebenen Link wird eigentlich alles erklärt (inklusive Beispiel wie schlecht so ein JPEG Screnshot aussehen kann).

himitsu 2. Apr 2012 00:38

AW: Screenshot vom Clientbereich der Mainform machen
 
Ich bin sowieso eher für PNGs und andere komprimierte Bitmaps.
GIF ist zwar auch nur Bitmap und neuerdings auch komprimiert, aber eben nur mit 256 Farben und wenn man ene blöde Implementierung verwendet, dann auch noch mit einer Standardfarbtabelle, welche recht unpassende Farben bereitstellt.

Furtbichler 2. Apr 2012 06:55

AW: Screenshot vom Clientbereich der Mainform machen
 
Zitat:

Zitat von himitsu (Beitrag 1159764)
GIF ist zwar auch nur Bitmap und neuerdings auch komprimiert

GIF kann schon immer komprimieren (LZW), das macht es aber auch nicht besser.

mkinzler 2. Apr 2012 09:08

AW: Screenshot vom Clientbereich der Mainform machen
 
Gif verwendet allerdings Farbpaletten und ist deshalb auf max. 8Bit (256-Farben) beschränkt

Helmi 2. Apr 2012 18:24

AW: Screenshot vom Clientbereich der Mainform machen
 
Hallo,

Danke für die Antworten!

Ich wollts jetzt eigentlich nicht glauben, das jpg "schlechtere" Bilder erzeugt.
Deswegen hab ich einen Screenshot erzeugt und den gleichzeitig als jpg und als png gespeichert.
So war ein direkter Vergleich möglich! - und siehe da - da ist echt ein großer Unterschied - vor allem bei Schriften!
Dann werd ich bei png bleiben.

himitsu 2. Apr 2012 18:36

AW: Screenshot vom Clientbereich der Mainform machen
 
JPEG speichert Bilder eben verlustbehaftet.

Bei Fotos und anderen Bildern, mit sehr vielen Farben, wo es nicht auf jedes Pixel ganz genau drauf ankommt, komprimiert es dafür besser,
da es einfach "unwichtige" Informationen wegläßt. (macht MP3 ja auch und da beschwert sich fast niemand)

Delphi-Referenz durchsuchenTJPEGImage.CompressionQuality := 100;

mkinzler 2. Apr 2012 20:59

AW: Screenshot vom Clientbereich der Mainform machen
 
Auch bei 100% ist das dann verlustbehaftet. Dann besser auf verlustfreies Kompressionsverfahren setzen (Z.B. PNG)


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:45 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz