Dialog beenden


  • Mod

    1. Für die Funtkion der MFC ist

    m_pMainWnd = m_pMainDlg;
    

    jedoch wichtig. Es ist das AfxGetMainWnd was in einigen Positionen benötigt wird.
    Die Frage ist: Was soll dieser Code in einem Stück MDI Code?
    2. Ein CDialog hat keinen Autodestruktor (OnPostNcDestroy), der beim Zersötrn des Dialoges auch den Dialog freigibt! Wenn Du den Dialog mit new anlegst, dann wird der Speicher beim Schließen des Dialoges nicht freigegeben.



  • Guten Abend!

    Gut zu wissen -> m_pMainDlg!

    Vielleicht habe ich mich etwas blöd ausgedrückt, also diese Dialoge stecken in einer DLL und ich möchte sie momentan in einem MDI anzeigen. Da der Nutzen dieser Dialoge aber auch für andere Anwendungen interessant sein könnte möchte ich die Dialoge in einer DLL bereit stellen.

    Wichtig ist jedoch dass ich auch eine Funktion hab die mir die Fenster auch wieder schließt, falls der Benutzer das nicht tut aber die Hauptanwendung beendet.

    Die Dialoge werden mit der genannten ShowGui()-Funktion angezeigt. Ich möchte den Dialog nur irgendwie schließen. DestroyWindow() wird in OnCancel vorgenommmen und delete in OnPosNcDestroy(). Aber egal wie ich es anstelle stürzt mein Proggie immer ab wenn ich versuche den Dialog zu schließen.

    Ich hab auch schon versucht eine WM_DESTROY Message an das Fenster zu schicken, aber immer das Gleiche 👎.

    Hilfe Hilfe 😕

    Schönes WE!



  • Hi!

    Hat niemand einen Tipp für mich?

    CChris :xmas1:


  • Mod

    Was ist das für eine DLL? Standard, extension DLL?
    Warm eine DLL?
    Was ist das für eine EXE?
    Soll die DLL eigenstöändig laufen oder läuft dieimmer im Paket und der gleichen Version wie die EXE?

    Rufst Du auch DestroyWindow aus der DLL heraus aus?
    Was sagt der Stack Trace wenn es kracht?



  • Hallo,

    Was ist das für eine DLL? Standard, extension DLL?

    Eine reguläre MFC-DLL

    Warm eine DLL?

    Weil es später einmal ein Teil einer großen Anwendung werden soll

    Was ist das für eine EXE?

    Momentan eine Mfc-Dialogbasierende Anwendung -> später aber eine beliebige exe (mit graphischer oberfläche)

    Ich habe das Problem gelöst, ich habe AFX_MANAGE_STATE(AfxGetStaticModuleState()); in der Close-Methode vergessen.

    Aber jetzt kracht es immer noch wenn ich die ESC-Taste im Dialog drücke. Wenn ich die Anwendung normal schließe klappt alles einwandfrei... was passiert denn wenn ich die Esc-Taste in meinem Dialog drücke??

    Danke
    CChris :xmas2:


  • Mod

    Bei einem nicht modalen Dialog gar nichts!



  • Also ich hatte mir ja nen Nicht-Modalen Dialog immmer so vorgestellt wie ein normales Fenster, außer dass da halt eine erweiterte Fensterprozedur implementiert ist, die Kinderfenster verwaltet. Warum sollte man den nicht wie ein ganz normales Fenster auch zumachen können? Oo



  • Bei einem nicht modalen Dialog gar nichts!

    ... so hab ich mir das auch vorgestellt, aber leider reagiert meine Anwendung trozdem auf die ESC-Taste.

    Darum wollte ich ja wissen, was im CDialog passiert wenn man auf die ESC-Taste drückt, also was alles aufgerufen wird.

    Also ich hatte mir ja nen Nicht-Modalen Dialog immmer so vorgestellt wie ein normales Fenster, außer dass da halt eine erweiterte Fensterprozedur implementiert ist, die Kinderfenster verwaltet. Warum sollte man den nicht wie ein ganz normales Fenster auch zumachen können? Oo

    Sorry, aber ich versteh nicht ganz wie du das meinst 😕

    Danke



  • Also für mich sieht das gerade echt so aus, als hättest du irgendein anderes Problem, doktorst da jetzt irgendwie rum und traust dich nicht, mal zu schauen was der Debugger so sagt.



  • Hallo,

    witzig... wieso soll ich mich nicht trauen zu schuaen was der debugger sagt 😃 ?

    Der Debugger hängt sich an folgender Stelle auf und durch die Methoden hindurch zu debuggen is nicht, weil ich irgendwann die Meldung bekomme dass der Quellcode nicht verfügbar ist:

    void CWnd::AssertValid() const
    {
    ...
    ASSERT(::IsWindow(m_hWnd));
    ...
    }

    Deshalb habe ich auch nicht die möglichkeit zu schauen welche Methoden aufgerufen werden wenn ich ESC-Taste drücke.

    Ich verwende IsDialog-Message um Definierte Taste wie z. B. ESC, Pfeil-Tasten oder Tab an mein Dialog weiter zuleiten.

    Viele Grüße!



  • Also ist das Problem, dass das Fenster-Handle Win32 gegenüber irgendwie schon freigegeben wurde, ohne dass das CWnd-Objekt (Also dein CDialog) was davon mitbekommen hat. Ist eventuell das Parent-Fenster von dem Dialog schon kaputtgemacht worden, bevor das CDialog-Objekt gelöscht wird?

    Ich würd das ja hier mal durch den Debugger schicken, aber du brennst bestimmt nicht so darauf, deinen Code herzugeben 😉


  • Mod

    Und was sagt der Callstack? Wer will in diesem Moment auf das Fensterzugreifen?



  • Halli Hallo,

    Denn Callstack kann man sich im Normalfall mit dem CallBrowser anzeigen lassen?
    Weil der zeigt mir nämlich garnichts an.

    Ich vermute, dass der Programmteil irgendwie nicht von meiner Anwendung aus aufgerufen wird weil im Callbrowser nichts drin steht.

    Und zwar vermute ich dass, weil ich eine eigene Hook erzeugt habe die mir die Nachrichten abfängt und IsDialogMessage() aufruft damit die Pfeil-Tasten usw. Funktionieren. Darum reagiert meine Anwendung jetzt auch auf die Esc-Taste.

    (Die Funktion habe ich nicht selber geschrieben, sondern von einem Bekannten bekommen)

    LRESULT FAR PASCAL GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
    {
    	LPMSG lpMsg = (LPMSG) lParam;
    	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    
    	if( (nCode >= 0 && PM_REMOVE == wParam) && 
    		 (lpMsg->message >= WM_KEYFIRST && lpMsg->message <= WM_KEYLAST) && 
    		 (IsDialogMessage(hWnd, lpMsg) || IsDialogMessage(hWndExpertMode, lpMsg))
    	  ) 
    	{
    		lpMsg->message = WM_NULL;
    		lpMsg->lParam = 0;
    		lpMsg->wParam = 0;
    	}
    	return CallNextHookEx(hHook, nCode, wParam, lParam);
    }
    

    Auf jeden Fall ist das sehr komisch weil das normale Beenden meiner Anwendung macht überhaupt keine Probleme, nur eben wenn ich die ESC-Taste drücke 😕

    Danke!

    CChris :xmas1:



  • Hat denn der MFC-App-MessageLoop nicht automatisch ein IsDialogMessage eingebaut? Kenne den Code dafür gerade nicht.



  • Hi,

    im Normalfall schon, aber wenn man einen nicht modalen Dialog in einer DLL definiert, dann nicht.

    CChriss :xmas2:



  • Guten Morgen,

    jetzt hab ich doch schon so viel geschrieben, dass irgendjemand eine Antwort haben muss :D.

    Ich komm einfach nicht weiter. Ich habe an dieser Stelle auch überhaupt keinen Anhaltspunkt woran der Fehler liegen könnte oder wonach ich suchen sollte.

    Folgendes habe ich probiert, funktioniert auch nicht, weil ich nicht einmal in die PreTranslateMessage rein komme.

    BOOL CMainDlg::PreTranslateMessage(MSG* pMsg)
    {
      if (pMsg->wParam == VK_ESCAPE)
        return 1;
    
      return CDialog::PreTranslateMessage(pMsg);
    }
    

    Jetzt kann ich mir nur noch vorstellen dass das Problem an meiner Message-Hook (siehe vorheriger Beitrag) liegt.

    Ich Prüfe die IsDialogMessage dort für zwei Dialoge (hab ich auch schon aus dem code herausgenommen und ich bekomme immer noch den fehler).

    Die hWnd's die ich für die IsDialogMessage verwende definiere ich mir wie folgt:

    Im Main-Dlg:

    BOOL CMainDlg::OnInitDialog()
    {
    	CDialog::OnInitDialog();
    	hWnd = m_hWnd;
    	hHook = ::SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, NULL, GetCurrentThreadId());
    	return TRUE;
    }
    
    BOOL ShowExpertMode()
    {
      ...
      m_pExpertMode->Create();
      hWndExpertMode = m_pExpertMode->m_hWnd;
      m_pExpertMode->ShowWindow(SW_SHOW);
    }
    

    Bin um jede Hilfe dankbar, weil ich wirklich nicht weiss wie ich das Problem lösen soll.

    Danke!
    CChris


  • Mod

    Dann Debugge bitte, sende mehr Code, Sag uns genauer was auf dem Stack bei einem Crash zu seen ist.
    Wie soll man Dir sonst helfen?

    EDIT:
    http://blog.m-ri.de/index.php/2008/07/04/mfc-fenster-in-anderen-applikationen-verwenden/



  • Hallo,

    ich würde ja debuggen oder schauen was auf dem Stack steht, aber es wird mir ja nichts angezeigt.

    Ich habe das Problem inzwischen zwar immer noch nicht gelöst, aber es zumindest unterbunden indem ich folgendes in meine GetMsgProc eingebaut habe:

    if( (nCode >= 0 && PM_REMOVE == wParam) &&
    (lpMsg->message >= WM_KEYFIRST && lpMsg->message <= WM_KEYLAST) &&
    (lpMsg->wParam!= VK_ESCAPE) &&
    (IsDialogMessage(hWnd, lpMsg) || IsDialogMessage(hWndExpertMode, lpMsg))
    )

    Aber unterbinden ist nicht die beste Lösung und darum fasse ich, das was ich mache nocheinmal kurz zusammen. Evtl. mache ich ja schon einen grundlegenden Fehler, denn ich habe sowie so noch ein kleines Auffassungsproblem was meine DLL betrifft:

    Wenn ich ein nicht modales Fenster als Hauptdialog in einer DLL verwende, muss ich dann einen eigenen Prozess/Thread starten?
    Wenn ja, macht dass die Hauptklasse meiner DLL automatisch wenn diese ist von CWinApp abgeleitet ist?

    Es folgt das Grundgerüst meiner DLL, ich habe das wichtigste zusammengefasst da ich keine debugging infos habe.

    Hautpklasse

    class CModelessDlgApp : public CWinApp
    {
    public:
    	CMainDlg* m_pMainDlg;
    
    public:
    	CModelessDlgApp();
    	virtual BOOL InitInstance();
    	void ShowGui();
    	void CleanUp();
    	DECLARE_MESSAGE_MAP()
    };
    
    //Dialog anzeigen
    void CModelessDlgApp::ShowGui()
    {
      if(NULL == m_pMainDlg)
      {
        m_pMainDlg = new CMainDlg();
        m_pMainWnd = m_pMainDlg;
        m_pMainDlg->Create(CMainDlg::IDD, NULL);
        m_pMainDlg->ShowWindow(SW_SHOW);
      }
      else
        m_pMainDlg->SetActiveWindow();
    }
    
    //Dialog schließen
    void CModelessDlgApp::CleanUp()
    {
      if(NULL != m_pMainDlg)
      {
        m_pMainDlg->DestroyWindow();
        m_pMainDlg = NULL;
      }
    }
    

    Globaler Teil der DLL

    CModelessDlgApp theApp;
    
    __declspec(dllexport) void ShowGui(void)
    {
      AFX_MANAGE_STATE(AfxGetStaticModuleState());
      theApp.ShowGui();
    }
    
    __declspec(dllexport) void ::CleanUp(void)
    {
      AFX_MANAGE_STATE(AfxGetStaticModuleState());
      theApp.CleanUp();
    }
    

    Dialog-Klasse

    //Message-Hook
    LRESULT FAR PASCAL GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
    {
    	LPMSG lpMsg = (LPMSG) lParam;
    	AFX_MANAGE_STATE(AfxGetStaticModuleState());
    
    	if( (nCode >= 0 && PM_REMOVE == wParam) && 
    		 (lpMsg->message >= WM_KEYFIRST && lpMsg->message <= WM_KEYLAST) &&
    		 (lpMsg->wParam!= VK_ESCAPE) &&
    		 (IsDialogMessage(hWnd, lpMsg) || IsDialogMessage(hWndExpertMode, lpMsg))
    	  ) 
    	{
    		lpMsg->message = WM_NULL;
    		lpMsg->lParam = 0;
    		lpMsg->wParam = 0;
    	}
    	return CallNextHookEx(hHook, nCode, wParam, lParam);
    }
    
    //Message-Hook starten in OnInitDialog
    BOOL CMainDlg::OnInitDialog()
    {
    	CDialog::OnInitDialog();
    	hWnd = m_hWnd;
    	hHook = ::SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, NULL, GetCurrentThreadId());
    	return TRUE;
    }
    
    //Message-Hook beenden
    void CMainDlg::OnDestroy()
    {
    	UnhookWindowsHookEx(hHook);
    	CDialog::OnDestroy();
    }
    
    //Dialog zerstören
    void CMainDlg::OnCancel()
    {
      DestroyWindow();
    }
    
    //Speicherplatz freigeben
    void CMainDlg::PostNcDestroy()
    {
      CDialog::PostNcDestroy();
      delete this;
    }
    

    So das war jetzt viel zu lesen, aber vllt. kann mir jemand weiter helfen oder ein paar hilfreiche tipps geben.

    Zu diesem Thema findet man auch nicht allzuviel hilfreiches im Internet.

    Viele Grüße!
    CChris :xmas1:



  • Jetzt hab ich alles so schön zusammengefasst, ist das jetzt immer noch nicht das was ich hätte posten sollen 😕

    Mir würde es ja schon reichen, wenn jemand sagt:
    - "Ja, so wie du deinen nicht modalen Dialog in einer DLL startest ist ok"
    - "Nein, so würde ich es nicht machen weil, das zu fehlern füren kann. Ich würde es so machen..."

    Viele Grüße
    CChris



  • Ist es eine gute Idee, eine weitere App-Instanz durch die Dll zugeschoben zu bekommen?


Anmelden zum Antworten