In einem SDI zwischen Views wechseln...
-
hi,
ich weiss das thema war schon öfter dran, aber ich bin jetzt noch nicht so richtig schlau draus geworden...
was ich suche ist folgendes: ein SDI-app bei dem man zwischen mehreren FormViews hin und herwechseln kann... so wie hier in der FAQ von estartu_de beschrieben:
http://www.c-plusplus.net/forum/viewtopic.php?t=81908nur mit dem unterschied, dass die View-Doc-Paare nicht wie dort beim hin- und herwechseln gelöscht und neu erstellt werden sollen, sondern beim switchen erhalten bleiben sollen.
hab schon versucht, die views in einer pointer-variablen zu speichern, die beim starten mit der createView funktion gefüttert werden, aber irgendwie überschreibt die funktion immer irgendwas und somit funktioniert immer nur die letzte damit erstellte view.
LG...
-
Vielleicht hilft dies weiter:
void CMainFrame::SwitchToView(CView* pNewView) { // Aktuelle View holen CView *pOldView = GetActiveView(); // Aktuelles Dokument holen CDocument *pDocument = pOldView->GetDocument(); CCreateContext pContext; if(pNewView == NULL) { AfxMessageBox("Konnte View nicht laden..."); return; } if(pOldView == NULL) { AfxMessageBox("Alte View nicht vorhanden..."); return; } // Neue View erstellen pNewView->Create(NULL,NULL,WS_CHILD|WS_BORDER, CFrameWnd::rectDefault,this,2,&pContext); // Update aufrufen pNewView->OnInitialUpdate(); // Neue View setzen ((CFrameWnd*)AfxGetApp()->m_pMainWnd)->SetActiveView(pNewView); // Neue View anzeigen pNewView->ShowWindow(SW_SHOW); // Alte View verstecken pOldView->ShowWindow(SW_HIDE); pNewView->SetDlgCtrlID(AFX_IDW_PANE_FIRST); ((CFrameWnd*)this)->RecalcLayout(); //View Neu zeichnen pNewView->Invalidate(); // Alte View löschen delete pOldView; }
-
danke, aber hier...
// Neue View erstellen pNewView->Create(NULL,NULL,WS_CHILD|WS_BORDER, CFrameWnd::rectDefault,this,2,&pContext);
... wird ja wieder ne neue view erstellt beim wechseln oder seh ich da was falsch???
-
Nein, dass siehst du soweit ganz korrekt. Du kannst dir ja die Funktion so anpassen das diese die View nicht mehr löscht und nur noch dort zu der anderen switcht. Zum Beispiel so:
void CMainFrame::SwitchToView(CView* pNewView) { // Aktuelle View holen CView *pOldView = GetActiveView(); // Aktuelles Dokument holen CDocument *pDocument = pOldView->GetDocument(); CCreateContext pContext; if(pNewView == NULL) { AfxMessageBox("Konnte View nicht laden..."); return; } if(pOldView == NULL) { AfxMessageBox("Alte View nicht vorhanden..."); return; } // Update aufrufen pNewView->OnInitialUpdate(); // Neue View setzen ((CFrameWnd*)AfxGetApp()->m_pMainWnd)->SetActiveView(pNewView); // Neue View anzeigen pNewView->ShowWindow(SW_SHOW); // Alte View verstecken pOldView->ShowWindow(SW_HIDE); pNewView->SetDlgCtrlID(AFX_IDW_PANE_FIRST); ((CFrameWnd*)this)->RecalcLayout(); //View Neu zeichnen pNewView->Invalidate(); }
War jetzt mal so auf die schnelle geändert und ich kann dir auch nicht versprechen das dies funktioniert. Aber wie schon gesagt kannst du diese Funktion ändern und dir so anpassen wie sie du brauchst.
-
okay, läuft soweit, das problem ist jetzt aber auch noch wie bei dem beispiel aus der faq, dass es probleme gibt, mit dem zuerst erstellten view...
erstellt werden die views jetzt so:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { ... m_pView = create_view<CTest6View, CTest6Doc>(this); m_pView2 = create_view<CTest6View2, CTest6Doc2>(this); return 0; }
m_pView und m_pView2 sind CForm*-Variablen, create_view ist die funktion aus der FAQ.
CTest6View wird malt sich immer über die scroll-balken und die statusbar, CTest6View2 sieht gut aus!
woran könnte das liegen? wahrscheinlich weil ich irgendwas ganz gewaltig falsch mache, aber nur was?!?!?
-
wie sollte ich denn dazu die view-doc-paare erstellen?
das mache ich bis jetzt mit der funktion aus der FAQ:
template<class View, class Doc> View* create_view(CWnd* f_pParent) { View* view = new View(); Doc* doc = new Doc(); CCreateContext createContext; createContext.m_pNewViewClass = 0; createContext.m_pNewDocTemplate = 0; createContext.m_pLastView = 0; createContext.m_pCurrentFrame = 0; createContext.m_pCurrentDoc = doc; view->CreateWnd(f_pParent, createContext); return view; }
das problem ist nur, dass er irgendwas überschreibt dadurch, weil immer nur die zuletzt erstellte view richtig funktioniert.
was mache ich nur falsch? kann doch nicht sooo schwer sein eigentlich?? :p
-
liesse sich das ganze nicht auch als sdi ohne doc/view unterstützung realisieren? aber wie ich das da mache ist mir erst recht nicht ganz klar!?????
-
Huhu, ich habe heute bei mir zwei neue Funktionen eingebaut.
Dadurch wird ein zusätzlicher View (mit Doc) erzeugt und über den anderen gelegt - bzw. wieder geschlossen.
Hilft dir das weiter?void CMainFrame::ZeigeDruckView() { m_pCurrentView = GetActiveView(); ASSERT(m_pCurrentView); // den nächsten view holen CView* pNextView; pNextView = create_view<CLnlView, CLnlDoc>(this); // die interne id austauschen UINT nTemp = ::GetWindowLong(m_pCurrentView->m_hWnd, GWL_ID); ::SetWindowLong(m_pCurrentView->m_hWnd, GWL_ID, ::GetWindowLong(pNextView->m_hWnd, GWL_ID)); ::SetWindowLong(pNextView->m_hWnd, GWL_ID, nTemp); m_pCurrentView->ShowWindow(SW_HIDE); pNextView->ShowWindow(SW_SHOW); // neuen View setzen SetActiveView(pNextView); // Toolbar aktualisieren m_wndToolBar2.ShowWindow(SW_HIDE); // layout updaten RecalcLayout(); // View neuzeichnen pNextView->Invalidate(); } void CMainFrame::SchliesseDruckView() { CView* pActiveView = GetActiveView(); ASSERT(pActiveView); // die interne id austauschen UINT nTemp = ::GetWindowLong(pActiveView->m_hWnd, GWL_ID); ::SetWindowLong(pActiveView->m_hWnd, GWL_ID, ::GetWindowLong(m_pCurrentView->m_hWnd, GWL_ID)); ::SetWindowLong(m_pCurrentView->m_hWnd, GWL_ID, nTemp); pActiveView->ShowWindow(SW_HIDE); m_pCurrentView->ShowWindow(SW_SHOW); // neuen View setzen SetActiveView(m_pCurrentView); // Toolbar aktualisieren CBasisView* pBasisView = dynamic_cast<CBasisView*>(m_pCurrentView); if (pBasisView && pBasisView->GetToolbarID()) { m_wndToolBar2.LoadToolBar(pBasisView->GetToolbarID()); m_wndToolBar2.ShowWindow(SW_SHOW); } else { m_wndToolBar2.ShowWindow(SW_HIDE); } // layout updaten RecalcLayout(); // View neuzeichnen m_pCurrentView->Invalidate(); // altes document löschen CDocument* pOldDoc = pActiveView->GetDocument(); delete pOldDoc; // alten view löschen pActiveView->DestroyWindow(); }
Wenn du den Code genauer ansiehst, wirst du sehen, dass sehr viel aus der dir schon bekannten Funktion übernommen ist. So wie ich schon sagte: Du musst nur ein wenig anpassen.
-
sorry, aber ich kriegs nicht hin... hab's versucht irgendwie in mein programm zu basteln, aber das wird nix. kenn mich einfach noch zu wenig aus mit VC.
aber es sieht mir doch schon wieder so aus, als würde die view jedes mal wieder gelöscht und neu erstellt, oder?ich weiss nicht, ob ich hier vorhabe unmögliches zu programmieren aber wieso weiss hier auch kaum einer was dazu und in keiner usegroup oder nirgendwo gibt's was darüber (jedenfalls find ich's nicht).
ich will doch einfach wie mit einem tabctrl zwischen views wechseln ohne dass die control-eingaben verloren gehen, die müssen alle kein eigenes document haben von mir aus auch komplett ohne doc/view-architektur!!!
ich glaub ich steck den kopf in den sand! bei visual basic, delphi etc ist das alles so verdammt einfach, wieso geht das hier nicht???????????????????????
naja, bin wohl zu blöd dafür, danke trotzdem für die hilfe!!!
-
Hey, das wird schon noch.
Du hast dir einfach etwas ausgesucht, was nicht alltäglich ist - wie du sicher auch schon an den wenigen Artikeln zu dem Thema erkannt hast.
Lass den Kopf nicht hängen, ich versuche, die Funktionen nochmal besser zu kommentieren.Diese Funktion versteckt den aktuellen View und erstellt einen anderen und zeigt den an.
void CMainFrame::ZeigeDruckView() { // Zeiger auf den gerade angezeigten View holen m_pCurrentView = GetActiveView(); // Sicherstellen, dass einer gefunden wurde. ASSERT(m_pCurrentView); // Den neuen View erstellen CView* pNextView = create_view<CLnlView, CLnlDoc>(this); // die interne id austauschen UINT nTemp = ::GetWindowLong(m_pCurrentView->m_hWnd, GWL_ID); ::SetWindowLong(m_pCurrentView->m_hWnd, GWL_ID, ::GetWindowLong(pNextView->m_hWnd, GWL_ID)); ::SetWindowLong(pNextView->m_hWnd, GWL_ID, nTemp); // Den neuen View anzeigen und den alten verstecken m_pCurrentView->ShowWindow(SW_HIDE); pNextView->ShowWindow(SW_SHOW); // neuen View aktivieren SetActiveView(pNextView); // layout updaten RecalcLayout(); // View neuzeichnen pNextView->Invalidate(); }
Du siehst, es wurde nichts gelöscht.
Der bisher angezeigte View wird in m_pCurrentView gespeichert, so kannst du ihn jederzeit wieder anzeigen, was auch in der anderen Funktion gemacht wird.void CMainFrame::SchliesseDruckView() { // Aktuell angeziegten View holen CView* pActiveView = GetActiveView(); ASSERT(pActiveView); // die interne id austauschen UINT nTemp = ::GetWindowLong(pActiveView->m_hWnd, GWL_ID); ::SetWindowLong(pActiveView->m_hWnd, GWL_ID, ::GetWindowLong(m_pCurrentView->m_hWnd, GWL_ID)); ::SetWindowLong(m_pCurrentView->m_hWnd, GWL_ID, nTemp); // Den alten View verstecken und den neuen anzeigen pActiveView->ShowWindow(SW_HIDE); m_pCurrentView->ShowWindow(SW_SHOW); // neuen View aktivieren SetActiveView(m_pCurrentView); // layout updaten RecalcLayout(); // View neuzeichnen m_pCurrentView->Invalidate(); // altes document löschen CDocument* pOldDoc = pActiveView->GetDocument(); delete pOldDoc; // alten view löschen pActiveView->DestroyWindow(); }
Ich lösche das Doc und den View in der Funktion, weil es jedes Mal neu erzeugt werden soll.
Du kannst nun folgendes machen:
Beide Views als Membervariable in den Header packen und dann an geeigneter Stelle erzeugen.
Dann kannst du einfach durch entsprechendes Anzeigen und verstecken umschalten.Verstanden? Sonst muss ich das echt mal ausarbeiten.
-
Sag nocvhmal genauer was du willst.
Du willst eine DOC und mehrere Views dafür! Richtig?
Wenn du mehrere DOC willst dann bist du bei SDI falsch.
Dafür gibt es MDI.Willst du sowas wie TABCONTROLLS dann suche dir eine Klasse bei Codegur/codeproject.
Ich verwendet dafür VisualFx.
-
also was ich vorhabe ist im grunde folgendes:
programm mit menü, tool- und statusbar und in der mitte soll platz für controls sein (also wie der windows-editor nur in der mitte keine große textbox sondern eine formview). diese formview möchte ich jetzt aber auswechseln können, um andere controls sichtbar zu machen!
ich brauch also im grunde gar kein DOC, von mir aus implementiere ich alles im Frame oder wo auch immer... und wenn es funktioniert könnte das auch alles als dialogbasierte anwendung gemacht werden, da weiss ich nur nicht, wie ich die views reinbauen soll (wenn das überhaupt geht).rauskommen soll ein programm, mit dem:
- bilder angezeigt werden sollen (1. view)
- aus den ausgewählten bildern exif-daten auslesen (2. view)
- drucken der bilder mit vielen optionen (3.view)
- Optionen und noch anderer kram (4. view usw.)
das soll aber alles unabhängig voneinander angewählt werden können (eben einfach hin und her schalten)
-
geht das ganze nicht auch als MDI, wobei jedes fenster immer nur maximiert dargestellt wird?
-
hat da einer vielleicht schon ein beispiel dafür?
sorry, wenn ich langsam nerve!
-
Hab grade durch Zufall was für dich in der FAQ der MSDN gefunden:
//How do I maximize my MDI child? void CMainFrame::ActivateFrame(int nCmdShow) { if (!m_bActivated) { m_bActivated = TRUE; nCmdShow = SW_SHOWMAXIMIZED; } CFrameWnd::ActivateFrame(nCmdShow); } //where m_bActivated is a member variable of your frame object.