【笔记】C++一种把信息发送给窗口进行异步处理的方法

前提:

1.Socket通信

2.MFC窗口

主要应用场景:Socket传递的数据过多,处理不及引起堵塞,最终导致响应慢的情况,可尝试使用该方法。

1.创建一个类用来注册消息

#pragma once
class CSrvCommThd;
class CCmdWnd
{
public:
    CCmdWnd(void);
    ~CCmdWnd(void);
    BOOL RegisterRptMsgFromSrvRecvWnd(HWND hWnd,INT iRcvMsgType);//注册SrvSocket线程中的处理的消息。
private:
    HWND m_hWndRcvCmd;
};
#include "stdafx.h"
#include "CmdMan.h"
#include "SrvSocket.h"
#include "主文件.h"
CCmdWnd::CCmdWnd(void)
{
    //m_pSrvSocket = NULL;
}


CCmdWnd::~CCmdWnd(void)
{

	if (theApp.m_pSrvSocket)
	{
		theApp.m_pSrvSocket->DeRegisterRptMsgRcvWnd(m_hWndRcvCmd);
	}
}
BOOL CCmdWnd::RegisterRptMsgFromSrvRecvWnd(HWND hWnd,INT iRcvMsgType)
{
    if (hWnd == NULL)
    {
        return FALSE;
    }
	m_hWndRcvCmd = hWnd;
    if (theApp.m_pSrvSocket)
    {
		theApp.m_pSrvSocket->RegisterRptMsgRcvWnd(hWnd,iRcvMsgType);
    }
    return TRUE;
}

2.在SvrSocket线程中添加注册/注销函数用于注册/注销窗口事件

2.1 SvrSocket头文件注意要包含"CmdMan.h",在类中添加下列代码

std::map<HWND,UINT>m_mapBroadcastWnd;
std::set<pair<HWND, DWORD> > m_CmdWndVec;
BOOL RegisterRptMsgRcvWnd(HWND hWnd,INT iRcvType = 1);
BOOL BBMSRegisterRptMsgRcvWnd(HWND hWnd, INT iRcvType = 1);

2.2 SvrSocket源文件

BOOL CSrvSocket::RegisterRptMsgRcvWnd(HWND hWnd,int iRcvType)
{
	m_mapBroadcastWnd[hWnd]=iRcvType;
	m_CmdWndVec.insert(make_pair(hWnd, iRcvType));
	return TRUE;
}
void CSrvSocket:: DeRegisterRptMsgRcvWnd(HWND hWnd)
{
	
	if (m_mapBroadcastWnd.find(hWnd)!= m_mapBroadcastWnd.end())
	{
		
		m_stackhWndClosed.push(hWnd);
		
	}

}

3 在窗口初始化函数OnInitDialog()中进行注册

RegisterRptMsgFromSrvRecvWnd(GetSafeHwnd(), CMD_1);
RegisterRptMsgFromSrvRecvWnd(GetSafeHwnd(), CMD_2);

GetSafeHwnd()是MFC框架中的一个成员函数,用于获取窗口的句柄(handle)。它的作用是返回一个有效的窗口句柄,如果窗口尚未创建或已经销毁,则返回NULL

窗口句柄是一个唯一标识窗口的整数值,它在操作系统层面用于识别和管理窗口。通过窗口句柄,可以对窗口进行各种操作,如发送消息、改变窗口属性等。

在MFC框架中,每个派生自CWnd类的窗口类都具有一个GetSafeHwnd()成员函数。这个函数可以在窗口对象中调用,以获取该窗口的句柄。

GetSafeHwnd()函数的使用场景包括:

  1. 在窗口类的成员函数中需要访问窗口句柄时,可以使用GetSafeHwnd()来获取句柄。
  2. 在消息处理函数中需要将窗口句柄传递给其他函数或API时,可以使用GetSafeHwnd()来获取句柄。
  3. 在需要判断窗口是否有效的情况下,可以使用GetSafeHwnd()来检查窗口句柄是否为NULL

需要注意的是,GetSafeHwnd()函数是为了安全起见而设计的。在MFC中,如果窗口对象已经被销毁,直接使用GetHwnd()可能会导致程序崩溃或其他错误。而使用GetSafeHwnd()可以避免这种情况,它会在窗口对象已经销毁时返回NULL,以避免访问无效的句柄。

4.给一个窗口进行消息映射处理

BEGIN_MESSAGE_MAP(CDlg, CBaseDialog)
    ON_MESSAGE(WM_USER_RECV_MSG, &CDlg::OnStnClickedStaticLogo)
END_MESSAGE_MAP()

ON_MESSAGE是MFC框架中的一个宏,用于将消息映射到消息处理函数。

在MFC中,窗口类可以通过重写消息处理函数来处理各种消息,例如鼠标点击、键盘输入等。但是,对于一些自定义的消息或者系统消息,MFC框架并没有提供对应的虚函数供开发者重写。这时,就可以使用ON_MESSAGE宏来将消息映射到一个特定的消息处理函数。

ON_MESSAGE宏的语法如下:

ON_MESSAGE(message, memberFxn)

其中,message是要映射的消息类型,可以是任何有效的消息值,如WM_USERWM_COMMAND等。memberFxn是一个消息处理函数的名称,它必须是窗口类的成员函数,并且具有特定的签名。

使用ON_MESSAGE宏可以实现以下功能:

  1. 将自定义消息或系统消息映射到特定的消息处理函数,以便在收到该消息时执行相应的逻辑。
  2. 扩展MFC框架的消息处理能力,处理一些MFC框架本身没有提供的消息。

使用ON_MESSAGE宏的步骤如下:

  1. 在窗口类的消息映射表中添加一条映射项,指定要映射的消息和消息处理函数。
  2. 在窗口类中定义消息处理函数,并按照特定的签名编写函数体。

示例代码如下:

BEGIN_MESSAGE_MAP(CMyWnd, CWnd)
    ON_MESSAGE(WM_MY_CUSTOM_MESSAGE, OnMyCustomMessage)
END_MESSAGE_MAP()

LRESULT CMyWnd::OnMyCustomMessage(WPARAM wParam, LPARAM lParam)
{
    // 处理自定义消息的逻辑
    // ...
    return 0;
}

在上述示例中,WM_MY_CUSTOM_MESSAGE是一个自定义消息,通过ON_MESSAGE宏将该消息映射到OnMyCustomMessage函数,当窗口接收到该消息时,将调用OnMyCustomMessage函数进行处理。

总而言之,ON_MESSAGE宏是MFC框架中用于将消息映射到消息处理函数的一种机制,可以扩展MFC框架的消息处理能力,处理自定义消息或系统消息。

5.在OnStnClickedStaticLogo函数中添加处理

LRESULT CDlg::OnStnClickedStaticLogo(WPARAM dwCmdCode, LPARAM lpAppFrame)
{
	if (lpAppFrame == NULL)
	{
		return FALSE;
	}
	stAppFrame* pAppFrame = (stAppFrame*)lpAppFrame;
	/*FunSrvHandleCmd pFun = NULL;
	pFun = m_msgHandleFunc[dwCmdCode];*/
	switch (dwCmdCode)
	{
	case CMD_LOG_IN_RSP:
		HandleCtrl1(pAppFrame);
		break;
	case PBBADS_CMD_CONTROL_REQ:
		HandleCtrl2(pAppFrame);
		break;
    default:
		break;
    }

    delete[](stAppFrame*)pAppFrame;
	return TRUE;
}

6. 在Socket接收函数中分发信息命令

for (auto& itrCmdWnd : m_CmdWndVec)
	{
		if(itrCmdWnd.second == pAppFrame->dwCmdCode)
		{
			::PostMessage(itrCmdWnd.first, WM_USER_RECV_MSG, (WPARAM)pAppFrame->dwCmdCode, (LPARAM)pAppFrame);//分发服务器任务至窗口进行异步处理
		}
	}
  1. PostMessage函数:该函数是Windows API中的一个函数,用于向指定的窗口发送一个消息。它的函数原型如下:

    BOOL PostMessage(
      HWND   hWnd,
      UINT   Msg,
      WPARAM wParam,
      LPARAM lParam
    );
    

    其中,hWnd参数指定要接收消息的窗口句柄;Msg参数指定要发送的消息类型;wParamlParam参数分别是消息的两个参数,可以用来传递一些数据。

  2. itrCmdWnd.first:这是一个迭代器,指向一个std::pair对象,该对象包含一个窗口句柄和一个布尔值。itrCmdWnd.first表示该std::pair对象的第一个元素,即窗口句柄。

  3. WM_USER_RECV_MSG:这是一个自定义的消息类型,它是一个整数值,通常定义在头文件中。在这里,它表示要发送的消息类型是接收到一个消息。

  4. pAppFrame->dwCmdCode:这是一个无符号整数值,表示要传递给窗口的消息参数之一。在这里,它表示接收到的消息的命令码。

  5. pAppFrame:这是一个指向应用程序框架对象的指针,它包含了要传递给窗口的消息参数之一。在这里,它表示接收到的消息帧。

这段代码的作用是向指定的窗口发送一个自定义消息,告诉窗口接收到了一个消息,并将消息的一些参数传递给该窗口。

总结:

为提高软件的响应速度,可采用异步处理的方式对消息进行处理,还可以一定程度上降低Socket堵塞的概率。

抽象:

(程序初始化时)

Socket:“窗口,我可能忙不过来,你来注册一下,搭把手。”

窗口:“行,我注册一下,用ON_MESSAGE进行了消息映射,你来活了丢给我就行,你好好跑腿XD~”

Socket:“我用::PostMessage丢给你,触发ON_MESSAGE,多谢兄弟,完事请你吃代码~”

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值