Zum Inhalt springen

Empfohlene Beiträge

Geschrieben

hi,

wie frage ich ab ob eine taste gedrückt gehalten wird?

Ich hab eine Schleife mit

while(_kbhit()== 0)
wenn jetzt jemand eine taste gedrückt hält bekomme ich probleme und es passiert nichts mehr in der Schleife kommt erstmal folgendes:
tmp = _getch(); 

if(_kbhit() == 1) 

{

	if(tmp != -32)

	{

		while(_kbhit() == 1) 

	        {

		      _getch();

		}

	}


}

das sorgt nur dafür, das wenn andere Tasten gleichzeitig gedrückt werden, diese sozusagen ignoriert werden, im rest der Schleife sind nur noch if-abfragen...

Zusagen ist noch, das man sich nur mit den Pfeiltasten nach oben und unten bewegen kann!

Woran liegt das jetzt das dann nichts mehr passiert, er scheint dann zu hängen, da er nicht mehr auf Eingaben reagiert, wie kann ich das jetzt beheben??

MfG Artery

Geschrieben

Es gibt Tasten bzw. auch Tastenkombinationen, denen kein Ascii-/Ansi-Code zugewiesen wurde (berühmtestes Beispiel hierfür sind wohl die Pfeiltaste ). Funktionen wie deine geben in solchen Fällen Sondercodes zurück. Ob diese dann korrekt ausgewertet werden (können) ist dann halt die Frage.

Schau mal dazu z.B. hier bzw zu dem Forenbereich hier.

Vielleicht hilft dir das ja weiter.

Geschrieben

:(

Ich habe es schon implementiert, das man sich mit den Pfeiltasten bewegen kann, das ist ja nicht das Problem :D

Sondern wenn ich jetzt z.b "Pfeiltaste nach unten" gedrückt halte, macht er noch kurz so weiter wie er sollte und ihrgendwann harkt er dann und macht nichts mehr!

Geschrieben (bearbeitet)

Wenn jetzt jemand 2 oder mehr tastengleichzeitig drückt kam es zu problemen, damit werden einfach alle anderen Tasten aus dem inbuffer genommen.

was evt noch von interesse wäre ist das:

So ungefähr sieht die Schleife aus, das unwichtige hab ich rausgelassen

while(1)

{

	while(_kbhit()== 0)

	{			

		tmp = _getch();

		if(_kbhit() == 1) 

		{

		      if(tmp != -32)

		     {

		                while(_kbhit() == 1)

		                {

			                _getch();

                                }

                     }

		}


               if()

               {

                          .......

                }


               else if(tmp == -32)

               {

	                 tmp2 = _getch();

	                 if(tmp == -32 && tmp2 == 72 || tmp == -32 && tmp2 == 80)

               {

	}


}

Edit: was mir noch einfällt er springt immer in eine Funktion in einer anderen Quelldatei, wenn die Pfeiltasten gedrückt wurden, könnte es ein das ert deswegen iwann hängt?

Bearbeitet von Artery
Geschrieben

Steckt da irgendeine Planung dahinter, oder ist der Code durch Ausprobieren entstanden?

Wenn du nicht weißt, wo und warum es hängt, wie kannst du dann beurteilen, was "unwichtig" ist und daher weggelassen werden kann?

Geschrieben

Der code ist deswegen unwichtig, weil er nur greift, wenn andere Tasten gedrückt werden deswegen hab ich das weggelassen, weil es nicht eintritt!

Aber ich kann gerne den ganzen code posten wenn du willst:

while(1)

	{

		while(_kbhit()== 0) // Die Schleife greift, wenn eine Taste gedrückt wurde

		{

			i = 0;

			sprintf(Profilnameraw,"<<<<<<<<<<<<<<<");


			tmp = _getch(); // Das erste Zeichen des Puffer wird genommen und in tmp geschrieben


			if(tmp == 27) // Wird escape gedrückt, wird das Programm sofort beendet

			{

				exit(1);

			}


			if(_kbhit() == 1) // Sollte immer noch eine Taste gedrückt sein, das heißt, das entweder Sie noch ein Vorzeichen hat, oder mehrere Tasten gedrückt wurden, springt er in die If-Abfrage

			{


				if(tmp != -32) // Wenn es sich nicht um das Vorzeichen -32 handelt soll er die While-Schleife ausführen

				{

					while(_kbhit() == 1) // Die While-Schleife leert den Puffer bis keine Eingabe mehr vorhanden ist

					{

						_getch();

					}

				}


			}


			if(ButtonCrsLoc == 0 && tmp == 13)

			{

				Optionen_Menü_main();

			}

			else if(VoidProfil == true && tmp == 'e') // Wenn der 'Cursor' gerade auf einem leeres Profil zeigt, und 'e' gedrückt wurde, dann wird in das if gesprugen

			{

				Text_Builder("                                                                                                                                                                                             ", ic::FG_LIGHTBLUE, 3, 12, 9, 12, 1, 24, 5, 24, 0, false);

				Text_Builder("Bitte geben Sie den Namen des Profils ein und bestätigen Sie ihre Eingabe mit Enter. Der Name darf nicht die Zeichen '<' und '>' beinhalten und darf nur 15 Zeichen lang sein!", ic::FG_LIGHTBLUE, 3, 12, 9, 12, 1, 24, 5, 24, 0, false);

				Text_Builder("              ", ic::FG_LIGHTBLUE,5,12, 7,12,YWert[ButtonCrsLoc],24, NULL, NULL, 30, true);

				SetCursor(5,12,0,YWert[ButtonCrsLoc],24,true,true);


				Profil_Menü_Button_Namen_ändern(YWert,ButtonCrsLoc,edit_tmp,i,i2,Profile,Profilnameraw,VoidProfil,ProfilText);


			}

			else if(VoidProfil == false && tmp == 'e' || VoidProfil == false && tmp == 'd' || VoidProfil == false && tmp == 13)

			{

				if(tmp == 'd')

				{

					while(_kbhit() == 1) // Der Puffer wird geleert

					{

						_getch();

					}


					Text_Builder("                                                                                                                                                                                             ", ic::FG_LIGHTBLUE, 3, 12, 9, 12, 1, 24, 5, 24, 0, false);

					Text_Builder("Möchten Sie wirklich dieses Profil löschen? Zum bestätigen drücken Sie 'enter', wenn nicht 'escape'!", ic::FG_LIGHTBLUE, 3, 12, 9, 12, 1, 24, 5, 24, 0, false);


					while(_kbhit() == 0)

					{

						edit_tmp = _getch();


						while(_kbhit() == 1)

						{

							_getch();

						}


						if(edit_tmp == 27)

						{

							sprintf(ProfilText, "Dies ist das Profil von: %s , Sie können dieses nun löschen 'd', editieren 'e' oder betreten mit 'enter'",Profile[ButtonCrsLoc-1].Profil_Name);

							Text_Builder("                                                                                                                                                                                             ", ic::FG_LIGHTBLUE, 3, 12, 9, 12, 1, 24, 5, 24, 0, false);

							Text_Builder(ProfilText, ic::FG_LIGHTBLUE, 3, 12, 9, 12, 1, 24, 5, 24, 0, false);

							break;

						}

						else if(edit_tmp == 13)

						{

							i = 0;


							while(i != 15)

							{

								Profile[(ButtonCrsLoc-1)].Profil_Name[i] = '\0';

								i++;

							}


							sprintf(Profile[(ButtonCrsLoc-1)].Profil_Name, "<LEER>");


							ProfileVTPro = fopen("Profile.VTPro", "wb");


							fwrite(Profile,sizeof(struct ProfilStruct),6,ProfileVTPro);


							fclose(ProfileVTPro);


							SetCursor(5,12,0,YWert[ButtonCrsLoc],24,false,true);

							std::cout << " ";

							Text_Builder("              ", ic::FG_LIGHTBLUE,5,12, 7,12,YWert[ButtonCrsLoc],24, NULL, NULL, 30, true);


							Text_Builder(Profile[(ButtonCrsLoc-1)].Profil_Name, ic::FG_LIGHTBLUE,5,12,7,12,YWert[ButtonCrsLoc],24, NULL, NULL, 30, true);


							Text_Builder("                                                                                                                                                                                             ", ic::FG_LIGHTBLUE, 3, 12, 9, 12, 1, 24, 5, 24, 0, false);

							Text_Builder("Dieses Profil ist leer, Sie können ein neues erstellen, drücken Sie dazu 'e'", ic::FG_LIGHTBLUE, 3, 12, 9, 12, 1, 24, 5, 24, 0, false);

							VoidProfil = true;

							break;

						}

					}

				}

				else if(tmp == 'e')

				{

					Text_Builder("                                                                                                                                                                                             ", ic::FG_LIGHTBLUE, 3, 12, 9, 12, 1, 24, 5, 24, 0, false);

					Text_Builder("Bitte geben Sie den Namen des Profils ein und bestätigen Sie ihre Eingabe mit Enter. Der Name darf nicht die Zeichen '<' und '>' beinhalten und darf nur 15 Zeichen lang sein!", ic::FG_LIGHTBLUE, 3, 12, 9, 12, 1, 24, 5, 24, 0, false);

					Text_Builder("              ", ic::FG_LIGHTBLUE,5,12, 7,12,YWert[ButtonCrsLoc],24, NULL, NULL, 30, true);

					SetCursor(5,12,0,YWert[ButtonCrsLoc],24,true,true);

					Profil_Menü_Button_Namen_ändern(YWert,ButtonCrsLoc,edit_tmp,i,i2,Profile,Profilnameraw,VoidProfil,ProfilText);

				}

				else if(tmp == 13)

				{

					exit(1);

				}

			}

			else if(tmp == -32) // Wenn eine Taste mit dem Vorzeichen -32 , z.B. eine Pfeiltaste, springt er in das else if

			{

				tmp2 = _getch();

				if(tmp == -32 && tmp2 == 72 || tmp == -32 && tmp2 == 80)

				{

					tmp = tmp2;


					if(tmp == 80)

					{

						if(ButtonCrsLoc == 6)

						{

							ArrowBuilder(3,12,YWert[ButtonCrsLoc],24,true,0);

							ButtonCrsLoc = 0;

							ArrowBuilder(3,12,YWert[ButtonCrsLoc],24,false,0);

						}

						else

						{

							ArrowBuilder(3,12,YWert[ButtonCrsLoc],24,true,0);

							ButtonCrsLoc = ButtonCrsLoc + 1;

							ArrowBuilder(3,12,YWert[ButtonCrsLoc],24,false,0);

						}

					}

					if(tmp == 72)

					{

						if(ButtonCrsLoc == 0)

						{

							ArrowBuilder(3,12,YWert[ButtonCrsLoc],24,true,0);

							ButtonCrsLoc = 6;

							ArrowBuilder(3,12,YWert[ButtonCrsLoc],24,false,0);

						}

						else

						{

							ArrowBuilder(3,12,YWert[ButtonCrsLoc],24,true,0);

							ButtonCrsLoc = ButtonCrsLoc - 1;

							ArrowBuilder(3,12,YWert[ButtonCrsLoc],24,false,0);

						}

					}

					if(ButtonCrsLoc == 0)

					{

						Text_Builder("                                                                                                                                                                                             ", ic::FG_LIGHTBLUE, 3, 12, 9, 12, 1, 24, 5, 24, 0, false);

						Text_Builder("Öffnet das Optionenmenü! (enter)", ic::FG_LIGHTBLUE, 3, 12, 9, 12, 1, 24, NULL, NULL, 0, true);

					}

					else if(Profile[ButtonCrsLoc-1].Profil_Name[0] == '<')

					{


						Text_Builder("                                                                                                                                                                                             ", ic::FG_LIGHTBLUE, 3, 12, 9, 12, 1, 24, 5, 24, 0, false);

						Text_Builder("Dieses Profil ist leer, Sie können ein neues erstellen, drücken Sie dazu 'e'", ic::FG_LIGHTBLUE, 3, 12, 9, 12, 1, 24, 5, 24, 0, false);

						VoidProfil = true;

					}

					else if(Profile[ButtonCrsLoc-1].Profil_Name != "<LEER>")

					{


						sprintf(ProfilText, "Dies ist das Profil von: %s , Sie können dieses nun löschen 'd', editieren 'e' oder betreten mit 'enter'",Profile[ButtonCrsLoc-1].Profil_Name);

						Text_Builder("                                                                                                                                                                                             ", ic::FG_LIGHTBLUE, 3, 12, 9, 12, 1, 24, 5, 24, 0, false);

						Text_Builder(ProfilText, ic::FG_LIGHTBLUE, 3, 12, 9, 12, 1, 24, 5, 24, 0, false);


						VoidProfil = false;

					}

				}

			}		

		}

	}

So das ist die gesamte Schleife...

Ich hoffe ihr könnt damit was anfangen!

MfG Artery

Geschrieben

Also ich habe mir den Quellcode jetzt nicht ganz durchgelesen (grad keine Zeit für), aber in dem Beispiel was ich gesehen hatte, war ein Timer drin, so dass nicht durchgehend abgefragt wurde, sondern Abfrage, x Millisekunden Pause und dann erst die nächste Abfrage.

Eventuell überlädt da ja irgendetwas, oder aber die CPU-Last geht so weit hoch, dass nichts anderes mehr gemacht wird bei dir. (Nur eine Vermutung / Überlegung)

Geschrieben

Timer? Wo meinst du genau?

Die einzigsten Befehle mit sleep > 0 werden nur dann ausgeführt, wenn man sich sowieso gerade nicht mit den Pfeiltasten bewegen kann..

Geschrieben

Ich weiß jetzt woran es liegt, und zwar daran

if(ButtonCrsLoc == 0)

					{

						Text_Builder("                                                                                                                                                                                             ", ic::FG_LIGHTBLUE, 3, 12, 9, 12, 1, 24, 5, 24, 0, false);

						Text_Builder("Öffnet das Optionenmenü! (enter)", ic::FG_LIGHTBLUE, 3, 12, 9, 12, 1, 24, NULL, NULL, 0, true);

					}

					else if(Profile[ButtonCrsLoc-1].Profil_Name[0] == '<')

					{


						Text_Builder("                                                                                                                                                                                             ", ic::FG_LIGHTBLUE, 3, 12, 9, 12, 1, 24, 5, 24, 0, false);

						Text_Builder("Dieses Profil ist leer, Sie können ein neues erstellen, drücken Sie dazu 'e'", ic::FG_LIGHTBLUE, 3, 12, 9, 12, 1, 24, 5, 24, 0, false);

						VoidProfil = true;

					}

					else if(Profile[ButtonCrsLoc-1].Profil_Name != "<LEER>")

					{


						sprintf(ProfilText, "Dies ist das Profil von: %s , Sie können dieses nun löschen 'd', editieren 'e' oder betreten mit 'enter'",Profile[ButtonCrsLoc-1].Profil_Name);

						Text_Builder("                                                                                                                                                                                             ", ic::FG_LIGHTBLUE, 3, 12, 9, 12, 1, 24, 5, 24, 0, false);

						Text_Builder(ProfilText, ic::FG_LIGHTBLUE, 3, 12, 9, 12, 1, 24, 5, 24, 0, false);


						VoidProfil = false;

					}
Deswegen hängt er, denn hinter
Text_Builder(ProfilText, ic::FG_LIGHTBLUE, 3, 12, 9, 12, 1, 24, 5, 24, 0, false);
versteckt sich ne etwas umfangreiche funktion und die ist der Grund dafür :/ Die Funktion:
 void Text_Builder(char Text[], ic::TextColor color, int X10, int X01, int X20, int X02, int Y10, int Y01,int YE10, int YE01, int sleeptime, bool Button) // Die Funktion gibt einen Text an der angegeben Stelle aus und unterteilt ihn "intelligent" in Zeilen. Die Funktion "erstellt" Rechtecke mit den gewünschten Eckdaten. Übergeben wird: Der Text, sowie die Textfarbe. X-Anfangs-, X-End, Y-Anfangswertw als 'Brüche' übergeben, z.b. X10 und X01 ergeben 2/12, das ist der Anfangswert und der Bruch aus X20, X02 ist der Bruch für den Endwert, ggf. werden auch die Y-Endwerte als Bruch übergeben. Dann wird noch die sleeptime übergeben, d.h. wie lang pause zwischen den Einzelnenzeichen gesetzt soll. Und auch ob es sich um einen Button handelt, da dann eine kleine Änderung an dem Y-Wert vorgenommen werden muss.

{


	if(YE10 != NULL && YE01 != NULL) //Sollte YE10, sowie YE01 gleich "NULL" sein, das bedeutet, der Text ist nur eine Zeile lang, springt das Programm in das else, wenn beide einen Wert haben, also der Text länger als eine Zeile ist, geht es in der If-Bedingung weiter

	{

		int Textrestlen = strlen(Text);

		int Zeilen = 1; // Steht von Anfang an auf 1, da sowieso mindestens eine Zeile gebraucht wird

		int iadd;

		int k = 0;

		int counter2 = 0;

		int counter = 0;


		int* Zeileninhalt = NULL; //Zeiger (Adresse) für späteres dynamisches Array sichern

		int* Zeilenreduce = NULL;




		while(Textrestlen >= ((DEF_WNDSIZEX * X10/X01) - (DEF_WNDSIZEX *X20/X02)) *(-1)) // Rechnet die Anzahl der benötigten Zeilen, sowie die Textrestlänge (Wie viele Zeichen in eine neue, nicht komplett befüllte Zeile kommen)

		{

			Textrestlen = Textrestlen - ((DEF_WNDSIZEX * X10/X01) - (DEF_WNDSIZEX *X20/X02)) *(-1);

			Zeilen++;

		}


		Zeileninhalt = new int [Zeilen]; //Anlegen eines dynamischen Arrays


		Zeilenreduce = new int [Zeilen];


		counter2 = ((DEF_WNDSIZEX * X10/X01) - (DEF_WNDSIZEX *X20/X02)) *(-1);


		for(int i = 1; i <= Zeilen;i++) // Berechnung der Anzahl der Zeichen in einer Zeile

		{

			if((counter + ((DEF_WNDSIZEX * X10/X01) - (DEF_WNDSIZEX *X20/X02)) *(-1)) <= strlen(Text))

			{	

				for(int j = counter2; ;j--)

				{

					if(Text[j] == 32 || Text[j] == 44 || Text[j] == 46 || Text[j] == 33) // Bei Punkten, Kommata, Ausrufezeichen und Leerzeichen, kann ein Zeilenumbruch entstehen

					{

						Zeileninhalt[k] = j - counter;

						Zeilenreduce[k] = j - counter;

						counter = j;

						counter2 = j + ((DEF_WNDSIZEX * X10/X01) - (DEF_WNDSIZEX *X20/X02)) *(-1);

						k++;

						break;

					}

				}		

			}

			else

			{

				Zeileninhalt[k] = strlen(Text) - counter;

				Zeilenreduce[k] = strlen(Text) - counter;

			}

		}		



		counter = 0;

		k = 0;


		ic::con.setTextColor(color); // Setzt die Textfarbe auf die Übergebene


		for(int i = 0; i <= Zeilen ; i++) // Rechnet iadd aus und "springt" sozusagen in die nächste Zeile

		{

			iadd = ( ((DEF_WNDSIZEX * X10/X01) - (DEF_WNDSIZEX *X20/X02)) - (Zeileninhalt[i]+1)); // In "iadd" steht die Größe des Abstandes zu den Rändern um den Text zu zentrieren (Ist der Abstand ungerade entsteht hier eine kleine ungenauigkeit!)

			if(iadd % 2 == 0)

			{

				iadd = iadd /2;

			}

			else

			{

				iadd= (iadd -1) /2;

			}


			if(i != 0)

			{

				counter = counter + Zeileninhalt[k];

				k++; 

			}






			for(int j = DEF_WNDSIZEX * X20/X02 + 1 + iadd; j <= DEF_WNDSIZEX * X10/X01 - iadd; j++) // Gibt den Text aus

			{

				if(Text[(Zeileninhalt[k]-Zeilenreduce[k]+counter)] == ' ' && j == DEF_WNDSIZEX * X20/X02 + 1 + iadd) // Sollte das Erste Zeichen der neuen Zeile ein Leerzeichen sein, wird es weggelassen

				{

					j++;

					Zeilenreduce[k]--;

				}


				if(Zeilenreduce[k] == 0 && Text[(Zeileninhalt[k]-Zeilenreduce[k]+counter)] == ' ' ) //Ist das letzte Zeichen einer Zeile ein Leerzeichen wird es weggelassen

				{


					break;

				}


				ic::con.setCurPos (j, DEF_WNDSIZEY * (Y10+k)/Y01 + 1);			


				if(Text[(Zeileninhalt[k]-Zeilenreduce[k]+counter)] == 'ö') // Umlaute werden korrekt umgewandelt

				{

					std::cout << char(148);

				}

				if(Text[(Zeileninhalt[k]-Zeilenreduce[k]+counter)] == 'ü')

				{

					std::cout << char(129);

				}

				if(Text[(Zeileninhalt[k]-Zeilenreduce[k]+counter)] == 'ä')

				{

					std::cout << char(132);

				}

				if(Text[(Zeileninhalt[k]-Zeilenreduce[k]+counter)] == 'ß')

				{

					std::cout << char(225);

				}

				if(Text[(Zeileninhalt[k]-Zeilenreduce[k]+counter)] == 'Ö')

				{

					std::cout << char(153);

				}

				if(Text[(Zeileninhalt[k]-Zeilenreduce[k]+counter)] == 'Ä')

				{

					std::cout << char(142);

				}

				if(Text[(Zeileninhalt[k]-Zeilenreduce[k]+counter)] == 'Ü')

				{

					std::cout << char(154);

				}

				else

				{

					std::cout << Text[(Zeileninhalt[k]-Zeilenreduce[k]+counter)];

				}	


				Zeilenreduce[k]--;


				Sleep(sleeptime);


			}

		}


		delete[] Zeileninhalt; // Speicherplatz wiederfreigeben um Memory leaks zu vermeiden

		delete[] Zeilenreduce;

		Zeileninhalt = NULL;

		Zeilenreduce = NULL;


	}

	else

	{

		int k=0;

		int iadd;


		ic::con.setTextColor(color); // Setzt die Textfarbe auf die übergebene Farbe


		iadd = ( (DEF_WNDSIZEX * X10/X01) - (DEF_WNDSIZEX *X20/X02) - strlen(Text)) / 2; // In "iadd" steht die Größe des Abstandes zu den Rändern um den Text zu zentrieren (Ist der Abstand ungerade entsteht hier eine kleine ungenauigkeit!)



		for(int i = DEF_WNDSIZEX * X20/X02 + 1 + iadd; i <= DEF_WNDSIZEX * X10/X01 - iadd; i++) // Gibt den Text aus

		{



			if(Button == true) // Da die Texte für "Buttons" nicht zentriert sind, und die in normalen Fenster es schon seien sollen, muss hier nochmal extra abgefragt werden, um was es sich handelt

			{

				ic::con.setCurPos (i, DEF_WNDSIZEY * Y10/Y01 + 1);

			}

			else

			{

				ic::con.setCurPos (i, DEF_WNDSIZEY * Y10/Y01);

			}


			if(k == (strlen(Text)))

			{

				break;

			}


			if(Text[k] == 'ö') // Umlaute werden korrekt umgewandelt

			{

				std::cout << char(148);

			}

			if(Text[k] == 'ü')

			{

				std::cout << char(129);

			}

			if(Text[k] == 'ä')

			{

				std::cout << char(132);

			}

			if(Text[k] == 'ß')

			{

				std::cout << char(225);

			}

			if(Text[k] == 'Ö')

			{

				std::cout << char(153);

			}

			if(Text[k] == 'Ä')

			{

				std::cout << char(142);

			}

			if(Text[k] == 'Ü')

			{

				std::cout << char(154);

			}

			else

			{

				std::cout << Text[k];

			}


			k++;

			Sleep(sleeptime);

		}


	}



}

Wäre schön wenn ihr nochmal drüber guckt, vielleicht krieg ich die Funktion noch so angepasst das es klappt :/

MfG Artery

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...