ダイナミックリンクライブラリで非モデリングダイアログを作成する問題について

3929 ワード

MFC  dll:
extern "C" AFX_API_EXPORT BOOL CommOpen(CChannel* pChannel,BOOL bOpen)//             
{
    //             
    AfxGetThread()->PostThreadMessage(CM_TEST1,0,0);//           
    MSG msg;
    CDirCheckDemoDlg* p = NULL;
    while (::GetMessage(&msg,NULL,0,0))
    {
        //                  
        if (!::IsWindow(p->GetSafeHwnd()) || !::IsDialogMessage(p->GetSafeHwnd(),&msg) )
        {           
            if (msg.message == CM_TEST1)
            {
                p = new CDirCheckDemoDlg;
                p->Create(IDD_DIRCHECK_DIALOG,AfxGetApp()->m_pMainWnd);
                p->CenterWindow();
                p->ShowWindow(SW_NORMAL);
                p->UpdateWindow();
            }
            //    
            ::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
        }
    }        
    return TRUE;//              
}
extern "C" AFX_API_EXPORT int Poll(CDevice* pDevice)//             
{

}


メインフレームワークが最初のエクスポート関数を呼び出すと、2番目のエクスポート関数は呼び出されません.
質問:どのようにしてメインフレームワークが最初のエクスポート関数を呼び出した後、(最初のエクスポート関数がtrueを返す限り)2番目のエクスポート関数を自動的に呼び出しますか?
解析:ダイナミックリンクライブラリで非モードダイアログコードの作成を開始するには
extern "C" AFX_API_EXPORT BOOL CommOpen(CChannel* pChannel,BOOL bOpen)
{
    //         
    AFX_MANAGE_STATE(AfxGetAppModuleState());
     CDirCheckDemoDlg *pDlg=new CDirCheckDemoDlg;
     pDlg->Create(IDD_DIRCHECK_DIALOG,AfxGetApp()->m_pMainWnd);
    pDlg->CenterWindow();
     pDlg->ShowWindow(SW_SHOW);
    pDlg->UpdateWindow();
    return TRUE;//              
}
extern "C" AFX_API_EXPORT int Poll(CDevice* pDevice)//             
{

}

ここではこのように書くと、実行後にメインフレームと非モードダイアログが詰まって、応答できなくなります.PAINTメッセージは、ダイアログボックスがずっと描かれているため、最終的にはカードが詰まっているように見え、実際にはメインフレームワークが2番目のエクスポート関数を自動的に呼び出します.カードが詰まっているため、ダイアログに内容を入力できません.whileループ受信メッセージの書き方に変更したが、もう一つの問題が発生し、受信メッセージを処理し続けた.つまりwhile()ループは終了できません(自分でwhileを飛び出してみたらメインフレームと非モダリティダイアログが詰まって応答できない)どうすれば最初の関数をtrueに戻すことができますか?この問題は矛盾した問題で面白いです...このような問題に遭遇した老鳥が解決方法を発表しました.この問題の鍵は、メインフレームと非モダリティダイアログが詰まって応答できない理由を分析することです
完璧な解決方法:
この方法もクラウドフライ(ユーザー名:sky 101010 ws)を凝縮し、彼に感謝しています.全対ではありませんが.以下に、EMCのソリューションを示します.
コードのみ貼り付けました:
CWinThread *cWinThread;
UINT Fun1Pro(LPVOID lpParameter);//      
extern "C" AFX_API_EXPORT BOOL CommOpen(CChannel* pChannel,BOOL bOpen)
{
	//            
 	if (bOpen)
 	{
  		if (cThread==NULL)
  		{   
   		//      
   		cThread=::AfxBeginThread(Fun1Pro,(LPVOID)pChannel);
  		} 
 	}
 	else
 	{  
  		//      ,        afxEndThread()  
  		TerminateThread(cThread->m_hThread,0);
  		p->DestroyWindow();
  		PostQuitMessage(0);
  		delete p;  
 }
 return TRUE;
}

UINT Fun1Pro(LPVOID lpParameter)
{
	MSG msg;
	p = new CDirCheckDemoDlg;    
	cWinThread->PostThreadMessage(CM_TEST1,0,0);//      
	while (::GetMessage(&msg,NULL,0,0))
    {
        //                  
        if (!::IsWindow(p->GetSafeHwnd()) || !::IsDialogMessage(p->GetSafeHwnd(),&msg) )
        {           
			switch (msg.message)
			{
			case CM_TEST1:
				p->Create(IDD_DIRCHECK_DIALOG,AfxGetApp()->m_pMainWnd);
				p->CenterWindow();
				p->ShowWindow(SW_NORMAL);
				p->UpdateWindow();
				break;
			case WM_CLOSE:
				{
					p->DestroyWindow();
					delete p;
					break;
				}
			case WM_DESTROY:
				{
					::PostQuitMessage(0);
					break;
				}
			}
        }
		::TranslateMessage(&msg);//      
		::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
    }
	return 0;
}

extern "C" AFX_API_EXPORT int Poll(CDevice* pDevice)
{
}

メインスレッドを使用するとextern"C"AFX_API_EXPORT BOOL CommOpen(CChannel*pChannel,BOOL bOpen)がtrueに戻ることができないサブスレッドを作成してメッセージを送信するのが主な考え方です.
最後にスレッド外終端スレッドの問題について、関数TerminateThread(cThread->m_hThread,0)を用いる.