WNDCLASS in einer DLL registrieren?



  • Kann ich in einer DLL eine Windowclass registrieren, um die dort geschriebenen WndProcs in anderen Programmen zu benutzen?
    Bspw. will ich in meinem Programm momentan eine bestimmte Statusleiste anzeigen, die WndProc ist in der DLL gespeichert, nur muss ja eine Klasse für die Prozedur registriert werden. Und das wollte ich direkt in der DllMain-Funktion machen. Scheint aber nicht zu klappen. Geht das überhaupt?
    Falls das etwas unverständlich wirkt, ich hänge mal Beispielcode an:

    #include <windows.h>
    #include "blabli.h"
    
    int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
    {
    	WNDCLASS		wc;
    	wc.style		= NULL;
    	wc.lpszMenuName = NULL;
    	wc.lpszClassName= TEXT ("statusleiste");
    	wc.lpfnWndProc	= WndProc_LoadingString;
    	wc.hInstance	= hInstance;
    	wc.hIcon		= NULL;
    	wc.hCursor		= NULL;
    	wc.cbWndExtra	= NULL;
    	wc.cbClsExtra	= NULL;
    
    #ifdef UNICODE
    	RegisterClassW (&wc);
    #else
    	RegisterClassA (&wc);
    #endif
    	return TRUE;
    }
    
    EXPORT LRESULT CALLBACK StatusLeisteProcA (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    // Code
    }
    
    EXPORT LRESULT CALLBACK StatusLeisteProcgW (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    // Code
    }
    
    //////////////////Anderes Programm
    
    hWndStatusLeiste = CreateWindow (TEXT ("statusleiste")//...
    


  • Eventuell hilft CS_GLOBALCLASS



  • Klappt irgendwie auch nicht 😞



  • Prüf mal den Rückgabewert von RegisterClass()

    (Ich meine auch mal in der MSDN mal gelesen zu haben dass man in der DllMain() möglichst nur Funktionen aus der kernel32.dll verwenden soll...)



  • Calling imported functions other than those located in Kernel32.dll may result in problems that are difficult to diagnose.

    Demnach solltest du das Registrieren der Fensterklasse wohl besser in eine Funktion auslagern, die du dann erst später (im Hauptprogramm) aufrufst - so in der Art von InitCommonControls 🙂



  • Du verwendest die falsche hInstance. Dem Windows ist es egal, von wo aus du die Klasse registrierst, aber die hInstance muss von der Applikation sein.



  • Nein, die Instanz der DLL ist schon richtig:

    Platform SDK schrieb:

    Handle to the instance that contains the window procedure for the class.

    ...und die Instanz die die Fensterprozedur enthält ist ja die der dll und nicht die der Anwendung.
    Wenn er sein RegisterClass also in eine InitMeineControls()-Funktion auslagern will, müsste er sich die Instanz in der DllMain schonmal irgendwie als globale Variable oder so sichern.
    ( GetModuleHandle(NULL) kann man nämlich vergessen, da das den instanz-handle der anwendung, welche die dll verwendet, zurückliefert... )



  • Die Richedit-DLL macht das auch in der DllMain. (ein einfaches laden reicht) Also wird das wohl in Ordnung sein!



  • Da hält sich Microsoft wohl an ihre eigenen Regeln nicht 😉
    ...aber ich würd eh ersma einfach Rückgabewerte prüfen - der wird wohl den Grund nennen warum es nicht klappt oder ob die DllMain überhaupt betreten wird (dann läge der Fehler wohl außerhalb der dll...)



  • Und wo steht die Regel? Die einzige Regel ist das man LoadLibrary nicht in der DllMain aufrufen soll.

    So funktioniert es:

    #include <windows.h>
    
    LRESULT CALLBACK ControlWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
    {
    	return DefWindowProc(hWnd, Msg, wParam, lParam);
    }
    
    BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
    {
    	if(fdwReason == DLL_PROCESS_ATTACH)
    	{
    		WNDCLASSEX WindowClass;
    		WindowClass.cbSize = sizeof(WindowClass);
    		WindowClass.lpszClassName = TEXT("Control");
    		WindowClass.lpfnWndProc = ControlWindowProc;
    		WindowClass.cbClsExtra = 0;
    		WindowClass.cbWndExtra = 0;
    		WindowClass.hbrBackground = reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH));
    		WindowClass.style = 0;
    		WindowClass.lpszMenuName = NULL;
    		WindowClass.hInstance = hinstDLL;
    		WindowClass.hIcon = NULL;
    		WindowClass.hIconSm = NULL;
    		WindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    
    		return RegisterClassEx(&WindowClass) != 0;
    
    	}
    
    	return TRUE;
    }
    


  • Sorry. Das CS_GLOBALCLASS war im vorherigen Code nicht eingebaut.

    #include <windows.h>
    
    LRESULT CALLBACK ControlWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
    {
    	return DefWindowProc(hWnd, Msg, wParam, lParam);
    }
    
    BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
    {
    	if(fdwReason == DLL_PROCESS_ATTACH)
    	{
    		WNDCLASSEX WindowClass;
    		WindowClass.cbSize = sizeof(WindowClass);
    		WindowClass.lpszClassName = TEXT("Control");
    		WindowClass.lpfnWndProc = ControlWindowProc;
    		WindowClass.cbClsExtra = 0;
    		WindowClass.cbWndExtra = 0;
    		WindowClass.hbrBackground = reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH));
    		WindowClass.style = CS_GLOBALCLASS;
    		WindowClass.lpszMenuName = NULL;
    		WindowClass.hInstance = hinstDLL;
    		WindowClass.hIcon = NULL;
    		WindowClass.hIconSm = NULL;
    		WindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    
    		return RegisterClassEx(&WindowClass) != 0;
    
    	}
    
    	return TRUE;
    }
    


  • Jetzt fällt mir gerade auf das plusman gar nicht cbSize gefüllt hat.



  • Ah könnte schon sein das mit der kernel32.dll Der Aufruf einer Funktion aus einer anderen DLL (hier user32.dll) lädt die DLL ja auch implizit.



  • !!!!!!!!!!!! schrieb:

    Jetzt fällt mir gerade auf das plusman gar nicht cbSize gefüllt hat.

    Er nimmt auch noch die alte WNDCLASS, nicht WNDCLASSEX - bei der WNDCLASS gibt es gar kein cbSize...



  • Also, ich habe jetzt mal das Registrieren der WNDCLASSEX nu in einer eigenen Funktion. So weit, so gut. Nur schien das immer noch nicht zu klappen. Also habe ich geprüft, was GetLastError mir dazu sagen vermochte, die Funktion spuckt den Fehler 87 aus, d.h. "The parameter is incorrect." Aber welcher Parameter ist gemeint?
    Ich habe die Funktion jetzt auf WNDCLASSEX angepasst und auch RegisterClassEx verwendet. Nichts!



  • Habe nen bisschen rumprobiert und mit deinem code dasselbe festgestellt.
    Nachdem ich noch
    wc.hbrBackground=NULL;
    ergänzt hatte funktionierte es dann 😉

    Das ganze lässt sich übrigens noch etwas kürzer schreiben:

    int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
    {
        WNDCLASS        wc;
    
        ZeroMemory(&wc,sizeof(WNDCLASS)); // In der WNDCLASS-Struktur alles auf NULL setzen
        wc.lpszClassName= TEXT ("statusleiste");
        wc.lpfnWndProc    = WndProc_LoadingString;
        wc.hInstance    = hInstance;
    
        RegisterClass(&wc); // Fallunterscheidung zu Unicode sollte schon in der windows.h (bzw. winuser.h) drin sein ;D
        return TRUE;
    }
    

Anmelden zum Antworten