Ich brauche Hilfe beim Arbeiten mit CSplitterWnd
-
Guten Tag
Ich verwende Visual Studio.Net 2003.
Ich habe folgendes Problem:
Ich will eine simple von CFormView abgeleitete SDI-Anwendung mit geteiltem Fenster erstellen.
Dazu habe ich 2 Dialoge erstellt und in CMainFrame dem CSplitterWnd hinzugefügt.BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/, CCreateContext* pContext) { if(!m_wndSplitter.CreateStatic(this,1,2)) return FALSE; if(!m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CMyTerminalView1), CSize(0,0),pContext)) return FALSE; if(!m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CMyTerminalView2), CSize(0,0), pContext)) return FALSE; return TRUE;Wenn ich das Programm erstelle wenn die Dialogfenster sind wie sie erstellt wurden, funktioniert alles.
Doch sobald ich bei einem der View's ein Bedienelement mit Membervariable erstelle, bekomme ich folgende Fehlermeldung: "Fehler beim Erstellen eines leeren Dokuments.".
Der Fehler wird in der Funktion AssertValid der View-Klasse erzeugt.
Weiters ist mir aufgefallen dass das Programm immer noch im Task Manager angezeigt wird obwohl es beendet wurde.Weis zufälligerweise was ich falsch gemacht habe?
mfg Sepp
-
Poste doch mal den Quellcode der AssertValid
-
Tag
Die AssertValid Funktion ist die vom Wizzard erstellte und wurde von mir nicht verändert.
Der Quellcode der 1. View:
// MyTerminalView1.cpp : Implementierung der Klasse CMyTerminalView1 // #include "stdafx.h" #include "MyTerminal.h" #include "MyTerminalDoc.h" #include "MyTerminalView1.h" #ifdef _DEBUG #define new DEBUG_NEW #endif IMPLEMENT_DYNCREATE(CMyTerminalView1, CFormView) BEGIN_MESSAGE_MAP(CMyTerminalView1, CFormView) END_MESSAGE_MAP() CMyTerminalView1::CMyTerminalView1() : CFormView(CMyTerminalView1::IDD) , m_strHistorie(_T("")) { EnableActiveAccessibility(); } CMyTerminalView1::~CMyTerminalView1() { } void CMyTerminalView1::DoDataExchange(CDataExchange* pDX) { CFormView::DoDataExchange(pDX); DDX_Text(pDX, IDC_EDIT_HISTORIE, m_strHistorie); } BOOL CMyTerminalView1::PreCreateWindow(CREATESTRUCT& cs) { return CFormView::PreCreateWindow(cs); } void CMyTerminalView1::OnInitialUpdate() { CFormView::OnInitialUpdate(); GetParentFrame()->RecalcLayout(); ResizeParentToFit(); } #ifdef _DEBUG void CMyTerminalView1::AssertValid() const { // Hier erzeugt dass Programm den Fehler CFormView::AssertValid(); } void CMyTerminalView1::Dump(CDumpContext& dc) const { CFormView::Dump(dc); } CMyTerminalDoc* CMyTerminalView1::GetDocument() const // Nicht-Debugversion ist inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMyTerminalDoc))); return (CMyTerminalDoc*)m_pDocument; } #endif //_DEBUGDie Include:
// MyTerminaldView1.h : Schnittstelle der Klasse CMyTerminalView1 // #pragma once #include "MyTerminalDoc.h" class CMyTerminalView1 : public CFormView { protected: // Nur aus Serialisierung erstellen CMyTerminalView1(); DECLARE_DYNCREATE(CMyTerminalView1) public: enum{ IDD = IDD_MYTERMINAL_1_FORM }; // Attribute public: CMyTerminalDoc* GetDocument() const; // Operationen public: // Überschreibungen public: virtual BOOL PreCreateWindow(CREATESTRUCT& cs); protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-Unterstützung virtual void OnInitialUpdate(); // Erster Aufruf nach Erstellung // Implementierung public: virtual ~CMyTerminalView1(); #ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif protected: // Generierte Funktionen für die Meldungstabellen protected: DECLARE_MESSAGE_MAP() private: // Sobald diese Variable hinzugefügt wird, wird der Fehler erzeugt. CString m_strHistorie; }; #ifndef _DEBUG // Debugversion in MyTerminalSendView.cpp inline CMyTerminalDoc* CMyTerminalView1::GetDocument() const { return reinterpret_cast<CMyTerminalDoc*>(m_pDocument); } #endifKönnte mir jemand verraten was ich falsch gemacht habe?
mfg Sepp
-
Ja ich weiß. Zeig bitte trotzdem den Code.
-
Achso, du willst den Code von AssertValid haben.
Hier ist die Funktion AssertValid und die dahinterliegenden Funktionen:
//ViewForm.cpp void CFormView::AssertValid() const { CView::AssertValid(); }//ViewCore.cpp void CView::AssertValid() const { CWnd::AssertValid(); }//WinCore.cpp void CWnd::AssertValid() const { if (m_hWnd == NULL) return; // null (unattached) windows are valid // check for special wnd??? values ASSERT(HWND_TOP == NULL); // same as desktop if (m_hWnd == HWND_BOTTOM) ASSERT(this == &CWnd::wndBottom); else if (m_hWnd == HWND_TOPMOST) ASSERT(this == &CWnd::wndTopMost); else if (m_hWnd == HWND_NOTOPMOST) ASSERT(this == &CWnd::wndNoTopMost); else { // should be a normal window ASSERT(::IsWindow(m_hWnd)); // should also be in the permanent or temporary handle map CHandleMap* pMap = afxMapHWND(); ASSERT(pMap != NULL); CObject* p; ASSERT((p = pMap->LookupPermanent(m_hWnd)) != NULL || (p = pMap->LookupTemporary(m_hWnd)) != NULL); ASSERT((CWnd*)p == this); // must be us // Note: if either of the above asserts fire and you are // writing a multithreaded application, it is likely that // you have passed a C++ object from one thread to another // and have used that object in a way that was not intended. // (only simple inline wrapper functions should be used) // // In general, CWnd objects should be passed by HWND from // one thread to another. The receiving thread can wrap // the HWND with a CWnd object by using CWnd::FromHandle. // // It is dangerous to pass C++ objects from one thread to // another, unless the objects are designed to be used in // such a manner. } }Der Fehler tritt nach dem Ausführen von CMyTerminalView1::PreCreateWindow auf.
Nachdem diese Funktion ausgeführt wird, wird mehrmals hintereinander AssertValid ausgeführt, bis der Fehler auftritt( Beim 5 mal tritt der Fehler auf).
m_hWnd in AssertValid von WinCore.cpp ist dabei NULL.Warum das m_hWnd aufeinmal NULL wird kann ich nicht herausfinden.
mfg Sepp
-
Schau Dir beim Debuggen einfach mal den Callstack an, wenn so ein ASSERT auftritt.
Dann wird dir evt. klar was Du evtl. versäumt hast.Die Ursache hier: Dein CView Zeiger bzw. Dein Objekt ist ungültig.
-
Tag
Leider reicht mein Programmierkönnen nicht aus den Fehler in meinem Quählcode zu finden.
Kann mir eventuell jemand sagen was ich falsch gemacht habe?
Ich habe das Projekt folgendermaßen erstellt:
Als erstes habe ich über den Assistent ein MFC-Projekt erstellt.
Ich habe dabei folgende Standardeinstelluingen geändert:
Ich habe SDI anstatt MDI gewählt.
Ich habe Geteiltes Fenster gewählt.
Ich habe CFormView anstatt CView als Darstellungsklasse gewählt.Als nächstes habe ich einen neuen Dialog vom Typ FormView erstellt und bei dieser View eine neue FormView-Klasse erstellt(CMyTerminalView2).
Als nächstes habe ich OnCreateClient der Klasse CMainFrame folgendermaßen geändert:
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/, CCreateContext* pContext) { if(!m_wndSplitter.CreateStatic(this,1,2)) return FALSE; if(!m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CMyTerminalView1), CSize(0,0),pContext)) return FALSE; if(!m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CMyTerminalView2), CSize(0,0), pContext)) return FALSE; return TRUE; }Wenn ich jetzt kompiliere wird das Projekt fehlerfrei erstellt.
Wenn ich aber in einem der FormView Dialoge ein Bedienelement hinzufüge, und diesem Element eine Membervariable zuweise bekomme ich den Fehler dass Dokument nicht erstellt werde konnte.
Was habe ich falsch gemacht, bzw was habe ich vergessen?mfg Sepp
-
Guten Tag
Ich habe den Fehler gefunden.
Ich habe vergessen das die Eingabe (RichEdit) zu initialisieren.
Dass hat den Fehler verursacht.Mit freundlichen Grüßen
Sepp