WndProc in Klasse... again >.<



  • Hmm, die WndProc wird auch nur von einem Fenster verwendet?



  • in diesem Programm gibts nur ein fenster...
    oder soll ich bei Peekmessage/GetMessage das hWnd mit angeben?
    klappt aber auch so nicht 😞



  • Die zv.jpg zeigt, dass der Zeiger mmm nicht inititialisiert ist.
    Prüf mal, ob sich der Kompiler einen Scherz erlaubt hat :

    // hier einen Breakpoint und kontrollieren 
    // ob bei jeder Message der Zeiger auf NULL gesetzt wird
    static MMMUSIC *mmm = NULL;
    

    Ich kann es mir zwar nicht vorstellen, aber wer weiss...
    Danach prüf mal ob es läuft wenn die lokale Variable mmm global ist.



  • beobachtung: bei WM_CREATE wird alles richtig zugewiesen, in den nächsten 2 Durchläufen (die jeweils beim DefWindowProc() enden, stimmt alles, beim dritten wird der Zeiger auf irgendeinen wert gesetzt

    hab das auch so versucht:

    static MMMUSIC *mmm = NULL/* = new MMMUSIC*/;
    	if(mmm) mmm = (MMMUSIC*) ((LPCREATESTRUCT)GetWindowLong(hWnd, 0))->lpCreateParams;
    	switch(msg)
    	{
    	case WM_CREATE:
    		SetWindowLong(hWnd, 0,(LONG) lParam);
    		mmm = (MMMUSIC*) ((LPCREATESTRUCT)GetWindowLong(hWnd, 0))->lpCreateParams;
    		mmm->InitDirectShow();
    		break;
    

    hat aber auch keine wirkung (wcex.cbWndExtra = 4; natürlich)

    EDIT: bei weiteren durchläufen ändert sich der zeiger ab und zu auch noch paar mal, mal 0x0000000f mal 0xfeeefeee mal sonst irgendwas...
    Ich versteh ganix mehr



  • Azrael, il Meraz schrieb:

    beim dritten wird der Zeiger auf irgendeinen wert gesetzt

    Das ist der Schlüsselsatz. Also nicht NULL sondern "irgendwas/wo".
    Probier mal so :

    ...
    case WM_CREATE:
     SetWindowLong(hWnd, 0,(LONG) lParam); // setzt voraus, dass lParam *mmm ist
    // mmm = (MMMUSIC*) ((LPCREATESTRUCT)GetWindowLong(hWnd, 0))->lpCreateParams;
     mmm = (MMMUSIC*) GetWindowLong(hWnd, 0);
     mmm->InitDirectShow();
     break;
    ...
    


  • so kommt er garnicht dazu, einen richtigen Zeiger zu bekommen - der is dann schon von anfang an verwirrt. bei WM_CREATE wird schon irgendein schrott zugewiesen...

    hmmm... weiß nicht warum, aber nun wird der Zeiger zwar nicht verändert, aber die daten der instanz werden überschrieben.. (also mit createstruct jetzt)

    EDIT: hab ma die ganze sache geuppt ( da hatte ich noch ne kranke lösung ausprobiert xD):
    http://xcpp.de/ressources/cpp/MulMed.rar



  • Das Set/GetWindowLong () und die CREATESTRUCT brauchst Du nur, wenn die WndProc in einer Klasse ist.
    Allerdings ist sie das nicht. Deshalb reicht folgendes :

    // so übergeben :
    INT WINAPI WinMain (...) {
    ...
     MMMUSIC *mmm = new (MMMUSIC);
    ...
     CreateWindowEx (...,mmm);
    ...
     delete (mmm);
    ...
    }
    
    // so initialisieren :
    LRESULT WINAPI WndProc(...) {
    ...
     static MMMUSIC *mmm = 0;
    ...
      case WM_CREATE : {
       mmm = (MMMUSIC *) lParam;
       mmm -> InitDirectShow();
       break;
      }
    ...
    }
    


  • ne - geht auch nicht 😣 hab ausprobiert. aber eigentlich will ich das ja auch den WndProc in die klasse tun, hier ist halt nur ein anderes Beispiel. Ich vertseh überhauptnicht, wie das nicht klappen kann...



  • hmmm - ich hab mir jetzt ne eigene Message definiert, damit geht das Oo

    #define WM_MMMCR WM_USER
    ...
    hWnd = CreateWindowEx(...);
    SendMessage(hWnd, WM_MMMCR, NULL, (LONG) mmm);
    ....
    case WM_MMMCR:
    		mmm = (MMMUSIC*) lParam;
    		mmm->InitDirectShow();
    		break;
    ...
    

    total krank, ich glaub, ich fass die WM_CREATE net mehr an...

    mal schaun, ob das auch mit SetWindowLong klappt und den member-wndproc...



  • Such lieber eine geeignete Stelle, wo "mmm->InitDirectShow()" aufgerufen wird.
    Vielleicht gleich nach CreateWindowEx () in der WinMain :

    // hier rein :
    WinMain (...)
    ...
    CreateWindowEx (...,mmm);
    mmm -> InitDirectShow();
    ...
    
    // hier raus :
    WndProc (...)
    ...
     case WM_CREATE : {
        mmm = (MMMUSIC *) lParam;
    //    mmm -> InitDirectShow();
        break;
       }
    ...
    


  • ne - klappt nicht - der zeiger ist wieder verwirrt...

    Ist die Lösung mit eigener Nachricht irgendwie schlechter Stil?



  • merker schrieb:

    case WM_CREATE:
        mmm = (MMMUSIC *)lParam;
        break;
    

    Win32 Programmer's Reference schrieb:

    WM_CREATE

    lParam

    Value of lParam. Points to a CREATESTRUCT structure that contains information about the window being created.

    Ich hab das Problem in C auch mal gehabt...



  • Ahhh, Dank an "keksekekse" für den Hinweis 🙂

    Funktioniert folgendes Casting :

    WinProc (...)
    ...
     case WM_CREATE : {
    //  mmm = (MMMUSIC *) lParam;
      mmm = (MMUSIC *) ((LPCREATESTRUCT) lParam) -> lpCreateParams;
      mmm -> InitDirectShow();
      break;
     }
    

    P.S.: Eigene Nachrichten sind kein schlechter Stil.



  • ne - immer noch verwirrter zeiger.

    Was spricht dann gegen ne eigene Nachricht?



  • Nichts spricht gegen die eigene Nachricht. Das ist auch eine schöne und saubere Lösung.
    Schliesslich geht es nur darum, einen in der WinMain erzeugten Zeiger zu übergeben.

    Mich verwirrt jetzt nur, warum der Zeiger nicht via "CreateWindowEx (..., mmm)" und WM_CREATE mit "mmm = (MMUSIC 😉 ((LPCREATESTRUCT) lParam) -> lpCreateParams" korrekt übergeben werden konnte.

    Aber das muss jetzt nicht das Problem sein 🙂



  • Also bei mir funktioniert der Code einwandfrei. Schau doch mal, per debugging printf(xyz) was genau bei Dir mit WM_CREATE ankommt. Mein Verdacht ist dahingehend, daß Klassenvariablen dynamisch sind oder so. Neue Idee: Ich versuchs mal auch mit ner c++-Klasse.

    #include <windows.h>
    #include <stdio.h>
    
    long _stdcall WndProc(HWND hwnd, unsigned int message, unsigned int wParam,
                                                                       long lParam)
    {
      HDC hdc;
      PAINTSTRUCT ps;
      CREATESTRUCT *lpcs;
      static long iAABBCCDD;
      char o[1000];
    
      switch(message)
    	{ case WM_CREATE:
    		  lpcs = (CREATESTRUCT *)lParam;
    		  iAABBCCDD = (long)(lpcs->lpCreateParams);
    		  return 0;
    	  case WM_PAINT:
    	      hdc = BeginPaint(hwnd, &ps);
    		  _snprintf(o, sizeof(o), "0x%08lX", iAABBCCDD);
              TextOut(hdc, 10, 10, o, strlen(o));
    		  EndPaint(hwnd, &ps);
    	      return 0;
    	  case WM_DESTROY:
    		  PostQuitMessage(0);
        }
      return DefWindowProc(hwnd, message, wParam, lParam);
    }
    
    int _stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                                                     char *szCmdLine, int iCmdShow)
    {
      HWND hwnd;
      MSG msg;
      WNDCLASS wc;
    
      ZeroMemory(&wc, sizeof(WNDCLASS));
      wc.style         = CS_HREDRAW | CS_VREDRAW;
      wc.lpfnWndProc   = WndProc;
      wc.hInstance     = hInstance;
      wc.hIcon         = LoadIcon(0, IDI_INFORMATION);
      wc.hCursor       = LoadCursor(0, IDC_ARROW);
      wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
      wc.lpszClassName = "mbclass";
      RegisterClass(&wc);
    
      hwnd = CreateWindow("mbclass", "Titel", WS_OVERLAPPEDWINDOW,
    					  CW_USEDEFAULT, CW_USEDEFAULT,
    					  CW_USEDEFAULT, CW_USEDEFAULT,
    					  0, 0, hInstance, (void *)0xAABBCCDD);
      ShowWindow(hwnd, iCmdShow);
      UpdateWindow(hwnd);
    
      while(GetMessage(&msg, 0, 0, 0) > 0)
          DispatchMessage(&msg);
    
      return msg.wParam;
    }
    


  • Ich hab noch eine Idee: Ist die Struktur MMM, deren Zeiger Du übergibst, denn auch nicht "flüchtig", d.h. wird sie freigegeben, nach dem der Zeiger übergeben ist? Das könnte vieles erklären.



  • der code funktioniert bei mir Oo.. aber in meinem fall hatte sich der zeiger am ende ja auch nicht verändert - nur die daten der struktur.... und ne - die mmm wird erst nach der Messageschleife freigegeben



  • Läuft's nun oder nicht ?



  • mit CreateWindowEx() -> nein
    mit eigener nachricht ja

    der zeiger auf die instanz bleibt mit WM_CREATE richtig, aber die daten der instanz werden zerwürfelt


Anmelden zum Antworten