AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi Screenshot via Handle
Thema durchsuchen
Ansicht
Themen-Optionen

Screenshot via Handle

Ein Thema von meg91 · begonnen am 15. Jun 2008 · letzter Beitrag vom 22. Jun 2008
Antwort Antwort
Benutzerbild von meg91
meg91

Registriert seit: 25. Apr 2006
131 Beiträge
 
Turbo Delphi für Win32
 
#1

Screenshot via Handle

  Alt 15. Jun 2008, 12:11
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:
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;
wahrscheinlich vergesse ich irgendwo etwas wieder freizugeben oder mein Zugriff auf die Handles ist falsch.
Sieht jemand den Fehler, ich komm einfach nicht drauf

gruß
markus
  Mit Zitat antworten Zitat
Benutzerbild von rollstuhlfahrer
rollstuhlfahrer

Registriert seit: 1. Aug 2007
Ort: Ludwigshafen am Rhein
1.529 Beiträge
 
Delphi 7 Professional
 
#2

Re: Screenshot via Handle

  Alt 15. Jun 2008, 17:36
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:
    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)));
Mit deiner rechnerei kann da (glaub ich mal so ganz einfach) nichts rauskommen. Ich tippe, es müsste so heißen:
Delphi-Quellcode:
    changeRGB(Round(i_gesRed / (i_width*i_height)),
              Round(i_gesGreen / (i_width*i_height)),
              Round(i_gesBlue / (i_width*i_height)));
Die Schleifen sind davon natürlich auch betroffen:
Delphi-Quellcode:
    for i_tmp_x := 1 to i_width do
    begin
      for i_tmp_y := 1 to i_heigth do
      begin
Sonstige Speicherfehler kann ich keine entdecken. Falls du wirklich nicht weiterkommst, mach mal einen Schrittweisen durchgang und such das Speicherloch oder häng mal FastMM rein.
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
Bernhard
Iliacos intra muros peccatur et extra!
  Mit Zitat antworten Zitat
Benutzerbild von meg91
meg91

Registriert seit: 25. Apr 2006
131 Beiträge
 
Turbo Delphi für Win32
 
#3

Re: Screenshot via Handle

  Alt 22. Jun 2008, 21:21
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;
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#4

Re: Screenshot via Handle

  Alt 22. Jun 2008, 21:42
nicht der Fehler aber eine riesen Unschönheit:
Delphi-Quellcode:
try
  ha_window := GetDC(h_window);
finally
  ReleaseDC(h_window, ha_window);
end;
Du rufst also ReleaseDC für das Fenster auch auf wenn bei der Funktion die Exception geworfen wird und somit die Werte unbestimmt sind.
So sollte es sein:
Delphi-Quellcode:
Ressource_anfordern();
try
  //mit Ressource arbeiten
finally
  Ressource_freigeben();
end;
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
Benutzerbild von meg91
meg91

Registriert seit: 25. Apr 2006
131 Beiträge
 
Turbo Delphi für Win32
 
#5

Re: Screenshot via Handle

  Alt 22. Jun 2008, 21:59
das mit dem sauberen Programmieren war eine gute Idee 8)

Habe mir nochmal meine Prozedur angeschaut und speichere jetzt den HDC zwischen
ha_window := GetWindowDC(h_window); ...und siehe da, auf einmal läuft alles

Danke

gruß
markus
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:13 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