发送消息和数据到主窗口----测试

基本框架已经完成了一半,现在就是测试一下,从子窗口中把消息和数据都传回主窗口,既然要传数据,那么,随便定义一个数据结构,然后,在具体的行情类中,使用其中保存的子窗口的句柄来把消息和数据传给主窗口

void CCTPMdSpi::StartMd()
{
    
    
	BarData* bar = new BarData;
	bar->BarTime = 210205;
	strcpy_s(bar->InstrumentID,sizeof("ABCD"), "ABCD");

	LPARAM a = WM_ABC;		//这里有个宏定义,是为了后面区分消息类型用的
	m_MdWin->GetParent()->PostMessageW(WM_TICK_DATA, (WPARAM)bar, a);
}

而主窗口中,收到消息和数据时,与子窗口中的数据一致:

//测试代码
LRESULT CGTTraderDlg::OnUpdateTick(WPARAM wParam, LPARAM lParam)
{
    
    
	BarData* bar = (BarData*)wParam;
	if (WM_ABC== lParam)
	{
    
    
		return 1;
	}
	return 0;
}

在这里插入图片描述

在这里插入图片描述
在具体发送消息的类中,使用了保存在类中的子窗口句柄,再调用了GetParent方法来得到主窗口句柄,但在测试过程中,因为为了方便调试,在一个死循环中多次调用GetParent方法会出现问题(导致问题的原因我没兴趣研究,毕竟我不是码农),尝试把GetParent方法在循环之获取父窗口句柄后,再循环的发送消息和数据,则没有问题了,所以后续为了不再多次调用GetParent方法,干脆在具体类中保存主窗口的句柄,在类中加上获取主窗口句柄的方法即可,这部分的代码已经完成。

既然消息和数据的传出和接收没有问题,现在就应该要先安排消息处理流程了。
首先,行情数据每个Tick数据过来之后应该需要对其处理,所以消息量是源源不断的,如果直接在主窗口线程中处理的话,必定会卡死界面,那么如果不想卡死主窗口界面的话,那肯定要找个"替死鬼”,也就是在主窗口中再开一个窗口,然后把主窗口接收到的消息都传给它,由子窗口来进行处理或分发到相应的响应对象中,大概如下图:
在这里插入图片描述

但是,问题来了,如果前面消息发送时,wParam已经有值了,那后面再传递时,wParam的值又是什么呢?其实这两次的值都应该在最开始消息传递时就已经确定,因为这些数据是从行情窗口发出的,它肯定知道这些数据是干嘛用的,所以这就需要的wParam拆成两部分来传递。Windows的系统消息也是会把wParam拆成高字节和低字节这样来区分,其实很好理解,wParam是数值型的,而计算机里面只认0和1,如果要传的是Bool类型的参数,那么两位二进制位足矣,每一位相当于一个参数的值,但是我们现在传递的消息处理对象的类型和数据实际需要处理的类型可能比较多,那么我们也可以按高低字节来,或者只按几个二进制位来做。

因为位操作必须要对无符号数据来做,而wParam的实际定义是unsigned int,那就刚好了,但是我不打算用二进制位来做,因为比较绕。
现在来整理一下,wParam的取值范围是:NNNNN…
而我只需要一位(10进制位)即可以标识数据处理对象类型
再想想,假如每个数据处理对象后续需要处理的类型有999种,也就是占用3位十进制位,
那么算起来的范围也不过是0~9 999,所以直接的用10进制来做就可以了。如果再做得通用一点的话,就把后面类型占用的位数做成宏。

//现在统一规定,WPARAM参数作为子消息类型,LPARAM参数为传递的数据
//根据wParam来区分,应该把数据发送给谁去处理,MainEngine不处理,只负责消息数据派发
void CMainEngine::DipatchMsg(WPARAM wParam, LPARAM lParam)
{
    
    
	int Power = int(pow(10, MSGBIT));		//先求出消息类型占用位数,
	int EngineType = int(wParam / Power);		//算整除,得出消息处理对象
	int MsgType = wParam % Power;		//求余数,得出消息类型

	switch (EngineType)
	{
    
    
	case MSG_2_DATA:
		getDataEngine()->OnAddMsg(MsgType, lParam);			//向消息处理对象添加消息
		break;
	case MSG_2_ACCOUNT:
		getTradeEngine()->OnAddMsg(MsgType, lParam);
		break;
	case MSG_2_STRATEGY:
		getStrategyEngine()->OnAddMsg(MsgType, lParam);
		break;
	}
}

OnAddMsg方法是把消息添加到处理对象的消息列表中。
想象一下咱们学校饭堂,每个人去到饭堂后,自己可以根据自己的喜好,选择不同或相同的菜,去相应的队列中排队取饭,每个人心中有不同的喜好(相当消息),当然,人是可以自己根据自己的喜好去选择不同的队列,但程序中则需要添加一个看门人,每个人跟看门人说想要打什么样的菜,看门人就会跟同学说应该去哪条队列中排队,而打饭的大叔(每条队列配一个打饭大叔)则依次的给每个人打相应的饭菜。

补充一点,消息处理对象漏掉了一个,就是主窗口,因为主窗口主要用于显示数据的功能(或许再加一些其它辅助功能),所以主窗口也是要接收处理消息和数据的,上面的示意图和代码都漏掉了这部分,后续在代码用补全,前面就不管了。

猜你喜欢

转载自blog.csdn.net/griffin041702/article/details/111187859