Wieder einmal Kapselung.



  • Vielleicht findest du auch hierdrin noch was nützliches:
    http://www.c-plusplus.net/forum/viewtopic.php?t=39356

    Kannst du den Pointer nicht einfach mit SetWindowLong/SetWindowLongPtr in GWL_USERDATA/GWLP_USERDATA speichern 😕



  • PS: wenn jemand ne besser Idee hat zum Thema reflektierende Nachrichten bitte
    melden ...

    Ich hab es gemacht und es ist total einfach. Was ist denn dein Problem?

    Im Parent-Fenster:

    case WM_CTLCOLOREDIT:
        return SendMessage((HWND)lParam, WM_CTLCOLOREDIT + Konstante, wParam, lParam);
    


  • moin meister ...

    kann im Moment nicht auf den Code zugreifen in dem ich es probiert habe.

    Das Problem:
    Wenn ich zum Bsp. eine ListView nehme und deren Inhalt komplett selber
    zeichnen möchte, wird an das Parent (AppWnd) WM_NOTIFY gesendet (von LV)
    Wenn DoNotifyLV eine Methode von CLV ist würde diese jetzt aufgerufen.

    Ich möchte aber von CLV eine CLVOD ableiten.
    Bei Create der APP ein clvod-Objekt erstellen und in der AppWndProc kein WM_Notify abfangen müssen wenn die LV gezeichnet wird.

    "Pseudocode"
    1.)
    // so soll es werden
    AppWndProc()
    ...

    WM_CREATE:
    m_LVOD = (CLVOD*) new CLVOD(hwnd);
    ...
    break;

    WM_NOTIFY:
    break;

    WM_CLOSE:
    delete m_LVOD;
    ...

    2.)
    // so ist es jetzt
    AppWndProc()
    ...

    WM_CREATE:
    m_LVOD = (CLVOD*) new CLVOD(hwnd);
    ...
    break;

    WM_NOTIFY:
    m_LVOD->DoNotify();
    break;

    WM_CLOSE:
    delete m_LVOD;
    ...

    wenn 1.) realisiert werden soll muß die LV in ein eigenes Fenster. In diesem wird WM_NOTIFY abgefangen, wobei die Behandlung von WM_NOTFY in einer virtuellen Methode realisiert wird.

    Das Fenster welches die LV beinhaltet ist dann "meine" LV welche in AppWnd eingesetzt wird.

    Somit wird der Mechanismus der MFC umgangen. Nachteil jedes "eigene Control"
    besteht aus 2 Fenstern und das finde ich ebend nicht so toll.

    mfg
    RB

    Ah warte mal: sehe gerade "Konstante"
    case WM_CTLCOLOREDIT:
    return SendMessage((HWND)lParam, WM_CTLCOLOREDIT + Konstante, wParam, lParam);

    Der Code dürfte denn in der BasisKlasse "CWnd" stehen oder ?
    Wo kommt die "Konstante" her, kann es sein Du zählst die Instanzen Deiner
    Edit-Klasse ?

    hilf mir mal auf die Sprünge ... 😞 Danke



  • moin meister...

    ich hab im moment nicht soviel zeit, ich werde später auf deinen Beitrag antworten, wenn mir was einfällt.

    Ich hab den Reflection Code in meine Fenster-Basisklasse getan (wird also immer ausgeführt), so brauch man kein zweites Fenster für die Controls. So lange alle (Parent-)Fenster mit meiner Library erstellt wurden ist das ja kein Problem.

    Und falls das nicht der Fall ist hab ich noch eine Methode subclass() mit dem man ein Handle an ein Fensterobjekt anbringen und dessen Fensterprozedur subclassen kann.

    Das mit der Konstante hab ich gemacht (so macht es die MFC glaub ich auch), weil wenn man die Original-Message zurücksendet, gibt es Probleme mit einigen Controls in Form eines Stacküberlaufs.

    Die Instanzen zähle ich nicht.



  • moin meister ...

    ok, ich glaube ich verstehe.

    Also wird WM_NOTIFY in BaseWnd abgefangen und zurück nach
    NMHDR.hwndFrom gesendet 🤡 ABER nur wenn es sich um ein Child handelt 🤡

    Zur Konstanten: welchen Wert wählt man dort, damit es zu keinen "Querschlägern" kommt.

    Der Wert der Konstanten wird ja wieder in der KontrolKlasse abgezogen, schon klar, demnach dürfte der Wert fast egal sein. 1 oder so was reicht da. 😕

    Werds heute Abend ausprobieren, habe auch keine Zeit (offiziell).

    mfg
    RB

    DANKE



  • also ich hab für die Konstante WM_USER + 1000 gewählt. (eventuell ist WM_APP besser?) bei 1 könnte ich mir vorstellen das es Konflikte gibt.

    ich hab mir dann eigene Nachrichten definiert:

    const UINT ReflectionBase = WM_USER + 1000;
    
    const UINT WM_NOTIFY_REFLECTED = WM_NOTIFY + ReflectionBase;
    const UINT WM_CTLCOLOREDIT_REFLECTED = WM_CTLCOLOREDIT + ReflectionBase;
    

    und fange dann in dem Control WM_NOTIFY_REFLECTED ab.

    Ich ziehe da nichts wieder ab.

    f :p



  • f schrieb:

    const UINT ReflectionBase = WM_USER + 1000;
    
    const UINT WM_NOTIFY_REFLECTED = WM_NOTIFY + ReflectionBase;
    const UINT WM_CTLCOLOREDIT_REFLECTED = WM_CTLCOLOREDIT + ReflectionBase;
    

    Ich habe gerade keine Doku zur Verfügung, aber bist du sicher, dass durch die Addition nicht der WM_USER-Bereich verlassen wird?
    Du darfst nicht beliebige Zahlen zu WM_USER addieren, das kann ins Auge gehen.



  • Danke für den Hinweis. Dass hatte ich gar nicht beachtet. 🙄

    WM_USER + 1000 ist aber nur 2024.

    Die MFC nimmt 0xBC00 (48128)



  • Es ging wohl eher um die Addition von WM_NOTIFY bzw. WM_CTLCOLOREDIT 😉



  • Okay. Der WM_USER Bereich geht laut Doku von WM_USER bis 0x7FFF.

    Also 1024 - 32767.

    Alle Nachrichten die man reflektieren muss liegen unter WM_USER (1024).

    Also dürfte ich im sicheren Bereich liegen. 🤡



  • moin meister ...

    habe nun ne ganze Weile schon versucht Deinem Vorschlag zu folgen.
    In der Theorie ist auch alles klar soweit.
    In der Praxis haberts gewaltig 😞

    Meine BaseWndProc (static):

    LRESULT CALLBACK MBWnd::DispatchWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {    
    	MBWnd* pWnd;
    
    	if ((message == WM_NCCREATE) || (message == WM_CREATE))    
    	{        
    		pWnd       = (MBWnd *) ((LPCREATESTRUCT) lParam)->lpCreateParams;        
    		pWnd->hWnd = hWnd;         
    		SetWindowLong (hWnd, 0, (LONG) pWnd);    
    	}    
    	else if (message == WM_GETMINMAXINFO)    
    	{        
    		return (0);    
    	}    
    	else    
    	{
    		// hier Nachrichten "reflektieren"
    		switch(message)
    		{
    		case WM_CTLCOLOREDIT:
    			pWnd = (MBWnd *) GetWindowLong ((HWND)lParam, GWL_USERDATA);
    			message = WM_CTLCOLOREDIT_REFLECT;
    			break;
    
    		default:
    			pWnd = (MBWnd *) GetWindowLong (hWnd, 0);
    		}
    	}     
    
    	return (pWnd->WindowProc (message, wParam, lParam));
    }
    

    CMainWnd ist von CBaseWnd genauso abgeleitet wie CEdit oder CButton usw.
    Nur bei Create wird bei den Controls nicht der this-Zeiger mit übergeben.
    Anstatt dessen wird SetwindowLong auf GWL_USERDATA verwendet, was schon mal schlecht ist, wenn doch wer anders GWL_USERDATA für eigene Zwecke verwenden möchte. Bis jetzt kenne ich aber noch keinen zum Glück 😃

    So wie es jetzt ist funktioniert es ja wenigstens.

    Ich möchte aber nicht die Button::WndProc wie jetzt aufrufen sondern
    SendMessage verwenden.

    Ok. ich könnte CEdit subclassen. Aber diese SubClassProc müßte doch wieder
    static in CEdit sein und der this-Zeiger fehlt mir.

    Ich könnte also wieder GWL_USERDATA verwenden um dann in der subclassproc den this-Zeiger für das CEdit zu erhalten. Aber ebend das möchte ich ja nicht, wenn
    doch noch ein Wahnsinniger kommt und die "tolle" KlassenLib verwenden will
    * was nicht zu hoffen ist *

    Ich habe schon überlegt mit SetProp/GetProp zu arbeiten

    SetProp(hwnd, "this", this);

    Letztlich möchte ich aber auch von einem "maskierten" Edit ein "farbiges maskiertes" Edit ableiten können. Das wird mit ner statischen SubProc auch nichts.

    Also SubProc -> this-Zeiger (GetProp) holen -> (z.B) OnChar() aufrufen. So daß alle gesubclassten Nachrichten wieder in die CEdit ( oder abgeleitet von CEdit ) Klasse weitergereicht werden.

    Aber das erreiche ich mit der jetzigen Lösung dummerweise auch, nicht anderes
    nur ohne SendMessage.

    Ich denke mal ich sehe den Wald vor Bäumen nicht.

    Besten Dank im Voraus
    mfg
    RB



  • moin...

    habs bei mir mit nem Thunk gemacht.

    infos hier: http://www.codeproject.com/atl/atl_underthehood_5.asp

    finde ich die beste lösung. 🙂



  • Hallo !!

    Für jedes Fenster eine neue Instanz erzeugen und dann die jeweiligen Fenster-Handles im Hauptfenster-Objekt als Array speichern ??

    Gruß, J.



  • Oder, wenn die Aufgaben der jeweiligen Fensterobjekte rechenintesiv sind:
    Das Eltern-Objekt in nen Server- und jedes Child-Objekt in einen eigenen Thread schicken ?
    Hmmm...hab das selbst aber noch nie gemacht.



  • moin meister ...

    @f:
    werds mal mit Thunk probieren ... Danke.
    Bin aber kein Fan davon, weil ich evtl. die Ergebnisse meiner Versuche auch noch auf PalmOS übertragen möchte, wenn es denn geht, und hier dürfte das mit Asm (Motorola-, Intel-, TI-Prozessoren) etwas anders funktionieren ...
    Ist aber nur als Ausblick und steht derzeit nicht an.

    @Joe:
    Rechenintensiv ? Nein mir geht nur darum, ohne MFC, weil ich die nicht habe
    mal wenigstens die Grundelemente der GUI in Klassen zu packen.
    Ich möchte denn aber schon sicher stellen, daß Ableitungen ohne Probleme
    und Einschränkungen möglich sind.

    mfg
    RB

    PS: dürfte bald alle Möglichkeiten durch haben 🙂


Anmelden zum Antworten