SetFocus() Problem?



  • MSS-Software schrieb:

    die wird in CAQDlg.h deklariert

    CDialog* Pruef_Auf;
    

    Ist das ein Member einer Klasse oder eine globale Variable?

    somit habe ich jetzt in der Test.cpp folgendes gemacht
    ...

    Pruef_Auf = new Handle;
    Handle->pBoxOne->EnableWindow(FALSE);
    

    Entscheide dich. Ist Handle ein Klassenname oder eine Variable? In der ersten Zeile benutzt du es als Klasse, in der zweiten als Zeiger. Es kann nicht beides sein.

    Zu welchem Zweck versuchst du da, eine neue Instanz zu erstellen?



  • zu 1:

    das ist eine Member

    zu 2:

    Handle soll die Instanz von CTest sein

    Wie du schon geschrieben hast, muss ich ja jetzt der Instanz von CTest die richtige Instanz von Pruefplaene zuweisen



  • MSS-Software schrieb:

    das ist eine Member

    Das heißt, die Adresse der "richtigen" Instanz von Pruefplaene ist ein Member einer anderen Klasse (ich vermute mal CAQDlg). Du musst diesen Zeiger (oder einen Zeiger oder eine Referenz auf die Instanz von CAQDlg, die diesen Zeiger beinhaltet) irgendwie dahin bringen, wo du die Instanz von CTest erstellst.

    Gibt es eigentlich irgendein System dahinter, welche Klasse einen Zeiger auf eine andere als Member hat? Ich vermute nämlich so langsam, dass du ein ernstes Designproblem hast. Oder gar kein Design.

    Handle soll die Instanz von CTest sein

    Ich dachte, pBoxOne wäre ein Member von Pruefplaene, nicht von CTest 😕



  • ich mach ma alles von vorne:

    Aufgabe: ich möchte, wenn ich eine Registerkarte klicke, sich ein Editfeld deaktiviert!

    Der Dialog, in dem sich die Registerkarten auch befinden, wird wie folgt aufgerufen:

    CAQDlg.h

    class CCAQDlg : public CDialog
    {
    // Konstruktion
    public:
    	CCAQDlg(CWnd* pParent = NULL);	// Standard-Konstruktor
    	CDialog* Pruef_Auf;
    

    CAQDlg.cpp

    #include "Pruefplaene.h"
    
    void CCAQDlg::OnStammdatenPrfplne() 
    {
    	// TODO: Code für Befehlsbehandlungsroutine hier einfügen
    	Pruef_Auf = new Pruefplaene;
    	Pruef_Auf->Create(IDD_Pruefplaene,NULL);
    	Pruef_Auf->ShowWindow(SW_SHOWNORMAL);
    }
    

    in der Header Datei, für den neuen Dialog, habe ich folgendes als Member gemacht:

    Pruefplaene.h

    CWnd* pBoxOne;
    

    das wird dann in der dazugehörigen cpp Datei bei OnInitDialog initialisiert

    Pruefplaene.cpp

    pBoxOne = GetDlgItem(IDC_Kundenname);
    

    so, da ich ja jetzt in die Klasse für die Registerkarten muss, habe ich bei der Header Datei dieser Klasse folgendes gemacht:

    TABPruefplaene.h

    class Pruefplaene;
    
    Pruefplaene* Handle; //Member
    

    und in der dazugehörigen cpp Datei dieses hier:

    TABPruefplaene.cpp

    #include "CAQDlg.h"
    #include "Pruefplaene.h"
    
    void CTABPruefplaene::OnLButtonDown(UINT nFlags, CPoint point) 
    {
    	Handle = new Pruef_Auf;
    	Handle->pBoxOne->EnableWindow(FALSE);
    	CTabCtrl::OnLButtonDown(nFlags, point);
    	if (m_aktuelleSeite != GetCurFocus())
    	{
    		m_tabellenSeite[m_aktuelleSeite]->ShowWindow(SW_HIDE);
    		m_aktuelleSeite = GetCurFocus();
    		m_tabellenSeite[m_aktuelleSeite]->ShowWindow(SW_SHOW);
    		m_tabellenSeite[m_aktuelleSeite]->SetFocus();
    	}
    }
    


  • ich bin schon die ganze zeit am überlegen, wie ich auf diese instanz zugreife

    aber mir fällt bei gott nichts ein



  • kann man nicht die Instanz per Funktion übergeben?

    irgendwie so nach dem Motto:

    Pruef_Auf = new Pruefplaene;
    Pruef_Auf = Create(IDD_Pruefplaene);
    Pruef_Auf = ShowWindow(SW_SHOW);
    Uebergabe(Pruef_Auf);
    

    Und diese Funktion wäre dann in der CPP deklariert, wo ich die Instanz auch brauche.

    void Uebergabe (??? Instanz)
    {
         Handle = Pruef_Auf;    //Global deklariert in der CPP als Typ ???
    }
    

    Die ??? deshalb, weil ich noch nicht wirklich drüber nachgedacht habe, was das für ein Typ sein könnte.

    Im weiteren Programm würde ich das dann so anwenden:

    Handle.pBoxOne->EnableWindow(FALSE);
    

    Theoretisch möglich???



  • was für einen Datentyp müsste ich da denn nehmen?

    Also Pruef_Auf hat folgende deklaration:

    Pruefplaene Pruef_Auf; //Member in der Header
    
    Pruef_Auf = new Pruefplaene;
    


  • MSS-Software schrieb:

    was für einen Datentyp müsste ich da denn nehmen?
    Also Pruef_Auf hat folgende deklaration:

    Pruefplaene Pruef_Auf; //Member in der Header
    
    Pruef_Auf = new Pruefplaene;
    

    new gibt dir einen Zeiger zurück. Das sind aber absolute Grundlagen.

    MSS-Software schrieb:

    Pruef_Auf = new Pruefplaene;
    Pruef_Auf = Create(IDD_Pruefplaene);
    Pruef_Auf = ShowWindow(SW_SHOW);
    Uebergabe(Pruef_Auf);
    

    Und diese Funktion wäre dann in der CPP deklariert, wo ich die Instanz auch brauche.

    Existiert denn zu diesem Zeitpunkt schon die Instanz der Klasse, an die du den Zeiger übergeben musst?

    Dein Hauptproblem liegt nicht in der Organisation der .h und .cpp-Dateien und der Includedirektiven. Du konzentrierst deine Lösungsansätze darauf, was wo deklariert wird, und wer was includet. Dein Programm ist aber kein statisches Gebilde. Dass die Deklaration einer Klasse an einer bestimmten Stelle im Code bekannt ist, stellt den Compiler zufrieden. Aber die Lebenszeit und den Zugriff auf deine Instanzen musst du selbst koordinieren. Dein Hauptproblem ist die fehlende Übersicht darüber, wann und wo eine Instanz von welcher Klasse angelegt wird, und wo du diese Instanz wieder brauchst. Du könntest möglicherweise Referenzen statt Zeigern benutzen, denn die musst du initialisieren.

    Oder wie wäre es, wenn du eine Singleton-Klasse anlegst, die die ganzen Zeiger auf deine Dialoge speichert und bei Bedarf wieder rausgibt? Das wäre zumindest mal ein System:

    [cpp]
    Pruef_Auf = new Pruefplaene;
    Merker::Instance().SetPruef(Pruef_Auf);
    [/cpp]

    // später, da, wo du es brauchst:
    Merker::Instance().GetPruef().pBoxOne->EnableWindow(FALSE);
    

    Ansonsten würde ich dir empfehlen, das ganze Thema Klassen und Instanzen an einem viel einfacheren Projekt noch mal gründlich durchzuarbeiten. Diese Flickschusterei bringt dich langfristig nicht weiter.



  • ja, da hast du recht

    hast du denn mal nen Link oder so zu einem guten Tut?

    von welcher Basisklasse sollte dieser Merker denn sein?



  • MSS-Software schrieb:

    hast du denn mal nen Link oder so zu einem guten Tut?

    Auf http://www.c-plusplus.net gibt's eine Menge gute Links. 😉



  • ich hab jetzt mal völlig neu gedacht

    ich mache jetzt nur noch eine Instanz, die ich da erstelle, wo ich sie auch brauche

    hab das jetzt so gelöst:

    Aufruf.cpp

    #include "TABPruefplaene.h"
    

    [cpp]
    void CCAQDlg::OnStammdatenPrfplne()
    {
    // TODO: Code für Befehlsbehandlungsroutine hier einfügen
    CTABPruefplaene::Create();
    }
    [/cpp]

    TABPruefplaene.h

    class Pruefplaene;    //als class gemacht, wegen der Header Probleme
    

    [cpp]
    class CTABPruefplaene : public CTabCtrl
    {
    // Konstruktion
    public:
    CTABPruefplaene();
    int m_aktuelleSeite;
    int m_Seitennummern;
    CDialog* m_tabellenSeite[4];
    Pruefplaene Pruef_Auf;*
    ....
    ....
    ....
    static afx_msg void Create();
    [/cpp]

    TABPruefplaene.cpp

    void CTABPruefplaene::Create()
    {
    	Pruef_Auf = new Pruefplaene;
    	Pruef_Auf->Create(IDD_Pruefplaene);
    	Pruef_Auf->ShowWindow(SW_SHOW);
    }
    

    Jetzt hab ich die Instanz auch da, wo ich sie brauche. Nun tut siche aber ein anderes kleines Problem auf, was ich nicht so ganz verstehe:

    Compiler meldet:

    error C2597: Ungueltige Referenz auf ein Datenelement 'CTABPruefplaene::Pruef_Auf' in einer statischen Member-Funktion

    error C2227: Der linke Teil von '->Create' muss auf Klasse/Struktur/Union zeigen

    error C2227: Der linke Teil von '->ShowWindow' muss auf Klasse/Struktur/Union zeigen



  • hab jetzt aus der Statischen Member eine normale gemacht

    void CreateTest();
    

    und den Aufruf so:

    CTABPruefplaene Handle;
    Handle.CreateTest();
    

    funzt jetzt

    Jetzt habe ich folgen Anweisung noch in den Konstruktor geschrieben:

    Pruef_Auf = new Pruefplaene;
    

    Soll den Sinn haben, dass ich diese Instanz für die ganze Klasse zur Verfügung habe. Ich krieg auch keine Fehler und nicht, aber sobald ich auf den Link klicke, der den Dialog öffnen soll, schließ sich auf einmal das ganze Programm.



  • MSS-Software schrieb:

    und den Aufruf so:

    CTABPruefplaene Handle;
    Handle.CreateTest();
    

    Kannst du denn einfach so eine Instanz von CTABPruefplaene erstellen? Ist das auch eine Klasse, die ein Fenster repräsentiert? Hast du nicht vielleicht schon irgendwo eine Instanz dieser Klasse?



  • ja, das ist die Instanz, die vorher den Dialog repräsentiert hat

    ich hab die ursprüngliche entfernt und da halt neu angelegt

    wenn ich

    Pruef_Auf = new Pruefplaene;
    

    mit in die Funktion schreibe, die Create(IDD_....) usw macht, funzt das ja wunderbar, nur sobal ich die in den Kunstruktor packe nicht mehr



  • MSS-Software schrieb:

    ja, das ist die Instanz, die vorher den Dialog repräsentiert hat

    Ist dir klar, dass diese Instanz wieder zerstört wird, wenn CCAQDlg::OnStammdatenPrfplne beendet ist? falls CreateTest keine blockierende Funktion ist - das vermute ich hier einfach mal - lebt dieses Objekt nicht besonders lange.



  • ja klar

    shit, da hab ich gar nicht dran gedacht

    sicher

    ok, wenn ich die Instanz anstatt im konstruktor nun wieder in der CreateTest erzeugen lasse, hab ich denn dann die Möglichkeit, innerhalb derselben Klasse auf diese Instanz in der Funktion zuzugreifen?



  • hab das dann mal so probiert:

    [cpp]
    void CTABPruefplaene::OnLButtonDown(UINT nFlags, CPoint point)
    {
    CTabCtrl::OnLButtonDown(nFlags, point);
    if (m_aktuelleSeite != GetCurFocus())
    {
    m_tabellenSeite[m_aktuelleSeite]->ShowWindow(SW_HIDE);
    m_aktuelleSeite = GetCurFocus();
    m_tabellenSeite[m_aktuelleSeite]->ShowWindow(SW_SHOW);
    m_tabellenSeite[m_aktuelleSeite]->SetFocus();
    CreateTest()::Pruef_Auf->GetDlgItem(IDC_Kundenname)->EnableWindow(FALSE);

    }
    }

    void CTABPruefplaene::CreateTest()
    {
    Pruef_Auf = new Pruefplaene;
    Pruef_Auf->Create(IDD_Pruefplaene, this);
    Pruef_Auf->ShowWindow(SW_SHOWNORMAL);
    }
    [/cpp]

    Abder da sagt er mir, dass Pruef_Auf kein Element von Global namespace ist;

    hab dann versucht die Instanz ganz außerhalb der Funktionen zu erzeugen, wobei ich dann die Fehlermeldung bekomme:

    Fehlende Speicherklasse oder Typspezifiziere

    class Pruefplaene* kann nicht in int konvertiert werden



  • Lass mal das CreateTest():: weg. Was soll das überhaupt?



  • ich muss ja auf die Instanz zugreifen, die in CreateTest() erstellt wird, weil er mir ja sonst wieder nen speicherproblem macht



  • hmm, das Problem liegt woanders

    und zwar hab ich das ja so gemacht in der Routine, wo der Dialog aufgerufen wird:

    #include "TABPruefplaene.h"
    
    CTABPruefplaene Handle;
    Handle.CreateTest();
    

    dann hab ich aber mal den include in die Header Datei der dazugehörigen cpp datei gepackt und das ganze als Member erzeugt:

    CCAQDlg.h

    #include "TABPruefplaene.h"
    
    CTABPruefplaene Handle; //Member
    

    CCAQDlg.cpp

    Handle.CreateTest();
    

    So, das gibt ein wunderbares Phänomen:

    keine Fehler und keine Warnungen, aber er führt mir das Programm nicht aus!!!


Anmelden zum Antworten