DoModal in wincore.cpp



  • Mein Programm stürzt regelmäßig ab (assertion), wenn ich die im DEBUG_Modus bin, RELEASE läuft einwandfrei. Ich habe das Problem zurückverfolgt bis zur ersten "ASSERT(ContinueModal());" Zeile im RunModalLoop.
    Jetzt frage ich mich, was hat diese Überprüfung für einen Sinn?
    In der Releaseversion wird diese Prüfung nicht vorgenommen, und vor allem: Es ist doch ganz normal, dass ContinueModal irgendwann false liefert, oder etwa nicht?

    Ich habe schon stundenlang diesen Microsoft Code analysiert, aber komme zu keiner sinnvollen Verwendung für diese Assertions. Weiß einer Rat?
    Danke!

    ===============================================================================
    Jetzt folgt der zugehörige Codeausschnit aus der wincore.cpp

    int CWnd::RunModalLoop(DWORD dwFlags)
    {
    	ASSERT(::IsWindow(m_hWnd)); // window must be created
    	ASSERT(!(m_nFlags & WF_MODALLOOP)); // window must not already be in modal state
    
    	// for tracking the idle time state
    	BOOL bIdle = TRUE;
    	LONG lIdleCount = 0;
    	BOOL bShowIdle = (dwFlags & MLF_SHOWONIDLE) && !(GetStyle() & WS_VISIBLE);
    	HWND hWndParent = ::GetParent(m_hWnd);
    	m_nFlags |= (WF_MODALLOOP|WF_CONTINUEMODAL);
    	MSG* pMsg = &AfxGetThread()->m_msgCur;
    
    	// acquire and dispatch messages until the modal state is done
    	for (;;)
    	{
    		ASSERT(ContinueModal());
    
    		// phase1: check to see if we can do idle work
    		while (bIdle &&
    			!::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE))
    		{
    			ASSERT(ContinueModal());
    
    			// show the dialog when the message queue goes idle
    			if (bShowIdle)
    			{
    				ShowWindow(SW_SHOWNORMAL);
    				UpdateWindow();
    				bShowIdle = FALSE;
    			}
    
    			// call OnIdle while in bIdle state
    			if (!(dwFlags & MLF_NOIDLEMSG) && hWndParent != NULL && lIdleCount == 0)
    			{
    				// send WM_ENTERIDLE to the parent
    				::SendMessage(hWndParent, WM_ENTERIDLE, MSGF_DIALOGBOX, (LPARAM)m_hWnd);
    			}
    			if ((dwFlags & MLF_NOKICKIDLE) ||
    				!SendMessage(WM_KICKIDLE, MSGF_DIALOGBOX, lIdleCount++))
    			{
    				// stop idle processing next time
    				bIdle = FALSE;
    			}
    		}
    
    		// phase2: pump messages while available
    		do
    		{
    			ASSERT(ContinueModal());
    
    			// pump message, but quit on WM_QUIT
    			if (!AfxGetThread()->PumpMessage())
    			{
    				AfxPostQuitMessage(0);
    				return -1;
    			}
    
    			// show the window when certain special messages rec'd
    			if (bShowIdle &&
    				(pMsg->message == 0x118 || pMsg->message == WM_SYSKEYDOWN))
    			{
    				ShowWindow(SW_SHOWNORMAL);
    				UpdateWindow();
    				bShowIdle = FALSE;
    			}
    
    			if (!ContinueModal())
    				goto ExitModal;
    
    			// reset "no idle" state after pumping "normal" message
    			if (AfxGetThread()->IsIdleMessage(pMsg))
    			{
    				bIdle = TRUE;
    				lIdleCount = 0;
    			}
    
    		} while (::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE));
    	}
    
    ExitModal:
    	m_nFlags &= ~(WF_MODALLOOP|WF_CONTINUEMODAL);
    	return m_nModalResult;
    }
    
    BOOL CWnd::ContinueModal()
    {
    	return m_nFlags & WF_CONTINUEMODAL;
    }
    
    void CWnd::EndModalLoop(int nResult)
    {
    	ASSERT(::IsWindow(m_hWnd));
    
    	// this result will be returned from CWnd::RunModalLoop
    	m_nModalResult = nResult;
    
    	// make sure a message goes through to exit the modal loop
    	if (m_nFlags & WF_CONTINUEMODAL)
    	{
    		m_nFlags &= ~WF_CONTINUEMODAL;
    		PostMessage(WM_NULL);
    	}
    }
    


  • vergessen:
    Ich starte einen neuen Arbeitsthread, rufe dann doModal für einen Wartedialog auf. Im ARbeitsthread wird ein bisschen gerechnet und anschließend ruft der Arbeitsthread EndDialog auf.


Anmelden zum Antworten