MFC子线程访问对话框界面(主线程)中的控件对象

wuxia2118 2018-06-18 07:32:44
程序是这样的,在一个子线程中用recv()函数接收网络传来的数据,然后要把接收来的这些数据显示在对话框界面中的一个列表框内。 原始程序我是在网上看到的,代码如下:(该代码的完整程序在https://blog.csdn.net/yansj_scu/article/details/24571721
DWORD WINAPI CTCPServerDlg::RespondProc(LPVOID lpPar)  
{
SOCKET *pClientSocket = (SOCKET*)lpPar;
char buff[4096]; /* 接收数据缓冲区 */

struct sockaddr_in sa;
int len = sizeof(sa);
getpeername(*pClientSocket, (struct sockaddr *)&sa, &len);

while(1)
{
Sleep(10);
int nRecv = ::recv(*pClientSocket, buff, 4096, 0);
if(nRecv > 0)
{
buff[nRecv] = '\0';
}

//对接收的数据进行处理
.......
}
}


我把它改成下面这样,编译正常,但是一运行就崩溃:
DWORD WINAPI CTCPServerDlg::RespondProc(LPVOID lpPar)  
{
SOCKET *pClientSocket = (SOCKET*)lpPar;
CTCPServerDlg *pThis = (CTCPServerDlg*)lpPar;

char buff[4096]; /* 接收数据缓冲区 */

struct sockaddr_in sa;
int len = sizeof(sa);
getpeername(*pClientSocket, (struct sockaddr *)&sa, &len);

while(1)
{
Sleep(10);
int nRecv = ::recv(*pClientSocket, buff, 4096, 0);
if(nRecv > 0)
{
buff[nRecv] = '\0'; //在接收的数据末尾处加\0
// AfxMessageBox(buff);
}

//对接收的数据进行处理
CString recvbuf;
recvbuf.Format("%s",buff);
pThis->c_recvbuf.AddString(recvbuf); //这是我添加的,会崩溃

}
}


我查了很多解决该问题的文章,有篇文章中的程序是这样的,可以将接收的数据显示到文本框中,代码如下:
//定义线程函数
DWORD WINAPI CTcpthDlg::RecvProc(LPVOID lpParameter)
{
SOCKET sock=((RECVPARAM*)lpParameter)->sock;
HWND hwnd=((RECVPARAM*)lpParameter)->hwnd;
delete lpParameter;

SOCKADDR_IN addrFrom;
int len=sizeof(SOCKADDR);

char recvBuf[200];
char tempBuf[300];
int retval;
while(TRUE)
{
retval=recv(sock,recvBuf,200,0);
if(SOCKET_ERROR==retval)
break;
sprintf(tempBuf,"%s说: %s",
inet_ntoa(addrFrom.sin_addr),recvBuf);
//利用PostMessage将消息传递给对话框。
::PostMessage(hwnd,WM_RECVDATA,0,(LPARAM)tempBuf);
}
return 0;
}

可我看不懂,它这个PostMessage里根本没看见有文本框的ID ,不知怎么的就把内容显示到文本框中去了。
还有篇文章,专门讲解我提的这个问题,可我也看不懂,不知怎么把它的方法用到我的这个程序里来,链接如下:
https://blog.csdn.net/xbmoxia/article/details/16981243

请问,怎么把子线程获取的数据显示到对话框的列表框中,如果不好实现,显示到编辑框中也行。
...全文
1464 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
Eleven 2018-06-21
  • 打赏
  • 举报
回复
你直接把主窗口的HWND窗口句柄作为线程函数的参数传递给线程就好了。
wuxia2118 2018-06-19
  • 打赏
  • 举报
回复
问题解决了,6楼说的是对的,需要使用发送消息的方法,经测试,SendMessage和PostMessage都可以。但是获取窗口句柄不能用这句 HWND hwnd=((RECVPARAM*)lpPar)->hwnd; 而只能用这句 hwnd = AfxGetMainWnd()->m_hWnd; 说明:我定义了一个结构体: struct RECVPARAM{ SOCKET sock; HWND hwnd; }; 代码如下:

DWORD WINAPI CTCPServerDlg::RespondProc(LPVOID lpPar)  
{  
    SOCKET *pClientSocket = (SOCKET*)lpPar; 
	// SOCKET *pClientSocket = new SOCKET;   
	CTCPServerDlg *pThis = (CTCPServerDlg*)lpPar; 
   HWND hwnd=((RECVPARAM*)lpPar)->hwnd;  //这句没有用
 	
	char buff[4096]; /* 接收数据缓冲区 */  
  
    struct sockaddr_in sa;   
    int len = sizeof(sa);   
    getpeername(*pClientSocket, (struct sockaddr *)&sa, &len);    
  
    while(1)  
    {  
        Sleep(10);  
        int nRecv = ::recv(*pClientSocket, buff, 4096, 0);  
        if(nRecv > 0)  
        {  
            buff[nRecv] = '\0';  //在接收的数据末尾处加\0 
			AfxMessageBox(buff);
        }  
  

        //对接收的数据进行处理 
		CString recvbuf;

	hwnd = AfxGetMainWnd()->m_hWnd;
		recvbuf.Format("%s",buff);
		//利用PostMessage将消息传递给对话框。
		::PostMessage(hwnd,WM_RECVDATA,0,(LPARAM)buff);
        
       }  
}  

	void CTCPServerDlg::OnRecvData(WPARAM wParam,LPARAM lParam)
{
	CString str=(char*)lParam;
	c_recvbuf.AddString(str);
}
走好每一步 2018-06-19
  • 打赏
  • 举报
回复
界面显示PostMessage就好了,直接在线程里操作界面是不大好的习惯
sichuanwww 2018-06-19
  • 打赏
  • 举报
回复
问题问得有毛病,只是在界面上显示东西而已。可以用消息,比如 SendMessage(mainH,WM_CHAR,1,0);给主窗口发消息; 然后在主窗口的WM_CHAR事件里赋值就可以了。
worldy 2018-06-19
  • 打赏
  • 举报
回复
HWND hwnd=((RECVPARAM*)lpPar)->hwnd; 当然可以使用这个,只是你在创建线程的时候,必须和hwnd对应。 使用AfxGetMainWnd()->m_hWnd你会将消息传递到主窗口上,如果是MDI应用,你将得不到你要的结果
schlafenhamster 2018-06-18
  • 打赏
  • 举报
回复
SOCKET *pClientSocket = (SOCKET*)lpPar; CTCPServerDlg *pThis = (CTCPServerDlg*)lpPar;
蒋晟 2018-06-18
  • 打赏
  • 举报
回复
lpPar明明是你传的tempBuf地址不是对话框的地址,为啥要强制转换成对话框类型?
wuxia2118 2018-06-18
  • 打赏
  • 举报
回复
你的 SOCKET *pClientSocket = (SOCKET*)lpPar; 这句不是我写的,它原来就有,而且这句是对的啊,因为我写这句服务器端都可正常收到客户端的数据,AfxMessageBox(buff);就可看到,这表明socket是没问题的。 问题还是收到了buff的数据,无法将这些数据显示到对话框里面
schlafenhamster 2018-06-18
  • 打赏
  • 举报
回复
原来 CTCPServerDlg *pThis = (CTCPServerDlg*)lpPar; 是对的 你的 SOCKET *pClientSocket = (SOCKET*)lpPar; 错的 原来 SOCKET *pClientSocket = new SOCKET; // 创建一个 ClientSocket 指针 *pClientSocket = ::accept(pThis->listensocketfd, (SOCKADDR*)&remoteAddr, &nAddrLen); // 这个指针内容为。。 是对的
wuxia2118 2018-06-18
  • 打赏
  • 举报
回复
这个lpPar 它原来的程序中就是这样写的,难道它原来的程序也写错了,我看不懂lpPar 是什么东西,只是照猫画虎
DWORD WINAPI CTCPServerDlg::WaitProc(LPVOID lpPar)  
{  
    sockaddr_in remoteAddr;  
    int nAddrLen = sizeof(remoteAddr);  
  
    CTCPServerDlg *pThis = (CTCPServerDlg*)lpPar;  
  
    CString strNotice; /* 通知消息 */  
  
    while(1)  
    {  
        Sleep(10);  
  
        /* 创建通信套接字 */  
        SOCKET *pClientSocket = new SOCKET;   
        *pClientSocket = ::accept(pThis->listensocketfd, (SOCKADDR*)&remoteAddr, &nAddrLen);  
          
        if(INVALID_SOCKET == *pClientSocket)  
        {  
            strNotice = "accept()失败,再次尝试 ...... ";  
            ::AfxMessageBox(strNotice);  
            continue;  
        }  
  
        DWORD dwThreadId = 1;  
  
        /* 启动相应线程与客户端通信 */  
        pThis->m_hRespondThread = ::CreateThread(NULL, NULL, CTCPServerDlg::RespondProc, ((LPVOID)pClientSocket), 0, &dwThreadId);   
          
        CloseHandle(pThis->m_hRespondThread);  
    }  
    return 0;  
}  

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧