大家好,在基于对话框的一个MFC程序中,我添加了一个
UINT ThreadFunc(LPVOID pParam);
也添加了相应的头文件等等。
在我定义的线程函数中我调用了自定义的一个函数,但是编译的时候这个函数名一直是undeclared identifier。
好像这个涉及到线程间通信,刚学多线程,请大家指教,具体一些。不胜感激。

解决方案 »

  1.   

    在我定义的线程函数中我调用了自定义的一个函数,但是编译的时候这个函数名一直是undeclared identifier。
    好像这个涉及到线程间通信,刚学多线程,请大家指教,具体一些。不胜感激。
    ===========
    编译出现问题,这个和线程间通信没有关系,你多贴点代码出来看看。
      

  2.   


    在对话框头文件中声明了:
    void DrawPicToHDC(IplImage *img, UINT ID);
        IplImage *img1;
        IplImage *img2;
        CCameraDS camera1;
    CCameraDS camera2;
        static UINT ThreadProc1(LPVOID pParam);
    static UINT ThreadProc2(LPVOID pParam);在对话框实现文件中定义了:
    void  CMy1Dlg::DrawPicToHDC(IplImage *img, UINT ID)

    CDC *pDC = GetDlgItem(ID)->GetDC(); 
    HDC hDC= pDC->GetSafeHdc(); 
    CRect rect; 
    GetDlgItem(ID)->GetClientRect(&rect); 
    CvvImage cimg; 

    cimg.CopyOf(img); 
    cimg.DrawToHDC(hDC,&rect); 

    ReleaseDC(pDC); 
    }然后在线程函数中调用函数DrawPicToHDC(IplImage *img, UINT ID)
    UINT ThreadProc1(LPVOID pParam)
    {
     //打开第一个摄像头
      
      
       CCameraDS camera1;   if(! camera1.OpenCamera(0)) //第一个摄像头
       {
          fprintf(stderr, "Can not open camera.\n");
        }
        
     IplImage *img1=0;
     
       while(1)
       {
          //获取一帧
          IplImage *img1 = camera1.QueryFrame();
          DrawPicToHDC(img1, IDC_STATIC);
          if (cvWaitKey(20) == 'q')
          break;
       }
       camera1.CloseCamera(); //可不调用此函数,CCameraDS析构时会自动关闭摄像头 return 0;
    }UINT ThreadProc2(LPVOID pParam)
    {
      
    ////打开第二个摄像头
       CCameraDS camera2;//打开第二个摄像头
       
       if(! camera2.OpenCamera(2)) //这里选择2是因为本程序运行后0和1都指向同一个摄像头
       {
          fprintf(stderr, "Can not open camera.\n");
    }IplImage *img2=0;while(1)
       {//获取一帧
          IplImage *img2 = camera2.QueryFrame(); //采用两个完全相同的摄像头时,程序在此崩溃
          DrawPicToHDC(img2, IDC_STATIC1);
    if (cvWaitKey(20) == 'q')
             break;
       }
    camera2.CloseCamera(); //可不调用此函数,CCameraDS析构时会自动关闭摄像头 return 0;
    }void CMy1Dlg::OnButton1() 
    {
    // TODO: Add your control notification handler code here
    HWND hwnd=GetSafeHwnd();
    AfxBeginThread(ThreadProc1,hwnd,THREAD_PRIORITY_NORMAL);
    }
    void CMy1Dlg::OnButton2() 
    {
    // TODO: Add your control notification handler code here
    HWND hwnd=GetSafeHwnd();
    AfxBeginThread(ThreadProc2,hwnd,THREAD_PRIORITY_NORMAL);
    }编译出错:'DrawPicToHDC' : undeclared identifier
    请问这是什么原因呢
      

  3.   

    然后在线程函数中调用函数DrawPicToHDC(IplImage *img, UINT ID)
    =====================
    你的线程函数好像不是类的成员函数啊,当然不能调用类成员函数DrawPicToHDC了。
      

  4.   

    那是不是把ThreadProc1和ThreadProc2作为CWinThread的派生类
    然后改成UINT CMy1Dlg::ThreadProc1(LPVOID pParam)
    UINT CMy1Dlg::ThreadProc2(LPVOID pParam)这样就行啦
    可是又有新问题了:
    f:\多线程1\多线程1dlg.cpp(213) : error C2352: 'CMy1Dlg::DrawPicToHDC' : illegal call of non-static member function
    f:\多线程1\多线程1dlg.h(27) : see declaration of 'DrawPicToHDC'
    f:\多线程1\多线程1dlg.cpp(240) : error C2352: 'CMy1Dlg::DrawPicToHDC' : illegal call of non-static member function
    f:\多线程1\多线程1dlg.h(27) : see declaration of 'DrawPicToHDC'声明时改为 static void DrawPicToHDC(IplImage *img, UINT ID);也不对
      

  5.   

    那是不是把ThreadProc1和ThreadProc2作为CWinThread的派生类
    然后改成UINT CMy1Dlg::ThreadProc1(LPVOID pParam)
    UINT CMy1Dlg::ThreadProc2(LPVOID pParam)这样就行啦
    可是又有新问题了:
    f:\多线程1\多线程1dlg.cpp(213) : error C2352: 'CMy1Dlg::DrawPicToHDC' : illegal call of non-static member function
    f:\多线程1\多线程1dlg.h(27) : see declaration of 'DrawPicToHDC'
    f:\多线程1\多线程1dlg.cpp(240) : error C2352: 'CMy1Dlg::DrawPicToHDC' : illegal call of non-static member function
    f:\多线程1\多线程1dlg.h(27) : see declaration of 'DrawPicToHDC'声明时改为 static void DrawPicToHDC(IplImage *img, UINT ID);也不对
    ==========
    我上面不是说了吗,线程函数改成成员函数之后,静态函数中不能引用非静态成员,所以还是不行。
    你可以在线程函数中向对话框发自定义消息,让对话框在响应自定义消息时自己去调用那个函数。
      

  6.   

    可不可以使用对象
    CMy1Dlg a;
    a.DrawPicToHDC(img1, IDC_STATIC);呢
    不过这样编译时通过了,执行时又出现问题了···
      

  7.   

    可不可以使用对象
    CMy1Dlg a;
    a.DrawPicToHDC(img1, IDC_STATIC);呢
    不过这样编译时通过了,执行时又出现问题了···
    ========
    这样编译当然没事,但是此时CMy1Dlg a这个对象和你的对话框就没有关系了。执行时当然不行了。
      

  8.   

    线程函数应该是静态的成员函数吧~!如果是外部函数,这样是否要定义成friend函数
      

  9.   

    我试了向对话框发自定义消息。
    在对话框头文件中定义自定义消息const WM_USRMSG=WM_USER+100;//定义用户消息
    声明自定义消息响应函数:afx_msg  void DrawPicToHDC(IplImage *img, UINT ID);
    在对话框实现文件中自定义映射:ON_MESSAGE(WM_USRMSG,DrawPicToHDC)
    自定义消息响应函数:
    void  CMy1Dlg::DrawPicToHDC(IplImage *img, UINT ID)

    CDC *pDC = GetDlgItem(ID)->GetDC(); 
    HDC hDC= pDC->GetSafeHdc(); 
    CRect rect; 
    GetDlgItem(ID)->GetClientRect(&rect); 
    CvvImage cimg; 

    cimg.CopyOf(img); 
    cimg.DrawToHDC(hDC,&rect); 

    ReleaseDC(pDC); 
    }
    定义线程函数:
    UINT ThreadProc1(LPVOID pParam)
    {
     //打开第一个摄像头
       CCameraDS camera1;   if(! camera1.OpenCamera(0)) //第一个摄像头
       {
          fprintf(stderr, "Can not open camera.\n");
        }
        
     IplImage *img1=0;
     
       while(1)
       {
          //获取一帧
          IplImage *img1 = camera1.QueryFrame();
          DrawPicToHDC(img1, IDC_STATIC);
          if (cvWaitKey(20) == 'q')
          break;
       }
       camera1.CloseCamera(); //可不调用此函数,CCameraDS析构时会自动关闭摄像头 return 0;
    }UINT ThreadProc2(LPVOID pParam)
    {
       
    ////打开第二个摄像头
       CCameraDS camera2;//打开第二个摄像头
       
       if(! camera2.OpenCamera(2)) //这里选择2是因为本程序运行后0和1都指向同一个摄像头
       {
          fprintf(stderr, "Can not open camera.\n");
    }IplImage *img2=0;while(1)
       {//获取一帧
          IplImage *img2 = camera2.QueryFrame(); //采用两个完全相同的摄像头时,程序在此崩溃
          DrawPicToHDC(img2, IDC_STATIC1);
    if (cvWaitKey(20) == 'q')
             break;
       }
    camera2.CloseCamera(); //可不调用此函数,CCameraDS析构时会自动关闭摄像头 return 0;
    }void CMy1Dlg::OnButton1() 
    {
    // TODO: Add your control notification handler code here
    HWND hwnd=GetSafeHwnd();
    AfxBeginThread(ThreadProc1,hwnd,THREAD_PRIORITY_NORMAL);
    }
    void CMy1Dlg::OnButton2() 
    {
    // TODO: Add your control notification handler code here
    HWND hwnd=GetSafeHwnd();
    AfxBeginThread(ThreadProc2,hwnd,THREAD_PRIORITY_NORMAL);
    }
    编译后还是说'DrawPicToHDC' : undeclared identifier,怎么会这样呢?
      

  10.   

    我试了向对话框发自定义消息。
    在对话框头文件中定义自定义消息const WM_USRMSG=WM_USER+100;//定义用户消息
    声明自定义消息响应函数:afx_msg void DrawPicToHDC(IplImage *img, UINT ID);
    在对话框实现文件中自定义映射:ON_MESSAGE(WM_USRMSG,DrawPicToHDC)
    ==========
    后面的没看,有几个问题:
    定义自定义一般的写法是:#define WM_USERMSG WM_USER+100
    自定义消息响应函数afx_msg void DrawPicToHDC(IplImage *img, UINT ID);这样写是不行的,一般定义成:afx_msg void MyMsgProc(WPARAM wParam, LPARAM lParam);
    你可以在MyMsgProc中调用DrawPicToHDC,而不是用DrawPicToHDC作为消息的处理函数。
      

  11.   

    自定义消息响应函数,一般返回值类型是 LRESULT,不是 void;LZ 需要理解一下类成员函数和全局函数的区别。
      

  12.   

    我在对话框头文件中声明了自定义消息响应函数:
    afx_msg LRESULT OnMessage(WPARAM wParam, LPARAM lParam);
    在对话框实现文件中自定义消息映射:
    ON_MESSAGE(WM_USERMSG, OnMessage)
    自定义消息响应函数:
    LRESULT CMy1Dlg::OnMessage(WPARAM wParam, LPARAM lParam)
    {
     DrawPicToHDC(IplImage *img, UINT ID);
     return 0;
    }
    定义线程函数:
    UINT ThreadProc1(LPVOID lpParam)
    {…
    HWND hWnd = (HWND)lpParam;
    SendMessage(hWnd, UM_MESSAGE, 0, 0);

    return 0;}
    UINT ThreadProc2(LPVOID lpParam)
    {…
    HWND hWnd = (HWND)lpParam;
    SendMessage(hWnd, UM_MESSAGE, 0, 0);

    return 0;}
    还是不对:f: \多线程1\多线程1dlg.cpp(198) : error C2065: 'img' : undeclared identifier
    f: \多线程1\多线程1dlg.cpp(198) : error C2275: 'IplImage' : illegal use of this type as an expression
            e:\opencv\cxcore\include\cxtypes.h(393) : see declaration of 'IplImage'
    f: \多线程1\多线程1dlg.cpp(198) : error C2275: 'UINT' : illegal use of this type as an expression
            e:\vc98\include\windef.h(162) : see declaration of 'UINT'
    f:\多线程1\多线程1dlg.cpp(198) : error C2146: syntax error : missing ')' before identifier 'ID'
    f:\多线程1\多线程1dlg.cpp(198) : error C2059: syntax error : ')'
    f: \多线程1\多线程1dlg.cpp(220) : error C2065: 'UM_MESSAGE' : undeclared identifier
      

  13.   

    调用的时候不要带类型,DrawPicToHDC(img, ID);
      

  14.   

    还有,问题很明显,参数得从 wParam,lParam 进行类型转换
      

  15.   

    DrawPicToHDC(IplImage *img, UINT ID);
    ============
    有这样调用函数的吗?调用函数还写参数类型啊?应该是这样吧:DrawPicToHDC(img, ID);: \多线程1\多线程1dlg.cpp(220) : error C2065: 'UM_MESSAGE' : undeclared identifier
    ================
    这个错误明显是拼写错误啊,应该是WM_MESSAGE
      

  16.   

    不好意思犯了低级错误,楼上的同学说参数得从 wParam,lParam 进行类型转换,能再请教下具体怎么写么
      

  17.   

    我进行了类型转换:
    LRESULT CMy1Dlg::OnMessage(WPARAM wParam, LPARAM lParam)
    {
     IplImage *img=(IplImage *)wParam;
     UINT ID=UINT(lParam);
     DrawPicToHDC(img,ID);
     return 0;
    }SendMessage(hWnd, WM_USERMSG, img1, IDC_STATIC);发生错误:
    c:\documents and settings\administrator\桌面\多线程1\多线程1dlg.cpp(224) : error C2664: 'SendMessageA' : cannot convert parameter 3 from 'struct _IplImage *' to 'unsigned int'
      

  18.   

    1、SendMessage(hWnd, WM_USERMSG, (WPARAM)img1, (LPARAM)IDC_STATIC); 2、你使用 IDC_STATIC 恐怕不妥。
      

  19.   

    是控件用得不对还是还是名字不对呢。
    SendMessage(hWnd, WM_USERMSG, (WPARAM)img1, (LPARAM)IDC_STATIC_PIC);
    SendMessage(hWnd,WM_USERMSG, (WPARAM)img2, (LPARAM)IDC_STATIC_PIC1);  编译还是出错:
    多线程1Dlg.obj : error LNK2001: unresolved external symbol "public: static unsigned int __cdecl CMy1Dlg::ThreadProc1(void *)" (?ThreadProc1@CMy1Dlg@@SAIPAX@Z)
    多线程1Dlg.obj : error LNK2001: unresolved external symbol "public: static unsigned int __cdecl CMy1Dlg::ThreadProc2(void *)" (?ThreadProc2@CMy1Dlg@@SAIPAX@Z)
    Debug/多线程1.exe : fatal error LNK1120: 2 unresolved externals
      

  20.   

    编译还是出错:
    多线程1Dlg.obj : error LNK2001: unresolved external symbol "public: static unsigned int __cdecl CMy1Dlg::ThreadProc1(void *)" (?ThreadProc1@CMy1Dlg@@SAIPAX@Z)
    多线程1Dlg.obj : error LNK2001: unresolved external symbol "public: static unsigned int __cdecl CMy1Dlg::ThreadProc2(void *)" (?ThreadProc2@CMy1Dlg@@SAIPAX@Z)
    Debug/多线程1.exe : fatal error LNK1120: 2 unresolved externals
    =================
    这个估计是以前将线程函数当作类的成员函数时留下H文件中函数声明没有删除造成的,将H文件中线程函数声明去掉就行了。
      

  21.   

    能运行了,但“该内存不能为read”,调试后在{ ASSERT(::IsWindow(m_hWnd)); return CDC::FromHandle(::GetDC(m_hWnd)); }中断,是窗口句柄出了问题吗,怎么改呀
      

  22.   

    声明了:
    IplImage *img;
        UINT ID;
        void DrawPicToHDC(IplImage *img, UINT ID);
    定义:
    void  CMyDlg::DrawPicToHDC(IplImage *img, UINT ID)

    CDC *pDC = GetDlgItem(ID)->GetDC(); 
        HDC hDC= pDC->GetSafeHdc(); 
    CRect rect; 
    GetDlgItem(ID)->GetClientRect(&rect); 
    CvvImage cimg; 

    cimg.CopyOf(img); 
    cimg.DrawToHDC(hDC,&rect); 

    ReleaseDC(pDC); 
    }
    是什么问题呢
      

  23.   

    GetDlgItem(ID)-> 这样调用太危险,可能是 GetDlgItem(ID) 是空指针,建议修改成 
        CWnd *p = GetDlgItem(ID);
        if (p != NULL)
            p->...
      

  24.   

    而且,你 GetDC 的指针(通过 GetDlgItem 得到)与 ReleaseDC (this)没有正确匹配,问之前先检查一下自己的代码,别老想别人帮忙;很明显的错误。
      

  25.   

    CDC *pDC = GetDlgItem(ID)->GetDC();  
    GetDlgItem(ID)->GetClientRect(&rect);  
    ============
    最大的可以是上面两句中的GetDlgItem(ID)得到的是指针是NULL,你在调用这两个之前必须要保证相关的控件必须要实际存在
      

  26.   

    定义线程的过程函数,不应该是
    UINT ThreadFunc(LPVOID pParam);这个样子啊。
    过程函数是回调函数,有Windows调用,所以应该是标准风格 _stdcall 
    DWORD WINAPI ThreadProc(
      LPVOID lpParameter   // thread data
    );
      

  27.   

    改成这样了
    void  CMyDlg::DrawPicToHDC(IplImage *img, UINT ID)

        CWnd *p = GetDlgItem(ID); //得到指针
        if(p!=NULL)//若指针不为零
        CDC *pDC =p->GetDC(); 
        HDC hDC=pDC->GetSafeHdc(); 
    CRect rect; 
    p->GetClientRect(&rect); 
    CvvImage cimg; 

    cimg.CopyOf(img); 
    cimg.DrawToHDC(hDC,&rect); 

    ReleaseDC(pDC); 
    }
    还是不对
    :\多线程重写—该内存不能为read\多线程重写dlg.cpp(201) : error C2065: 'pDC' : undeclared identifier
    f:\多线程重写—该内存不能为read\多线程重写dlg.cpp(201) : error C2227: left of '->GetSafeHdc' must point to class/struct/union
    执行 cl.exe 时出错.
      

  28.   

    你都不使用 { } 当然编译出现问题了,试一试CWnd *p = GetDlgItem(ID); //得到指针
      if(p!=NULL)//若指针不为零
      {
         CDC *pDC =p->GetDC();
        if (pDC != NULL)
        {
         HDC hDC=pDC->GetSafeHdc();  
         CRect rect;  
         p->GetClientRect(&rect);  
         CvvImage cimg;       cimg.CopyOf(img);  
         cimg.DrawToHDC(hDC,&rect);       p->ReleaseDC(pDC);
        }
     }
      

  29.   

    是不是还是句柄的问题呢?
    我在CPP文件里定义了一个全局HWND 类型的变量,用于存储对话框句柄 HWND hWnd;
    线程函数中:
     SendMessage((HWND)lpParam, WM_USERMSG, (WPARAM)img1, (LPARAM)IDC_STATIC_PIC);
     SendMessage((HWND)lpParam, WM_USERMSG, (WPARAM)img2, (LPARAM)IDC_STATIC_PIC1);
    按钮的函数:
    AfxBeginThread(ThreadProc1,hWnd,THREAD_PRIORITY_NORMAL);
    AfxBeginThread(ThreadProc2,hWnd,THREAD_PRIORITY_NORMAL);
    是不是跟我定义的函数的句柄不一致呢
    void  CMyDlg::DrawPicToHDC(IplImage *img, UINT ID)
     {   
    CWnd *pWnd = GetDlgItem(ID); //得到指针 
       if(pWnd!=NULL)//若指针不为零 
       { 
          CDC *pDC =pWnd->GetDC(); 
         if (pDC != NULL) 
         { 
          HDC hDC=pDC->GetSafeHdc();   
          CRect rect;   
          pWnd->GetClientRect(&rect);   
          CvvImage cimg;   
      
          cimg.CopyOf(img);   
          cimg.DrawToHDC(hDC,&rect);   
      
          pWnd->ReleaseDC(pDC); 
         } 
      }
    }