Dialog beenden



  • 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?



  • Hi!

    Zunächst einmal Danke für deine Antwort!

    Aber ich versteh Deine Frage nicht ganz. Wieso eine weitere App-Instanz, es wird doch für jeden Aufrfer der DLL nur eine Instanz erzeugt (das globale theApp Objekt).

    Viele Grüße
    CChris


Anmelden zum Antworten