线程中创造对话框。
单独的消息映射测试过了,没问题.
连上线程后就错误,点击按钮就出错了.怎么做呢?
void CTestDlg::OnBnClickedButton2()
{
HANDLE hThread = (HANDLE)_beginthreadex(
NULL, 
0, 
ProcCreate, 
this, 
0, 
NULL
);
CloseHandle(hThread);

unsigned int WINAPI ProcCreate(LPVOID lpParameter)
{
CWnd* pParent= new CTestDlg();
pParent->SendMessage(UM_CREATE_DLG);
return 0;
}
消息函数LRESULT CTestDlg::OnCreateDlg(WPARAM wParam,LPARAM lParam)

解决方案 »

  1.   

    这个是用MFC吗,MFC中用户线程和工作线程是有区别的,一般用户线程用CWinThread类来创建
    工作线程用AfxBeginThread函数来创建
      

  2.   

    new CTestDlg只是构造了一个CTestDlg对象,并没有创建窗口,所以不能SendMessage。
    如果想让线程与CTestDlg通讯,应该把lpParameter参数强制转换为CTestDlg*类型:
    CTestDlg* dlg = (CTestDlg*)lpParameter;
    dlg->SendMessage(UM_CREATE_DLG);
      

  3.   

    CWnd* pParent= new CTestDlg(); 
    之后要Create
    pParent->Create(xxx);
    pParent->ShowWindow(SW_SHOW);
      

  4.   

    dll中能建立象MFC中的消息循环机制吗?
      

  5.   


    unsigned int WINAPI ProcCreate(LPVOID lpParameter) 
    {  
    CTestDlgDlg* dlg = (CTestDlgDlg*)lpParameter; 
    dlg->SendMessage(UM_CREATE_DLG,0,0);
    return 0; 
    } void CTestDlgDlg::OnButton2() 
    {
    // TODO: Add your control notification handler code here
    HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ProcCreate, this, 0, NULL );
    CloseHandle(hThread); 
    }LRESULT CTestDlgDlg::OnCreateDlg(WPARAM wParam,LPARAM lParam)
    {
    CTestDlgDlg dlg;
    dlg.DoModal();
    // dlg.Create(...)
    return 0;
    }
      

  6.   

    unsigned int WINAPI ProcCreate(LPVOID lpParameter) 

    CWnd* pParent= new CTestDlg(); 
    pParent->SendMessage(UM_CREATE_DLG); 
    return 0; 

    改为:
    unsigned int WINAPI ProcCreate(LPVOID lpParameter) 

    CTestDlg dlg;
    dlg.Create(xxx);   //xxx为CTestDlg的ID
    dlg.SendMessage(UM_CREATE_DLG); 
    return 0; 
      

  7.   

    cnzdgs的是正确的~又简单,能说明下为什么吗?
      

  8.   


    你创建的工作者线程。
    创建对话框,发送消息, 应该创建UI线程,
    用CWinThread类来创建
      

  9.   

    CTestDlg是一个类,需要用类来构造对象并创建之后才会有对话框,这个对话框是与该对象相关联的,并是不是随便一个CTestDlg就可以。要在线程中访问对话框,常用的方法是在创建线程时把对话框对象的指针作为参数传给线程,这一步你的代码中已经做了,线程开始运行后,线程函数的参数就是传递过来的指针,强制转换成CTestDlg*类型就可以用了。
      

  10.   

    谢谢cnzdgs
    但是我理解错了,我做的是要在一个对话筐中用线程调用dll中的create.create方法是创造对话框,该对话框是在dll中的。
    主对话框只能用线程调同create,不能再设消息循环。怎么弄呢?
    我做的
    class CMyThread:public CWinThread
    {
    DECLARE_DYNCREATE(CMyThread)
    public:
    BOOL InitInstance();
    };
    IMPLEMENT_DYNCREATE(CMyThread,CWinThread)
    BOOL CMyThread::InitInstance()
    {
    g_Dlg=CreateMyDlg();
    return 0;
    }
    void CTestDlg::OnBnClickedButton3()
    {
    CWinThread* pThread = AfxBeginThread(RUNTIME_CLASS(CMyThread));
    }
    但是创建的窗口闪下就没了,为什么呢,dll中的
    MYDLL_API VDLG CreateMyDlg(void)
    {
    AFX_MANAGE_STATE(AfxGetStaticModuleState())
    MyDllDlg *pDlg = new MyDllDlg();
    pDlg->Create(IDD_DIALOG1); pDlg->ShowWindow(SW_SHOW ); return pDlg;
    }
      

  11.   

    上面的很多大哥说应该创建UI线程才能做,但是我按照cnzdgs 
    的方法就行了,我看书上也说用创建UI线程的方法,这是为什么呢?
      

  12.   

    BOOL CMyThread::InitInstance() 

    g_Dlg=CreateMyDlg(); 
    return TRUE

      

  13.   

    。。我太粗心了,但是我调用这个后,再用同样的方法调用dll中的DestoryVtDlg(&g_Dlg)
    class CMyThread2:public CWinThread
    {
    DECLARE_DYNCREATE(CMyThread2)
    public:
    BOOL InitInstance();
    };
    IMPLEMENT_DYNCREATE(CMyThread2,CWinThread)
    BOOL CMyThread2::InitInstance()
    {
    DestoryVtDlg(&g_Dlg);
    return TRUE;
    }void CTestDlg::OnBnClickedButton4()
    {
    CWinThread* pThread = AfxBeginThread(RUNTIME_CLASS(CMyThread2));
    }
    DLL中的
    MYDLL_API void DestoryVtDlg(VDLG *dlg)
    {
    if(*dlg == NULL)
    return; AFX_MANAGE_STATE(AfxGetStaticModuleState())
    MyDllDlg *pDlg = (MyDllDlg*)(*dlg);
    pDlg->SendMessage(WM_CLOSE);
    delete pDlg;
    *dlg = NULL;
    }
    就会出现错误,想解决的就是这个问题
      

  14.   

    一个线程创造,一个线程删除。都是调用dll中的函数,并且创造的对话框是dll中的对话框
      

  15.   

    这个我知道,但是我要实现的是别人可以直接用2线程来调用我的dll的方法创造删除我dll中的对话框,别人不需要用消息循环
      

  16.   

    在这里delete pDlg可能会出问题,非模态对话框通常重载PostNcDestroy函数来delete this释放对象。
      

  17.   

    另外,你要响应WM_CLOSE消息来调用DestroyWindow才能销毁对话框,不知道你有没有处理。
      

  18.   

    程序就是:
    有一个dll,调用dll中的函数createDlg()创造一个非模态对话筐,destroy(void*)摧毁一个非模态对话筐.
    希望实现的是在随便一个客户的mfc中使用线程来createDlg(),和destroy(void*).但是在该客户只是简单的使用线程来调用这两个函数,不用创造消息循环.
    程序出错的话只能改dll中的程序.
    现在的dll中只是简单的创造非模态对话筐.
      

  19.   

    就是一个是在线程中直调dll中的函数,一个是在线程中SentMessage,在该消息中调用dll中的函数.
      

  20.   

    可以在createDlg函数中创建线程然后返回,线程中用new构造对象、创建非模态对话框并执行消息循环;在destroy中向对话框发送WM_CLOSE消息,由对话框自己来DestroyWindow和delete this。
      

  21.   

    您的意思是在createDlg中再创一个线程,然后在该线程中创建非模态对话框?在dll中用消息循环?可以在createDlg函数中创建线程然后返回,
    这句话不是很理解,新手,谢谢了.
      

  22.   

    动态new一个CTestDlg对象后,必须调用CWnd::Create或CWnd::CreateEx或CDialog::Create后才能发送窗口消息
      

  23.   

    既然你是要做一个DLL独自来处理创建和销毁对话框,自然是所有相关代码都在DLL中。
    EXE通过调用createDlg来创建非模态对话框,创建完后自然要返回,而不能在该函数中执行消息循环,否则就等于是模态了。
    因为要求EXE不需要处理消息循环,而createDlg又必须在创建对话框之后立即返回,所以只能是创建一个线程,在线程中来处理消息循环。
    又因为对话框与消息循环需要在同一线程中,所以对话框也要在线程中创建。
      

  24.   

    不知道我理解的对不对,您的意思是不是在createDlg中创造一个线程来创造窗口和处理消息循环.
      

  25.   

    感觉好象想通了,按原来那样在EXE的线程中调用DLL的CreateDlg就会因为没有处理消息循环所以就只是创造了窗口,但是该窗口会“没有响应”。 
    您说的"在MFC应用程序项目(对话框、SDI、MDI)中,主线程会执行MFC中提供的消息循环,所以在某个消息响应函数中,创建非模态对话框之后可以直接返回,不需要自己写消息循环。"
    就是说在EXE的消息循环中调用DLL的CreateDlg,那样就因为"在MFC应用程序项目(对话框、SDI、MDI)中,主线程会执行MFC中提供的消息循环",所以就可以实现了是吧.
    但是我在dll中用线程创造窗口后,怎么处理消息循环.自己在dll中自定义消息循环??
      

  26.   

    可以自己写消息循环的代码,参考MSDN中GetMessage说明中的例子;也可以用CWinThread类,该类中带有消息循环,InitInstance函数要返回TRUE。
      

  27.   

    好的~非常感谢。
    还有一个小问题不理解,就是如果在mfc中不用线程而是直接创造非模态窗口的话,您说的窗口是属于线程的,那是不是MFC中自己创造线程了建立窗口呢?
      

  28.   

    没明白你问的是什么。举例来说,一个基于对话框的项目,主对话框是用DoModal来显示的,DoModal里面带有消息循环代码,在创建和显示对话框之后,线程一直处于消息循环中,程序可以添加一些消息的响应函数,响应函数执行返回后,线程会回到消息循环。如果在某个消息的响应函数中创建了非模态对话框并返回,DoModal的消息循环也会自动处理新对话框的消息。
      

  29.   

    结贴,谢谢各位的帮助,特别是cnzdgs !!!