Alternative zu GetAsyncKeyState()



  • Hi Leute,
    ich hab n kleines chat Programm geschrieben: man gibt den text in einer textbox ein, drückt enter, und kriegt den text in der textbox drüber wieder raus. Mein Problem ist jetzt das enter drücken. Mit VK_RETURN hat das iwie nich geklappt, wahrscheinlich weils in der textbox is =(. Deshalb frag ich das ganze jetzt mit GetAsyncKeyState() ab. Die Funktion bringt nur leider ne ziemlich hohe CPU auslastung mit sich. Deshalb wüsst ich gern, wie ich das hinkrieg, dass es etwas "sparender is". Gibts da vllt auch ne windows message oder so?
    Würde mich über Hilfe sehr freuen.

    MfG Daniel



  • Hallo

    du musst das editfeld subclassen. dazu änderst du seine WndProc
    via SetWindowLong und GWL_WNDPROC als parameter.
    (natürich vorher alte prozedur mit GetWindowLong sichern).

    in deiner funktion kannst du jetzt VK_RETURN behandeln.

    Immer am Ende CallWindowProc aufrufen!



  • ach und was muss ich da als dritten parameter verwenden?
    jetzt schauts so aus:
    SetWindowLongPtr(feld, GWL_WNDPROC, NULL);
    stimmt so oder?



  • hm, nein 🙂

    du musst dir eine WndProc für das Feld schreiben:

    LRESULT CALLBACK (*old)(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
    
    LRESULT CALLBACK HookProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        if (msg == WM_KEYDOWN && LOWORD(wParam) == VK_RETURN)
            mache_was_tolles();
        return CallWindowProc(old, hWnd, msg, wParam, lParam);
    }
    // in der main:
    old = GetWindowLong(feld, GWL_WNDPROC); // alte speichern
    SetWinowLong(feld, GWL_WNDPROC, HookProc); // hier die prozedur einsezten
    

    dann sollte das ganze funktionieren.

    edit: natürlich musst du das ganze noch richtig casten, wenn die typen
    nicht passen :p



  • das
    LRESULT CALLBACK (*old)(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
    mag er nich:
    Spiel.cpp|52|error C2059: syntax error : '('|
    wenn ichs so mach:
    LRESULT CALLBACK *old(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
    Spiel.cpp|52|error C2165: 'left-side modifier' : cannot modify pointers to data|

    und so:
    LRESULT CALLBACK old(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
    old = GetWindowLong(feld, GWL_WNDPROC); // alte speichern
    Spiel.cpp|246|error C2659: '=' : overloaded function as left operand|

    wie muss ich das machen? o.O



  • sry aber ich hab noch keinen kompiler im kopf 🙂

    LRESULT (CALLBACK *old)(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
    


  • ich glaub ich bin zu blöd dafür 😕
    bei der funktion GetWindowLongPtr:
    error C2440: '=' : cannot convert from 'LONG' to 'LRESULT (__stdcall *)(HWND,UINT,WPARAM,LPARAM)'|
    wenn ich als typ LONG_PTR nehm klappt zwar der rückgabewert der funktion aber dafür bei dem return nich mehr 😞



  • killmichnich schrieb:

    ich glaub ich bin zu blöd dafür

    ja



  • ich hab doch gesagt casten!

    wenn ein long nicht in ein 'LRESULT (__stdcall *)(HWND,UINT,WPARAM,LPARAM)'
    passt, müssen wir es halt reinquetschen:

    old = reinterpret_cast<LRESULT (__stdcall *)(HWND,UINT,WPARAM,LPARAM)>(blabla);
    

    😉



  • ok thx für die noob-hilfe, jetzt krieg ich keine errors mehr, aber wenn ich das Programm start is die textbox nich mehr da o.O
    fehlt da noch irgendwas?



  • zeig uns bitte deinen code, dieses ratespiel ist zu mühselig. leitest du alles was du nicht behandelst an die alte wndproc weiter?



  • ich habs jetzt so gemacht wie er gesagt hat:

    LRESULT (CALLBACK *old)(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
    LRESULT CALLBACK HookProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        if (msg == WM_KEYDOWN && LOWORD(wParam) == VK_RETURN)
            //mache_was_tolles();
        return CallWindowProc(old, hWnd, msg, wParam, lParam);
    }
    
     old = reinterpret_cast<LRESULT (__stdcall *)(HWND,UINT,WPARAM,LPARAM)>(GetWindowLongPtr(feld, GWL_WNDPROC)); // alte speichern
    
    SetWindowLongPtr(feld, GWL_WNDPROC, reinterpret_cast<long>(HookProc));
    


  • zeig uns bitte genug code um es reproduzierbaren zu können. bei dem code, wie du ihn geposted hast, ist es klar, daß es nicht funktioniert, weil CallWindowProc() nur aufgerufen wird wenn (msg == WM_KEYDOWN && LOWORD(wParam) == VK_RETURN)



  • ok sry:

    HWND CreateMainWindow(HINSTANCE hInstance);
    
    HWND activewindow;
    
    // Callback Funktion zur Nachrichtenbehandlung
    LRESULT CALLBACK MessageHandler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
    
    //LRESULT (CALLBACK *old)(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
    
    LRESULT (CALLBACK *old)(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
    LRESULT CALLBACK HookProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        if (msg == WM_KEYDOWN && LOWORD(wParam) == VK_RETURN)
            //mache_was_tolles();
        return CallWindowProc(old, hWnd, msg, wParam, lParam);
    }
    
    // Das Fensterhandle
    HWND hWnd = 0;
    static HWND feld;
    
    // 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
    {
        // Fenster erzeugen und Handle speichern
    
        //MessageBox(NULL, "Druecke A und D um dich nach links und rechts zu bewegen\nEsc zum beenden", NULL, MB_OK);
    
        hWnd = CreateMainWindow(hInstance);
    
        // Wenn der Rueckgabewert 0 ist, ist ein Fehler aufgetreten
        if(0 == hWnd)
        {
            MessageBox(0, "Fenster konnte nicht erzeugt werden", "Fehler", MB_OK);
            return -1;
        }
    
        MSG msg;
    
        // Diese Schleife laeuft bis die Nachricht WM_QUIT empfangen wird
        while (GetMessage (&msg, NULL, 0, 0))
        {
            /* Translate virtual-key messages into character messages */
            TranslateMessage(&msg);
            /* Send message to WindowProcedure */
            DispatchMessage(&msg);
        }
    
        // Rueckgabewert an Windows
        return 0;
    }
    
    HWND CreateMainWindow(HINSTANCE hInstance)
    {
        WNDCLASSEX wndClass =
        {
            sizeof(WNDCLASSEX),                                 // Groesse angeben
            CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW,    // Standardstile
            MessageHandler,                                     // Callback-Funktion
            0,                                                  // Zusaetzliche Angaben
            0,                                                  // nicht benoetigt
            hInstance,                                          // Anwendungsinstanz
            LoadIcon(NULL, IDI_WINLOGO),                        // Windows-Logo
            LoadCursor(NULL, IDC_ARROW),                        // Normaler Cursor
            (HBRUSH)GetStockObject(WHITE_BRUSH),                // Weisser Pinsel
            NULL,                                               // kein Menue
            "WindowClass",                                      // Der Name der Klasse
            LoadIcon(NULL, IDI_WINLOGO)                         // Windows Logo
        };
    
        // Klasse registrieren
        RegisterClassEx(&wndClass);
    
        return CreateWindowEx(NULL,                   // Keine erweiterten Stile nutzen
                              "WindowClass",          // Klassenname
                              "Surface",              // Fenstertitel
                              WS_OVERLAPPEDWINDOW |   // Fenster
                              WS_VISIBLE,             // Eigenschaften
                              0, 0,                 // Anfangsposition
                              1024, 768,  // und Groesse des Fensters
                              NULL,                   // Handle des Elternfensters
                              NULL,                   // Handle des Menues
                              hInstance,              // Anwendungsinstanz
                              NULL);                  // wird nicht benoetigt
    }
    
    // Diese Funktion wird von Windows aufgrufen, wenn
    // eine Nachricht fuer Ihr Programm vorliegt
    LRESULT CALLBACK MessageHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    
        switch(msg)
        {
            case WM_CREATE:
            {
                //feld=CreateWindowEx(WS_EX_CLIENTEDGE, "edit", text.c_str(), WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL, 20, 450, 784, 200, hwnd, NULL, ((LPCREATESTRUCT) lParam) -> hInstance, NULL);
    
                old = reinterpret_cast<LRESULT (__stdcall *)(HWND,UINT,WPARAM,LPARAM)>(GetWindowLongPtr(feld, GWL_WNDPROC)); // alte speichern
    
                break;
            }
            // Programm beenden, wenn das Fenster
            // geschlossen wird
            case WM_DESTROY:
                    PostQuitMessage(0);
                    return 0;
                 break;
    
            case WM_COMMAND:
              {
    
                 if (lParam == (LPARAM)button)
                 {
                    if (HIWORD(wParam) == BN_CLICKED)
                    {
    
                        ShowWindow(feld, SW_SHOW);
                        SetWindowLongPtr(feld, GWL_WNDPROC, reinterpret_cast<long>(HookProc));
    
                    }
                 }
                 break;
              }
    
            case WM_TIMER:
            {
                if(hWnd==GetActiveWindow())
                {
                    KillTimer(hWnd, 1);
                    flash=false;
                    FlashWindow(hWnd, flash);
                }
                else
                {
                    if(flash)
                    {
                        flash=false;
                    }
                    else if(!flash)
                    {
                        flash=true;
                    }
                }
                FlashWindow(hWnd, flash);
                break;
    
            }
    
            case WM_KEYDOWN:
                switch(wParam)
                {
                    case VK_RETURN:
                    {
                        char ctext[256];
                        memset(&ctext, NULL, sizeof(ctext));
                         for(int i=0; i<sizeof(ctext); i++)
                         {
                             ctext[i]=NULL;
                         }
                        GetWindowText(feld, ctext, sizeof(ctext));
                        send(s1, ctext, strlen(ctext), 0);
                        SetWindowText(feld, NULL);
    
                            break;
                        }
    
                    case VK_ESCAPE:
                    CloseHandle(threadHandle);
                    DeleteCriticalSection(&g_csPrint);
                    PostQuitMessage(0);
                    break;
    
                }
                break;
        }
    
        // Standardnachrichtenverarbeitung von Windows
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    

    das dürfte alles relevante sein, oder?



  • so hier

    WNDPROC oldProc;
    // ...
    // ...
    	hWndEdit = GetDlgItem(hDlg, IDC_EDIT1);
    	oldProc = SetWindowLong(hWndEdit, GWL_WNDPROC, EditProc);
    // ...
    // ...
    
    LRESULT CALLBACK EditProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    	switch(uMsg) {
    		case WM_GETDLGCODE:
    			if(wParam == VK_RETURN)
    				return DLGC_WANTMESSAGE;
    			break;
    		case WM_KEYDOWN:
    			if(wParam == VK_RETURN) {
    				MessageBox(hWnd,_T("VK_RETURN received!"),NULL,MB_OK);
    				return 0;
    			}
    			break;
    	}
    	return CallWindowProc(oldProc, hWnd, uMsg, wParam, lParam);
    }
    

    siehe auch martins blog http://blog.m-ri.de/?s=subclass



  • also sry asdca, ich hab das wieder nich ganz geblickt welches HWND ich da wo einsetzen muss. aber ich will ja nich weiter nerven.
    Ich hatte nen geistesblitz und hab das jetzt einfach so gemacht:

    while (GetMessage (&msg, NULL, 0, 0))
        {
            /* Translate virtual-key messages into character messages */
            TranslateMessage(&msg);
            /* Send message to WindowProcedure */
            if(msg.message==WM_KEYDOWN && msg.wParam==VK_RETURN)
            {
                char ctext[256];
                memset(&ctext, NULL, sizeof(ctext));
                    for(int i=0; i<sizeof(ctext); i++)
                    {
                        ctext[i]=NULL;
                    }
                GetWindowText(feld, ctext, sizeof(ctext));
                send(s1, ctext, strlen(ctext), 0);
                SetWindowText(feld, NULL);
    
            }
            else if(msg.wParam!=VK_RETURN)
            {
                DispatchMessage(&msg);
            }
    
        }
    

    so geht das doch auch oder?


Log in to reply