Entwickler-Ecke

Windows API - Screenshot mit BitBlt, Unterschiede zwischen WinXP und Vista


Schlitzesofa - Do 08.01.09 19:21
Titel: Screenshot mit BitBlt, Unterschiede zwischen WinXP und Vista
Hallo,

ich habe ein Programm geschrieben, welches mit BitBlt Screenshots anfertigt und in diesen Screenshots nach Symbolen sucht.
Die Sysmbole werden dabei mit abgespeicherten Referenz-Bitmaps auf Indentität verglichen. (z.B. Buchstaben für die Schrifterkenung)
Das funktioniert unter Windows XP auch einwandfei.

Nun habe ich letztens das Programm unter Vista laufen lassen und muste feststellen, daß er zwar den Screenshot macht, aber die Symbole nicht mehr erkennt. Meine Vermutung ist, daß es was mit der Farbtiefe zu tun hat. Denn wenn ich ein Screenshot in Windows XP mache und ihn dann in Vista als Bild öfnne, dann erkennt mein Programm innerhalb dieses Bildes wieder alle Symbole.
In beiden Betriebssystemen habe ich die Anzeige auf 32 Bit gestellt.
Gibt es evt. irgendwelche Unterschiede im Befehl BitBlt zwischen WinXP und Vista? Oder werden in Vista die Farben evt. durch irgendelche DirectX-Routinen "verschmiert"?

hier mein Quelltext:


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:
procedure ScreenCapture(Bmp: TBitmap);
//speichert Screenshot in Bmp
var
  DeskWnd: HWnd;
  DeskDC: HDC;
  DeskCv: TCanvas;
  R: TRect;
  W, H: Integer;
begin
  if Bmp = nil then Exit;
  DeskWnd := GetDesktopWindow;
  DeskDC := GetWindowDC(DeskWnd);
  DeskCv := TCanvas.Create;
  DeskCv.Handle := DeskDC;
  W := Screen.Width;
  H := Screen.Height;
  R := Bounds(00, W, H);
  try
    Bmp.HandleType := bmDIB;
    Bmp.PixelFormat := pf24Bit;
    Bmp.Width := W;
    Bmp.Height := H;
    Bmp.Canvas.CopyMode := cmSrcCopy;
    Bmp.Canvas.CopyRect(R, DeskCv, R);
  finally
    DeskCv.Free;
    ReleaseDC(DeskWnd, DeskDC);
  end;
end;


P.S.:
Ich weiß, daß ich die Farbtiefe im Quelltext auf 24 Bit gestellt habe (die Anzeige ist auf 32 Bit eingestellt), aber das Proramm funktioniert ja trotzdem in XP. Ich habe sie auch schon auf 32 Bit umgestellt, was aber auch nicht funktioniert (kein Wunder, denn die Refrenz-Bilder sind vermutlich 24 Bit Farbtiefe).

Vielen Dank

Moderiert von user profile iconNarses: Delphi-Tag repariert


elundril - Do 08.01.09 19:25

hallo und :welcome: im DF,

bitte umrahme deinen quelltext zur besseren lesbarkeit mit den delphi-tags: [delphi][/delphi]

lg elundril


Hidden - Do 08.01.09 20:30

Hi :)

Ich befürchte du hast unter deinem post das Häkchen "BBCode in dieser Nachricht deaktivieren" gesetzt. Mach das mal weg, dann kann man deinen Quelltext auch lesen ;)

mfG,


JayEff - Do 08.01.09 21:14

user profile iconHidden hat folgendes geschrieben Zum zitierten Posting springen:
Hi :)

Ich befürchte du hast unter deinem post das Häkchen "BBCode in dieser Nachricht deaktivieren" gesetzt. Mach das mal weg, dann kann man deinen Quelltext auch lesen ;)

mfG,

Nein, es ist der zweite öffnende Delphi-tag der mitten im Code steht: Bmp.Han[delphi]dleType := bmDIB; ;) den sollte man entfernen.


jaenicke - Do 08.01.09 21:24
Titel: Re: Screenshot mit BitBlt, Unterschiede zwischen WinXP und V
user profile iconSchlitzesofa hat folgendes geschrieben Zum zitierten Posting springen:
Die Sysmbole werden dabei mit abgespeicherten Referenz-Bitmaps auf Indentität verglichen. (z.B. Buchstaben für die Schrifterkenung)
Woher stammen denn diese Referenz-Bitmaps?


Schlitzesofa - Fr 09.01.09 16:16
Titel: Re: Screenshot mit BitBlt, Unterschiede zwischen WinXP und V
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconSchlitzesofa hat folgendes geschrieben Zum zitierten Posting springen:
Die Sysmbole werden dabei mit abgespeicherten Referenz-Bitmaps auf Indentität verglichen. (z.B. Buchstaben für die Schrifterkenung)
Woher stammen denn diese Referenz-Bitmaps?


Zunächst erstmal danke für die korrekte Darstellung meines Quelltextes. Es war mein erstes mal, da habe ich wohl mal aus Versehen den falschen Knopf gedrückt.


Also die Referenzbilder sind selbst auch aus Screenshots extrahiert (in WinXP angefertigt).
Also Screenshot --> in Paint ausschneiden und als Bitmap abspeichern.

Wahrscheinlich würde es funktionieren, wenn ich die Referenzbilder für Vista aktualisieren würde, doch das ist mir zu viel Arbeit.


jaenicke - Fr 09.01.09 16:26

Das Problem ist doch, dass unter Vista die Icons ohnehin andere sind, sei es für Textdateien oder andere. Zudem macht es bei der Beschriftung einen Unterschied, ob ClearType aktiviert ist oder nicht. Zudem kann ich die Icongröße auf dem Desktop ja jederzeit ändern. Genauso wie die Farbtiefe. Oder den Abstand der Icons untereinander.

Worum es dir genau geht bei der Erkennung weiß ich ja nicht, aber bei allgemeinen Fällen wird das so nichts.

Wenn du also nicht von deinem Programm auf dem Zielsystem die Referenzbilder im Rahmen einer Einrichtung anfertigen lässt, dann wirst du da nicht viel Erfolg haben fürchte ich. :nixweiss:

Eine sinnvollere Alternative wäre vielleicht der Weg, den Programme gehen, die sich die Positionen der Symbole auf dem Desktop merken und wiederherstellen. Die greifen auf die Symbole ja direkt zu, und dann kann man von dort aus auch das aktuelle Symbol direkt auslesen, also dessen Pfad.


Schlitzesofa - Sa 10.01.09 03:48

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Das Problem ist doch, dass unter Vista die Icons ohnehin andere sind, sei es für Textdateien oder andere. Zudem macht es bei der Beschriftung einen Unterschied, ob ClearType aktiviert ist oder nicht. Zudem kann ich die Icongröße auf dem Desktop ja jederzeit ändern. Genauso wie die Farbtiefe. Oder den Abstand der Icons untereinander.

Worum es dir genau geht bei der Erkennung weiß ich ja nicht, aber bei allgemeinen Fällen wird das so nichts.

Wenn du also nicht von deinem Programm auf dem Zielsystem die Referenzbilder im Rahmen einer Einrichtung anfertigen lässt, dann wirst du da nicht viel Erfolg haben fürchte ich. :nixweiss:

Eine sinnvollere Alternative wäre vielleicht der Weg, den Programme gehen, die sich die Positionen der Symbole auf dem Desktop merken und wiederherstellen. Die greifen auf die Symbole ja direkt zu, und dann kann man von dort aus auch das aktuelle Symbol direkt auslesen, also dessen Pfad.



Es geht mir nicht um Icons oder Desktop-Verknüpfungen,
sondern mir geht es darum, daß die Software aus einem Programmfenster Zahlen und zum Teil auch Buchstaben ausliest.
Dazu habe ich die Zahlen 0 bis 9 und auch einige betroffene Buchstaben bzw. Wörter vorher mittels Screenshots abgespeichert und als Referenz-Bitmaps hinterlegt.
Das ganze ist notwendig, wenn man Programme überwachen will, die über keine vorgesehene Programmier-Schnittstelle verfügen.
Es ist also auch davon auszugehen, daß die Darstellung innerhalb des Programmfensters unabhängig vom verwendeten Betriebssystem ist (es sei denn Vista legt irgendwelche Effekte drüber, was ich eben nicht genau weiss).


JayEff - Sa 10.01.09 05:24

Kann man nicht die fensterhandles der ausgabeelemente suchen und ihre eigenschaften auslesen? Ich weiß nicht genau wie das geht, aber ich glaube doch, es müsste gehen...?


jaenicke - Sa 10.01.09 11:20

user profile iconSchlitzesofa hat folgendes geschrieben Zum zitierten Posting springen:
Es ist also auch davon auszugehen, daß die Darstellung innerhalb des Programmfensters unabhängig vom verwendeten Betriebssystem ist (es sei denn Vista legt irgendwelche Effekte drüber, was ich eben nicht genau weiss).
Ja, tut es und XP ggf. auch, ClearType z.B. nämlich. Hast du die gemachten Screenshots von XP und Vista mal auf solche Unterschiede hin verglichen?

ListViews, TreeViews, etc. kann man übrigens auch direkt auslesen, wie user profile iconJayEff auch sagte:
http://www.delphipraxis.net/topic52045_fremde+treeview+auslesen.html


Schlitzesofa - Sa 10.01.09 16:49

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconSchlitzesofa hat folgendes geschrieben Zum zitierten Posting springen:
Es ist also auch davon auszugehen, daß die Darstellung innerhalb des Programmfensters unabhängig vom verwendeten Betriebssystem ist (es sei denn Vista legt irgendwelche Effekte drüber, was ich eben nicht genau weiss).
Ja, tut es und XP ggf. auch, ClearType z.B. nämlich. Hast du die gemachten Screenshots von XP und Vista mal auf solche Unterschiede hin verglichen?

ListViews, TreeViews, etc. kann man übrigens auch direkt auslesen, wie user profile iconJayEff auch sagte:
http://www.delphipraxis.net/topic52045_fremde+treeview+auslesen.html



Vielen Dank,

ClearType war des Rätsels Lösung!
Ich habe es abgeschalten und jetzt funktioniert die Zahlenerkennung wieder.


HPW - Do 29.01.09 09:29

Hallo,

Zitat:
Die Sysmbole werden dabei mit abgespeicherten Referenz-Bitmaps auf Indentität verglichen.


Mit welchem Algorithmus wird das denn gemacht?
Wenn man bei jedem Pixel (Scanline) anfängt den Bereich der linken oberen Ecke jeder Referenz-Bitmap zu vergleichen, wird das doch sehr aufwendig und un-performant oder?

Hans-Peter


jaenicke - Do 29.01.09 14:22

Hallo und :welcome:!

user profile iconHPW hat folgendes geschrieben Zum zitierten Posting springen:
Mit welchem Algorithmus wird das denn gemacht?
Wenn man bei jedem Pixel (Scanline) anfängt den Bereich der linken oberen Ecke jeder Referenz-Bitmap zu vergleichen, wird das doch sehr aufwendig und un-performant oder?
Eine große Wahl hast du dabei ja nicht. Irgendwie musst du die Pixel ja vergleichen. Wobei du bei exakter Identität auch sehr schnell mit CompareMem arbeiten kannst.

Ansonsten gibt es hier auch etwas zu dem Thema:
http://www.delphi-forum.de/viewtopic.php?p=529340#529340
(diese Ergänzung bezog sich auf den Quelltext weiter oben.)

Aber wenn du dazu eine Frage hast, dann erstelle bitte auch ein entsprechendes Thema.


HPW - Do 29.01.09 16:14

Danke für die Info und den Link.
Ich dachte es gäbe hier vielleicht einen besseren Ansatz/Algorithmus.

Zitat:
Aber wenn du dazu eine Frage hast, dann erstelle bitte auch ein entsprechendes Thema.


Werde ich tun wenn dazu noch weitere Fragen aufkommen.

Danke

Hans-Peter