最近再写一个程序,需要在一个新创建的线程中,调用对话框上的CRichEdit控件作为该线程的输出。
其中在主线程中的代码如下:
……
        CWinThread * sproofthread=AfxBeginThread(&Sproof,NULL);
//CWinThread * sproofthread=AfxBeginThread(Sproof,NULL,THREAD_PRIORITY_NORMAL,0,0,NULL); //WaitForSingleObject(snifferthread,INFINITE);
Sleep(2000); ::WaitForSingleObject(sproofthread->m_hThread,INFINITE);
Sproof的代码如下:
UINT CQQFinderDlg::Sproof(LPVOID pParam)
{

CQQFinderDlg * m_wnd=(CQQFinderDlg *)AfxGetApp()->m_pMainWnd;
while(1)
{ if(m_wnd->TimerProc()!=2)
{
break;
} ::Sleep(8000);
}

    return 1;
}而TimerProc()中必须要向对话框中的一个CRichEdit空间输出信息,我是这样调用的:
CHARFORMAT cf1;
cf1.cbSize = sizeof (CHARFORMAT);
cf1.bCharSet=GB2312_CHARSET;
cf1.dwMask = CFM_CHARSET |CFM_FACE | CFM_SIZE | CFM_COLOR;
cf1.yHeight = 180;
cf1.crTextColor=RGB(255,253,0);
sprintf(cf1.szFaceName, "宋体"); CRichEditCtrl detail;
CQQFinderDlg * pMnd=(CQQFinderDlg *)AfxGetApp()->m_pMainWnd; detail.Attach(::GetDlgItem(this->m_scanpage,IDC_DETAIL));
if(detail.SetDefaultCharFormat(cf1)==0)
{
::MessageBox(NULL,"设置RichEdit字体错误!","错误",NULL);
return 1;
}
detail.SetWindowText("[+] 开始欺骗主机……\n");
问题如下:当程序运行到if(detail.SetDefaultCharFormat(cf1)==0)的时候,程序就死了,没有任何反应,不会再向下运行,我跟进SetDefaultCharFormat后发现其实它最后是用SendMessage发送了个消息。这个问题困扰了我很久,我在想是不是主线程中::WaitForSingleObject(sproofthread->m_hThread,INFINITE)的原因,或是什么别的问题,请高手帮助。
另外还有一个问题也顺便问了,:)我用             detail.SetSel(detail.GetTextLength(),detail.GetTextLength());
            detail.ReplaceSel(buff); 
(detail是个CRichEditCtrl控件)
作为输出,为什么输出的内容不能每次调用时就显示出来(即和ReplaceSel对应一行一行显示),而是要等到全部程序都运行完了,才会把所有内容一次性显示出来?

解决方案 »

  1.   

    在线程中不能直接操作控件,你可以用SendMessage来发送消息组控件,进行操作第二个问题,我想你是放在一个循环里吧,界面的更新是在CPU有时间的时候才更新的,你放在里面的话,由于数据一直更新,没让出空闲时间,所以就等到最后才一次性更新了,建议放到线程中,这样才不会影响显示
      

  2.   

    界面更新需要回到主线程来操作,如果不需要及时更新的话,用PostMessage,然后再操作,当然也可以直接在线程里面用SendMessage对Window的句柄操作,MFC指针不是线程安全的.
      

  3.   

    多谢各位!
    能不能给几行代码让我看看? detail.SetSel(detail.GetTextLength(),detail.GetTextLength());
     detail.ReplaceSel(buff); 
    我并没有在循环里调用,是正常的程序流程中调用的。但我也发现只要一调用MessageBox前面的内容就能显示出来,有什么办法能让他一行一行的显示呢?请问下,怎么给你们加分?不好意思,我是第一次在这里发贴。
      

  4.   

    把::WaitForSingleObject(sproofthread->m_hThread,INFINITE)去掉试试
      

  5.   

    但::WaitForSingleObject(sproofthread->m_hThread,INFINITE)是程序里必须要的,要等这个线程结束后我的主程序里才能进行下一步操作。
      

  6.   

    我用SendMessage的方法试了一下,也不行,请大家帮我看看是什么问题。
    首先自定义了个消息
    #define WM_DETAIL (WM_USER+100)
    处理函数:
    long OnDetail(WPARAM w,LPARAM l);
    消息映射:
    ON_MESSAGE(WM_DETAIL,OnDetail)处理函数如下:
    long CQQFinderDlg::OnDetail(WPARAM w,LPARAM l)
    {
    char * add=(char *)w;
    m_detail.Attach(::GetDlgItem(this->m_scanpage,IDC_DETAIL));
    m_detail.SetSel(m_detail.GetTextLength(),m_detail.GetTextLength());
    m_detail.ReplaceSel(add);
    m_detail.Detach();
    return 1;
    }在线程中我是这样发消息的:
    CQQFinderDlg * pMnd=(CQQFinderDlg *)AfxGetApp()->m_pMainWnd; char buff[500];
    sprintf(buff,"[+] 开始欺骗网络中的在线主机……\n");
    ::SendMessage(pMnd->m_hWnd,WM_DETAIL,(WPARAM)buff,0);结果一到SendMessage程序又死(停顿)了,和原来直接操作控件一样停滞不前。
    是不是获取主窗口不对?
    请高手帮助,在线等!!
      

  7.   

    SendMessage是代替的调用CWnd的函数,就是在MSDN里面是MESSAGE而不是NOTIFICATION的那种,你这个情况想让他回到主线程,自定义消息用PostMessage.
      

  8.   

    SendMessage消息死锁,把在OnDetail里面的SetSel,ReplaceSel,转成用PostMessage发送的消息。
      

  9.   

    各位大哥快帮忙啊!!!
    用PostMessage虽然可以了,但输出明显非常大大滞后,完全失去了输出的意义。
    我是完全按照SuperScan的界面来做的,它的CRichEditCtrl却能非常及时的输出信息,但我用起来后,却要等程序停顿下来才会一次性输出。还有这个线程往CRichEditCtrl输出的问题,输出实在是滞后得让人无法忍受
      

  10.   

    check MTGDI sample in MSDN
      

  11.   

    在线程中我是这样发消息的:
    CQQFinderDlg * pMnd=(CQQFinderDlg *)AfxGetApp()->m_pMainWnd;char buff[500];
    sprintf(buff,"[+] 开始欺骗网络中的在线主机……\n");
    ::SendMessage(pMnd->m_hWnd,WM_DETAIL,(WPARAM)buff,0);请问lz的这个线程每两次发消息之间有停顿没有?如果这个线程始终争夺CPU,从不停一下让出
    CPU给别人的话,其他线程的处理(比如界面刷新)肯定体现出争抢CPU的样子--短暂停滞,然后一次处理累积的大量信息,又短暂停滞,显得不实时了。
      

  12.   

    线程中不能调用控件。
    CWinThread* mCWinThread;
    HANDLE hThread;
    //unsigned long id;
    BOOL k = false;
    //hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)GetADS,NULL,0,&id);
    HWND *Hwnd = new HWND;
    *Hwnd = this->m_hWnd;
    mCWinThread = AfxBeginThread(GetADS,LPVOID(*Hwnd),NULL,NULL);
    hThread= mCWinThread->m_hThread;
    //WaitForSingleObject(hThread,INFINITE);~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    UINT GetADS(LPVOID pParam)
    {
    ::PostMessage(HWND(pParam),WM_USER+100,0,0);
    Sleep(100);
    return 0;
    }
    发自定义消息
      

  13.   

    多谢各位,我已经放弃了在线程中调用CRichEditCtrl做输出。
    但现在的问题,仍然是
    detail.SetSel(detail.GetTextLength(),detail.GetTextLength());
    detail.ReplaceSel(buff); 
    不能一行一行显示,非要等到程序停顿下来,CRichEditCtrl才会一次性输出出来,我用了sleep也不行,不知道各位有什么好的解决办法?