Mehrere Controls mit einer Funktion subclassen



  • Also, bis jetzt habe ich das sbuclasen von einem Control so gemacht:

    WNDPROC	wProcCtrl;
    
    LRESULT CALLBACK SubClassControl_Callback(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){
    
    	switch(message){
    /*
    do something here
    */
    	}
    	return CallWindowProc(wProcCtrl, hWnd, message, wParam, lParam);
    }
    
    void SubClassControl(HWND hParent, int Ctrl_ID){
    
    	wProcCtrl = (WNDPROC)SetWindowLong(GetDlgItem(hParent, Ctrl_ID), GWL_WNDPROC, (LONG)SubClassControl_Callback);
    }
    

    Damit bin ich bis jetzt ganz gut gefahren. Wie sieht es aber aus, wenn ich nun mehrere Controls gleichen Typs, sagen wir mal Buttons, subclassen möchte. Und die Callback Funktion für alle Buttons das gleiche machen soll. Das geht ja jetzt mit meiner Funktion "SubClassControl_Callback" gar nicht, weil darin ja die Variable wProcCtrl vorkommt. Oder lieg ich da falsch? Haben die Buttons vor dem Subclassen vieleicht auch alle die gleiche WNDPROC. Wie wäre es dann, wenn ich bei Controls unterschiedlichen Types, die ich Subclassen möchte, die gleiche Subclassroutine verwenden möchte, weil zufälligt die Änderung die ich durchführen will, bei den unterschiedliche Controls auf gleiche Art und Weise zu bewerkstelligen sind?



  • Hol Dir einfach mit GetWindowLong die Adresse der Windowsprozedur von verschiedenen Controls und vergleiche die mal.



  • Ja da hast du recht, ich habe das jetzt mal bei einigen Editcontrols probiert und die Adresse für die Original WNDPROC ist die gleiche. Bei Button und Editcontrol unterscheiden sie sich, hab ich eigentlich auch so erwartet.

    Kann man anstelle von

    return CallWindowProc(wProcCtrl, hWnd, message, wParam, lParam);
    

    auch

    return DefWindowProc(hWnd, message, wParam, lParam);
    

    in der Callback Funktion schreiben, damit wäre doch dann mein Problem gelöst?


  • Mod

    WinApi Neuling schrieb:

    Bei Button und Editcontrol unterscheiden sie sich, hab ich eigentlich auch so erwartet.

    Kann man anstelle von

    return CallWindowProc(wProcCtrl, hWnd, message, wParam, lParam);
    

    auch

    return DefWindowProc(hWnd, message, wParam, lParam);
    

    in der Callback Funktion schreiben, damit wäre doch dann mein Problem gelöst?

    1. Kann man nicht davon ausgehen, dass jeder Button die selbe WndProc verwendet. Wenn da eine DLL ist oder ein Hook, kann die jederzeit auch einen subclass durchführen. Man muss also die alte Adresse speichern.
    2. Nein! Man darf in keinem Fall DefWindowProc ausführen. Denn dies bedeutet ja nicht, dass die "Standard" Button Klasse die Nachricht bekommt, sondern der Standard-Windows Handler und der macht in 99% aller Fälle was anderes...
    3. Bei PJ Naughter gibt es einen netten Code für Hook-Wnd oder bei DiLascia CSubclassWnd, der das wunderschön in einer Klasse abbildet.



  • In der Subclass-Funktion CtrlProc musst du schon return CallWindowProc(hwnd,...) zurückgegen, nicht DefWindowProc! Bei mehreren Subclasses mit einer CALLBACK-Funktion unterscheiden sich nur die WNDPROCs der einzelnen Controls. Diese sind am besten in einem globalen Array für beide Funktionen festzulegen.

    [cpp]global:
    WNDPROC OldCtrl[3];

    Dialog-Funktion:

    int id[3]; // Control-IDs
    hwnd hwndCtrl[3]; // Control-HWNDs
    ....

    for(i=0;i<3,i++)
    {
    hwndCtrl[i]=GetWindowDlg(hwndDlg,ID_CTRL);
    OldCtrl[i]=(WNDPROC)SetWindowLong(hwndCtrl[i],GWL_WINDOWPROC,(LONG)CtrlProc);
    }
    ....

    CALLBACK-Funktion CtrlProc:
    int id;
    id = GetWindowLong(hwnd,GWL_ID); // evtl. umrechnen auf Indizes (0,..2)

    // Abfragen auf wParam, lParam

    return CallWindowProc(OldCtrl[id],hwnd,....);[/cpp]



  • Die Lösung mit

    return CallWindowProc(OldCtrl[GetWindowLong(hwnd,GWL_ID) - Ctrl_ID0],hwnd,....);
    

    ist mir auch schon in den Sinn gekommen, d.h. ich numeriere alle Elemente der Controls mit einer fortlaufenden Nummer beginnend mit Ctrl_ID0. Dann erstelle ich ein array of WNDPROC mit der Anzahl der Controls und es sollte mit obigem return-Code funktionieren. Der einzige Wermutstropfen ist, dass bei jedem Aufruf des Eventhandlers immer

    GetWindowLong(hwnd,GWL_ID) - Ctrl_ID0
    

    ausgeführt wird. Stellt dies ein zeitliches, also performantes Problem dar?

    Danke für die Info mit DefWindowProc. Hatte es mal so ausprobiert und der Themed Style des Controls war weg, sowas hab ich dann schon irgendwie erwartet.


  • Mod

    Wirf mal einen Blick auf
    http://www.naughter.com/hookwnd.html

    Das Ding hat alles was man so benötigt ohne komplexe Verwaltung 😉



  • Martin Richter schrieb:

    Wirf mal einen Blick auf
    http://www.naughter.com/hookwnd.html

    Das Ding hat alles was man so benötigt ohne komplexe Verwaltung 😉

    I no speak c++ 😞

    Totzdem vielen Danke für deine Mühe.


  • Mod

    WinApi Neuling schrieb:

    I no speak c++ 😞
    Totzdem vielen Danke für deine Mühe.

    Wie glaubst Du dann entwickeln zu können?
    Der Code ist gut. Auch wnen Du kein englisch kannst schau Dir das Sample an...


Anmelden zum Antworten