Mehrere Fragen zu MDI
-
Hey,
also bei mir sind jetzt gleich mal mehrere Fragen aufgetaucht, auf die ich keine Antwort weiß.

Und zwar:1. Ich hab noch Probleme mit dem Prompt einzelner Menüeinträge. Habe einen extra Menüpunkt eingefügt (Extras), und dazu einen Eintrag (Optionen) und will, das in der Statusbar der Text angezeigt wird, den ich im Prompt des Optionen-Menüpunkts eingetragen habe. Nur kommt da dann No Message Line Prompt found.
Bei Prompt schreib ich da rein: Zeigt die Programm-Optionen an.\nOptionen
Bringt trotzdem nichts, der Menüpunkt heißt aber Optionen und in der Stringtable stehts auch korrekt drin, ID stimmt auch. Gibts noch was zu beachten ??2. Zum Thema Toolbar mit eigenen Icons: Ich brauche die Sachen wie Kopieren, Ausschneiden, Speichern unter... nicht, habe die im Menü und von der Toolbar entfernt und will jetzt 3 eigene Buttons dort aufnehmen. Geht das etwas einfacher als die Toolbar.bmp zu verändern ? Meine .ico sind 32bit und mehr als 16 Farben, hab gelesen, dass VS das nicht unterstützt. Gibts einen Weg, 3 eigene Buttons in die Toolbar einzufügen mit meinen eigenen Icons ??
3. Habe ich ein MDI-Projekt, im Doc wird ein Thread angeworfen, der mit per Sendmessage mitteilt, dass er neue Daten hat und gibt die mir gleich als LPARAM mit. Ich will jetzt ein neues Childframe öffnen, wenn die ID des übergebenen struct anders ist. D.h. jetzt also ich brauch ein neues Window, soll aber genauso wie das bereits geöffnete aussehen. Also gleiches View sozusagen !? Wie kann man das am besten anstellen ??
Wäre super, wenn mir jemand helfen könnte, die Fragen zu beantworten. Komme da nicht so richtig weiter.

Schonmal Thx an Alle !
-
zu 1. Jede Wette, dass Deine ID nicht stimmt. Du bekommst die ID im Debug Output angezeigt. Zeig mal den entsprechenden Auschnitt, dann schau in die resource.h rein, was steht dort zu dieser ID.
zu 2. Ändere die Toolbar.bmp, öffne die RC Datei und suche den entsprechenden Toolbars-Eintrag
IDR_MAINFRAME TOOLBAR 16, 15 BEGIN BUTTON ...Ergänze dort einfach die passenden IDs. Achte darauf, dass die Anzahl der Icons mit der Anzahl der Enträge hier zusammenpasst.
zu 3. CDocTemplate::CreateNewFrame
-
Ah ok, verstehe. Das mit der ID und Resource.h stimmt, hatte die falsche ID drinstehen.

Und zum 2.: Das müsstest du mir bitte nochmal genau erklären.

Müsste also die bmp mit nem externen Tool bearbeiten, sprich meine Icons über die vorhandenen legen, dann das rc-File öffnen und den Rest müsstest du mir nochmal erklären.Zu 3.: Das werd ich mir genauer anschauen.
Schonmal Vielen Dank

-
zu 2. Was soll ich da erklären. Schau Dir doch selber an, wie VS die Toolsbars in der RC-Datei einträgt. Ist doch kein Hexenwerk. Augen auf und angesehen... Was soll ich da groß schreiben!
-
Hätte ich jetzt fast vergessen:
Wollte nur noch zu 3. bemerken, dass alles jetzt funktioniert, habe mir aber meine Toolbar selber erstellt und eigene Bitmaps draufgesetzt.Sieht jetzt so aus (Auszug):
// eigene Toolbar TBBUTTON Btn; Btn.idCommand = 0; Btn.fsStyle = TBSTYLE_SEP; Btn.fsState = TBSTATE_ENABLED; Btn.iString = 0; Btn.iBitmap = 0; Btn.dwData = 0; if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC)) { TRACE0("Fehler beim Erstellen der Symbolleiste.\n"); return -1; // Fehler beim Erstellen } CBitmap bm; m_img.Create(16, 16, ILC_COLOR32, 7, 0); m_wndToolBar.SetButtons(NULL, 7); m_wndToolBar.GetToolBarCtrl().InsertButton(0, &Btn); // Separator einfügen bm.LoadBitmap(MAKEINTRESOURCE(IDB_NEWDOC)); m_img.Add(&bm, RGB(0,0,0)); m_wndToolBar.SetButtonInfo(1, ID_FILE_NEW, TBSTYLE_BUTTON, 0); m_wndToolBar.GetToolBarCtrl().InsertButton(2, &Btn); ::SendMessage(m_wndToolBar, TB_CHANGEBITMAP, (WPARAM)(int)ID_FILE_NEW, (LPARAM) (UINT)0); bm.m_hObject = NULL; bm.LoadBitmap(MAKEINTRESOURCE(IDB_RUN)); m_img.Add(&bm, RGB(0,0,0)); m_wndToolBar.SetButtonInfo(3, ID_START, TBSTYLE_BUTTON, 1); ...Nochmal vielen Dank für deine Hilfe !

-
Hi,
eine Frage hätte ich noch, weiß aber nicht ob das die Letzte im dem Thread hier ist.

Und zwar:Ich will von meiner Viewklasse aus auf CMainFrame zugreifen, im Header meiner Viewklasse habe ich einmal:
CMainFrame *pMainFrm;und will den Pointer in OnInitialUpdate initialisieren mit:
pMainFrm = (CMainFrame*)AfxGetMainWnd(); ASSERT(pMainFrm);Das Initialisieren und Casten... funktioniert, aber wenn ich den Pointer dann verwenden will, kommt dauernd "use of defined type CMainFrame" !
Verstehe das nicht, die Klasse ist im View bekannt (per Forward-Declaration), angelegt und korrekt gecastet wird auch, aber bei der Verwendung wird gemeckert.
Kann mir jemand helfen ??
-
1, Es zeigt einen Designfehler auf, dass Du überhaupt aus dem View in den Frame hineingreifen willst. Was steht dort was Du benötigst.
2. Dein View kennt CMainFRame nicht weil Du den Header, in dem CMainFrame deklariert wird nicht included hat.
-
Ok, an das mit dem Header includen hab ich noch gar nicht gedacht !
Ich habe in meiner Toolbar 3 Buttons, und wenn im Childframe auf ein Button geklickt wird, dann soll abhängig vom geklickten Button in der Toolbar die 3 Buttons enabled, disabled werden.
Habe dazu On_Update_Command_UIs im View, nur springt von den dreien nur der erste an, ich will aber, dass alle 3 anspringen und darin dann den jeweiligen Button in der Toolbar disablen oder enablen.
So sieht das bei mir aus:
Die 3 HandlerON_UPDATE_COMMAND_UI(ID_START, OnUpdateIDStart) ON_UPDATE_COMMAND_UI(ID_START, OnUpdateIDPause) ON_UPDATE_COMMAND_UI(ID_START, OnUpdateIDStop) ... void C...View::OnUpdateIDStart(CCmdUI *pCmdUI) { pCmdUI->Enable(showIDStart); } void C...View::OnUpdateIDPause(CCmdUI *pCmdUI) { pCmdUI->Enable(showIDPause); } void C...View::OnUpdateIDStop(CCmdUI *pCmdUI) { pCmdUI->Enable(showIDStop); }Die Variablen jeweils sind BOOL, werden wenn ein bestimmter Button geklickt wird, auf TRUE oder FALSE gesetzt, nur springt immer nur der erste Handler (OnUpdateIDStart) an, habe das durch setzen eines Breakpoints gemerkt.
Kann man überhaupt mehrere Buttons gleichzeitig in der Toolbar disablen ??
Habe sonst grad keine weitere Idee...
-
Und was glaubst Du soll das System machen wenn Du das hier machst:
ON_UPDATE_COMMAND_UI(ID_START, OnUpdateIDStart) ON_UPDATE_COMMAND_UI(ID_START, OnUpdateIDPause) ON_UPDATE_COMMAND_UI(ID_START, OnUpdateIDStop)DWIM willst Du?
Das System soll selbst wissen, wenn der Button ID_START heißt, dass Du beim ertsen, den ersten ID_START Button meinst, beim zweiten, den zweiten und beim dritten den dritten...
Am Besten hör auf zu Programmieren... Die Systeme sind noch nicht reif für das was Du denkst <duck&wech>
-
Oh, ok *schäm*
Man kann sagen, dass ich das total übersehen habe. Copy & Paste eben...
Natürlich erstmal vielen Dank für die Hilfe, aber
Martin Richter schrieb:
Am Besten hör auf zu Programmieren... Die Systeme sind noch nicht reif für das was Du denkst <duck&wech>
was soll das wieder heißen ?
-
Ich hab da gleich mal noch ne Frage.

Und zwar zum Thema neues Childframe erstellen:
Habe in der App-Klasse folgenden CodeCMultiDocTemplate* pDocTemplate; pDocTemplate = new CMultiDocTemplate(IDR_...TYPE, RUNTIME_CLASS(C...Doc), RUNTIME_CLASS(CChildFrame), // Benutzerspezifischer MDI-Child-Rahmen RUNTIME_CLASS(C...View)); if (!pDocTemplate) return FALSE; AddDocTemplate(pDocTemplate); return TRUE;einfach in eine Funktion ausgelagert, rufe die natürlich am Anfang auf, ich will ja ein Childwindow am Anfang haben und ich rufe die Funktion später wieder auf, wenn ich die brauche.
Meine Frage: Erstellt es mir dadurch ein leeres Fenster oder eins, was genau wie das Erste, also wie in den Ressourcen definiert, ist ??Das würde mich mal noch interessieren...
-
Ich erwecke den Thread hier nochmal.

Ich will, wenn bestimmte Bedingungen zutreffen, in meiner App-Klasse eine Funktion aufrufen, die dann ein neues Childframe erzeugt, dass eben genauso aussieht wie das jetzige, also dasselbe Doc verwendet.
Mein Problem ist, ich weiß nicht, wie diese Funktion aussehen soll, so ist sie bis jetzt bei mir:
BOOL C...App::CreateFrame(C...Doc *pDoc) { CMultiDocTemplate *pDocTemplate; pDocTemplate = new CMultiDocTemplate(IDR_...TYPE, RUNTIME_CLASS(C...Doc), RUNTIME_CLASS(CChildFrame), // Benutzerspezifischer MDI-Child-Rahmen RUNTIME_CLASS(C...View)); if (!pDocTemplate) return false; AddDocTemplate(pDocTemplate); CFrameWnd *pFrame; pFrame = pDocTemplate->CreateNewFrame(pDoc, NULL); // hier gibts ne Assert... pFrame->InitialUpdateFrame(pDoc, TRUE); return true; }Und ich rufe die Funktion in meiner Doc-Klasse über theApp.CreateNewFrame(this) auf, die Pointer sind alle gültig, das steht mal fest.
/ 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); // hier bleibt er stehen CObject* p=NULL;Trotzdem gibts die Assert !
Oder kann man das über ID_FILE_NEW irgendwie realisieren ??
Verstehe das nicht...
-
Hab dazu jetzt nen anderen Ansatz, ich rufe, wenn ich es brauche, diese Funktion in der App-Klasse aus der Doc-Klasse:
if (!AppStart) { if (AfxMessageBox("Dadurch werden die selben Daten in ein neues Logfile geschrieben.\r\nFortsetzen ?", MB_OKCANCEL | MB_ICONEXCLAMATION | MB_DEFBUTTON1, 0) == IDOK) { CWinApp::OnFileNew(); return; } else return; } else { CWinApp::OnFileNew(); AppStart = false; }AppStart wird im Ctor der App-Klasse auf true gesetzt und dann ja auf false. Ich will diese Funktion später wieder aufrufen, nur knallt es dann bei mir bei CWinApp::OnFileNew().
Der CallStack:> mfc80d.dll!AfxAssertValidObject(const CObject * pOb=0x00000000, const char * lpszFileName=0x5aad7178, int nLine=499) Line 78 C++ mfc80d.dll!CMDIChildWnd::Create(const char * lpszClassName=0x0020d128, const char * lpszWindowName=0x01aebf28, unsigned long dwStyle=1087340544, const tagRECT & rect={...}, ... mfc80d.dll!CMDIChildWnd::LoadFrame(unsigned int nIDResource=129, unsigned long dwDefaultStyle=1087340544, CWnd * pParentWnd=0x00000000, CCreateContext * pContext=0x02c2fa08) Line 618 + 0x3b bytes C++ mfc80d.dll!CDocTemplate::CreateNewFrame(CDocument * pDoc=0x01aed7a0, CFrameWnd * pOther=0x00000000) Line 277 + 0x22 bytes C++ mfc80d.dll!CMultiDocTemplate::OpenDocumentFile(const char * lpszPathName=0x00000000, int bMakeVisible=1) Line 121 + 0x13 bytes C++ mfc80d.dll!CDocManager::OnFileNew() Line 848 C++ mfc80d.dll!CWinApp::OnFileNew() Line 22 C++ ....exe!C...App::OnNew() Line 196 + 0x8 bytesUnd dann bleibt er da stehen:
if (pOb == NULL) { TRACE(traceAppMsg, 0, "ASSERT_VALID fails with NULL pointer.\n"); if (AfxAssertFailedLine(lpszFileName, nLine)) AfxDebugBreak(); // hier steht er dann... return; // quick escape }Kann mir jemand was dazu sagen ??
-
Du hast keinen gültigen CWinApp Zeiger!
Wie rufst Du die Methode den auf?
Spezielle Deine Methode....exe!C...App::OnNew() Line 196 + 0x8 byteshier ist relevant.
-
Ach so, ok.
Ich rufe die über theApp.OnNew() auf, also über das App-Objekt !
EDIT:
überC...App* pApp = dynamic_cast<C...App*>(AfxGetApp()); ASSERT(pApp); pApp->OnNew();Passiert das Gleiche !
EDIT2:
Hängt es vielleicht damit zusammen, dass ich diese Funktion aus meiner Doc-Klasse aus aufrufe ??
-
Habe es immer noch nicht, weiß nicht, wie ich einen gültigen CWinApp-Pointer kriegen kann.
Über den direkten Aufruf kriegt man ja "cannot access protected member..." als Compiler-Error !
-
Ich mach hier nochmal ein push !
Habs immer noch nicht hinbekommen, hier schon im Forum ohne Ende gesucht, gegoogelt, aber bis jetzt hat keine Lösung funktioniert !
Hat da noch jemand nen Vorschlag, hab langsam die Schn**** voll, verstehe es nicht !
Nochmal ein Danke von mir.

-
Ich will, wenn bestimmte Bedingungen zutreffen, in meiner App-Klasse eine Funktion aufrufen, die dann ein neues Childframe erzeugt, dass eben genauso aussieht wie das jetzige, also dasselbe Doc verwendet.
Wirklich das bestehende CDocument? Wenn ja, kannst du lediglich eine neue View innerhalb des Childframe erzeugen. Suche hierzu in der Hilfe nach "AddView()".
Wenn Du aber für alle "Ereignisse" einen neuen ChildFrame anlegen willst, dann musst Du die Aktion im Mainframe abfangen, und ein komplett neues Document/View Paar innerhalb des Mainframe erzeugen (das ist dann ein MDI).
Gruß, Gio
-
Ich hab es soeben hingekriegt, mache das (vllt nicht ganz sauber) per Postmessage aus meiner Doc an MainFrame und gebe dort als WParam ID_FILE_NEW an und Message ist WM_COMMAND.
So funktioniert es wie es soll !
Aber trotzdem danke für deine Hilfe !!
