Delphi-PRAXiS
Seite 1 von 7  1 23     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Bildschirmfoto knipst nicht alles (https://www.delphipraxis.net/196531-bildschirmfoto-knipst-nicht-alles.html)

KodeZwerg 29. Mai 2018 00:15

Bildschirmfoto knipst nicht alles
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hi, ich probiere mich mal am Knipsen von Fenstern, es funktioniert ja eigentlich auch schon relativ gut.
Bei manchen Programmen die ich Knipse fehlt leider Bildinhalt, ich habe mal mit professioneller Screenshot-Software den Fehler geknipst damit ich es irgendwie besser Erklären kann.
Im Hintergrund mein geknipstes Bild in IrfanView, im Vordergrund das was ich Knipsen wollte Anhang 49152
Da sieht man das in der Menu-Leiste nicht alles vom Original aufgenommen wurde.
Das ist eines der Probleme, das andere, wenn ich OpenGL/DirectX Anwendungen starte und Knipse entstehen nur schwarze Bilder, gibts da ein Trick?

Mit diesem Code erstelle ich die Bilder.
Delphi-Quellcode:
procedure TForm1.Screenshot (const FullWindow: Boolean = True);
var
  Win: HWND;
  DC: HDC;
  Bmp: TBitmap;
  FileName: string;
  WinRect: TRect;
  Width: Integer;
  Height: Integer;
begin
  Form1.Label1.Caption := 'Error: No Handle!';
  Form1.Hide;
  try
    Application.ProcessMessages;
    Win := GetForegroundWindow;
    if Win = 0 then Exit;
    Form1.Label1.Caption := 'Error during save!';

    if FullWindow then
    begin
      GetWindowRect(Win, WinRect);
      DC := GetWindowDC(Win);
    end else
    begin
      Windows.GetClientRect(Win, WinRect);
      DC := GetDC(Win);
    end;
    try
      Width := WinRect.Right - WinRect.Left;
      Height := WinRect.Bottom - WinRect.Top;

      Bmp := TBitmap.Create;
      try
        Bmp.Height := Height;
        Bmp.Width := Width;
        BitBlt(Bmp.Canvas.Handle, 0, 0, Width, Height, DC, 0, 0, SRCCOPY);
        FileName := 'Screenshot_' +
          FormatDateTime('mm-dd-yyyy-hhnnss', Now());
        Bmp.SaveToFile(Format('.\%s.bmp', [FileName]));
      finally
        Form1.Label1.Caption := 'Saved!';
        Bmp.Free;
      end;
    finally
      ReleaseDC(Win, DC);
    end;
  finally
    Form1.Show;
  end;
end;

Zacherl 29. Mai 2018 00:51

AW: Bildschirmfoto knipst nicht alles
 
Zitat:

Zitat von KodeZwerg (Beitrag 1403258)
wenn ich OpenGL/DirectX Anwendungen starte und Knipse entstehen nur schwarze Bilder, gibts da ein Trick?

Ob dein anderes Problem dadurch auch behoben würde (ich vermute stark, ja), kann ich nicht sagen, aber bezüglich Hardware-beschleunigter Grafik sollte die Desktop Duplication API Abhilfe schaffen. Das ist der vorgesehene Weg ab Windows 8, um den Monitorinhalt abzugreifen. Ist zwar nicht ganz unkompliziert, aber es gibt eine ausführliche Demo Anwendung.

KodeZwerg 29. Mai 2018 01:03

AW: Bildschirmfoto knipst nicht alles
 
Das könnte ich einbauen mit OSVersion Kontrolle, aber ich selbst benutze Windows 7.
Hast Du da eventuell noch eine Api auf die ich zurückgreifen könnte?
Danke für den Tipp Zacherl!

Zacherl 29. Mai 2018 01:15

AW: Bildschirmfoto knipst nicht alles
 
Zitat:

Zitat von KodeZwerg (Beitrag 1403263)
Hast Du da eventuell noch eine Api auf die ich zurückgreifen könnte?

Vor der Desktop Duplication API ging der "korrekte" Weg über einen Mirror Driver. Für DirectX/GL bleibt dir ansonsten nur die Möglichkeit über Hooks (ist aber auch nur Murks). Ansonsten gibt es noch die MSDN-Library durchsuchenPrintWindow API. Hardware-beschleunigte Inhalte wirst du damit allerdings auch nicht screenshoten können.

KodeZwerg 29. Mai 2018 01:19

AW: Bildschirmfoto knipst nicht alles
 
Ja ok, mit DX/GL das seh ich total ein und lass es mehr als außen vor.
PintWindow kenne ich auch noch nicht, da schau ich mal nach.
Ich glaube nicht das der TC hardwarebeschleunigung an den fehlenden Stellen macht, das muss eine andere Ursache haben.
Zacherl Danke nochmal, bei Problemem melde ich mich wieder!

KodeZwerg 29. Mai 2018 01:34

AW: Bildschirmfoto knipst nicht alles <GELÖST>
 
PrintWindow ist für mich DIE LÖSUNG!!! Vielen lieben Dank!
Habs bereits erfolgreich eingebaut und es knippst den TC ohne fehlenden Bildinhalt!

Frage: Funktioniert PrintWindow auch noch mit Windows 10?

Delphi-Quellcode:
function MyPrintWindow(const Win: HWND = 0; var Bmp: TBitmap; const FullWindow: Boolean = True): Boolean;
var
  rect: TRect;
begin
  Result := False;
  if Win = 0 then Exit;
  if FullWindow then
   GetWindowRect(Win, rect)
   else
   Windows.GetClientRect(Win, rect);
  bmp.Width := rect.Right - rect.Left;
  bmp.Height := rect.Bottom - rect.Top;
  Result := PrintWindow(Win, Bmp.Canvas.Handle, 0) ;
end;
Mini-Upgrade, so wirds bei Bedarf ohne Fenster-Rahmen geknippst.

Ps: Der erste Parameter sollte ein Prozess-Handle sein was ein Window besitzt.

EWeiss 29. Mai 2018 05:52

AW: Bildschirmfoto knipst nicht alles
 
Verdammt noch mal :wall: :duck: eigentlich bin ich ja zu blöd für so was. ;)
Aber trotzdem bei mir knipst alles und ich kann es sogar noch etwas verschönern.

Sorry das musste sein!

gruss

KodeZwerg 29. Mai 2018 07:55

AW: Bildschirmfoto knipst nicht alles
 
Du kannst es ja mit FullWindow = False mal probieren.

Zacherl 29. Mai 2018 13:42

AW: Bildschirmfoto knipst nicht alles
 
Bitte bitte :) Du solltest deinen Code allerdings noch um ein
Delphi-Quellcode:
Bitmap.Canvas.Lock
vor dem
Delphi-Quellcode:
PrintWindow
und ein
Delphi-Quellcode:
Bitmap.Canvas.Unlock
danach erweitern. Ansonsten kann es vorkommen, dass seltsame Effekte auftreten wie z.B., dass das Zielfenster unkontrolliert anfängt zu flackern, während der Screenshot erstellt wird.

EWeiss 29. Mai 2018 14:33

AW: Bildschirmfoto knipst nicht alles
 
Zitat:

Zitat von Zacherl (Beitrag 1403319)
Bitte bitte :) Du solltest deinen Code allerdings noch um ein
Delphi-Quellcode:
Bitmap.Canvas.Lock
vor dem
Delphi-Quellcode:
PrintWindow
und ein
Delphi-Quellcode:
Bitmap.Canvas.Unlock
danach erweitern. Ansonsten kann es vorkommen, dass seltsame Effekte auftreten wie z.B., dass das Zielfenster unkontrolliert anfängt zu flackern, während der Screenshot erstellt wird.

PrintWindow ist eine sehr schlechte Lösung um Screen Shots zu erstellen.

Warum?

Weil es nur mit einem Fenster richtig funktioniert in dem auch alle dafür benötigten Messagen korrekt verarbeitet werden.
Wenn dem nicht so ist lass es lieber.

Die Messagen die du behandeln musst sind WM_PRINT, WM_PRINTCLIENT nur damit kannst du korrekt auf den bereitgestellten wParam DC Zeichnen.
WM_PAINT sollte dann komplett ignoriert werden.

Verwende lieber etwa auf dieser Art.
Code:
BOOL CaptureScreen(HBITMAP& hBitmap)
{
    HDC hDCScreen = ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
    const int cx = ::GetDeviceCaps(hDCScreen, HORZRES);
    const int cy = ::GetDeviceCaps(hDCScreen, VERTRES);
    HDC hDCMem = ::CreateCompatibleDC(hDCScreen);
    hBitmap = ::CreateCompatibleBitmap(hDCScreen, cx, cy);
    HBITMAP hBmpOld = (HBITMAP)::SelectObject(hDCMem, hBitmap);

    // Note: CAPTUREBLT flag is required to capture layered windows
    DWORD dwRop = SRCCOPY | CAPTUREBLT;
    BOOL bRet = ::BitBlt(hDCMem, 0, 0, cx, cy, hDCScreen, 0, 0, dwRop);

    ::SelectObject(hDCMem, hBmpOld);
    ::DeleteDC(hDCMem);
    ::DeleteDC(hDCScreen);

    return bRet;
}
Zitat:

Du kannst es ja mit FullWindow = False mal probieren.
Sollte kein Problem sein.. warum auch ob ich nun den gesamten Screen kopiere oder nur den Teil der unter meiner Anwendung liegt spielt absolut keine rolle.
Es bleibt sich gleich.

gruss


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:51 Uhr.
Seite 1 von 7  1 23     Letzte »    

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