Prüfen ob das aktuelle Fenster den Focus hat
Abend
Versuche michgerade daran, das Spiel SNAKE in C zu Programmiern.
Soweit funktioniert auch alles, die Schlange bewegt sich, frist kleine '#' und wächst dabei.
Auch kann sie sich selbst beisen und man verliert.
Nun zu meinem Problem.
Die gedrükte Pfeiltaste frage ich mit:
GetAsyncKeyState(Links oder rechts oder rauf oder runter, jenachdem welche taste ich abfragen möchte ob sie gedrückt wurde)
Also zum Beispiel:
GetAsyncKeyState(VK_LEFT);
nun zu meinem Problem.
Wenn ich das CMD fenster, in dem sich die Schnlage bewegt aus dem Focus nehme, werden die Pfeiltasten trotzdem noch eingelsen.
Also wenn ich in einem Ordner Pfeil hoch oder runter drücke, bewegt sich im Hintergrund die Schlange.
Gibt es hier eine Möglichgeit sowas in den Programmcode einzuarbeiten:
if(Ja ich habe den Focus)
um eine Weitere richtingsänderung der Schlange zu unterbinden, wenn das CMD Fenster nicht den Focus hat?
Schonmal Danke für eine Antwort
Mfg
Power-Poler
Versuche michgerade daran, das Spiel SNAKE in C zu Programmiern.
Soweit funktioniert auch alles, die Schlange bewegt sich, frist kleine '#' und wächst dabei.
Auch kann sie sich selbst beisen und man verliert.
Nun zu meinem Problem.
Die gedrükte Pfeiltaste frage ich mit:
GetAsyncKeyState(Links oder rechts oder rauf oder runter, jenachdem welche taste ich abfragen möchte ob sie gedrückt wurde)
Also zum Beispiel:
GetAsyncKeyState(VK_LEFT);
nun zu meinem Problem.
Wenn ich das CMD fenster, in dem sich die Schnlage bewegt aus dem Focus nehme, werden die Pfeiltasten trotzdem noch eingelsen.
Also wenn ich in einem Ordner Pfeil hoch oder runter drücke, bewegt sich im Hintergrund die Schlange.
Gibt es hier eine Möglichgeit sowas in den Programmcode einzuarbeiten:
if(Ja ich habe den Focus)
um eine Weitere richtingsänderung der Schlange zu unterbinden, wenn das CMD Fenster nicht den Focus hat?
Schonmal Danke für eine Antwort
Mfg
Power-Poler
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 221687
Url: https://administrator.de/forum/pruefen-ob-das-aktuelle-fenster-den-focus-hat-221687.html
Ausgedruckt am: 21.02.2025 um 11:02 Uhr
12 Kommentare
Neuester Kommentar
Hallo Power-Poler,
rein empirisch würde ich ja ein getch() in eine Threadfunktion packen, dann hat sich dein Problem von selbst erledigt. Wer braucht schon GetAsyncKeyState()
Ansonsten, schau mal ins MSDN, da findest du WinAPIs, wie GetActiveWindow() oder GetFocus().
Grüße
rubberman
rein empirisch würde ich ja ein getch() in eine Threadfunktion packen, dann hat sich dein Problem von selbst erledigt. Wer braucht schon GetAsyncKeyState()
Ansonsten, schau mal ins MSDN, da findest du WinAPIs, wie GetActiveWindow() oder GetFocus().
Grüße
rubberman
Zitat von @Power-Poler:
Naja getch() würde zwar gehen, aber dan würde die Schlange auf Input warten, was ja nicht sin der Sache ist.
Naja getch() würde zwar gehen, aber dan würde die Schlange auf Input warten, was ja nicht sin der Sache ist.
Darum habe ich von einer Threadfunktion gesprochen, die asynchron auf Input wartet
Grüße
rubberman
Naja, das ist nicht sooo schwer. Für Standard-C gibt es da _beginthread() und _beginthreadex(), Die WinAPI hätte da auch noch was zu bieten, aber für deine Zwecke reicht die erstgenannte Funktion völlig aus. Im MSDN findet sich wie immer die entsprechende Referenz. Wie du siehst wird die entsprechende Funktion übergeben, die als Thread laufen soll. Ebenso ist es möglich einen Parameter für die Threadfunktion als Voidpointer zu übergeben. Das bedeutet für die Threadfunktion, dass sie immer vom Typ void ist (also keinen Wert zurück geben kann) und einen Parameter vom Typ void* akzeptiert. Dieser zeigt dann auf den Speicherbereich der vorher deklarierten Variable aus der aufrufenden Funktion.
Mal ein Beispiel mit entsprechenden Kommentaren.
Wie du siehst, reagiert das Programm auf Pfeiltasten und Esc zum Beenden. Die Schleife in der Mainfunktion läuft unabhängig davon weiter, während der Wert für iInput in der Threadfunktion verändert wird.
Soweit ziemlich simpel, oder?
Grüße
rubberman
Mal ein Beispiel mit entsprechenden Kommentaren.
#include <windows.h>
#include <process.h>
#include <stdio.h>
#include <conio.h>
// vordefinierte Werteliste
#define ESC 27 {{comment_single_line_double_slash:1}}
#define RIGHT 333 {{comment_single_line_double_slash:2}}
#define LEFT 331 {{comment_single_line_double_slash:3}}
#define UP 328 {{comment_single_line_double_slash:4}}
#define DOWN 336 {{comment_single_line_double_slash:5}}
void __cdecl Fn_GetKey(void *const pInt); // Prototyp der Threadfunktion
int main(void)
{
int iInput = 0; // Wert wird von der Threadfunktion geändert
char chOutput = '\x0f'; // Startzeichen
// Threadfunktion aufrufen, Zeiger auf iInput wird übergeben
if (_beginthread((void(*)(void*))Fn_GetKey, 0, (void*)&iInput) == ((uintptr_t)(intptr_t)-1))
return EXIT_FAILURE; // wenn Thread nicht erstellt werden konnte, raus hier
while (iInput != ESC) // Endlosschleife bis Escape
{
switch(iInput)
{
case RIGHT:
chOutput = '\x10';
break;
case LEFT:
chOutput = '\x11';
break;
case UP:
chOutput = '\x1e';
break;
case DOWN:
chOutput = '\x1f';
}
printf("%c\n", chOutput); // Ausgabe
Sleep(200);
}
return EXIT_SUCCESS;
}
// Threadfunktion, Parameter *pInt ist Zeiger auf Speicherbereich von iInput
void __cdecl Fn_GetKey(void *const pInt)
{
int iKey = 0;
do // Endlosschleife bis Escape
{
iKey = _getch(); // Warte auf Tastatureingabe
// Bei F- oder Pfeiltasten, gibt der erste Aufruf 0 oder 224 zurück
// Führe _getch() erneut aus um den Scancode aus dem Puffer zu lesen
// http://msdn.microsoft.com/en-us/library/aa299374(v=vs.60).aspx
if (iKey == 0 || iKey == 224)
iKey = 256 + _getch(); // 256 wird zwecks Unterscheidung zu ASCII Werten addiert
*((int*)pInt) = iKey; // Schreibe neuen Wert in den adressierten Speicherbereich
} while (iKey != ESC);
_endthread(); // Thread beenden
}
Soweit ziemlich simpel, oder?
Grüße
rubberman
Gemeint ist die Startadresse der Funktion. Das ist lediglich ein Name und steht dort eigentlich zum besseren Verständnis und nicht um dich zu verwirren 
Dazu solltest du dir vielleicht GetKeyboardState() ansehen. Diese Funktion füllt ein Bytearray mit dem Status aller Tasten, bei dem du mit bitweisem UND prüfen kannst ob eine bestimmte Taste gedrückt wurde. Mit logischem UND kannst du mehrere solcher Tests zusammenfassen, um herauszufinden ob bestimmte Tastenkombinationen gedrückt wurden. (Ist aber nur Theorie, hatte heute keine Zeit da was zu testen.)
Grüße
rubberman
EDIT:
Kurz skizziert für Kombinationen der Pfeiltasten ...
Dazu solltest du dir vielleicht GetKeyboardState() ansehen. Diese Funktion füllt ein Bytearray mit dem Status aller Tasten, bei dem du mit bitweisem UND prüfen kannst ob eine bestimmte Taste gedrückt wurde. Mit logischem UND kannst du mehrere solcher Tests zusammenfassen, um herauszufinden ob bestimmte Tastenkombinationen gedrückt wurden. (Ist aber nur Theorie, hatte heute keine Zeit da was zu testen.)
Grüße
rubberman
EDIT:
Kurz skizziert für Kombinationen der Pfeiltasten ...
#include <windows.h>
#include <process.h>
#include <stdio.h>
#include <conio.h>
// vordefinierte Werteliste
#define ESC 27 // Escape (ASCII 27)
#define RIGHT 333 // Pfeil rechts (256 + Scancode 77)
#define LEFT 331 // Pfeil links (256 + Scancode 75)
#define UP 328 // Pfeil oben (256 + Scancode 72)
#define DOWN 336 // Pfeil unten (256 + Scancode 80)
#define UPRIGHT 1000 // 4 frei definierte Werte > 511
#define UPLEFT 1001
#define DOWNRIGHT 1002
#define DOWNLEFT 1003
void __cdecl Fn_GetKey(void *const pInt); // Prototyp der Threadfunktion
int main(void)
{
int iInput = 0; // Wert wird von der Threadfunktion geändert
char szOutput[3] = "\x0f"; // Startzeichen
// Threadfunktion aufrufen, Zeiger auf iInput wird übergeben
if (_beginthread((void(*)(void*))Fn_GetKey, 0, (void*)&iInput) == ((uintptr_t)(intptr_t)-1))
return EXIT_FAILURE; // wenn Thread nicht erstellt werden konnte, raus hier
while (iInput != ESC) // Endlosschleife bis Escape
{
switch(iInput)
{
case RIGHT:
strcpy(szOutput, "\x10");
break;
case LEFT:
strcpy(szOutput, "\x11");
break;
case UP:
strcpy(szOutput, "\x1e");
break;
case DOWN:
strcpy(szOutput, "\x1f");
break;
case UPRIGHT:
strcpy(szOutput, "\x1e\x10");
break;
case UPLEFT:
strcpy(szOutput, "\x1e\x11");
break;
case DOWNRIGHT:
strcpy(szOutput, "\x1f\x10");
break;
case DOWNLEFT:
strcpy(szOutput, "\x1f\x11");
}
printf("%s\n", szOutput); // Ausgabe
Sleep(200);
}
return EXIT_SUCCESS;
}
// Threadfunktion, Parameter *pInt ist Zeiger auf Speicherbereich von iInput
void __cdecl Fn_GetKey(void *const pInt)
{
int iKey = 0;
BYTE rgKeys[256];
do // Endlosschleife bis Escape
{
iKey = _getch(); // Warte auf Tastatureingabe
// Bei F- oder Pfeiltasten, gibt der erste Aufruf 0 oder 224 zurück
// Führe _getch() erneut aus um den Scancode aus dem Puffer zu lesen
// http://msdn.microsoft.com/en-us/library/aa299374(v=vs.60).aspx
if (iKey == 0 || iKey == 224)
iKey = 256 + _getch(); // 256 wird zwecks Unterscheidung zu ASCII Werten addiert
GetKeyState(0); // Diesen Aufruf verstehe ich selbst nicht, funktioniert aber nicht ohne.
GetKeyboardState(rgKeys); // Den Status aller Tasten in rgKeys speichern.
// Tastenkombinationen abfragen
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
if (rgKeys[VK_UP] & 0x80 && rgKeys[VK_RIGHT] & 0x80)
iKey = UPRIGHT;
else if (rgKeys[VK_UP] & 0x80 && rgKeys[VK_LEFT] & 0x80)
iKey = UPLEFT;
else if (rgKeys[VK_DOWN] & 0x80 && rgKeys[VK_RIGHT] & 0x80)
iKey = DOWNRIGHT;
else if (rgKeys[VK_DOWN] & 0x80 && rgKeys[VK_LEFT] & 0x80)
iKey = DOWNLEFT;
*((int*)pInt) = iKey; // Schreibe neuen Wert in den adressierten Speicherbereich
} while (iKey != ESC);
_endthread(); // Thread beenden
}
Ich hab mich noch mal kurz mit der ursprünglichen Frage beschäftigt.
Bei mir funktioniert es letztlich mit der Funktion GetGUIThreadInfo().
Grüße
rubberman
Bei mir funktioniert es letztlich mit der Funktion GetGUIThreadInfo().
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
GUITHREADINFO gti; // http://msdn.microsoft.com/en-us/library/windows/desktop/ms632604(v=vs.85).aspx
HWND hwndMe = GetConsoleWindow(); // eigenes Fensterhandle
memset(>i, 0, sizeof(gti)); // Speicherbereich der Struktur von Datenmüll befreien
gti.cbSize = sizeof(gti); // Größe der Struktur muss laut Doku festgelegt werden
for (;;) // Endlosschleife
{
GetGUIThreadInfo(0, >i); // Struktur mit Daten füllen
// Wenn die Member hwndActive und hwndFocus dem eigenen Fensterhandle entsprechen,
// solltest du davon ausgehen können, dass du eingehende Tastatureingaben auf dein
// Fenster anwenden kannst.
if (gti.hwndActive == hwndMe && gti.hwndFocus == hwndMe)
puts("JA");
else
puts("NEIN");
Sleep(200);
}
return 0;
}
rubberman
Hallo Power-Poler.
Die Bedingung macht durchaus Sinn. Wie du in der Referenz zu _beginthread nachlesen kannst, gibt die Funktion den Wert -1L zurück, wenn sie fehlschlägt. Darum lasse ich oben im Code das Programm per
Du musst natürlich bedenken, was beim Kompilieren passiert. Jede *.cpp Datei (wieso eigentlich cpp, wenn du C Code schreibst?) wird separat zu einer Objektdatei kompiliert. Erst der Linker macht aus den einzelnen Objektdateien die *.exe. Im Normalfall hat der Compiler also immer nur eine Quelldatei im Auge und versucht den Code darin zu optimieren.
Ergo: Wenn du die Mainfunktion von den darin aufgerufenen Funktionen trennst, mag das für dich übersichtlicher werden, den Compiler beschneidest du aber damit in seiner Fähigkeit den Gesamtcode zu optimieren. Der Zugewinn an Übersichtlichkeit ist marginal, der Performanceverlust deines Programms kann dagegen oft überwiegen. Einfach alle unterschiedlichsten Funktionen in ein separates Paar Quell- und Headerdateien zu packen macht im Zweifelsfall keinen Sinn. Sinnvoll wäre allerdings die Präprozessoranweisungen (wie
Bei großen Projekten solltest du schon trennen, um den Überblick nicht zu verlieren. Dann aber so, dass es sinnvoll wird. Bspw. alle Funktionen und Strukturen, die einem bestimmten Themenzweck dienen, zusammen mit denen, die evtl. von diesen aufgerufen werden, zusammenfassen.
Grüße
rubberman
Die Bedingung macht durchaus Sinn. Wie du in der Referenz zu _beginthread nachlesen kannst, gibt die Funktion den Wert -1L zurück, wenn sie fehlschlägt. Darum lasse ich oben im Code das Programm per
return EXIT_FAILURE;
enden, sobald dieser Fall eintritt. Wenn die Funktion in deinem Fall 48 zurückgibt, ist also alles in Ordnung. Was folgt denn bei dir auf diese Bedingung?Zitat von @Power-Poler:
Kann natürlich sein, das mein Denkfehler dort liegt, das ich überhaupt versuche das ganze voneinander zu trennen.
Geschmackssache.Kann natürlich sein, das mein Denkfehler dort liegt, das ich überhaupt versuche das ganze voneinander zu trennen.
Du musst natürlich bedenken, was beim Kompilieren passiert. Jede *.cpp Datei (wieso eigentlich cpp, wenn du C Code schreibst?) wird separat zu einer Objektdatei kompiliert. Erst der Linker macht aus den einzelnen Objektdateien die *.exe. Im Normalfall hat der Compiler also immer nur eine Quelldatei im Auge und versucht den Code darin zu optimieren.
Ergo: Wenn du die Mainfunktion von den darin aufgerufenen Funktionen trennst, mag das für dich übersichtlicher werden, den Compiler beschneidest du aber damit in seiner Fähigkeit den Gesamtcode zu optimieren. Der Zugewinn an Übersichtlichkeit ist marginal, der Performanceverlust deines Programms kann dagegen oft überwiegen. Einfach alle unterschiedlichsten Funktionen in ein separates Paar Quell- und Headerdateien zu packen macht im Zweifelsfall keinen Sinn. Sinnvoll wäre allerdings die Präprozessoranweisungen (wie
#define ...
) und die Funktionsprototypen in eine Headerdatei zu bringen. Das Includieren dieses Headers lässt den Compiler den Code des Headers an dieser Stelle einlesen (so, als würde er dort geschrieben stehen). Das erhöht die Übersichtlichkeit und behindert den Compiler in keinem Fall.Bei großen Projekten solltest du schon trennen, um den Überblick nicht zu verlieren. Dann aber so, dass es sinnvoll wird. Bspw. alle Funktionen und Strukturen, die einem bestimmten Themenzweck dienen, zusammen mit denen, die evtl. von diesen aufgerufen werden, zusammenfassen.
Grüße
rubberman
Zitat von @Power-Poler:
Ich hoffe ja noch (keine Ahnung ob es klappt) später sobald das ganze doch größer wird, und ich c++ Funktionen brauche, einfach den Compiler anzuweisen in c++ zu kompilieren.
Umgekehrt wird ein Schuh draus. VS kompiliert standardmäßig als C++, wenn du nicht explizit in den Projekteigenschaften einstellst, dass als C kompiliert werden soll. In dem Fall zieht VS aber den Uralt - C89 - Standard an. Ergo: VS ist nicht besonders gut geeignet um C zu lernen.Ich hoffe ja noch (keine Ahnung ob es klappt) später sobald das ganze doch größer wird, und ich c++ Funktionen brauche, einfach den Compiler anzuweisen in c++ zu kompilieren.
BTW Wenn du C++ Code schreiben willst, gewöhne dir C besser gar nicht erst an. Das versaut den Stil. Da spreche ich aus eigener Erfahrung. Ich bin so auf C und die prozedurale Schreibweise geprägt, dass ich wohl nie behaupten werde, einigermaßen vernünftiges C++ zu schreiben. Die beiden Sprachen sind unterschiedlicher als du denkst, auch wenn C aus Kompatibilitätsgründen fast vollständig in C++ aufgeht.
EDIT:
Ahh, da liegt mein Problem.
Hehe. Noch deutlicher hätte ich es auch wirklich nicht schreiben können Ahh, da liegt mein Problem.
Grüße
rubberman