Direct Input Tastatur Problem!!!



  • Hallo, in diesem BeispielCode wird gezeigt wie man Directinput(Tastatur) nutzt, aber dieser Code zeigt nur, wen eine taste gedrückt ist, und auch gedrückt gehalten wird.
    Ich möchte aber das so haben das wen man eine taste drückt, nur die schrieft einmal aufblinkt, sprich nur ein einmaliges signal gesendet wird, beim drück.
    Und nur nachdem losslassen der taste und wiederholtem drücken soll die schrift wieder aufblinken.
    Ich möchte den windowsnachrichtenverarbeitung net nutzen.
    Ich bedanke mich für Hilfe, mfg Gott der 2.
    cu

    #include <windows.h>
    #include <dinput.h>
    
    HWND CreateMainWindow(HINSTANCE hInstance);
    
    //Callback Funktion zur Nachrichtenbehandlung
    LRESULT CALLBACK WindowFunc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
    
    // DirectInput-Objekte initialisieren
    BOOL InitDirectInput(HINSTANCE hInst);
    
    // Objekte/Speicher freigeben
    void CleanUpDirectInput(void);
    
    // Fehlermeldung erzeugen
    BOOL Error(char* msg);
    
    // Eingaben behandeln
    void ProcessInput(void);
    
    // Das Fensterhandle
    HWND hWnd = 0;
    
    // Zeiger auf das DirectInput Interface
    LPDIRECTINPUT8 lpDI = NULL; 
    
    LPDIRECTINPUTDEVICE8 lpDIKeyboard = NULL;
    
    // Windows main-Funktion
    int WINAPI WinMain(HINSTANCE hInstance,      // Handle der Programminstanz
                       HINSTANCE hPrevInstance,  // Handle der letzten Instanz
                       LPSTR lpCmdLine,          // Kommandozeile
                       int nCmdShow)             // Art wie das Fenster angezeigt werden soll
    {   
        MessageBox(NULL,"Dieses Beispiel zeigt wie man ein DirectInput8-Objekt\n"
                        "anlegt und die Kontrolle über die Tastatur erhält.\n"
                        "Wenn die Tasten Links, Rechts, Oben, Unten, Control\n"
                        "oder Space gedrückt werden, wird dies angezeigt.\n",
                        "Beschreibung",MB_OK);
    
        // Fenster erzeugen und Handle speichern
        hWnd = CreateMainWindow(hInstance);
    
        // Wenn der Rückgabewert 0 ist, ist ein Fehler aufgetreten
        if(0 == hWnd)
        {
            return Error("Fehler beim Erzeugen des Fenster");
        }
    
        if(!InitDirectInput(hInstance))
        {
            return FALSE;
        }        
    
    	// Struktur, in der Informationen zur Nachricht gespeichert werden
        MSG msg;
    
        // Endlosschleife
    
        while(TRUE)
    	{    
            if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
            {
                if(msg.message == WM_QUIT)
                {
                    break;
                }
    
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
             // wenn keine Nachricht vorliegt, 
            else
            {
                // kann gezeichnet werden
                ProcessInput();
            }
        }
    
        // Rückgabewert an Windows
        return 0;
    }
    
    HWND CreateMainWindow(HINSTANCE hInstance)
    {
        WNDCLASSEX wndClass;                                   // WNDCLASSEX Struktur
    
        // Struktur initialisieren
        wndClass.cbSize        = sizeof(WNDCLASSEX);           // Größe angeben (nie vergessen!)
        wndClass.style         = CS_DBLCLKS | CS_OWNDC |
                                 CS_HREDRAW | CS_VREDRAW;      // Standard Stile
        wndClass.lpfnWndProc   = WindowFunc;                   // Die Callback Funktion angeben
    
        wndClass.cbClsExtra    = 0;                            // Zusätzliche Angaben, wird nicht benötigt
        wndClass.cbWndExtra    = 0;                            // Zusätzliche Angaben, wird nicht benötigt
        wndClass.hInstance     = hInstance;                    // Anwendungsinstanz
    
        wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // Schwarzer Pinsel
        wndClass.hCursor       = LoadCursor(NULL, IDC_ARROW);  // Normaler Cursor
        wndClass.lpszMenuName  = NULL;                         // Das Fenster hat kein Menü
        wndClass.lpszClassName = "WindowClass";                // Der Name der Klasse
        wndClass.hIcon         = LoadIcon(NULL, IDI_WINLOGO);  // Windows Logo
        wndClass.hIconSm       = LoadIcon(NULL, IDI_WINLOGO);  // Windows Logo
    
        RegisterClassEx(&wndClass);
    
        return CreateWindowEx(NULL,                   // Keine erweiterten Stile nutzen
                              "WindowClass",          // Klassenname
                              "DirectInput8-Keyboard",// Fenstertitel
                              WS_OVERLAPPEDWINDOW |   // Fenster
                              WS_VISIBLE,             // Eigenschaften
                              100, 100,               // Anfangsposition und
                              400, 300,               // Größe des Fensters
                              NULL,                   // Handle des Elternfensters
                              NULL,                   // Handle des Menüs
                              hInstance,              // Anwendungsinstanz
                              NULL);                  // wird nicht benötigt
    }
    
    // Diese Funktion wird von Windows aufgrufen, wenn eine Nachricht
    // für Ihr Programm vorliegt
    LRESULT CALLBACK WindowFunc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        // testen, um welche Nachticht es sich handelt
        switch(msg)
        {
            case WM_KEYDOWN:
    			switch(wParam)
    			{
    				case VK_ESCAPE:                     
                        DestroyWindow(hWnd);
                    break;
                }
                break;
    
    		break;
    
            case WM_DESTROY:
                CleanUpDirectInput();
    			PostQuitMessage(0);
    		break;
    
        }
    
        // Wenn wir uns nicht um die Nachricht gekümmert haben wird sie 
        // an die Standardnachrichtenverarbeitung von Windows geschickt
        return (DefWindowProc(hwnd, msg, wParam, lParam));
    }
    
    BOOL InitDirectInput(HINSTANCE hInst)
    {
        // DirectInput8-Objekt anlegen
        if(FAILED(DirectInput8Create(hInst, DIRECTINPUT_VERSION, 
                                     IID_IDirectInput8,(void**)&lpDI,NULL)))
        { 
            return Error("Fehler beim Anlegen des DirectInput8-Objekts");
        } 
    
        // Gerät für die Tastatur festlegen
        if(FAILED(lpDI->CreateDevice(GUID_SysKeyboard, &lpDIKeyboard, NULL)))
        {
            return Error("Fehler beim Anlegen des Tastatur-Geräts");    
        }
    
        // c_dfDIKeyboard ist eine vordefinierte Variable
        if(FAILED(lpDIKeyboard->SetDataFormat(&c_dfDIKeyboard)))
        {
            return Error("Fehler beim Setzen des Datenformats");        
        }
    
        // Kooperationsebene festlegen
        if(FAILED(lpDIKeyboard->SetCooperativeLevel(hWnd,DISCL_FOREGROUND | 
                                                         DISCL_NONEXCLUSIVE)))
        {    
            return Error("Fehler beim Setzen des Kooperationsebene (DirectInput)");        
        }
    
        // Zugang zur Tastatur verschaffen
        lpDIKeyboard->Acquire();
    
        return TRUE;
    }
    
    void ProcessInput(void)
    {
        // alle Tasten der Tastatur
        bool bKeyboard[256]; 
    
        int y = 20; int x = 20;
    
        if(FAILED(lpDIKeyboard->GetDeviceState(sizeof(bKeyboard),(LPVOID)&bKeyboard))) 
        { 
            // die Tastatur wurde zwischenzeitlich 
            // durch eine andere Anwendung genutzt
            // Kontrolle wiederholen
            lpDIKeyboard->Acquire();
            return;
        } 
    
        HDC hDC = GetDC(hWnd);
    
        // die gedrückte Taste ausgeben
        if(bKeyboard[DIK_LEFT])
        {
            TextOut(hDC,x,y,"Links     ",10);
            x += 50;
        }
    
        if(bKeyboard[DIK_RIGHT])
        {
            TextOut(hDC,x,y,"Rechts    ",10);
            x += 50;
        }
    
        if(bKeyboard[DIK_UP])
        {
            TextOut(hDC,x,y,"Hoch      ",10);
            x += 50;
        }
    
        if(bKeyboard[DIK_DOWN])
        {
            TextOut(hDC,x,y,"Runter    ",10);
            x += 50;
        }
    
        if(bKeyboard[DIK_SPACE])
        {
            TextOut(hDC,x,y,"Space     ",10);
            x += 50;
        }
    
        if(bKeyboard[DIK_RCONTROL])
        {
            TextOut(hDC,x,y,"Control   ",10);
            x += 50;
        }
    
        for(int i=x;i<250;i++)
        {
            TextOut(hDC,i,y," ",1);
        }
    
        ReleaseDC(hWnd,hDC);
    }
    
    void CleanUpDirectInput(void)
    {
        if(NULL != lpDIKeyboard)
        {
            lpDIKeyboard->Unacquire();
            lpDIKeyboard->Release();
            lpDIKeyboard = NULL;
        }
    
        if(NULL != lpDI)
        {
            lpDI->Release();
            lpDI = NULL;
        }
    }
    
    // Fehlermeldung ausgeben
    BOOL Error(char* msg)
    {
        // in das Ausgabefenster
        OutputDebugString(msg);
        OutputDebugString("\n");
    
        // und als MessageBox
        MessageBox(0,msg,"Error",MB_OK);
    
        return FALSE;
    }
    


  • Ich habe mir 2 mal so ein char[256] Array erzeugt, und die Abfrage geht dann immer abwechselnd in die beiden rein. Dann kann man den Unterschied zwischen 2 Abfragen erkennen, und somit ob eine Taste losgelassen/runtergedrückt wurde.



  • ??? 😕 wie meinst du das ich kann c++ noch net so lange, kannst da das etwas genauer beschreiben, oder den Code so endern das es geht.
    Bedanke mich schon mal an dieser Stellen.
    mfg



  • Yo, oder wenn es nur um 1 Taste geht 'ne boolean reinkladdern.



  • hm. wenn man eine dinput klasse hätte, könnte man 2 arrays nehmen, eins für den alten und eins für den neuen status der tasten. in der abfrage methode füllt man dann ein array mit dem neuen state, davor aber kopiert man dessen inhalt in das andere array. nun macht man die ausgabe des textes davon abhängig, ob der status des entsprechenden keys in beiden arrays gleich ist... muss sicher noch überarbeitet werden, aber im prinzip ginge da (oder??)
    sorry, 0x00000001 , falls du dsowas gemeint hattest.



  • Ich verstehe wie ihr das meint, aber hat direct input keine einfachere Lösung,
    könnt ihr ein bsp coden, ich weis nicht wie man das umsetzen soll, wie ihr das meint 😞



  • Warum lest ihr nicht einfach die Antworten der Anderen und _denkt_ darüber nach, bevor ihr noch was sagt?

    Bye, TGGC (Der Held ist zurück)



  • sorry



  • So, ich hab mir meine gedanken gemacht, aber die umsetzung gelingt mir einfach net 😞 kann nicht bitte einer ein beispiel zum code schreiben, BITTE!!!
    mfg



  • bool g_bKeyboard[256] // Globales array, da keine klasse vorhanden ist
    ZeroMemory(g_bKeyboard, sizeof(bool)) // bin mir nicht sicher, ob man sizeof(bool) oder sizeof (g_bKeyboard) nehmen muss
    
    void ProcessInput(void) 
    { 
        // alle Tasten der Tastatur 
        bool bKeyboard[256];  
    
        int y = 20; int x = 20; 
    
        // altes array sichern
        for (int i = 0; i < 256; i++)
        {
          g_bKeyboard[i] = bKeyboard[i];
        }
    
        if(FAILED(lpDIKeyboard->GetDeviceState(sizeof(bKeyboard),(LPVOID)&bKeyboard)))  
        {  
            // die Tastatur wurde zwischenzeitlich  
            // durch eine andere Anwendung genutzt 
            // Kontrolle wiederholen 
            lpDIKeyboard->Acquire(); 
            return; 
        }  
    
        HDC hDC = GetDC(hWnd); 
    
        // die gedrückte Taste ausgeben 
        if(bKeyboard[DIK_LEFT] && !g_bKeyboard[DIK_LEFT]) // prüfen, ob die taste zwischendurch losgelassen wurde, muss natürlich bei allen keyabfragen erfolgen
        { 
            TextOut(hDC,x,y,"Links     ",10); 
            x += 50; 
        } 
    
        if(bKeyboard[DIK_RIGHT]) 
        { 
            TextOut(hDC,x,y,"Rechts    ",10); 
            x += 50; 
        } 
    
        if(bKeyboard[DIK_UP]) 
        { 
            TextOut(hDC,x,y,"Hoch      ",10); 
            x += 50; 
        } 
    
        if(bKeyboard[DIK_DOWN]) 
        { 
            TextOut(hDC,x,y,"Runter    ",10); 
            x += 50; 
        } 
    
        if(bKeyboard[DIK_SPACE]) 
        { 
            TextOut(hDC,x,y,"Space     ",10); 
            x += 50; 
        } 
    
        if(bKeyboard[DIK_RCONTROL]) 
        { 
            TextOut(hDC,x,y,"Control   ",10); 
            x += 50; 
        } 
    
        for(int i=x;i<250;i++) 
        { 
            TextOut(hDC,i,y," ",1); 
        } 
    
        ReleaseDC(hWnd,hDC); 
    }
    


  • Babbo schrieb:

    ZeroMemory(g_bKeyboard, sizeof(bool)) // bin mir nicht sicher, ob man sizeof(bool) oder sizeof (g_bKeyboard) nehmen muss
    

    Bei sizeof(bool) müsste man ja noch angeben, wie viele davon... 🙂



  • Anstatt das Array dauernd zu kopieren könnte man auch zwei am Anfang erstellen, und die dann jeweils abwechselnd benutzen. Das sollte schneller sein. Am besten man speichert einen pointer der auf das aktuelle Array zeigt und einen der auf das andere zeigt. Die Zeiger kann man dann flippen, ähnlich wie Back und Frontbuffer bei der Grafik.
    Nur so als Tipp. Aber ich hab den Eindruck Gott V 2.0 wird schon froh sein wenns überhaupt mal geht...



  • Ja dann wehre ich scht froh 😞
    Der Code scheint net zu funzen, dann wen ma drückt blinkt da die schrieft net auf. 😞
    Ich weis keinen Rat 😕



  • bin nicht sicher, aber könnte es nicht sein, dass es einfach zu schnell wieder verschwindet (es=der text). Vielleicht versucht du mal eine andere prüfung, z.b. eine variable, die bei jedem tastendruck erhöht wird, und die du dann am edne der funktion auf den screen bringst...
    ansonsten wüsste ich nicht, wo der fehler liegt...



  • jo bin auch hintergekommen, der dürchlaüft so schnell die schleife, auf meinem 66 mhz rechner kann man es sehen. Der code an sich is ja auch logisch. Bedanke mich für eure Hilfe. 😃
    mfg


Anmelden zum Antworten