Programmieren mit C++

Borland C++

MFC mit BC++ benutzen

Dialoge aus MFC-Extension-DLLs exportieren

Wie kann man Dialoge aus MFC-Extension-DLLs exportieren?

Frage

Auf den ersten Blick scheint es sehr einfach zu sein, Dialoge von MFC-Extension-DLLs zu exportieren. Es genügt, die entsprechende Klasse mittels AFX_EXT_CLASS zu exportieren - und die Angelegenheit sollte erledigt sein. Baut man eine Anwendung und ggfs. DLLs komplett neu auf, wird es in der Regel auch problemlos funktionieren. Mit zunehmender Anzahl Änderungen und Erweiterungen in Anwendung, DLL und Ressourcen kommt es dann jedoch meist zu schwer lokalisierbaren Bugs, die letztlich auf eine einfache Ursache zurückzuführen sind:

Die übliche Vorgehensweise zur Adressierung von Ressourcen sind IDs, die in Form einer Integer-Konstante im Ressourcen-Editor definiert werden. Damit lassen sich Text-Ressourcen über einen einfachen Aufruf laden.

CString strText;
strText.LoadString( ID_MY_TEXT );
afxDump 

Die Ressourcen-ID wird hier durch die Konstante ID_MY_TEXT dargestellt und der Inhalt der Ressource durch afxdump auf dem debug Fenster ausgegeben. Hierbei kann es jedoch passieren, daß falsche Texte aus MFC-Extension-DLLs geladen werden. Der Grund hierfür ist, daß sowohl die Anwendung, als auch die DLLs Ressourcen besitzen und diese ggfs. gleiche Ressourcen-IDs für unterschiedliche Ressourcen verwenden.

Beim Zugriff auf Ressourcen, sucht die Anwendung naturgemäß zunächst in den Ressourcen der Anwendung selbst. Anschließend in den Ressourcen von anwendungsspezifischen DLLs und erst zuletzt in MFC-Extension-DLLs. Somit bestimmt die Reihenfolge der Suche, welche Ressource im Falle einer doppelt vergebenen Ressourcen-ID gefunden wird.

Lösung

Zur Abhilfe kann eine Klasse eingesetzt werden, die – bei geringfügigen Änderungen in der DLL Hauptdatei und dem Dialog – einen freien Aufruf eines Dialogs aus beliebigen Quellen gestattet, in der Form

CMyApp::OnDLLDialog()
{
  CDLLDialog dlg;
 
  dlg.DoModal();
}

Eine Export-Funktion wird hier nicht benötigt, da die Klasse intern das Ressourcen-Handle der DLL bei der Konstruktion umsetzt und das ursprüngliche Handle wieder bei der Zerstörung restauriert. Der zugehörige Code der Klasse CEXTDLLState ist recht einfach:

Klasse für sicheren Zugriff

CEXTDLLState::CEXTDLLState()
{
  m_hInstOld = AfxGetResourceHandle();
  AfxSetResourceHandle(extensionDLL.hModule);
}
 
CEXTDLLState::~CEXTDLLState()
{
  AfxSetResourceHandle(m_hInstOld);
}

Damit ist es jedoch noch nicht getan. Einige kleinere Änderungen sind zusätzlich nötig.

Die Dateien ExtDllState.h und ExtDllState.cpp sollten zunächst in ein öffentliches Include-Verzeichnis kopiert werden, damit sie immer im Zugriff sind.

Konstruktor und Destruktor der Klasse CEXTDLLState

Im Hauptfile der DLL, nach dem die DLL benannt ist, befindet sich eine Zeile der Form

static AFX_EXTENSION_MODULE MY_DLL_NAMEDLL = { NULL, NULL };

Wobei die Variable MY_DLL_NAME der Name der DLL ist, die durch den Namen „extensionDLL“ ersetzt wird. Nachfolgend sind folgende Zeilen einzusetzen:

#include "EXTDLLState.h"
#include "ExtDllState.cpp"

Desweiteren muß nach Vorkommen von MY_DLL_NAMEDLL im Rest der Datei gesucht und eventuelle Fundstellen durch „extensionDLL“ ersetzt werden. Da die Variable statisch ist, kann sie nur in dieser Hauptdatei vorkommen, so daß nach Durchsuchen dieser Datei keine weiteren Fundstellen möglich sind. Für den Export des Dialogs muß ferner die Quelldatei der korrespondierenden Dialog-Klasse bearbeitet und

#include "EXTDLLState.h"

eingefügt werden. Die Funktion DoModal() muß überschrieben werden, was am einfachsten mit dem Class Wizard zu bewerkstelligen ist, der jedoch eine Dummy-Zeile einfügt.

int CMyDLLDlg::DoModal()
{
  // TODO: Add your specialized code here and/or call the base class
  return CDialog::DoModal();
}

Die Dummy-Zeile, die mit „TODO“ beginnt, ist wie folgt zu ersetzen:

Änderungen der DLL-Hauptdatei

int CDLLDlgDlg::DoModal()
{
  CEXTDLLState State;
 
  return CDialog::DoModal();
}

Durch diesen Ansatz erhält man einen komfortablen Weg zum Exportieren von Klassen, die Ressourcen verwenden. Allerdings muß man immer darauf achten, daß an allen Stellen, an denen auf Ressourcen zugegriffen wird, CEXTDLLState zuvor definiert wird - ganz speziell bei nichtmodalen Dialogen.

Die Klasse CEXTDLLState kann darüber hinaus an jeder beliebigen Stelle verwendet werden, um auf MFC-Extension-DLLs zuzugreifen. Auch bei nicht eindeutigen Ressourcen-IDs erhält man immer die gewünschten Ressourcen.

Funktion DoModal()





Sachgebiet


© 2009-2012 by Alojado Publishing. Alle Rechte vorbehalten. Ausgewiesene Marken gehören ihren jeweiligen Eigentümern.
Mit der Benutzung dieser Seite erkennen Sie die Nutzungsbedingungen und die Datenschutzerklärung an. Der Betreiber übernimmt keine Haftung für den Inhalt verlinkter externer Internetseiten.
Seite erzeugt 2012-05-20 01:38:56 von textarchiv.alojado.de