Eigene Messages erstellen ...



  • ja bin ein wenig neidisch. aber so viel kannst du auch wieder nicht 🙄



  • Original erstellt von <****a>:
    aber so viel kannst du auch wieder nicht 🙄

    Hast recht. 😉



  • Aber es hat wenigstens funktioniert

    Aber eines Begreife ich nicht so ganz, ich habe versucht die beiden globalen Variablen StartupInfo und ProcessInformation ebenfalls lokal in die WndProc einzubinden dann wird das andere Programm aber nicht mehr gestartet mache ich die Variablen wieder global funktioniert das wieder 😕

    Dann noch zwei Fragen zu den WM_User Messages wieviele davon kann ich machen und wie kann ich überhaupt mehrere definiern ?

    Und noch eine Frage nebenher ich bekomme ja bei CreateProcess die ProcessID des gestarteten Programms (richtig wäre thread), kann ich darüber auch den Handle des Parent-Windows bekommen ?

    Hier nochmal die beiden modifizierten Programme:

    Client:

    #include <windows.h>
    
    #define WM_MYMSG WM_USER
    
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
    
    STARTUPINFO         StartupInfo;
    PROCESS_INFORMATION ProcessInformation;
    
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow)
    {
        char        szAppName[] = "DX-Client";
        HWND        hwnd;
        MSG         msg;
        WNDCLASSEX  wndclass;
    
        wndclass.cbSize         = sizeof (wndclass);
        wndclass.style          = CS_HREDRAW | CS_VREDRAW;
        wndclass.lpfnWndProc    = WndProc;
        wndclass.cbClsExtra     = 0;
        wndclass.cbWndExtra     = 0;
        wndclass.hInstance      = hInstance;
        wndclass.hIcon          = LoadIcon (NULL, IDI_APPLICATION);
        wndclass.hCursor        = LoadCursor (NULL, IDC_ARROW);
        wndclass.hbrBackground  = (HBRUSH) GetStockObject (WHITE_BRUSH);
        wndclass.lpszMenuName   = NULL;
        wndclass.lpszClassName  = szAppName;
        wndclass.hIconSm        = LoadIcon (NULL, IDI_APPLICATION);
    
        RegisterClassEx (&wndclass);
    
        hwnd = CreateWindow (szAppName, "DX-Client", WS_OVERLAPPEDWINDOW,
                             CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                             NULL, NULL, hInstance, NULL);
    
        ShowWindow (hwnd, iCmdShow);
        UpdateWindow (hwnd);
    
        while (GetMessage (&msg, NULL, 0, 0))
        {
            TranslateMessage (&msg);
            DispatchMessage (&msg);
        }
    
        return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
    {
        HWND hwnd_Server;
    
        switch (iMsg)
        {
            case WM_CREATE:
                CreateProcess ("DX-Server.exe", NULL, NULL, NULL, false, NORMAL_PRIORITY_CLASS, NULL, NULL, &StartupInfo, &ProcessInformation);
                return 0;
            case WM_PAINT:
                hwnd_Server = FindWindow("DX-Server","DX-Server");
                SendMessage(hwnd_Server, WM_MYMSG, NULL ,NULL);
                return 0;
            case WM_DESTROY:
                hwnd_Server = FindWindow("DX-Server","DX-Server");
                SendMessage(hwnd_Server, WM_CLOSE, NULL ,NULL);
                PostQuitMessage (0);
                return 0;
        }
    
        return DefWindowProc (hwnd, iMsg, wParam, lParam);
    }
    

    Server:

    #include <windows.h>
    
    #define WM_MYMSG WM_USER
    
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow)
    {
        char        szAppName[] = "DX-Server";
        HWND        hwnd;
        MSG         msg;
        WNDCLASSEX  wndclass;
    
        wndclass.cbSize         = sizeof (wndclass);
        wndclass.style          = CS_HREDRAW | CS_VREDRAW;
        wndclass.lpfnWndProc    = WndProc;
        wndclass.cbClsExtra     = 0;
        wndclass.cbWndExtra     = 0;
        wndclass.hInstance      = hInstance;
        wndclass.hIcon          = LoadIcon (NULL, IDI_APPLICATION);
        wndclass.hCursor        = LoadCursor (NULL, IDC_ARROW);
        wndclass.hbrBackground  = (HBRUSH) GetStockObject (WHITE_BRUSH);
        wndclass.lpszMenuName   = NULL;
        wndclass.lpszClassName  = szAppName;
        wndclass.hIconSm        = LoadIcon (NULL, IDI_APPLICATION);
    
        RegisterClassEx (&wndclass);
    
        hwnd = CreateWindow (szAppName, "DX-Server", WS_OVERLAPPEDWINDOW,
                             CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                             NULL, NULL, hInstance, NULL);
    
        ShowWindow (hwnd, iCmdShow);
        UpdateWindow (hwnd);
    
        while (GetMessage (&msg, NULL, 0, 0))
        {
            TranslateMessage (&msg);
            DispatchMessage (&msg);
        }
    
        return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
    {
        switch (iMsg)
        {
            case WM_CREATE:
                return 0;
            case WM_PAINT:
                return 0;
            case WM_DESTROY:
                PostQuitMessage (0);
                return 0;
            case WM_MYMSG:
                MessageBox(NULL,"Der Server hat eine Nachricht vom Typ WM_MYMSG bekommen !", "Message", MB_OK);
                return 0;
        }
    
        return DefWindowProc (hwnd, iMsg, wParam, lParam);
    }
    


  • mehrere messages, kein problem:

    #define WM_MYMSG1 WM_USER+1
    #define WM_MYMSG2 WM_USER+2
    #define WM_MYMSG3 WM_USER+3
    ...
    

    wie viele man machen kann, weiss ich jetzt nich ausm kopf, muste mal in der msdn gucken ... aber es dürften mehrere tausend sein 🙂

    grüsse



  • 1. Du solltest die Strukturen auch ausnullen sowie bei STARTUPINFO cb besetzen. Bsp. aus der MSDN-Library:

    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    
    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    ZeroMemory( &pi, sizeof(pi) );
    
    CreateProcess(...);
    
    // Wenn du die Handles nicht mehr brauchst gleich schließen
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );
    

    2. WM_USER + n (also WM_USER+1, WM_USER+2, ...)

    ich bekomme ja bei CreateProcess die ProcessID des gestarteten Programms (richtig wäre thread)

    wieso? du erzeugst doch einen Prozess

    kann ich darüber auch den Handle des Parent-Windows bekommen?

    es gibt nicht das Parent-Window (ein Programm kann ja mehrere davon haben)! Aber du könntest z.B. mit EnumWindows die Fenster durchgehen und dann mit GetWindowThreadProcessId checken, ob das Fenster zum selben Thread gehört 🙂



  • Wieviele WM_USER-Messages du machen kannst findest du hier



  • @WebFritzi:

    @John: Voll daneben!!! WM_MYMSG ist doch ein UINT und kann somit sehr wohl im switch behandelt werden!

    WM_MYMSG ist wie Du selbst sagst eine Variable! Damit kein konstanter Ausdruck! Deshalb kann sie nicht im switch case behandelt werden!

    UINT msg;
    UINT my_msg;
    
    switch (msg) {
       case my_msg:    // <--- geht nicht, weil nicht konstant!
          break;
    
    }
    

    Es kommt zum Fehler von DarkMight1:

    Beim Compilieren bekomme ich die Meldung das WM_MYMSG kein Konstanter Ausdruck ist.

    --------------------
    WebFritzi:

    Beide Programme server und client rufen RegisterWindowMessage() mit dem gleichen String auf.
    Schau doch mal hin! Im Server-Prog ist das nicht mal definiert!

    Das meinte ich! Wenn zwei oder mehrere Programme sich unterhalten wollen, so muß jedes Programm RegisterWindowMessage() aufruften. Das ist der von mir beschriebene Idealfall, daß es DarkMight1 nicht so macht, ist mir schon klar, das ist ja auch nicht richtig. Es hat es vergessen im "server" die Nachricht zu registrieren.

    ....
    John

    [ Dieser Beitrag wurde am 12.04.2003 um 20:27 Uhr von John editiert. ]



  • Das meinte ich!

    Dann drück dich doch das nächste mal besser aus.

    Beide Programme server und client rufen RegisterWindowMessage() mit dem gleichen String auf.

    hört sich nämlich an wie ein Beobachtung im Code von DarkMight1. Was solls... wir haben das Problem ja jetzt gelöst.



  • Wenn ich das nun so ändere wie flenders das beschrieben hat kann ich die beiden oben genannten Variablen nun auch lokal in der WndProc behandeln !!!

    Ich habe vor dem Server einen String (oder vielleicht die Startadresse des Strings) zu übermitteln geht das irgendwie oder gibt es da andere Möglichkeiten ??



  • @DarkMight1: WM_COPYDATA

    @WebFritzi: Mitdenken!



  • Ok in dem Client-Programm habe ich nun WM_COPYDATA eingebunden, mir ist nur nicht klar wofür copydatastruct.dwData da ist.

    Hier mal das listing wie es jetzt aus sieht.

    #include <windows.h>
    #include <string.h>
    
    #define WM_MYMSG WM_USER
    
    HWND    hwnd;
    
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow)
    {
        char        szAppName[] = "DX-Client";
        MSG         msg;
        WNDCLASSEX  wndclass;
    
        wndclass.cbSize         = sizeof (wndclass);
        wndclass.style          = CS_HREDRAW | CS_VREDRAW;
        wndclass.lpfnWndProc    = WndProc;
        wndclass.cbClsExtra     = 0;
        wndclass.cbWndExtra     = 0;
        wndclass.hInstance      = hInstance;
        wndclass.hIcon          = LoadIcon (NULL, IDI_APPLICATION);
        wndclass.hCursor        = LoadCursor (NULL, IDC_ARROW);
        wndclass.hbrBackground  = (HBRUSH) GetStockObject (WHITE_BRUSH);
        wndclass.lpszMenuName   = NULL;
        wndclass.lpszClassName  = szAppName;
        wndclass.hIconSm        = LoadIcon (NULL, IDI_APPLICATION);
    
        RegisterClassEx (&wndclass);
    
        hwnd = CreateWindow (szAppName, "DX-Client", WS_OVERLAPPEDWINDOW,
                             CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                             NULL, NULL, hInstance, NULL);
    
        ShowWindow (hwnd, iCmdShow);
        UpdateWindow (hwnd);
    
        while (GetMessage (&msg, NULL, 0, 0))
        {
            TranslateMessage (&msg);
            DispatchMessage (&msg);
        }
    
        return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
    {
        HWND                hwnd_Server;
        COPYDATASTRUCT      copydatastruct;
        char                String[] = "Test-String";
        STARTUPINFO         StartupInfo;
        PROCESS_INFORMATION ProcessInformation;
    
        switch (iMsg)
        {
            case WM_CREATE:
    
                ZeroMemory(&StartupInfo, sizeof(STARTUPINFO));
                StartupInfo.cb = sizeof(STARTUPINFO);
                ZeroMemory(&ProcessInformation, sizeof(PROCESS_INFORMATION));
    
                CreateProcess ("DX-Server.exe", NULL, NULL, NULL, false, NORMAL_PRIORITY_CLASS, NULL, NULL, &StartupInfo, &ProcessInformation);
    
                CloseHandle(ProcessInformation.hProcess);
                CloseHandle(ProcessInformation.hThread);
                return 0;
            case WM_PAINT:
    
                hwnd_Server = FindWindow("DX-Server","DX-Server");
                copydatastruct.cbData = sizeof (String);
                copydatastruct.lpData = String;
    
                SendMessage(hwnd_Server, WM_COPYDATA, (WPARAM) hwnd, (LPARAM) ©datastruct);
    
                return 0;
            case WM_DESTROY:
                hwnd_Server = FindWindow("DX-Server","DX-Server");
                SendMessage(hwnd_Server, WM_CLOSE, NULL ,NULL);
                PostQuitMessage (0);
                return 0;
        }
    
        return DefWindowProc (hwnd, iMsg, wParam, lParam);
    }
    

    Ich müste jetzt nur noch wissen wie ich den String wieder aus der Nachricht rausbekomme, hier mein erster Versuch:

    LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
    {
        COPYDATASTRUCT copydatastruct;
    
        switch (iMsg)
        {
            case WM_CREATE:
                return 0;
            case WM_PAINT:
                return 0;
            case WM_DESTROY:
                PostQuitMessage (0);
                return 0;
            case WM_COPYDATA:
                copydatastruct = (COPYDATASTRUCT) lParam;
                MessageBox(NULL,"WM_COPYDATA", "Message", MB_OK);
                return 0;
        }
    
        return DefWindowProc (hwnd, iMsg, wParam, lParam);
    }
    

    Das sagt der Compiler dazu:
    I:\Projects\DX_Server\DX-Server.cpp(59) : error C2440: 'type cast' : 'long' kann nicht in 'struct tagCOPYDATASTRUCT' konvertiert werden
    Quelltyp konnte von keinem Konstruktor angenommen werden, oder die Ueberladungsaufloesung des Konstruktors ist mehrdeutig



  • @John: Ne, wer hier mitdenken muss, das bist du! Du solltest deine Beiträge so schreiben, dass sie jeder versteht. Das war hier nicht der Fall! Beiträge sind nicht zum Interpretieren da, sondern zum Helfen. Und mit Beiträgen, in denen du dich nicht eindeutig ausdrückst, hilfst du keinem!



  • ...und du hälst UINT MY_MSG für 'ne Konstante :o

    Mein Gott bist du kleinlich...oder peinlich! :p



  • Bist du fertig?

    [ Dieser Beitrag wurde am 14.04.2003 um 01:07 Uhr von WebFritzi editiert. ]



  • Eine einfachere alternative Lösung wäre die Verwendung von PostThreadMessage. Kann von jedem Prozess oder Thread zu einem Thread gesendet werden. Die Empfänger-Thread-ID muß aber bekannt. Entweder über die Registry (eintragen vom Thread und ausleses vom Message-Sender) oder über einen gemeinsam bekannten Klassennamen. Vor- und Nachteile muß jeder selber abwägen.
    Ich wollte nur zeigen, dass es noch mindestens eine Lösung mehr gibt.

    Blackbird



  • hi,
    ich glaube jemand hat bei WM_PAINT : BeginPaint () und EndPaint () vergessen



  • Also ich habe das mit WM_COPYDATA jetzt hinbekommen. Der String kommt an das blöde ist nur das ab und zu mal so komisches Zeugs mit auftaucht wo ich mir nicht reklären wo jetzt der Fehler liegen soll.

    Hier noch mal die beiden Listings:

    Client:

    #include <windows.h>
    #include <string.h>
    
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
    void    SendCmd (HWND, HWND, char*);
    
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow)
    {
        char        szAppName[] = "DX-Client";
        MSG         msg;
        WNDCLASSEX  wndclass;
        HWND        hwnd;
    
        wndclass.cbSize         = sizeof (wndclass);
        wndclass.style          = CS_HREDRAW | CS_VREDRAW;
        wndclass.lpfnWndProc    = WndProc;
        wndclass.cbClsExtra     = 0;
        wndclass.cbWndExtra     = 0;
        wndclass.hInstance      = hInstance;
        wndclass.hIcon          = LoadIcon (NULL, IDI_APPLICATION);
        wndclass.hCursor        = LoadCursor (NULL, IDC_ARROW);
        wndclass.hbrBackground  = (HBRUSH) GetStockObject (WHITE_BRUSH);
        wndclass.lpszMenuName   = NULL;
        wndclass.lpszClassName  = szAppName;
        wndclass.hIconSm        = LoadIcon (NULL, IDI_APPLICATION);
    
        RegisterClassEx (&wndclass);
    
        hwnd = CreateWindow (szAppName, "DX-Client", WS_OVERLAPPEDWINDOW,
                             CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                             NULL, NULL, hInstance, NULL);
    
        ShowWindow (hwnd, iCmdShow);
        UpdateWindow (hwnd);
    
        while (GetMessage (&msg, NULL, 0, 0))
        {
            TranslateMessage (&msg);
            DispatchMessage (&msg);
        }
    
        return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
    {
        HWND                hwnd_Server;
        STARTUPINFO         StartupInfo;
        PROCESS_INFORMATION ProcessInformation;
    
        switch (iMsg)
        {
            case WM_CREATE:
                ZeroMemory(&StartupInfo, sizeof(STARTUPINFO));
                ZeroMemory(&ProcessInformation, sizeof(PROCESS_INFORMATION));
    
                CreateProcess ("DX-Server.exe", NULL, NULL, NULL, false, NORMAL_PRIORITY_CLASS, NULL, NULL, &StartupInfo, &ProcessInformation);
    
                CloseHandle(ProcessInformation.hProcess);
                CloseHandle(ProcessInformation.hThread);
                return 0;
            case WM_PAINT:
                SendCmd (NULL, FindWindow("DX-Server",NULL),"Test-String\0");
                return 0;
            case WM_DESTROY:
                hwnd_Server = FindWindow("DX-Server","DX-Server");
                SendMessage(hwnd_Server, WM_CLOSE, NULL ,NULL);
                PostQuitMessage (0);
                return 0;
        }
    
        return DefWindowProc (hwnd, iMsg, wParam, lParam);
    }
    
    void SendCmd (HWND Sender, HWND Empfaenger, char* Commando)
    {
        COPYDATASTRUCT *    cds;
        cds = new COPYDATASTRUCT;
        cds->cbData = sizeof(char) * strlen(Commando);
        cds->lpData = Commando;
        cds->dwData  = NULL;
        SendMessage(Empfaenger, WM_COPYDATA, (WPARAM) Sender, (LPARAM) cds);
    
        free(cds);
    }
    

    Server:

    #include <windows.h>
    
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow)
    {
        char        szAppName[] = "DX-Server";
        HWND        hwnd;
        MSG         msg;
        WNDCLASSEX  wndclass;
    
        wndclass.cbSize         = sizeof (wndclass);
        wndclass.style          = CS_HREDRAW | CS_VREDRAW;
        wndclass.lpfnWndProc    = WndProc;
        wndclass.cbClsExtra     = 0;
        wndclass.cbWndExtra     = 0;
        wndclass.hInstance      = hInstance;
        wndclass.hIcon          = LoadIcon (NULL, IDI_APPLICATION);
        wndclass.hCursor        = LoadCursor (NULL, IDC_ARROW);
        wndclass.hbrBackground  = (HBRUSH) GetStockObject (WHITE_BRUSH);
        wndclass.lpszMenuName   = NULL;
        wndclass.lpszClassName  = szAppName;
        wndclass.hIconSm        = LoadIcon (NULL, IDI_APPLICATION);
    
        RegisterClassEx (&wndclass);
    
        hwnd = CreateWindow (szAppName, "DX-Server", WS_OVERLAPPEDWINDOW,
                             CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                             NULL, NULL, hInstance, NULL);
    
        ShowWindow (hwnd, iCmdShow);
        UpdateWindow (hwnd);
    
        while (GetMessage (&msg, NULL, 0, 0))
        {
            TranslateMessage (&msg);
            DispatchMessage (&msg);
        }
    
        return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
    {
        switch (iMsg)
        {
            case WM_DESTROY:
                PostQuitMessage (0);
                return 0;
            case WM_COPYDATA:
                COPYDATASTRUCT * cds;
                cds = (COPYDATASTRUCT *)lParam;
                MessageBox(NULL,(char *) cds->lpData, "Message", MB_OK);
                return 0;
        }
    
        return DefWindowProc (hwnd, iMsg, wParam, lParam);
    }
    

    und hier mal das komische Zeugs was ab und zu mal in der MessageBox auftaucht:

    http://marco.kaminski.bei.t-online.de/files/gedoens.JPG

    [ Dieser Beitrag wurde am 14.04.2003 um 11:46 Uhr von DarkMight1 editiert. ]



  • Ein Tip ins Blaue: Du hast das abschließende Nullbyte vergessen, oder?
    [cpp]
    cds->cbData = sizeof(char) * strlen(Commando) + 1;[/cpp]



  • Deshalb habe ich ja an den übertragenen String \0 mit drangehangen.

    SendCmd (NULL, FindWindow("DX-Server",NULL),"Test-String\0");
    

    Aber das hilft wohl nichts, jetzt funktioniert es jedenfalls !!!

    [ Dieser Beitrag wurde am 14.04.2003 um 14:51 Uhr von DarkMight1 editiert. ]



  • Also... entweder schickst du den String mit 0 rüber, oder du hängst sie serverseitig an die empfangene Zeichenfolge.

    SendCmd (NULL, FindWindow("DX-Server",NULL),"Test-String\0");
    

    hilft natürlich nix!
    [cpp]
    cds->cbData = sizeof(char) * strlen(Commando); // Länge des Strings ohne 0 Zeichen![/cpp]
    ergibt 11, weil strlen das abschließende 0-Zeichen nicht mitzählt. Deshalb sollst du ja noch 1 dazu addieren.
    sizeof(char) * strlen("Test-String\0") == 1 * strlen("Test-String\0") == 11

    Klar?


Anmelden zum Antworten