Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » VC++ / MFC » Einbinden einer Klasse in ein Visual-Studio-Projekt

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
10.06.2004, 16:48 Uhr
~Bastler
Gast


Hi Leute!

Bin bei der Suche nach einer Antwort auf mein Problem im Netz auf dieses Board gestossen.

Vielleicht könnt Ihr mir ja weiterhelfen.
Bin kein Crack, also wenn machbar eventuelle Antworten ein bischen ausführlicher gestalten.
Vorab vielen Dank,
der Bastler

Jetzt zum Problem:
Ich möchte in meinem Programm mehrere Adressen abspeichern. Habe mir zu diesem Zweck, um nicht unnötigerweise Speicherplatz zu vergeuden, eine doppelt verkette Liste generiert.
Diese Liste wird durch zwei Klassen, die miteinander arbeiten, gemanaged.

Ich brauche also nur noch hergehen und z.B. folgendes initialisieren:
....
LinkedList Adresse;
Adresse.SetNewElement(Name, Strasse); //Name und Strasse vom Typ CString
....
(habe somit also die verkette Liste erzeugt und ein Element in ihr abgelegt)

Ich habe das ganze Gereppel zunächst als Win32-Konsolenanwendung programmiert und getestet. Klappte auch alles wie gewünscht.
Jetzt zum eigentlichen Problem.

Die beiden Klassen sollen jetzt in ein Visual C++ - Projekt eingebunden werden und dort in einem Programm mit GUI ihren Dienst versehen.
Das Hineinkopieren (ich verzichte hier mal bewusst auf das Wort Einbinden) scheint wohl zu funktionieren.
Meine 2 Header- und 2 cpp-Dateien werden im Projekt angezeigt.
In der "Hauptdatei" (die Datei, in der die Zeile CAdresseApp theApp; zu finden ist) konnte ich dann auch problemlos ein Objekt der Liste erzeugen (siehe Code oben).
Wenn ich dann aber in einem anderen Fenster (und damit verbunden in einer anderen C++-Datei in diesem Projekt) wieder auf das Adresse-Objekt zugreifen will, dann mault der Compiler, dass Adresse ein nicht deklarierter Bezeichner sei. Und das, obwohl ich im Kopf dieser Datei per INCLUDE die Datei "LinkedList.h" für die verkette Liste bekannt gemacht habe.

Abschliessend nochmal zum besseren Verständnis, was ich vor habe:
Ich möchte bei Programmstart einmal ein Objekt der verketten Liste erzeugen und später im Programm von mehreren Fenstern aus darauf zugreifen (z.B. neue Adresse ablegen, löschen, ändern,.....)

Wäre wirklich super, wenn mir da jemand weiterhelfen könnte, eventuell gehe ich ja auch von falschen Vorstellungen aus.

Nochmals besten Dank,
Ciao und Tschüss,
der Bastler
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
10.06.2004, 17:06 Uhr
Tommix



Hallo,
wo genau steht dieses "LinkedList Adresse;" ?
Wenn es eine global Variable sein soll (sowas macht man aber nicht) muss es noch in den anderen Dateien per

C++:
extern LinkedList Adresse;


bekannt gemacht werden. Eigentlich wäre es aber besser, das z.B. in die Doc-Klasse, so es diese gibt, als Member einzubauen, zur Not auch in die CAdresseApp.

Gruss, Tommix
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
11.06.2004, 11:43 Uhr
~Bastler
Gast


Hi Tommix!

Erst mal besten Dank, dass Du Dich meinem Problem angenommen hast.

Also:
Die Zeile steht in der Funktion

C++:
BOOL CAdresseApp::InitInstance()

nach den vom Visual Studio generierten Zeilen

C++:
#ifdef _AFXDLL
    Enable3dControls();            // Diese Funktion bei Verwendung von MFC in gemeinsam genutzten DLLs aufrufen
#else
    Enable3dControlsStatic();    // Diese Funktion bei statischen MFC-Anbindungen aufrufen
#endif



Was meinst Du damit, "sowas macht man aber nicht"? Meinst Du globale Variablen zu benutzen oder diese so zu deklarieren?

Und was wäre die DOC-Klasse?

Besten Dank,
der Bastler
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
12.06.2004, 09:08 Uhr
Tommix



Hallo,
man benutzt nach Möglichkeit keine globalen Variablen.
Wenn Du Adresse in einer Funktion deklarierst, ist die Variable auch nur in dieser Funktion gültig. Du kannst die Variable zur Member-Variablen von CAdresseApp machen, in den Du in AdresseApp.h in die Klassendeklaration einfügst:

C++:
class CAdresseApp: public CWinApp
{
...
public:
  LinkedList Adresse;
...
};


Dann kannst Du überall mit

C++:
AfxGetApp()->Adresse


darauf zugreifen. Doc-Klassen gibt es in SDI und MDI Projekten mit Doc-View-Architektur. Die Doc ist zum Speichern von Daten gedacht und die View zum Anzeigen. Das ist in Visual C++ in 21 Tagen" (siehe E-Books) ganz gut beschrieben.

Gruss, Tommix

Dieser Post wurde am 12.06.2004 um 09:10 Uhr von Tommix editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
14.06.2004, 10:56 Uhr
Bastler



Hi Tommix!

Habe Deine Tipps ausprobiert, funktioniert jetzt auch! Hierfür erst mal ein Danke an Dich.

Kurz nochmal alles zusammen gefasst.

Habe jetzt in 'Adresse.cpp' eingefügt:


C++:
...
CAdresseApp::CAdresseApp()
{
    // ZU ERLEDIGEN: Hier Code zur Konstruktion einfügen
    // Alle wichtigen Initialisierungen in InitInstance platzieren
}

/////////////////////////////////////////////////////////////////////////////
// Das einzige CAdresseApp-Objekt

CAdresseApp theApp;
CLinkedList Adresse;        // N E U
...



Danach erschien Adresse in der Klassenansicht unter dem Ordner 'Global'

Habe dann in mit


C++:
extern CLinkedList Adresse;



das Objekt in einer anderen Datei, welche die Funktionen eines weiteren Fensters definiert, bekannt gemacht und konnte dann dort darauf zugreifen


Soweit nochmal zum Nachvollziehen. Der Tipp mit

C++:
AfxGetApp()->Adresse



hat übrigens bei mir nicht funktioniert. Habe bestimmt wieder irgendwas übersehen.

Abschliessend aber noch eine Frage:
Du sagtest ja, dass man globale Objekte/Variablen möglichst vermeiden soll. Ich wüsste jetzt aber keinen anderen Lösungsansatz für mein Vorhaben.
Wie würdest Du so etwas realisieren, wenn Du von verschiedenen Fenstern (also Funktionen) aus immer wieder auf die gleichen Datenmenge zugreifen müsstest. Ich kann doch nicht jedes mal die komplette Adress-Liste an die gerade aktuelle Funktion übergeben?!
Ach ja, mein Projekt ist weder ein SDI noch ein MDI, sondern Dialogfeldbasiert.

Ciao und nochmals Danke,
Bastler
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
14.06.2004, 11:51 Uhr
Tommix



Hallo,

In dem Fall würde ich Liste zur Member-Variablen des Hauptdialoges machen. Die anderen Funktionen bekommen dann einen Zeiger oder eine Referenz:

C++:
void f1(LinkedList* pAdresse)
{
    pAdresse->DoSomething();
}

void f2(LinkedList& adresse)
{
    adresse.DoSomething();
}

// Funktion ändert adresse nicht:
void f3(const LinkedList& adresse)
{
    adresse.NurLeseOperation();
}


Eine Klasse kann sich adresse auch "merken", wenn mehrere Funktionen darauf Zugriff haben sollen:

C++:
CMyClass::CMyClass(LinkedList& adresse): m_adresse(adresse)
// m_adresse ist member vom Typ LinkedList&
{
}

CMyClass::foo()
{
    m_adresse.DoSomething();
}



Gruss, Tommix
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
17.06.2004, 14:50 Uhr
Bastler



Hi!

Ich glaub', oder nein, ich weiss, ich brauch noch mal Hilfe. :

Und zwar:
Du hast geschrieben, das ich Liste zur Member-Variablen des Hauptdialoges machen soll.
Hab' das so verstanden, dass ich in der Klassenansicht mit der rechten Maustaste die Klasse des Hauptdialoges (CAdresseDlg) angeklickt und aus dem Menü "Member-Variable hinzufügen..." gewählt habe. Dort habe ich dann als Variablentyp "CLinkedList" und als Variblenname "m_llAdresse" angegeben und das Teil als "public" (war das korrekt, oder hätte ich besser "privat" nehmen sollen?) definiert.

Visual setzt die Definition dann in die Header-Datei ("AdresseDlg.h") des Hauptdialoges:

C++:
...
class CAdresseDlg : public CDialog
{
// Konstruktion
public:
    CLinkedList m_llAdresse;
    CInterpretDlg(CWnd* pParent = NULL);    // Standard-Konstruktor
    
// Dialogfelddaten
...


In der Klassenansicht taucht die Variable dann auch auf. So weit, so gut.

Wenn ich dann aber in der Initialisierungsroutine "OnInitDialog()" des Hauptdialogfeldes (zu finden in der Datei "AdresseDlg.cpp") z.B. mittels

C++:
m_llAdresse.  ...


auf die Funktionen der Klasse "CLinkedList" zugreifen will, so erscheint nicht mehr das Fensterchen, in dem man aus den möglichen Funktionen mittels up/down auswählen kann. Da stimmt doch bestimmt wieder was nicht. Was hab' ich übersehen?
Tippe ich den Namen der Funktion von Hand ein und lass alles neu erstellen, so ergibt sich aber trotzdem kein Fehler. Der Compiler schluckt und "verdaut" es.
So weit zu meinem jetzigen ersten Problem.

Das Zweite wäre dann folgendes:
Vorausgesetzt, ich hab oben keinen gravierenden Fehler gemacht und mein Vorgehen entspricht in etwa Deinen Vorstellungen, so weiss ich jetzt nicht, wie ich eine Referenz von m_llAdresse an einen vom Hauptdialog (HD) aufzurufenden Nebendialog (ND) übergeben kann. Aufgerufen wird der ND per Klick auf einen Button. Hier der Quelltext dazu:

C++:
void CAdresseDlg::OnAdresse()
{
    // TODO: Code für die Behandlungsroutine der Steuerelement-Benachrichtigung hier einfügen

    m_dAdrDlg.DoModal();      // m_dAdrDlg ist vom Typ CAdrDlg, der Klasse für den ND
}  


Der Funktion "DoModal()" kann ich aber doch keine Parameter mitgeben, oder?
Wie macht man dieses dann?

Vielleicht könntest Du (oder gerne auch jemand anderes) mir noch mal helfen. Hoffe, ich bin nicht zu nervig, aber ich bin leider totaler Beginner was MFC und leicht Fortgeschrittener was C++ angeht. Ihr werdet 's also nicht leicht haben mit mir.

Besten Dank vorab,
Bastler
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
17.06.2004, 15:39 Uhr
Tommix



Hallo,
Du musst dem Nebendialog die m_llAdresse noch bekannt machen, indem Du beispielsweise in dem Nebendialog eine Membervariable vom Typ CLinkedList* m_pAdresse hinzufügst (private) und außerdem Eine public Memberfunktion z.B.

C++:
void CAdrDlg::SetAdresse(CLinkedList* pAdresse)
{
  m_pAdresse = pAdresse;
}


Den Hauptdialog änderst Du dann so:

C++:
void CAdresseDlg::OnAdresse()
{
    // TODO: Code für die Behandlungsroutine der Steuerelement-Benachrichtigung hier einfügen

    m_dAdrDlg.SetAdresse(&m_llAdresse);
    m_dAdrDlg.DoModal();      // m_dAdrDlg ist vom Typ CAdrDlg, der Klasse für den ND
}  


Danach kannst Du in dem Nebendialog über m_pAdresse->SetNewElement(...) usw. auf die Liste zugreifen.

Gruss, Tommix
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ VC++ / MFC ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: