Messages in Threads



  • Jetzt frickel ich schon seit Tagen hier rum und bekomm's einfach nicht ans Laufen...! 😡

    Also ich hab' eine DLL, die von der JavaVM geladen wird und von der dann Funktionen von Java aus aufgerufen werden.
    Die DLL soll eine GUI werden.
    Entsprechend erstelle ich in der Initialisieren-Funktion einen eigenen Thread, damit die Funktion returnen kann und das Java-Prog -UNABHÄNGIG- von der GUI (DLL) arbeiten kann.
    Java soll nur ab und an nach neuen Aktionen pollen.

    Das Problem ist jetzt:
    Ich erstelle mir halt einen Thread und ein Window in diesem, ich bin aber nicht in der Lage auf Messages zu reagieren.
    Es erscheint ein Fenster, welches ich aber nicht durch ESC, ALT+F4, oder Klicken des X beenden kann, ich kann es nichtmal verschieben! Es ist völlig regungslos! Das Java-Prog läuft aber weiter (was es auch soll), und ich kann das Fenster und den Thread von Java aus vernünftig deinitialisieren und beenden.

    Ich bin mir auch gar nicht so sicher, wo ich jetzt Peeken soll und wie ein MessageHandler für den Thread auszusehen hat.

    Ich poste jetzt einfach mal was Code, vielleicht sieht ja jemand auf Anhieb das Problem.

    DLLMain.cpp:

    #define TH_INIT     100
    #define TH_RUN      200
    #define TH_DEINIT   300
    
    // GLOBALS
    HINSTANCE   g_hDLLInst = NULL;
    int         g_TH_STATUS;
    uintptr_t   g_noThread;
    bool        g_bBeenden;
    
    CGUI *GUI = NULL;
    
    BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)
    {
        switch(fdwReason)
        {
            case DLL_THREAD_ATTACH :
            case DLL_THREAD_DETACH :
            case DLL_PROCESS_DETACH :
                break;
            case DLL_PROCESS_ATTACH :
                g_hDLLInst = hDLLInst;
                break;
        }
        return TRUE;
    }
    
    // Von Java unabhängige Ausführungs-Schleife
    void ThreadSchleife(void* Parameter)
    {
        MSG msg;
    
        while(!g_bBeenden)
        {
            while(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
            {
                if(GetMessage(&msg, NULL, 0, 0 ) == -1) return;
                TranslateMessage(&msg);              PostThreadMessage((DWORD)g_noThread, msg.message, msg.wParam, msg.lParam);
            }
    
            if(g_bBeenden) g_TH_STATUS = TH_DEINIT;
    
            switch(g_TH_STATUS)
            {
                case TH_INIT :
                    GUI = new CGUI(g_hDLLInst);
                    GUI->Init();
                    g_TH_STATUS = TH_RUN;
                    break;
                case TH_RUN :
                    GUI->Hauptschleife();
                    break;
                case TH_DEINIT :
                    GUI->Deinit();
                    delete GUI;
                    GUI = NULL;
                    break;
            }
        }
    
        if(GUI != NULL)
        {
            GUI->Deinit();
            delete GUI;
            GUI = NULL;
        }
    }
    
    // wird von Java gecallt
    JNIEXPORT jboolean JNICALL Initialisieren(JNIEnv*, jobject)
    {
        g_TH_STATUS = TH_INIT;
        g_bBeenden = false;
        g_noThread = _beginthread(ThreadSchleife, 0, NULL);
        if(g_noThread == -1) return false;
        else return true;
    }
    
    JNIEXPORT jboolean JNICALL EingabeVorhanden(JNIEnv*, jobject)
    {
        return true;
    }
    
    JNIEXPORT jint JNICALL EingabeHolen(JNIEnv*, jobject)
    {
        return 10;
    }
    
    JNIEXPORT jboolean JNICALL Deinitialisieren(JNIEnv*, jobject)
    {
        g_bBeenden = true;
    
        return true;
    }
    

    GUI.h

    class CGUI
    {
        public :
            CGUI(HINSTANCE);
            ~CGUI();
            bool Init();
            void Hauptschleife();
            bool Deinit();
    
        private :
            HINSTANCE   m_hInst;
            HWND        m_hWnd;
    };
    
    LRESULT CALLBACK MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    
    extern int g_TH_STATUS;
    

    GUI.cpp

    CGUI::CGUI(HINSTANCE hInstance)
    {
        m_hInst = hInstance;
        m_hWnd = NULL;
    }
    
    bool CGUI::Init()
    {
        WNDCLASSEX wndclassex = {0};
        wndclassex.cbSize = sizeof(WNDCLASSEX);
        wndclassex.style = CS_HREDRAW | CS_VREDRAW;
        wndclassex.lpfnWndProc = MessageHandler;
        wndclassex.hInstance = m_hInst;
        wndclassex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
        wndclassex.lpszClassName = "XXX";
        RegisterClassEx(&wndclassex);
    
        m_hWnd = CreateWindowEx(WS_EX_CLIENTEDGE,
                                "XXX", "-=[ e ]=-",
                                WS_SYSMENU,
                                CW_USEDEFAULT, CW_USEDEFAULT, SCREEN_WIDTH, SCREEN_HEIGHT,
                                NULL, NULL, m_hInst, NULL);
        if(m_hWnd == NULL) return false;
    
        ShowWindow(m_hWnd, SW_SHOW);
        UpdateWindow(m_hWnd);
    
        return true;
    }
    
    void CGUI::Hauptschleife()
    {
        MSG msg;
        PAINTSTRUCT ps;
    
        if(PeekMessage(&msg, m_hWnd, 0, 0, PM_NOREMOVE))
        {
            if(GetMessage(&msg, m_hWnd, 0, 0 ) == -1) return;   // Fehler
            TranslateMessage(&msg);
            switch(msg.message)
            {
                case WM_PAINT :
                    BeginPaint(m_hWnd, &ps);
                    EndPaint(m_hWnd, &ps);
                    break;
                case WM_CLOSE :
                    g_TH_STATUS = 300;
                    break;
            }
        }
    }
    
    bool CGUI::Deinit()
    {
        BOOL Fehler = UnregisterClass("XXX", m_hInst);
        if(Fehler) return true;
        else return false;
    }
    
    LRESULT CALLBACK MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        switch(uMsg)
        {
            case WM_PAINT :
                PAINTSTRUCT ps;
                BeginPaint(hWnd, &ps);
                EndPaint(hWnd, &ps);
                return 0;
    
            case WM_MOUSEMOVE :
            {
                return 0;
            }
    
            case WM_KEYDOWN :
                // If ESC key is pressed, quit the app
                if(wParam == VK_ESCAPE) PostQuitMessage(0);
                return 0;
    
            case WM_QUIT :
            case WM_CLOSE :
                g_TH_STATUS = 300;
                return 0;
            case WM_DESTROY :
                return 0;
        }
    
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    

    Naja, wenn einem was auffällt...
    ...immer her damit! 🙂

    Thanks & good night...

    Sarge



  • Also das Vorgehen ist:

    • Von Java wird die DLL geladen -> DllMain
    • Von Java wird -> Initialisieren() aufgerufen
    • Ab jetzt wird ab und an nach neuen Aktionen gepollt -> EingabeVorhanden() / EingabeHolen()
    • Irgendwann wird dann deinitet -> Deinitialisieren()

    Also wenn mich jemand aus meiner 😕 -Lage befreien könnte... 😉 🕶

    N8...



  • Esc Meta Alt Ctrl Shift
    Eight Megs And Constantly Swapping
    Warum werden die Funktionen nicht mit Passwörtern versehen?



  • Soa, jetzt hab' ich irgendwas hier, was zumindest so tut, als würde es laufen.

    Also opfert eure Zeit erstmal anders, als durch meinen Code zu sehen.

    Vielen Dank an diejenigen, die überhaupt mal reingeguckt haben...

    Schönes Pfingsten!

    CU



  • Soa, hab' also einen halbwegs funktionierenden Message-Callback für meinen Thread.
    Wenn ich das Window per X oder ALT-F4 close, wird richtigerweise WM_QUIT gesendet und alles läuft super.
    Wenn ich aber z.B. ESC drücke, und in dem gleichen Message-Callback

    case WM_KEYDOWN :
                // Bei ESC beenden
                if(wParam == VK_ESCAPE)
                {
                    PostQuitMessage(0);
                }
                return 0;
    

    implementiere, funktioniert das Beenden nicht!

    "The PostQuitMessage function posts a WM_QUIT message to the thread's message queue and returns immediately" 😕
    Ich weiß nicht wohin der das sendet, jedenfalls nicht an meinen Message-Callback!! 😞

    PostThreadMessage() ist ja eher für user-defined messages... 🙄

    Hat einer'n Plan wie ich PostQuitMessage auf meinen Fall anwenden kann??

    Oder Infos über PostThreadMessage?
    Ist in

    BOOL PostThreadMessage(DWORD idThread, // thread identifier
      UINT Msg,       // message
      WPARAM wParam,  // first message parameter
      LPARAM lParam   // second message parameter
    );
    

    das DWORD idThread wirklich dasselbe wie der bei

    uintptr_t _beginthread( 
       void( __cdecl *start_address )( void * ),
       unsigned stack_size,
       void *arglist 
    );
    

    zurückgegebene "uintptr_t" ??? 😕

    Isset vielleicht einfacher für Threads die MFC zu benutzen?


Anmelden zum Antworten