Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Screenshot des aktiven Fenster genau wie Alt+Druck (https://www.delphipraxis.net/186812-screenshot-des-aktiven-fenster-genau-wie-alt-druck.html)

Alex_ITA01 2. Okt 2015 07:48

Screenshot des aktiven Fenster genau wie Alt+Druck
 
Hallo zusammen,
ich erstelle wie folgt ein Screenshot eines Fensters:

Delphi-Quellcode:
var
  aFormat : Word;
  aBMP    : TBitMap;
  AData   : THandle;
  APalette : HPALETTE;

  procedure ScreenShot(Wnd: HWND; ATo: TBitmap);
  var
    hDCMem : HDC;
    DC    : HDC;
    rect  : TRect;
    bmp   : HBITMAP;
    hOld  : HGDIOBJ;
  begin
    hDCMem := CreateCompatibleDC(0);

    GetWindowRect(Wnd, rect);

    DC := GetDC(Wnd);
    bmp := CreateCompatibleBitmap(DC, rect.Right-rect.Left, rect.Bottom-rect.Top);
    ReleaseDC(Wnd, DC);

    hOld := SelectObject(hDCMem, bmp);
    SendMessage(wnd, wm_Print, hDCMem, PRF_CHILDREN or PRF_CLIENT or PRF_ERASEBKGND or PRF_NONCLIENT or PRF_OWNED);

    SelectObject(hDCMem, hold);
    DeleteObject(hDCMem);

    ATo.FreeImage;
    ATo.Handle := bmp;
  end;

begin
  aBMP := TBitmap.Create;
  try
    ScreenShot(Self.Handle, aBMP);  //<- Self.Handle ist meine "Form1"

    // Bild in Zwischenablage
    aBMP.SaveToClipBoardFormat(aFormat, AData, APalette);
    ClipBoard.SetAsHandle(aFormat,AData);
  finally
    aBMP.Free;
  end;
Das funktioniert auch soweit.
Nur wenn ich eine zweite Form über diese Form1 lege und dann den Screenshot mache, dann wird nur von der Form1 der Screenshot erstellt aber das was von Form2 in dem sichtbaren Bereich der Form1 ist, wird nicht mitgenommen. Also die Funktion sollte so sein, wie Alt+PrintScreen. Da wird ja einfach das aktuelle Fenster ge-screenshot-et bis zum jeweiligen Rahmen. Auch wenn andere Fenster in dem sichtbaren Bereich rein ragen, wird eben deren Ausschnitt auch genommen.

Habt ihr eine Idee, wie man genau das macht? Oder kann ich einfach die Tastenkombination Alt+PrintScreen als Command abschicken, das würde mir auch reichen.

Grüße

hathor 2. Okt 2015 08:19

AW: Screenshot des aktiven Fenster genau wie Alt+Druck
 
To simulate the ALT-PRINTSCREEN keyboard combination use this line i.e. to capture the active window:

keybd_event(VK_SNAPSHOT, 1, 0, 0);


To simulate the PRINTSCREEN keyboard button press use this line i.e. to capture the entire screen:

keybd_event(VK_SNAPSHOT, 0, 0, 0);

Alex_ITA01 2. Okt 2015 08:35

AW: Screenshot des aktiven Fenster genau wie Alt+Druck
 
It works, fine.
Thanks

Zacherl 2. Okt 2015 14:57

AW: Screenshot des aktiven Fenster genau wie Alt+Druck
 
An alternative more "clean" solution is MSDN-Library durchsuchenPrintWindow.

hathor 2. Okt 2015 15:33

AW: Screenshot des aktiven Fenster genau wie Alt+Druck
 
http://www.delphibasics.info/home/de...lphisourcecode

HolgerX 2. Okt 2015 17:37

AW: Screenshot des aktiven Fenster genau wie Alt+Druck
 
Oder nehme stat 'self.Handle' 'Screen.ActiveForm.Handle' dann wird immer der ScreenShot von dem aktuellen Fenster deiner App gemacht.

Harry Stahl 2. Jul 2016 16:50

AW: Screenshot des aktiven Fenster genau wie Alt+Druck
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von Zacherl (Beitrag 1317522)
An alternative more "clean" solution is MSDN-Library durchsuchenPrintWindow.

Bin gerade auch auf diese Frage gestoßen und habe den Thread hier gefunden, daher lasse ich ihn noch mal aufleben.

Denn: Den Hinweis mit Printwindow fand ich erst mal gut, denn der funktioniert auch über mehrere Monitore und bei Fenstern mit oder ohne Rahmen und z.B. bei mit der VCL benutzen Fensterstyles.

Allerdings:

Das Fenster wird immer im Windows-Basis Stil gemalt, nicht so wie es aktuell auf dem Monitor angezeigt wird (siehe anliegenden Screenshot).

Kann man das noch irgendwie beeinflussen?

HolgerX 2. Jul 2016 18:21

AW: Screenshot des aktiven Fenster genau wie Alt+Druck
 
Teste doch mal:

Delphi-Quellcode:
Type
  TScreenShotSource = (sssActiveForm,sssActiveFormClient,sssPrimaryScreen,sssDesktopScreen);

procedure MakeScreenShot(const ATarget: TBitmap;ASource : TScreenShotSource;ASourceHandle : HWND = 0);
var
  tmpHandel : HWND;
  SourceDC: HDC;
  Rec: TRect;
begin
  tmpHandel := 0;
  SourceDC := 0;

  try
    ATarget.PixelFormat := pfDevice;
    if ASourceHandle > 0 then begin
      tmpHandel := ASourceHandle;
      case ASource of
        sssActiveFormClient : begin
                                SourceDC := GetDc(tmpHandel);
                                GetClientRect(tmpHandel,Rec);
                              end;
        else begin
          SourceDC := GetWindowDc(tmpHandel);
          GetWindowRect(tmpHandel,Rec);
        end;
      end;
    end else begin
      case ASource of
        sssActiveForm      : begin
                                tmpHandel := GetForegroundWindow;
                                SourceDC := GetWindowDc(tmpHandel);
                                GetWindowRect(tmpHandel,Rec);
                              end;
        sssActiveFormClient : begin
                                tmpHandel := GetForegroundWindow;
                                SourceDC := GetDc(tmpHandel);
                                GetClientRect(tmpHandel,Rec);
                              end;
        sssPrimaryScreen   : begin
                                tmpHandel := GetDesktopWindow;
                                SourceDC := GetDc(tmpHandel);
                                GetWindowRect(tmpHandel,Rec);
                              end;
        sssDesktopScreen   : begin
                                tmpHandel := GetDesktopWindow;
                                SourceDC := GetDc(tmpHandel);
                                Rec.Left := 0;
                                Rec.Top := 0;
                                Rec.Right := Screen.DesktopWidth;
                                Rec.Bottom := Screen.DesktopHeight;
                              end;
        else exit;
      end;
    end;

    ATarget.Width := Rec.Right - Rec.Left;
    ATarget.Height := Rec.Bottom - Rec.Top;

    BitBlt(ATarget.Canvas.Handle, 0, 0, ATarget.Width, ATarget.Height, SourceDC, 0, 0, SRCCOPY);
  finally
    ReleaseDC(tmpHandel, SourceDC);
  end;
end;

Aufruf z.B.

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  tmpBitMap : TBitMap;
begin
  tmpBitMap := TBitMap.Create;
  try
    case RadioGroup1.ItemIndex of
     0 : MakeScreenShot(tmpBitMap, sssPrimaryScreen);
     1 : MakeScreenShot(tmpBitMap, sssDesktopScreen);
     2 : MakeScreenShot(tmpBitMap, sssActiveForm);
     3 : MakeScreenShot(tmpBitMap, sssActiveFormClient);
     else exit;
    end;
    Image1.Picture.Assign(tmpBitMap);
  finally
    tmpBitMap.Free;
  end;
end;

Harry Stahl 3. Jul 2016 00:21

AW: Screenshot des aktiven Fenster genau wie Alt+Druck
 
Liste der Anhänge anzeigen (Anzahl: 1)
@HolgerX: Danke für den Source, jedoch brauch ich es gar nicht zu probieren, da ich es zuvor schon so versucht hatte (bringt ungenaue Ergebnisse, wenn Fenster ohne Rahmen sind, oder z.B. VCL-Windows mit Styles).

Habe es jetzt so gelöst, dass ich für das Sammeln der verfügbaren Fenster die PrintWindow-Funktion nutze, da es hier erst mal nur eine Vorschau ist (siehe anliegenden Screenshot).

Für die Durchführung des tatsächlichen Screnshots für das gewählte Fenster arbeite ich dann mit der simulierten Tastaturfolge Alt+Druck (nur das bringt in allen Fällen korrekte Ergebnisse). Das geht dann zwar über die Zwischenablage, ist aber verschmerzbar (kleiner Tipp: man muss danach etwas warten, bis das Bitmap in der Zwischenablage ist, Windows braucht je nach Fenstergröße ein paar Millisekungen dafür).

HolgerX 3. Jul 2016 07:42

AW: Screenshot des aktiven Fenster genau wie Alt+Druck
 
Hmm..

meine Funktion arbeitet doch garnicht mit PrintWindow!?

Hab hier kein Win10 zum testen..

himitsu 4. Jul 2016 12:34

AW: Screenshot des aktiven Fenster genau wie Alt+Druck
 
Zitat:

Zitat von Harry Stahl (Beitrag 1341827)
kleiner Tipp: man muss danach etwas warten, bis das Bitmap in der Zwischenablage ist, Windows braucht je nach Fenstergröße ein paar Millisekungen dafür

Oder man wartet nicht, sondern reagiert auf die Message, welche Windows rum schickt, nachdem sich die Zwischenablage geändert hat.

t.roller 4. Jul 2016 14:32

AW: Screenshot des aktiven Fenster genau wie Alt+Druck
 
Aus den Infos der folgenden Links kann man sich was zusammen stricken:

...benachrichtigt werden, wenn die Zwischenablage geändert wird

Basic Clipboard Operations (Cut/Copy/Paste)

ALT+DRUCK


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:55 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