![]() |
Screenshot via Handle
Hallo,
ich habe eine Funktion geschrieben, die es ermöglicht einen Screenshot von einem Programm zu machen, welches ich über einen Handle ausfindig gemacht habe. Es soll kein richtiger Screenshot enstehen, sondern nur eine Durchschnittsfarbe berechnet werden. Soweit funktioniert das auch, nur wenn man den Taskmanager öffnet, kann man zusehen, wie der Speicherverbrauch meines Programms kontinuierlich ansteigt, bis sich mein ganzer PC aufhängt. Die IDE sag dazu auch nichts mehr, weil die dabei auch den Dienst versagt :( Es muss an diesem Stück Code liegen, weil sobald ich diese Prozedure nicht benutze alles ganz normal funktioniert
Delphi-Quellcode:
wahrscheinlich vergesse ich irgendwo etwas wieder freizugeben oder mein Zugriff auf die Handles ist falsch.
var
h_window: HWND; //das ist das Fenster welches gescannt werden soll procedure HandleToPix2(); var //h_desktop: THandle; i_tmp_x, i_tmp_y: Integer; i_gesRed, i_gesGreen, i_gesBlue: Integer; bRed, bGreen, bBlue: Byte; //b_tmp: TBitmap; //c_tmp: TCanvas; c_color: TColor; r_window: TRect; i_width, i_height: Integer; PixelColor: Integer; ha_window: THandle; const c_aspectorato = (4/3); //c_aspectorato = (16/9); c_vertical = 7; begin try //ha_window := GetWindowDC(h_window); ha_window := GetDC(h_window); GetWindowRect(ha_window , r_window); i_width := r_window.Right - r_window.Left; i_height := r_window.Bottom - r_window.Top; i_gesBlue := 0; i_gesGreen := 0; i_gesRed := 0; for i_tmp_x := 1 to round(c_aspectorato*c_vertical) do begin for i_tmp_y := 1 to c_vertical do begin PixelColor := GetPixel(ha_window, r_window.Left + round((i_width / (c_aspectorato*c_vertical))*i_tmp_x), r_window.Top + round((i_height/c_vertical)*i_tmp_y)); bBlue := GetBValue(PixelColor); bGreen := GetGValue(PixelColor); bRed := GetRValue(PixelColor); // c_color := c_tmp.Pixels[round((i_width / (c_aspectorato*c_vertical))*i_tmp_x), round((i_height/c_vertical)*i_tmp_y)]; // bBlue := GetBValue(c_color); // bGreen := GetGValue(c_color); // bRed := GetRValue(c_color); rgb_threshold(bRed, bGreen, bBlue); i_gesBlue := i_gesBlue + bBlue; i_gesGreen := i_gesGreen + bGreen; i_gesRed := i_gesRed + bRed; end; end; //Werte ausgeben changeRGB(Round(i_gesRed / (round(c_aspectorato*c_vertical)*c_vertical)), Round(i_gesGreen / (round(c_aspectorato*c_vertical)*c_vertical)), Round(i_gesBlue / (round(c_aspectorato*c_vertical)*c_vertical))); finally ReleaseDC(h_window, ha_window); end; end; Sieht jemand den Fehler, ich komm einfach nicht drauf gruß markus |
Re: Screenshot via Handle
HI Markus,
1. du willst die Durchschnittsfarbe eines Fensters herausfinden. Warum benützt du dazu das Bildschirm-Seitenverhältniss? Ich schlage schrittweises Abtasten ohne Seitenverhältniss vor. 2. Redmond kennt weder rgb_threshold noch changeRGB. 3. wo ich doch grade von Seitenverhältniss spreche:
Delphi-Quellcode:
Mit deiner rechnerei kann da (glaub ich mal so ganz einfach) nichts rauskommen. Ich tippe, es müsste so heißen:
changeRGB(Round(i_gesRed / (round(c_aspectorato*c_vertical)*c_vertical)),
Round(i_gesGreen / (round(c_aspectorato*c_vertical)*c_vertical)), Round(i_gesBlue / (round(c_aspectorato*c_vertical)*c_vertical)));
Delphi-Quellcode:
Die Schleifen sind davon natürlich auch betroffen:
changeRGB(Round(i_gesRed / (i_width*i_height)),
Round(i_gesGreen / (i_width*i_height)), Round(i_gesBlue / (i_width*i_height)));
Delphi-Quellcode:
Sonstige Speicherfehler kann ich keine entdecken. Falls du wirklich nicht weiterkommst, mach mal einen Schrittweisen durchgang und such das Speicherloch oder häng mal
for i_tmp_x := 1 to i_width do
begin for i_tmp_y := 1 to i_heigth do begin ![]() Was natürlich auch sein kann, ist, dass du zu viel Speicher durch zu große Zahlen belegst. Nimm für i_gesRed, i_gesGreen, i_gesBlue mal Int64, um einen größeren Bereich abzudecken. Bernhard |
Re: Screenshot via Handle
mein Problem ist nicht die Berechnung, die funktioniert perfekt. Es muss irgendwas mit den Handles zu tun habe, da ich exakt die gleiche Funktion verwende um einen Screenshot vom kompletten Desktop auszuwerten, also GetDC
hier mal eine aktualisierte Version, die aber nach wie vor, das Problem des Speicherverbrauchs hat
Delphi-Quellcode:
procedure HandleToPix(h_handle: HWND);
var i_tmp_x, i_tmp_y: Integer; i_gesRed, i_gesGreen, i_gesBlue: Integer; bRed, bGreen, bBlue: Byte; c_tmp: TCanvas; c_color: TColor; r_window: TRect; i_width, i_height: Integer; p_window: ^HWND; const c_aspectorato = (4/3); //c_aspectorato = (16/9); c_vertical = 7; begin c_tmp := TCanvas.Create; p_window := @h_handle; try c_tmp.Handle := GetWindowDC(p_window^); //c_tmp.Handle := GetDC(p_window^); GetWindowRect(p_window^, r_window); i_width := r_window.Right - r_window.Left; i_height := r_window.Bottom - r_window.Top; //c_tmp.BrushCopy(Rect(0,0,i_width, i_height), GetWindowDC(h_handle), Rect(0,0,i_width, i_height)); BitBlt(c_tmp.Handle, 0, 0, i_width, i_height, GetWindowDC(h_handle), 0, 0, SRCCOPY); i_gesBlue := 0; i_gesGreen := 0; i_gesRed := 0; for i_tmp_x := 1 to round(c_aspectorato*c_vertical) do begin for i_tmp_y := 1 to c_vertical do begin c_color := c_tmp.Pixels[round((i_width / (c_aspectorato*c_vertical))*i_tmp_x), round((i_height/c_vertical)*i_tmp_y)]; bBlue := GetBValue(c_color); bGreen := GetGValue(c_color); bRed := GetRValue(c_color); rgb_threshold(bRed, bGreen, bBlue); i_gesBlue := i_gesBlue + bBlue; i_gesGreen := i_gesGreen + bGreen; i_gesRed := i_gesRed + bRed; end; end; //Werte ausgeben changeRGB(Round(i_gesRed / (round(c_aspectorato*c_vertical)*c_vertical)), Round(i_gesGreen / (round(c_aspectorato*c_vertical)*c_vertical)), Round(i_gesBlue / (round(c_aspectorato*c_vertical)*c_vertical))); finally ReleaseDC(p_window^, c_tmp.Handle); freeandnil(c_tmp); end; //BitBlt(c_tmp.Handle, 0, 0, b_tmp.Width, b_tmp.Height, GetWindowDC(h_window), 0, 0, SRCCOPY); //BitBlt(c_tmp.Handle, 0, 0, i_width, i_height, GetWindowDC(h_window), 0, 0, SRCCOPY); end; |
Re: Screenshot via Handle
nicht der Fehler aber eine riesen Unschönheit:
Delphi-Quellcode:
Du rufst also ReleaseDC für das Fenster auch auf wenn bei der Funktion die Exception geworfen wird und somit die Werte unbestimmt sind.
try
ha_window := GetDC(h_window); finally ReleaseDC(h_window, ha_window); end; So sollte es sein:
Delphi-Quellcode:
Ressource_anfordern();
try //mit Ressource arbeiten finally Ressource_freigeben(); end; |
Re: Screenshot via Handle
das mit dem sauberen Programmieren war eine gute Idee 8)
Habe mir nochmal meine Prozedur angeschaut und speichere jetzt den HDC zwischen
Delphi-Quellcode:
...und siehe da, auf einmal läuft alles
ha_window := GetWindowDC(h_window);
Danke gruß markus |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:13 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