Entwickler-Ecke
Windows API - Screenshot eines Fensters erstellen
elundril - Sa 26.06.10 03:15
schon mal probiert sich das bild direkt in delphi anzeigen zu lassen um zu sehen ob der code zumindestens was macht?
jaenicke - Sa 26.06.10 06:59
Zwei gängige Probleme wären:
1. Der Zielprozess wurde mit Adminrechten gestartet. Es kann sein, dass das dann nicht klappt, da dann die Kommunikation eingeschränkt ist, wenn der eigene Prozess keine hat.
2. Es handelt sich um ein DirectX- oder OpenGL-Fenster. In diesem Fall geht es nicht so einfach.
Hast du einmal versucht von einem anderen Fenster mit dem selben Code einen Screenshot zu machen? Um den Code an sich zu testen meine ich.
Boldar - Sa 26.06.10 13:57
Ich habe als Fenster testweise Notepad genommen, das ist wohl kaum dirctx, das Handle ist gültig und meine IDE wird mit Adminrechten gestartet, also erben die Programme diese doch?
Ich werde das mit dem Anzeigen lassen gleich mal probieren.
jaenicke - Sa 26.06.10 15:03
Dann zeig doch einfach mal deinen Code, in dem du das Fenster von Notepad findest. :gruebel:
Denn den Code hier aus der Library hatte ich selbst schonmal mit Notepad ausprobiert soweit ich mich erinnere. Ich werde es heute Abend noch einmal testen, wenn ich vorn der Arbeit komme (hab Pause :D).
Boldar - Sa 26.06.10 15:20
Ich habe momentan folgenden Code:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82:
| program gamestream;
{$APPTYPE CONSOLE}
uses SysUtils, windows, classes, graphics, tlhelp32, dialogs;
var WIndowhandle:THandle;
function FormularSaveScreenShot(FileName: String; h : hWnd): Boolean; var Rec: TRect; iWidth, iHeight: Integer; begin with TBitmap.Create do try GetWindowRect(h, Rec);
iWidth := Rec.Right - Rec.Left;
iHeight := Rec.Bottom - Rec.Top; Width := iWidth; Height := iHeight; BitBlt(Canvas.Handle, 0, 0, iWidth, iHeight, GetWindowDC(h), 0, 0, SRCCOPY); Result := True; try SaveToFile(Filename) except Result := False end; finally ReleaseDC(h, GetWindowDC(h)); Free; end; end;
function MyEnumWindowProc(AHandle: THandle; LParam: LongWord): boolean; stdcall; var ProcessID: THandle; begin ProcessID := 0; GetWindowThreadProcessID(AHandle, ProcessID); Result := not (ProcessID = LParam); if not Result then WindowHandle := AHandle; end;
function GetWindowHandleByExeName(const AExeName: string): THandle; var SnapShot: THandle; p: TProcessEntry32; ProcessHandle: THandle; begin Result := 0; WindowHandle := 0; ProcessHandle := 0; p.dwSize := SizeOf(p); SnapShot := CreateToolhelp32Snapshot(TH32CS_SnapProcess, 0); try if Process32First(SnapShot, p) then repeat if AnsiLowerCase(AExeName) = AnsiLowerCase(p.szExeFile) then ProcessHandle := p.th32ProcessID; until (ProcessHandle <> 0) or not Process32Next(SnapShot, p); EnumWindows(@MyEnumWindowProc, ProcessHandle); Result := WindowHandle; finally CloseHandle(SnapShot); end; end;
var H: THandle; var bmp: TBitmap;
begin h:=Getwindowhandlebyexename('notepad.exe'); sleep(1000); if formularsavescreenshot ('C:\img.bmp', h) then showmessage ('succes'); readln; end. |
elundril - Sa 26.06.10 15:35
Folgendes zu diesem Befehl:
Delphi-Quelltext
1:
| CreateToolhelp32Snapshot |
| MSDN hat folgendes geschrieben: |
If the specified process is a 64-bit process and the caller is a 32-bit process, this function fails and the last error code is ERROR_PARTIAL_COPY (299).
|
Ich denke das könnte der Grund sein??? Hast du eigentlich GetLastError() mal aufgerufen?
lg elundril
Boldar - Sa 26.06.10 17:29
Das handle ist gültig, ich habe es auch schon mit einem 32-bit-Process probiert, und getlasterror ist null.
Und formularsavescreenshot gibt true zurück. Alles irgendwie sehr komisch.
---
Moderiert von
Narses: Beiträge zusammengefasst---
Also, folgendes geht:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| procedure MakeScreenShot(const ATarget: TBitmap); var DesktopDC: HDC; begin DesktopDC := CreateDC('DISPLAY', nil, nil, nil); try ATarget.PixelFormat := pfDevice; ATarget.Width := 1280; ATarget.Height := 1024; BitBlt(ATarget.Canvas.Handle, 0, 0, 1280, 1024, DesktopDC, 0, 0, SRCCOPY); finally DeleteDC(DesktopDC); end; end; |
und gibt ein screenshot des Desktops zurück.
Folgendes:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
| function FormularSaveScreenShot(FileName: String; h : hWnd): Boolean; var Rec: TRect; iWidth, iHeight: Integer; begin result:=false; with TBitmap.Create do try GetWindowRect(h, Rec);
iWidth := Rec.Right - Rec.Left; iHeight := Rec.Bottom - Rec.Top; Width := iWidth; Height := iHeight; BitBlt(Canvas.Handle, 0, 0, iWidth, iHeight, GetWindowDC(h), 0, 0, SRCCOPY); Result := True; try SaveToFile(Filename) except Result := False end; finally ReleaseDC(h, GetWindowDC(h));
Free; end; end; |
geht nicht und gibt ein leeres Bitmap zurück. Selbst mit admin-rechten. Wenn ich allerdings als h das Handle des eigenen Fensters übergebe, funktioniert das einwandfrei.
Delete - Sa 26.06.10 20:02
Klasse Fehlerbehandlung:
Result := True;. :roll: Woher weißt du, dass alle vorherigen Funktionsaufrufe fehlerfrei waren?
| Zitat: |
| Selbst mit admin-rechten. Wenn ich allerdings als h das Handle des eigenen Fensters übergebe, funktioniert das einwandfrei. |
Lass doch mal das rumngewurstel mit den unterschiedlichen Benutzerkonten und starte dein Programm und das Programm, von dem du den Screenshot haben willst im gleichen Kontext.
Boldar - Sa 26.06.10 20:06
Luckie hat folgendes geschrieben : |
Klasse Fehlerbehandlung:Result := True;. :roll: Woher weißt du, dass alle vorherigen Funktionsaufrufe fehlerfrei waren?
|
Ist ja nicht von mir, aber wenns ne exception gibt, kommt er ja nie dahin.
Luckie hat folgendes geschrieben : |
| Zitat: | | Selbst mit admin-rechten. Wenn ich allerdings als h das Handle des eigenen Fensters übergebe, funktioniert das einwandfrei. |
Lass doch mal das rumngewurstel mit den unterschiedlichen Benutzerkonten und starte dein Programm und das Programm, von dem du den Screenshot haben willst im gleichen Kontext. |
Ich habe sowohl beide als Admin, als auch beide als normaler User, als auch verschiedene gemischte Varianten probiert.
Naja, wenns so nicht geht, mache ich halt nen screenshot und schneide das dann raus.
elundril - Sa 26.06.10 21:39
Ich zitiere mich ja nur ungern aber:
elundril hat folgendes geschrieben : |
Hast du eigentlich GetLastError() mal aufgerufen?
lg elundril |
jaenicke - Sa 26.06.10 22:54
Das wird damit gar nix zu tun haben. Das gefundene Fenster ist einfach
irgendein Fenster vom Editor. Das muss aber nicht das sichtbare sein...
Wie wäre es, wenn du in deiner Callback-Prozedur schaust, ob das Fenster zumindest sichtbar ist? ;-)
(Ob es das ist was du willst, ist nochmal ne andere Frage, hab grad keine Lust zu testen.)
So in der Art meine ich in MyEnumWindowProc:
Delphi-Quelltext
1:
| Result := not ((ProcessID = LParam) and IsWindowVisible(AHandle)); |
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!