Keystroke Abfrage?



  • Hey,
    Ich bin noch ein ziemlicher C++ neuling und arbeite gerade an dem ersten Programm, dass für mich wirklich einen Sinn ergibt. Es ist ein Timer für ein Spiel 😉

    Hier ist jetzt mal der code ( Ich weiß , dass er noch stark verbessert werden kann 😃 )

    #include <iostream>
    #include <Windows.h>
    #include <conio.h>
    #include <ctime>
    
    using namespace std;
    
    int main()
    {
    
    	int Sekunden = clock();
    	int oBlueTmr = 0;
    	int tBlueTmr = 0;
    
    	char hotkey;
    
    	if (/* Hier brauche ich dann irgendeine Tastenabfrage die an jedem Zeitpunkt des Programms geändert werden kann */)
    	{
    		cout << "Der Timer fuer ihren Blue wurde gestellt" << endl << endl;
    		for (;;)
    		{
    
    			if (Sekunden == 60000)
    			{
    				Sekunden - 60000;
    
    				oBlueTmr++;
    			}
    
    			if (oBlueTmr == 1)
    			{
    				cout << "Ihr blue wurde gespawned!" << endl;
    				Beep(800, 200);
    			}
    
    		}
    	}
    
    	else if (/* Hier brauche ich dann irgendeine Tastenabfrage die an jedem Zeitpunkt des Programms geändert werden kann */)
    	{
    		cout << "Der Timer fuer den gegnerischen Blue wurde gestellt!" << endl << endl;
    		for (;;)
    		{
    
    			if (Sekunden == 60000)
    			{
    				Sekunden - 60000;
    
    				tBlueTmr++;
    			}
    
    			if (tBlueTmr == 1)
    			{
    				cout << "Der gegnerische blue wurde gespawned!" << endl;
    				Beep(800, 200);
    			}
    
    		}
    	}
    
    	return 0;
    
    }
    

    Ich möchte jetzt, dass wenn ich ein Taste drücke, sich einer der beiden Timer starte. Jedoch sollte das auch parallel laufen können.
    D.H. Wenn ich Taste 'o' drücke, soll der erste Timer gestartet werden und wenn ich die Taste 't' drücke, soll er während der andere Timer noch läuft auch den anderen Timer starten... Irgendwelche Lösungsvorschläge? 😛 😕



  • Geht mit Standardmitteln nicht. Warum gleich sowas schwere zum starten ? 🙄

    Du must einen globalen Hotkey definieren (dein Programm bekomm sonst logischerweise keinen Input wenn es nicht aktiv ist), auf Windows z.B. so:

    #include <iostream>
    #include <Windows.h>
    
    using namespace std; 
    
    int main()
    {
    	RegisterHotKey(0, 42, 0, 'O');
    	RegisterHotKey(0, 43, 0, 'T');
    
    	MSG message;
    	while(GetMessage(&message, NULL, 0, 0))
    	{
    		TranslateMessage(&message);
    		DispatchMessage(&message);
    
    		switch(message.message)
    		{
    			case WM_HOTKEY:
    				switch(message.wParam)
    				{
    					case 42:
    						cout << "O Pressed" << endl;
    						break;
    					case 43:
    						cout << "T Pressed" << endl;
    						break;
    				}
    				break;
    		}
    	}
    	return 0;
    }
    

    Billiglösung für das Problem (keine Ahnung wie ich das großartig erklären soll):

    #include <iostream>
    #include <Windows.h>
    
    using namespace std; 
    
    int time1=0, time2=0;
    
    void ProcessMessages()
    {
    	MSG message;
    	while(PeekMessage(&message, 0, 0, 0, PM_REMOVE))
    	{
    		TranslateMessage(&message);
    		DispatchMessage(&message);
    
    		switch(message.message)
    		{
    			case WM_HOTKEY:
    				switch(message.wParam)
    				{
    					case 42:
    						time1 = 4000;
    						break;
    					case 43:
    						time2 = 4000;
    						break;
    				}
    				break;
    		}
    	}
    }
    
    int main()
    {
    	RegisterHotKey(0, 42, 0, 'O');
    	RegisterHotKey(0, 43, 0, 'T');
    
    	while(true)
    	{
    		ProcessMessages();
    
    		Sleep(1000);
    
    		if(time1 != 0)
    		{
    			time1 -= 1000;
    			if(time1 <= 0)
    			{
    				time1 = 0;
    				cout << "timer1 stopped!" << endl;
    			}
    		}
    
    		if(time2 != 0)
    		{
    			time2 -= 1000;
    			if(time2 <= 0)
    			{
    				time2 = 0;
    				cout << "timer2 stopped!" << endl;
    			}
    		}
    	}
    	return 0;
    }
    

    Wie du siehst ist das ganze nicht soo simpel, such dir lieber was anderes zum lernen. 😉



  • DarkShadow44 schrieb:

    Geht mit Standardmitteln nicht. Warum gleich sowas schwere zum starten ? 🙄

    Du must einen globalen Hotkey definieren (dein Programm bekomm sonst logischerweise keinen Input wenn es nicht aktiv ist), auf Windows z.B. so:

    #include <iostream>
    #include <Windows.h>
      
    using namespace std; 
    
    int main()
    {
    	RegisterHotKey(0, 42, 0, 'O');
    	RegisterHotKey(0, 43, 0, 'T');
    
    	MSG message;
    	while(GetMessage(&message, NULL, 0, 0))
    	{
    		TranslateMessage(&message);
    		DispatchMessage(&message);
    
    		switch(message.message)
    		{
    			case WM_HOTKEY:
    				switch(message.wParam)
    				{
    					case 42:
    						cout << "O Pressed" << endl;
    						break;
    					case 43:
    						cout << "T Pressed" << endl;
    						break;
    				}
    				break;
    		}
    	}
    	return 0;
    }
    

    Billiglösung für das Problem (keine Ahnung wie ich das großartig erklären soll):

    #include <iostream>
    #include <Windows.h>
      
    using namespace std; 
    
    int time1=0, time2=0;
    
    void ProcessMessages()
    {
    	MSG message;
    	while(PeekMessage(&message, 0, 0, 0, PM_REMOVE))
    	{
    		TranslateMessage(&message);
    		DispatchMessage(&message);
    
    		switch(message.message)
    		{
    			case WM_HOTKEY:
    				switch(message.wParam)
    				{
    					case 42:
    						time1 = 4000;
    						break;
    					case 43:
    						time2 = 4000;
    						break;
    				}
    				break;
    		}
    	}
    }
    
    int main()
    {
    	RegisterHotKey(0, 42, 0, 'O');
    	RegisterHotKey(0, 43, 0, 'T');
    
    	while(true)
    	{
    		ProcessMessages();
    
    		Sleep(1000);
    
    		if(time1 != 0)
    		{
    			time1 -= 1000;
    			if(time1 <= 0)
    			{
    				time1 = 0;
    				cout << "timer1 stopped!" << endl;
    			}
    		}
    
    		if(time2 != 0)
    		{
    			time2 -= 1000;
    			if(time2 <= 0)
    			{
    				time2 = 0;
    				cout << "timer2 stopped!" << endl;
    			}
    		}
    	}
    	return 0;
    }
    

    Wie du siehst ist das ganze nicht soo simpel, such dir lieber was anderes zum lernen. 😉

    Also ich verstehe das soweit eigentlich ganz gut 😃 Werde mich mal dransetzen und es ausprobieren. Vielen Dank für die Antwort!



  • DarkShadow44 schrieb:

    Geht mit Standardmitteln nicht. Warum gleich sowas schwere zum starten ? 🙄

    Du must einen globalen Hotkey definieren (dein Programm bekomm sonst logischerweise keinen Input wenn es nicht aktiv ist), auf Windows z.B. so:

    Wie du siehst ist das ganze nicht soo simpel, such dir lieber was anderes zum lernen. 😉

    Alsooo
    Ich habe hier jetzt schonmal einen kleinen Erfolg, aber das was dabei rauskommt hatte ich auch schon vorher mit einen wesentlich simpleren Weg ( indem ich hotkey = _getch(); gemacht habe) geklappt.

    Ich möchte ja auch, dass beide Timer gleichzeitig laufen können.
    Ich habe mir überlegt evtl nicht eine sondern 2 Keystroke abfragen zu machen!
    Eine regiert nur auf den einen Buchstaben und die andere eben auf den anderen.

    Wie kann ich das machen? 😕 Wenn das Programm vollständig ist, sollten es 6 abfragen sein also das Programm dient erstmal zu Testzwecken 😛

    Hier ist mal der code

    #include <iostream>
    #include <Windows.h>
    #include <conio.h>
    #include <ctime>
    
    using namespace std;
    
    int oBlueTmr = 0;
    int tBlueTmr = 0;
    
    void ProcessMessages()
    {
    	MSG message;
    	while (PeekMessage(&message, 0, 0, 0, PM_REMOVE))
    	{
    		TranslateMessage(&message);
    		DispatchMessage(&message);
    
    		switch (message.message)
    		{
    		case WM_HOTKEY:
    
    			if (message.wParam == 42)
    			{
    				cout << "Der Timer fuer ihren Blue wurde gestellt" << endl << endl;
    				while (oBlueTmr != 1)
    				{
    					int oSekunden = clock();
    
    					if (oSekunden > 10000)
    					{
    						cout << "Zahl über 10 sek\n";
    						oSekunden - oSekunden;
    					}
    					if (oSekunden == 10000)
    					{
    
    						oSekunden - oSekunden;
    
    						oBlueTmr++;
    					}
    
    					if (oBlueTmr == 1)
    					{
    						cout << "Ihr blue wurde gespawned!" << endl;
    						Beep(800, 200);
    					}
    
    				}
    			}
    
    			else if (message.wParam == 43)
    			{
    				cout << "Der Timer fuer den gegnerischen Blue wurde gestellt!" << endl << endl;
    				while ( tBlueTmr != 1)
    				{
    					int tSekunden = clock();
    					if (tSekunden > 10000)
    					{
    						tSekunden - tSekunden; 
    					}
    					if (tSekunden = 10000)
    					{
    						tSekunden - 10000;
    
    						tBlueTmr++;
    					}
    
    					if (tBlueTmr == 1)
    					{
    						cout << "Der gegnerische blue wurde gespawned!" << endl;
    						Beep(800, 200);
    					}
    
    				}
    			}
    
    			}
    			break;
    		}
    
    }
    
    int main()
    {
    
    	RegisterHotKey(0, 42, 0, 'O');
    	RegisterHotKey(0, 43, 0, 'T');
    
    	while (true)
    	{
    		ProcessMessages();
    
    	}
    
    	return 0;
    
    }
    


  • Aus diesem Beitrag schließe ich mal das du verstanden hast warum deine "Timer" nicht parralel ablaufen.
    Eine Lösung wären Threads

    Wenn du allerdings weiter mit RegisterHotKey und GetMessage arbeiten willst, solltest du beachten das die Message-Pump von Windows Threadpsezifisch ist, d.h. nur in dem Thread in dem du RegisterHotKey aufrufst kannst du auch mit GetMessage arbeiten (außer du gibst als Windowhandle ein Fenster eines anderen Threads an, aber ich denke nicht das es dass ist was du willst).
    Auch wenn du in deinem Beispiel keine Resourcen hast auf die beide Timer zugreifen, solltest du Wissen wie man verschiedene Threads synchronisiert und warum man das machen muss. Stichwort:Muetx wäre zumindest mit C++ Standard eine Möglichkeit.

    Ansonsten, wenn du viele solche Timer hast wäre ein Threadpool noch eine Idee.
    Auch solltest du dir überlegen ob du wirklich über HotKeys gehen willst, denn dadurch erhält dein Programm auch dann Input wenn es nicht den Focus hat. Also auch dann wenn es minimiert oder im Hintergrund ist. Für ein Spiel nicht unbedingt ideal.

    Hier mal ein Beispiel das du leicht selber erweitern können solltest. Ist jetzt allerdings speziell für Windows.

    #include <Windows.h>
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
    	PTP_POOL threadPool = CreateThreadpool(0);
    	PTP_WORK threadpoolWork = CreateThreadpoolWork([](PTP_CALLBACK_INSTANCE instance, PVOID data, PTP_WORK work) -> void {
    		cout<<"Timer O"<<endl;
    	}, 0,0);
    	PTP_WORK threadpoolWork2 = CreateThreadpoolWork([](PTP_CALLBACK_INSTANCE instance, PVOID data, PTP_WORK work) -> void {
    		cout<<"Timer T"<<endl;
    	}, 0,0);
    
    	char key = 0;
    	while(key != 'q'){
    		key = getchar();
    		if(key == 'o'){
    			SubmitThreadpoolWork(threadpoolWork);
    		}
    		if(key == 't'){
    			SubmitThreadpoolWork(threadpoolWork2);
    		}
    	}
    
    	WaitForThreadpoolWorkCallbacks(threadpoolWork, false);
    	WaitForThreadpoolWorkCallbacks(threadpoolWork2, false);
    	CloseThreadpoolWork(threadpoolWork);
    	CloseThreadpoolWork(threadpoolWork2);
    	CloseThreadpool(threadPool);
    
    	return 0;
    }
    

    DarkShadow44 schrieb:

    Wie du siehst ist das ganze nicht soo simpel, such dir lieber was anderes zum lernen. 😉

    Beherzige DarkShadows rat! Auch wenn du seinen Code wie du selber sagst verstanden hast, verstehen (im Sinne von fremden code lesen und dann sagen "so wird das also gemacht") ist bei weitem nicht alles.

    floorball



  • Auch solltest du dir überlegen ob du wirklich über HotKeys gehen willst, denn dadurch erhält dein Programm auch dann Input wenn es nicht den Focus hat. Also auch dann wenn es minimiert oder im Hintergrund ist. Für ein Spiel nicht unbedingt ideal.

    Ich denke genau das ist der Sinn der Sache. Dass das Programm im Hintergrund läuft, auf Knopfdruck nen Timer startet und dir Ereignisse aus einem bestehenden Spiel vorhersagt. (League of Legends hab ich Recht ? :p)

    Ich habe hier jetzt schonmal einen kleinen Erfolg, aber das was dabei rauskommt hatte ich auch schon vorher mit einen wesentlich simpleren Weg ( indem ich hotkey = _getch(); gemacht habe) geklappt.

    Jaja aber mit HotKeys nimmt das Programm auch den Tastendruck an wenn das Programm minimiert ist. Und genau DAS willst du doch oooder ?

    Betreffend Threads: Ich hab doch schon eine Lösung gepostet was die gleichzeitigkeit löst. Klar, die minimale Auflösung sind 1000ms, aber das kann man ja noch reduzieren (reicht aber ansich aus). Ansich könnte man jetzt hergehen und jeden Timer als neuen Thread starten, aber das wird noch um einiges schwerer.
    Dummy-code:

    void ThreadFuncTimer1() // aber bitte nur einmal auf einmal starten
    {
        Sleep(42000);
        cout << "timer1 ended!";
    }
    

    Mein Programm macht doch genau das was du willst oder etwa nicht ? 😕
    Es hat schon seinen Grund dass ich ich nur eine Schleife für alle Timer habe.



  • DarkShadow44 schrieb:

    Betreffend Threads: Ich hab doch schon eine Lösung gepostet was die gleichzeitigkeit löst. Klar, die minimale Auflösung sind 1000ms, aber das kann man ja noch reduzieren (reicht aber ansich aus).

    Beim erstem code verstehe ich nicht ganz wo da der timer ist 😃
    Wenn man die Ziffer '42' also o drückt wird einfach timer1 auf 4000 gesetzt oder? 😕



  • Oje, darum meinte ich dass es nichts zum anfangen ist..
    Beim registrieren der Hotkeys gebe ich ihnen die IDs 42 und 43, diese IDs werden verwendet um sie auseinanderzuhalten. Du kannst ja auch einen Hotkey der komplexer ist definieren (Shift+Strg+Alt+Z z.B.). Ich hätte als IDs auch 0 und 1 nehmen können, aber mit 42 und 43 sieht man schön den Unterschied. Mit dem char Code von 'O' und 'T' hat das nix zu tun, laut ASCII Tabelle ist der nämlich anders.

    Das gesamte Programm ist in einer Endlosschleife, die läuft so ab

    1. Nachrichten prüfen (ob Hotkey gedrückt wurde)
    2. 1000ms schlafen
    3. von den timern 1000 abziehen, wenn sie jetzt 0 sind ist der Timer abgelaufen. Logischerweise ist die minimale Auflösung 1000ms, und es ist nicht perfekt genau. Aber die Nachrichtenabfrage geht so flott, die paar Nanosekunden reißens nicht raus.

    Bei diesem Ansatz brauchst du
    a) keine Threads und hast
    b) keine das Programm blockierende Schleife

    Klar, man köntne es auch noch mit Threads lösen, aber wie gesagt das wird noch schwerer.

    Darum nochmal der Rat: Such dir was einfacheres, nicht gleich sowas zum Start! 😉



  • Jetzt habe ich es gecheckt und erfolgreich durchgeführt 🙂
    Danke für die Hilfe 👍



  • DarkShadow44 schrieb:

    Oje, darum meinte ich dass es nichts zum anfangen ist..
    Beim registrieren der Hotkeys gebe ich ihnen die IDs 42 und 43, diese IDs werden verwendet um sie auseinanderzuhalten. Du kannst ja auch einen Hotkey der komplexer ist definieren (Shift+Strg+Alt+Z z.B.). Ich hätte als IDs auch 0 und 1 nehmen können, aber mit 42 und 43 sieht man schön den Unterschied. Mit dem char Code von 'O' und 'T' hat das nix zu tun, laut ASCII Tabelle ist der nämlich anders.

    Das gesamte Programm ist in einer Endlosschleife, die läuft so ab

    1. Nachrichten prüfen (ob Hotkey gedrückt wurde)
    2. 1000ms schlafen
    3. von den timern 1000 abziehen, wenn sie jetzt 0 sind ist der Timer abgelaufen. Logischerweise ist die minimale Auflösung 1000ms, und es ist nicht perfekt genau. Aber die Nachrichtenabfrage geht so flott, die paar Nanosekunden reißens nicht raus.

    Bei diesem Ansatz brauchst du
    a) keine Threads und hast
    b) keine das Programm blockierende Schleife

    Klar, man köntne es auch noch mit Threads lösen, aber wie gesagt das wird noch schwerer.

    Darum nochmal der Rat: Such dir was einfacheres, nicht gleich sowas zum Start! 😉

    Jetzt habe ich noch EIN Problem 😃 😛
    Ich habe ein ähnliches Programm für ein anderes Spiel geschrieben, welches aufzeichnet wie oft ich die Tasten 'X' und 'Y' drücke. Diese Tasten kann ich nun aber nichtmehr in meinem Spiel verwenden 😡



  • DarkShadow44 schrieb:

    Oje, darum meinte ich dass es nichts zum anfangen ist..
    Beim registrieren der Hotkeys gebe ich ihnen die IDs 42 und 43, diese IDs werden verwendet um sie auseinanderzuhalten. Du kannst ja auch einen Hotkey der komplexer ist definieren (Shift+Strg+Alt+Z z.B.). Ich hätte als IDs auch 0 und 1 nehmen können, aber mit 42 und 43 sieht man schön den Unterschied. Mit dem char Code von 'O' und 'T' hat das nix zu tun, laut ASCII Tabelle ist der nämlich anders.

    Das gesamte Programm ist in einer Endlosschleife, die läuft so ab

    1. Nachrichten prüfen (ob Hotkey gedrückt wurde)
    2. 1000ms schlafen
    3. von den timern 1000 abziehen, wenn sie jetzt 0 sind ist der Timer abgelaufen. Logischerweise ist die minimale Auflösung 1000ms, und es ist nicht perfekt genau. Aber die Nachrichtenabfrage geht so flott, die paar Nanosekunden reißens nicht raus.

    Bei diesem Ansatz brauchst du
    a) keine Threads und hast
    b) keine das Programm blockierende Schleife

    Klar, man köntne es auch noch mit Threads lösen, aber wie gesagt das wird noch schwerer.

    Darum nochmal der Rat: Such dir was einfacheres, nicht gleich sowas zum Start! 😉

    Jetzt habe ich noch EIN Problem 😃 😛
    Ich habe ein ähnliches Programm für ein anderes Spiel geschrieben, welches aufzeichnet wie oft ich die Tasten 'X' und 'Y' drücke. Diese Tasten kann ich nun aber nichtmehr in meinem Spiel verwenden 😡



  • Das ist der Sinn von Hotkeys.

    Lösung:

    1. SetWindowsHookEx und die Message abfangen
    2. Gleich direkt eine Dll injecten
    3. GetAsyncKeyState (ganz böse)
    4. Die Input Nachricht über SendMessage oder so simulieren.

    Und nochmal der Rat: Such dir was einfacheres, nichts wo sich selbst erfahrenere Programmierer schwertun!



  • Oder such dir ne Bibliothek mit der das viel leichter und übersichtlicher verpackt ist, und zusätzlich auch noch "cross-plattform" ist, z.B. SFML

    Außer es soll unbedingt mit diesen windows funktionen direkt gemacht werden

    mfg


Log in to reply