![]() |
Screenshot machen (zum 125.000sten Mal *gg*)
Hallo!
Ich möchte mir so eine Screenshot-Routine bauen, wie sie z.B. der PaintShopPro hat. Bisher mache ich das so:
Delphi-Quellcode:
Geht auch erstmal soweit. Ich hole mir mit GetForegroundWindow das Handle vom aktiven Fenster. Passt. Das Problem dabei: Ich möchte dabei auch evtl. aufgeklappte Menüs mit erfassen. Die verschwinden aber wie von Zauberhand im Screenshot.
procedure GrabScreenshotFromWindow(AHandle: HWND;
ATargetBitmap: Graphics.TBitmap); var C: TCanvas; R: TRect; begin C:=TCanvas.Create; C.Handle:=GetWindowDC(AHandle); GetWindowRect(AHandle, R); ATargetBitmap.Width:=R.Right - R.Left; ATargetBitmap.Height:=R.Bottom - R.Top; ATargetBitmap.Canvas.CopyRect(R, C, R); ReleaseDC(0, C.Handle); C.Free; end; Ich vermute, die Routine im PaintShopPro arbeitet ein bisschen anders. Die holt sich zwar das WindowRect vom betreffenden Fenster, "schnappschießt" dann aber den kompletten Bildschirminhalt und schneidet dann den nicht relevanten Teil weg. Die Preisfrage ist also: Wie "schnappschießt" man den kompletten Bildschirminhalt mit allen Fenstern, auch denen mit "exotischen" Zuständen wie aufgeklappte Menüs? Grüße Cody |
AW: Screenshot machen (zum 125.000sten Mal *gg*)
Es gibt eigentlich genügend Threads zu diesem Thema.
Der Grund, warum es bei dir nicht geht: Du holst dir das Handle des aktiven Fensters und sagts, daß dieses Fenster sich in dein Bitmap reinzeichnen soll. Es wird dabei nichts vom Desktop kopiert. Was mit deiner Methode gehen würde: - Allen Fenstern (diese vorher suchen) sagen sie sollen sich in dein Bitmap zeichnen, entsprechend ihrer Position auf dem Desktop und entsprechend der Z-Ausrichtung, von hinten nach vorne. |
AW: Screenshot machen (zum 125.000sten Mal *gg*)
Dazu kommen noch Overlays usw., die man nur mit ein wenig mehr Aufwand auslesen kann.
|
AW: Screenshot machen (zum 125.000sten Mal *gg*)
Was die Menüs und anderes angeht, würde es ja schon reichen, mit dem DC vom Desktop den Screenshot zu machen, und den auf die Maße des Fensters zu begrenzen. Das Desktop-Handle ist imho immer 0, also GetDC(0).
Edit: Und zumindest unter Win7 mit aktivem Aero bekomme ich damit sogar Overlay-Fensterinhalte. Bei Fullscreen könnte das aber ggf. anders aussehen, und ohne Aero habe ich's schlicht nie getestet. |
AW: Screenshot machen (zum 125.000sten Mal *gg*)
Habs! Das Stichwort GetDC(0) war die Erleuchtung. Zumindest hatte ich dadurch schon mal einen Ansatz vor Augen. Dadurch habe ich im
![]()
Delphi-Quellcode:
Scheint soweit auch mit Overlays und Alphatransparenzen klar zu kommen (Menüschatten etc.)
procedure CaptureScreen(ABitmap: Graphics.TBitmap);
const CAPTUREBLT = $40000000; var hdcScreen: HDC; hdcCompatible: HDC; hbmScreen: HBITMAP; begin hdcScreen:= CreateDC('DISPLAY', nil, nil, nil); hdcCompatible:= CreateCompatibleDC(hdcScreen); hbmScreen:= CreateCompatibleBitmap(hdcScreen, GetDeviceCaps(hdcScreen, HORZRES), GetDeviceCaps(hdcScreen, VERTRES)); SelectObject(hdcCompatible, hbmScreen); ABitmap.Handle:= hbmScreen; BitBlt(hdcCompatible, 0, 0, ABitmap.Width, ABitmap.Height, hdcScreen, 0, 0, SRCCOPY or CAPTUREBLT); DeleteDC(hdcScreen); DeleteDC(hdcCompatible); end; procedure GrabScreenshotFromWindow(AHandle: HWND; ATargetBitmap: Graphics.TBitmap); var R: TRect; DeskBMP: Graphics.TBitmap; begin DeskBMP:= Graphics.TBitmap.Create; try CaptureScreen(DeskBMP); GetWindowRect(AHandle, R); ATargetBitmap.Width:=R.Right - R.Left; ATargetBitmap.Height:=R.Bottom - R.Top; ATargetBitmap.Canvas.CopyRect(R, DeskBMP.Canvas, R); finally DeskBMP.Free; end; end; |
AW: Screenshot machen (zum 125.000sten Mal *gg*)
Liste der Anhänge anzeigen (Anzahl: 1)
So, inzwischen ist doch noch ein Problemchen aufgetaucht: Ich habe mich als gewohnheitsmäßiger Multimonitor-User an das
![]() Zitat:
Liegt das Fenster gänzlich auf einem sekundären Bildschirm, dann ist der Screenshot komplett weiß. Hat jemand eine Idee woran das nun wieder liegt? EDIT: *Kopfklatsch* - Das war mal wieder ein zu niedriger Kaffeepegel *gg* Ich habe mit GetDeviceCaps die Auflösung geholt und da scheints etwas inkonsequent zu werden beim Win32API. Zwar habe ich den DC für den kompletten Desktop über alle Bildschirme richtig geholt, aber GetDeviceCaps liefert trotzdem nur den primären Monitor: Zitat:
|
AW: Screenshot machen (zum 125.000sten Mal *gg*)
Zitat:
CreateDC(TEXT("DISPLAY"),NULL,NULL,NULL) --> DC für primären Bildschirm CreateDC(TEXT("DISPLAY"),TEXT("DISPLAY"),NULL,NULL ) --> DC für alle Bildschirme Während im unteren deine Interpetation steht: CreateDC(TEXT("DISPLAY"),NULL,NULL,NULL) --> DC für alle Bildschirme Probier mal mit 2x 'DISPLAY', vielleicht war es das ja schon. (Wie ich solche Finten in Dokus liebe...) |
AW: Screenshot machen (zum 125.000sten Mal *gg*)
Hat sich zwischenzeitlich erledigt. Siehe EDIT im Post vorher. Bei solchen Gelegenheiten merkt man dann wieder, dass der Multimonitor-Betrieb nicht zum ursprünglichen Design von Windows gehörte sondern bei Win98 quasi "drangeflanscht" wurde.
Richtig eklig wird es immer dann, wenn Bildschirmkoordinaten plötzlich negativ werden weil ein Monitor logisch gesehen links vom primären Bildschirm liegt. |
AW: Screenshot machen (zum 125.000sten Mal *gg*)
So, das sollte sie nun sein, die Screenshotfunktion die unter allen erdenklichen Multimonitor-Geometrien funktioniert. Man sollte aber bedenken, dass CreateDC('DISPLAY' laut MSDN erst ab Windows 2000 funktioniert.
Delphi-Quellcode:
procedure CaptureScreen(ABitmap: Graphics.TBitmap);
const CAPTUREBLT = $40000000; var hdcScreen: HDC; hdcCompatible: HDC; hbmScreen: HBITMAP; DeskHeight, DeskWidth, LeftOffset, TopOffset: Integer; begin hdcScreen:= CreateDC('DISPLAY', NIL, NIL, NIL); hdcCompatible:= CreateCompatibleDC(hdcScreen); DeskHeight:= Screen.DesktopHeight; DeskWidth:= Screen.DesktopWidth; LeftOffset:= Screen.DesktopLeft; TopOffset:= Screen.DesktopTop; hbmScreen:= CreateCompatibleBitmap(hdcScreen, DeskWidth, DeskHeight); SelectObject(hdcCompatible, hbmScreen); ABitmap.Handle:= hbmScreen; BitBlt(hdcCompatible, 0, 0, ABitmap.Width, ABitmap.Height, hdcScreen, LeftOffset, TopOffset, SRCCOPY or CAPTUREBLT); DeleteDC(hdcScreen); DeleteDC(hdcCompatible); end; procedure GrabScreenshotFromWindow(AHandle: HWND; ATargetBitmap: Graphics.TBitmap); var R: TRect; DeskBMP: Graphics.TBitmap; WinHeight, WinWidth, LeftOffset, TopOffset: Integer; begin DeskBMP:= Graphics.TBitmap.Create; R:= Screen.DesktopRect; LeftOffset:= Abs(R.Left); TopOffset:= Abs(R.Top); try CaptureScreen(DeskBMP); GetWindowRect(AHandle, R); Inc(R.Left, LeftOffset); Inc(R.Top, TopOffset); Inc(R.Right, LeftOffset); Inc(R.Bottom, TopOffset); WinHeight:= R.Bottom - R.Top; WinWidth:= R.Right - R.Left; ATargetBitmap.Width:= WinWidth; ATargetBitmap.Height:= WinHeight; ATargetBitmap.Canvas.CopyRect(Rect(0, 0, WinWidth, WinHeight), DeskBMP.Canvas, R); finally DeskBMP.Free; end; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:32 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz