Forum: PC-Programmierung Fenstererkennung / Objekterkennung


von Ben I. (beninho)


Lesenswert?

Hallo,

welche Möglichkeiten gibt es geöffnete Fenster zu erkennen? Hab mir 
überlegt als kleine Programmierübung ein Minesweeper-Lösungsprogramm zu 
schreiben. Am liebsten in C, evtl. auch C++. Jetzt frage ich mich, wie 
ich die einzelnen Felder erkennen kann. Oder wie ich zumindest schon mal 
das Minesweeper-Fenster erkennen kann.

von Klaus W. (mfgkw)


Lesenswert?

Es gibt eine Windows-Funktion EnumWindows(), mit der man sich
durch die Fenster hangeln kann.
Man muß sich selbst eine Funktion schreiben, die dann für
jedes gefundene Fenster einmal aufgerufen wird
(call back-Funktion). Diese kann sich dann über das Handle
des Fensters weitere Info holen (Titel etc.) und entscheiden,
ob es das gesuchte ist.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Das ist eine Möglichkeit. Eine andere aber ist, Windows nach einem 
Fenster suchen zu lassen, wenn vom Fenster der Titel und/oder die 
Fensterklasse bekannt ist.

http://msdn.microsoft.com/en-us/library/ms633499%28VS.85%29.aspx

Beides lässt sich mit Werkzeugen wie Spy++ herausfinden.

von Tastendrücker (Gast)


Lesenswert?

Dein Vorhaben schreit doch förmlich nach AutoIt (www.autoitscript.com).

TD

von Fenstergucker... (Gast)


Lesenswert?

Das habe ich mal so gemacht:
1
while (!(GetKeyState(VK_SHIFT)&0x8000)) {}; // Mauszeiger auf gewünschtes Fenster setzen und auf SHIFT warten
2
POINT pt;
3
GetCursorPos(&pt);
4
hWnd=WindowFromPoint(pt);

Ziel war es, den Inhalt eines Fensters als Bitmap abzuspeichern.

von MaWin (Gast)


Lesenswert?

> while (!(GetKeyState(VK_SHIFT)&0x8000)) {};

Aktives blockieren eines Threads ?

100% Prozessorlast, weil man zu blöd ist, ein Ereignis (hier WM_KEYDOWN 
VK_SHIFT) programmtechnisch erfassen zu können ?

Das ist kein Vorbild, sicher nicht.

von Fenstergucker... (Gast)


Lesenswert?

@MaWin
Trotz Deiner gemeinen Stichelei eine Antwort:

A. Mir Blödheit zu unterstellen ist eine Frechheit!
B. Hast Du schon mal ein kleines Programm geschrieben, weil Du in 5 
Minuten eine Lösung brauchtest, die letztendlich nur 1x eingesetzt 
wurde? Wenn Du in solchen Fällen immer alles absolut ideal 
programmierst, dann ziehe ich den Hut vor Dir und verbeuge mich so, dass 
mein Kopf fast den Fußboden berührt.
C. Ich habe nie behauptet, dieses Vorgehen sei vorbildlich. Um Dich zu 
zitieren: "sicher nicht".

von Zwie B. (zwieblum)


Lesenswert?

MaWin schrieb:
>> while (!(GetKeyState(VK_SHIFT)&0x8000)) {};
>
> Aktives blockieren eines Threads ?
>
> 100% Prozessorlast, weil man zu blöd ist, ein Ereignis (hier WM_KEYDOWN
> VK_SHIFT) programmtechnisch erfassen zu können ?
>
> Das ist kein Vorbild, sicher nicht.

He, Windoofprofi, du weißt aber schon an welches Fenster WM_KEYDOWN 
geschickt wird, oder?

von beninho (Gast)


Lesenswert?

Danke für die Vorschläge. Hab mich jetzt noch nicht wirklich damit 
beschäftigt, werde aber mal noch rumprobieren, vor allem Rufus Vorschlag 
klingt vielversprechend.
Ich habe mich jetzt mal willkürlich für C# entschieden, das hat auf den 
ersten Blick ein Stück einfacher als C++ ausgeschaut. Die Maus kann ich 
schon mal emulieren und damit die Felder öffnen.
Einen ersten einfachen Lösungsalgorithmus habe ich in C geschrieben.

Mein momentanes Problem ist jetzt, wie ich am besten die Zahlen, also 
den Bildschirminhalt abfragen bzw. die Bildschirmausgabe anzapfen kann. 
Ergoogeln konnte ich leider gar nichts in der Richtung. Meine einzige, 
sehr umständliche, Idee wäre, nach jedem Klick einen Screenshot zu 
machen und diesen als Bitmap abzuspeichern. Das muss doch irgendwie 
eleganter gehen?

von Sven H. (dsb_sven)


Lesenswert?

Wenn du C# nutzt solltest du für solche Windows Funktionen auf jeden 
Fall mal hier vorbei gucken:

http://www.pinvoke.net/

Da findest du (insbesondere bei user32 --> funktionen aus der 
user32.dll) viele Möglichkeiten mit Windows zu interagieren, die das 
.NET von Hause aus nicht mitbringt.

von beninho (Gast)


Lesenswert?

Ich werd jetzt mal bei den Screenshots bleiben, Tastendrücken kann ich 
emulieren und danach versuche ich die Zwischenablage auszulesen. Mal 
schauen, ob das was wird.

von beninho (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich bin immer noch an meinem Minesweeper-Solver. Dauert alles etwas, 
aber ich mache das ja auch eher nebenbei. Mein aktueller Stand:

Was so einigermaßen funktioniert:
1. Suche ein MineSweeper-Fenster mit FindWindow bzw. GetProcessesByName 
- Öffne eines, falls keines geöffnet ist.
2. Fenster in den Vordergrund bringen mit SetForegroundWindow
3. Größe und Position des Fensters bestimmen mit GetWindowInfo
4. Fenster an die Position (0,0) (= linkes, oberes Bildschirmeck) 
bringen
5. Screenshot des Fensters mit CopyFromScreen machen
(5b Screenshot mit .Save abspeichern)
6. Pixelfarbe einlesen mit GetPixel
7. Mausklicks emulieren mit mouse_event

Was noch fehlt:
- die Routinen, um die Felder zu erkennen und zu unterscheiden
- mit dem Lösungsalgorithmus verbinden
- Lösungsalgorithmus verbessern
- alles miteinander verbinden
- alles insgesamt verbessern

Mein momentanes Problem ist folgendes:
Ich verschiebe das Fenster (siehe 4.) und lasse mir die Koordinaten in 
Textboxes ausgeben (Code im Anhang). Die Koordinaten, die dort 
ausgegeben werden, sind allerdings die Koordinaten VOR dem Verschieben. 
Klicke ich ein 2.Mal auf den Button, führe den Code also ein 2.Mal aus, 
werden die richtigen Koordinaten ausgegeben. Für jemanden mit etwas 
Erfahrung ist der Fehler wahrscheinlich schnell gefunden, aber ich weiß 
nicht, was ich falsch mache.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.