使用 CMFCDesktopAlertWnd 类的 MFC 应用程序上未显示警报对话框的通知

问题描述 投票:0回答:1

我有一个使用TCP/IP协议发送和接收数据的项目,同时,

我会在屏幕左下角显示一个警报对话框,以了解是否有任何数据正在发送

我想将它构建成一个函数并单独在线程上运行。但是发送数据后,我没有收到任何通知,也没有任何错误。

有没有人帮你解决这个问题。非常感谢。

这是我的代码:

UINT JobManager::JobInfoAlert(LPVOID pParam)
{
THREADSTRUCT*   ts = (THREADSTRUCT*)pParam;
WSADATA wsData;
WORD ver = MAKEWORD(2, 2);

int wsOk = WSAStartup(ver, &wsData);
if (wsOk != 0)
{
    AfxMessageBox(L"Can't Initialize winsock! Quitting");
    return 1;
}

// Create a socket
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET)
{
    AfxMessageBox(L"Can't create a socket! Quitting");
    return 1;
}

// Bind the ip address and port to a socket
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(54000);
hint.sin_addr.S_un.S_addr = INADDR_ANY; // Could also use inet_pton .... 

bind(listening, (sockaddr*)&hint, sizeof(hint));

// Tell Winsock the socket is for listening 
listen(listening, SOMAXCONN);

// Wait for a connection
sockaddr_in client;
int clientSize = sizeof(client);

SOCKET clientSocket = accept(listening, (sockaddr*)&client, &clientSize);

char host[NI_MAXHOST];      // Client's remote name
char service[NI_MAXSERV];   // Service (i.e. port) the client is connect on

ZeroMemory(host, NI_MAXHOST); // same as memset(host, 0, NI_MAXHOST);
ZeroMemory(service, NI_MAXSERV);

if (getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0)
{
    //cout << host << " connected on port " << service << endl;
}
else
{
    inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
    //cout << host << " connected on port " <<
    //ntohs(client.sin_port) << endl;
}

// Close listening socket
closesocket(listening);

// While loop: accept and echo message back to client
char buf[4096];
while (true)
{
    ZeroMemory(buf, 4096);

    // Wait for client to send data
    int bytesReceived = recv(clientSocket, buf, 4096, 0);
    if (bytesReceived == SOCKET_ERROR)
    {
        AfxMessageBox(L"Error in recv(). Quitting");
        break;
    }

    if (bytesReceived == 0)
    {
        AfxMessageBox(L"Client disconnected");
        break;
    }

    CMFCDesktopAlertWnd* pPopup = new CMFCDesktopAlertWnd;
    int m_nAnimation = 2;
    int m_nAnimationSpeed = 30;
    int m_nTransparency = 180;
    bool m_bSmallCaption = false;
    bool m_bAutoClose = false;
    int m_nAutoCloseTime = 3;
    pPopup->SetAnimationType((CMFCPopupMenu::ANIMATION_TYPE) m_nAnimation);
    pPopup->SetAnimationSpeed(m_nAnimationSpeed);
    pPopup->SetTransparency((BYTE)m_nTransparency);
    pPopup->SetSmallCaption(m_bSmallCaption);
    pPopup->SetAutoCloseTime(m_bAutoClose ? m_nAutoCloseTime * 1000 : 0);
    CPoint m_ptPopup = CPoint(-1, -1);
    pPopup->Create(ts->_this, IDD_ALERT_JOB, NULL, m_ptPopup, 
    RUNTIME_CLASS(JobAlertDlg));
    pPopup->SetWindowText(_T("Message"));
    //cout << string(buf, 0, bytesReceived) << endl;

    // Echo message back to client
    send(clientSocket, "OK", bytesReceived + 1, 0);
}

// Close the socket
closesocket(clientSocket);

// Cleanup winsock
WSACleanup();
return 0;
}

BOOL JobManager::OnInitDialog()
{
  THREADSTRUCT *_param = new THREADSTRUCT;
  _param->_this = this;
  CWinThread *ptrThread = AfxBeginThread(JobInfoAlert, _param)
  CDialog::OnInitDialog();
  return true;
}
c++ mfc
1个回答
0
投票

您正在工作线程的上下文中创建警报对话框,这意味着该窗口将由该线程拥有,而其父(

JobManager
对话框)将(大概)由UI(主)线程拥有。这是要避免的设置。此外,工作线程是由
AfxBeginThread()
函数的重载版本创建的,它不会创建消息循环,这意味着它不会处理(警报)窗口的消息。

既然您决定创建一个单独的线程来处理套接字通信,那么最好将后台与 UI 操作分开 - 它们可以异步通信。一个非常简单的方法是在对话框类中定义自定义消息 (

WM_APP+nnnn
) 和
ON_MESSAGE()
处理程序。工作线程会将这些消息发布到对话窗口。您可以在
wParam
lParam
参数中传递信息,通常(但不一定)
wParam
包含整数、枚举、代码等数据,而
lParam
较大的项目(通常是指针),尽管在 x64 下它们是都是 64 位。例如,通知代码可以放置在
wParam
中 - 您可以按照您希望的方式定义消息及其参数。

因此,您应该将创建警报对话框的代码移出线程函数,例如在上述消息处理程序中。这将在 UI 线程的上下文中创建警报对话框,因此它将由 UI 线程拥有。您的代码需要更多改进,例如,在失败、断开连接等情况下,工作线程显示消息框并终止,而

JobManager
对话框似乎没有收到任何通知。您应该将此类信息放入自定义消息中(由处理程序处理),以便对话框类可以采取相应的操作,例如启用/禁用控件或关闭。

轻微内存泄漏,工作线程在退出之前应该释放

THREADSTRUCT
中为
OnInitDialog()
分配的内存,您只需分配它并将其传递给线程即可。或者您可以完全避免分配/释放它,您似乎只使用
_this
成员,因此您可以直接将其作为
LPVOID
参数传递。

© www.soinside.com 2019 - 2024. All rights reserved.