Einen CDialog in eine Erweiterungs-DLL packen
-
Ich habe das Ziel Dialoge als Plugins zu verwenden und später über LoadLibary() nachzunutzen. Dazu machte ich bislang folgendes:
- anlegen einer Erweiterungs-Dll
- anlegen eines Dialoges in der Ressourcenansicht
- anlegen einer Klasse für den Dialog mit dem Klassenassistenten
- anpassen der Klasse für die DLL (siehe http://www.codeproject.com/KB/docview/sdicviewdll.aspx)
... und dann rauchts.
in der Dialog-Klasse steht ja
// Dialogfelddaten enum { IDD = IDD_DIALOG1 };diese IDD ist in der resource.h definiert. Wenn ich resource.h einbinde wird das Projekt erfolgreich kompiliert.
Anschließend erstelle ich mir eine mfc-dialog-app und will diesen Dialog wie folgt sichtbar machen:
typedef UINT ( * LPDLLFUNC)(CRuntimeClass**); LPDLLFUNC lpfnDllFunc = NULL; HINSTANCE hDLL = NULL; CDialog *dlg; hDLL = LoadLibrary("FX1.dll"); if(hDLL) { lpfnDllFunc = (LPDLLFUNC)::GetProcAddress(hDLL,"Init"); if (!lpfnDllFunc) { AfxMessageBox("Function not found in DLL"); FreeLibrary(hDLL); return; } CRuntimeClass* pNewViewClass; lpfnDllFunc(&pNewViewClass); ASSERT(pNewViewClass); dlg = (CDialog*)pNewViewClass; dlg->DoModal(); } else { AfxMessageBox("Dll not found!"); }in der Zeile dlg->DoModal(); ist nun endgültig feierabend mit der Fehlermeldung:
Zugriffsverletzung bei lesen an Position sowieso. in der Zeile darüber sehe ich beim Debuggen, dass pNewViewClass->m_lpszClassName meiner selbstgeschriebenen Klasse entspricht. Ich vermute, dass es irgendwas mit den Ressourcen zu tun hat aber sicher bin ich mir auch nicht.Brauche Dringend Eure Hilfe.
Danke, Emu
-
Hier noch fix ein Beispielprojekt: http://www.nukleo.de/files/prj.rar
-
Warum nimmst Du eine Erweiterungs DLL, wenn Du die internen Klassen gar nicht exportierst und verwendest?
Ist die EXE auch so gebaut, dass sie die MFC als DLL-Version verwendet?
-
Hm,... verwende ich die Klasse nicht? siehe FX1.cpp Dll-Hauptdatei:
extern "C" AFX_EXT_API UINT Init(CRuntimeClass** view) { // Replace YourDLLName with the AFX_EXTENSION_MODULE variable above // your DllMain. new CDynLinkLibrary(FX1DLL); // Replace CYourClass with the name of CView derived class you are exposing. *view = RUNTIME_CLASS(vMyCDialog); return(0); }Ich exportiere zwar nicht die Klasse aber eine Funktion, die mir eine Instanz dieser Klasse zurückliefert. Ist so dem oben genannten Beispiel von codeproject entnommen. Bringt am Ende ein paar sehr elegante vorteile mit sich,.... wennet läuft

Und zu 2. ... jau MFC als dll.
-
Das ist doch acuh kompletter Quatch. Du bekommst eine CRuntimeClass/RUNTIME_CLASS und kein Objekt, wenn Du Init in dieser Form ausführst!
Du müsstest mit der erzeugten CRuntimeClass erst ein CreateObjekt durchführen. Dann hast Du ein Objekt auf das Du DoModal ausführen kannst.
-
Entschuldige,.... hab den Code halt nicht richtig verstanden. OK,... hab jetzt folgendes drauß gemacht:
void CTestProject4Dlg::OnBnClickedButton1() { typedef UINT ( * LPDLLFUNC)(CRuntimeClass**); LPDLLFUNC lpfnDllFunc = NULL; HINSTANCE hDLL = NULL; hDLL = LoadLibrary("FX1.dll"); if(hDLL) { lpfnDllFunc = (LPDLLFUNC)::GetProcAddress(hDLL,"Init"); if (!lpfnDllFunc) { AfxMessageBox("Function not found in DLL"); FreeLibrary(hDLL); return; } CRuntimeClass* pNewViewClass; lpfnDllFunc(&pNewViewClass); ASSERT(pNewViewClass); CDialog* pd = (CDialog*)pNewViewClass->CreateObject(); pd->DoModal(); } else { AfxMessageBox("Dll not found!"); } }weiterhin erhalte ich bei DoModal() eine Fehlermeldung:
`Debug Assertion Failed!
Program: ...
File: f:\so\vctools\vc7libs\ship\atlmfc\include\afxwin1.inl
Line: 24
For information ....`
Nochmal'ne neue Version des Projekts:
http://www.nukleo.de/files/prj.rarDanke!!!
-
Eieiei,... manchmal könnt man vom Glauben abkommen aber dann kommt doch wieder etwas Tunnel am Ende des Lichts

Obige Vorgehensweise funktioniert. Beim Anlegen beider Projekte ist auf gleiche Zeichensatz-kodierung Unicode/Multibyte zu achten. Ich habs jetzt mit Unicode und es läuft.
Nun können die Plugins kommen.
CU
-
Normalerweise müsstest Du dann Linker Fehler bekommen, wenn die Module unterschiedlich gebaut sind. Oder verwendest Du etwas noch VC6?
-
hm,... nee. Solche Meldungen erhalte ich nicht. Hier mal der Output, wenn ich die Projektmappe mit unterschiedlicher Codierung kompiliere:
1>------ Neues Erstellen gestartet: Projekt: FX1, Konfiguration: Debug Win32 ------ 1>Die Zwischen- und Ausgabedateien für das Projekt "FX1" mit der Konfiguration "Debug|Win32" werden gelöscht. 1>Kompilieren... 1>stdafx.cpp 1>Kompilieren... 1>FX1.cpp 1>vMyCDialog.cpp 1>Code wird generiert... 1>Ressourcen werden kompiliert... 1>Manifest in Ressourcen wird kompiliert... 1>Verknüpfen... 1>LINK : ..\debug\FX1.dll wurde nicht gefunden oder beim letzten inkrementellen Verknüpfungsvorgang nicht erstellt; vollständige Verknüpfung wird durchgeführt. 1> Bibliothek "..\debug\FX1.lib" und Objekt "..\debug\FX1.exp" werden erstellt. 1>Das Manifest wird eingebettet... 1>Projekt : warning PRJ0018 : Folgende Umgebungsvariablen konnten nicht gefunden werden: 1>$(ConfigName) 1>Das Buildprotokoll wurde unter "file://c:\Dokumente und Einstellungen\schl_em\Desktop\prj\prj\FX1\BuildLog.htm" gespeichert. 1>FX1 - 0 Fehler, 0 Warnung(en) 2>------ Neues Erstellen gestartet: Projekt: TestProject4, Konfiguration: Debug Win32 ------ 2>Die Zwischen- und Ausgabedateien für das Projekt "TestProject4" mit der Konfiguration "Debug|Win32" werden gelöscht. 2>Kompilieren... 2>stdafx.cpp 2>Kompilieren... 2>TestProject4.cpp 2>TestProject4Dlg.cpp 2>Code wird generiert... 2>Ressourcen werden kompiliert... 2>Manifest in Ressourcen wird kompiliert... 2>Verknüpfen... 2>LINK : ..\debug\TestProject4.exe wurde nicht gefunden oder beim letzten inkrementellen Verknüpfungsvorgang nicht erstellt; vollständige Verknüpfung wird durchgeführt. 2>Das Manifest wird eingebettet... 2>Projekt : warning PRJ0018 : Folgende Umgebungsvariablen konnten nicht gefunden werden: 2>$(ConfigName) 2>Das Buildprotokoll wurde unter "file://c:\Dokumente und Einstellungen\schl_em\Desktop\prj\prj\TestProject4\BuildLog.htm" gespeichert. 2>TestProject4 - 0 Fehler, 0 Warnung(en) ========== Alles neu erstellen: 2 erfolgreich, Fehler bei 0, 0 übersprungen ==========Meinste da wäre mit Linker-Meldungen zu rechnen, wenn er dynamisch zur Laufzeit bindet? Beim Ausführen hängt er dann in Datei afxwin1.inl an der Stelle
_AFXWIN_INLINE HINSTANCE AFXAPI AfxGetResourceHandle() { ASSERT(afxCurrentResourceHandle != NULL); return afxCurrentResourceHandle; }für mich auch kein Anzeichen dafür, dass es an falscher Kodierung liegt.
-
Ist mir auch klar. Du castest ja selbst und lädst explizit.
In dem Fall kann der Linker ja nichts machen Würdest Du explizit die DLL-Klasse importieren käme es zu Problemen, weil dann evtl. die Signaturen nicht mehr stimmen...
-
Hi Nukleo, ich habe genau das Problem, welches du gelöst hast. Leider funktioniert der Code ab
CDialog* pd = (CDialog*)pNewViewClass->CreateObject();
pd->DoModal();nicht. Genauer gesagt CreateObject() gibt nix zurück. Folglich schmiert mir DoModal auch ab. Ich wollte mir dein Projekt anschauen, nur ist es lieder nicht mehr verfügbar. Könntest du es noch online stellen?
-
ok, habs doch noch selbst geschaft