策略为王源代码分析-工程方案结构分析

Published

1.主界面和弹出框的菜单定义

G:\stock\Tskingfromgoogle\src\StkUI\StkUI.rc

界面所有菜单项和对应的事件在此文件定义。

IDR_MAINFRAME MENU
BEGIN
    POPUP "系统(&S)"
    BEGIN
        MENUITEM "连接Internet服务器(&N)...",        ID_SYS_CONNECTSERVER
        MENUITEM "断开Internet服务器(&D)",           ID_SYS_DISCONNECTSERVER

 

2.画图的函数

画图的函数都在StkUI\View\StockGraph.cpp和SktUI\View\DrawTech.cpp中

void CStockGraph::DrawTechBIAS( CDC * pDC, CRect rect, BOOL bDrawTitle )
{
	CKData	& kdata	=	m_CurStock.GetKData(m_nCurKType);
	m_techparam.bias.AttachParameters( AfxGetProfile().GetTechParameters().bias );

	double	dMin = 0, dMax = 0;
	if( !m_techparam.bias.GetMinMaxInfo( m_nIndexStart, m_nIndexEnd, &dMin, &dMax )
		|| !DrawAxis( pDC, rect, m_nHeightSubtitle, 5, dMin, dMax, FALSE, TRUE, 2 ) )
		return;
	
	DrawTechUtil1(	pDC, rect, bDrawTitle, dMin, dMax, STT_BIAS, &(m_techparam.bias), &kdata,
					AfxGetProfile().GetColor(CColorClass::clrLine1), drawtechtype_line );
}

 

本地数据目录为:

G:\stock\Tskingfromgoogle\src\Bin

股票行情列表主窗口

G:\stock\Tskingfromgoogle\src\StkUI\View\SListView.cpp

 

定义了底部tab标签,然后定义GridCtrl类型的变量用于显示每只股票的列

protected:
	CGridCtrl	m_Grid;

通过G:\stock\Tskingfromgoogle\src\StkUI\GridCtrl.h显示每只股票的列

STKLIB中的类及其继承关系

StkLib的几个全局静态变量

工程StkLib的几个全局静态变量:
      g_stockcontainer:AfxGetStockContainer()可以得到该变量的引用,该
              变量记录所有股票的行情信息和基本信息,CStockInfo的数组。
      g_domaincontainer:AfxGetDomainContainer()可以得到该变量的引用,
              该变量记录所有板块的信息。
      g_groupcontainer:AfxGetGroupContainer()可以得到该变量的引用,该
              变量记录所有分组的信息。
      g_stdatabase:AfxGetDB()可以得到该变量的引用,该变量实现了本软件的
              数据文件接口。
      g_stprofile:AfxGetProfile()可以得到该变量的引用,该变量记录当前软
              件的一些设置。
STKLIB中主要类和继承关系:

这个工程是实现股票数据结构、技术指标计算的动态连接库,代码与平台无关。

 

1. 股票数据结构相关的类

  class CKData

  ::K线数据数组类

    KDATA是K线数据结构

    CKDATA是将封装了股票数据的相关的操作

  class CDRData

  ::除权除息数组类

    DRDATA除权数据结构

    CDRDATA封装了除权数据的操作
  class CBaseData

  ::财务资料数组类

    BASEDATA财务信息数据结构

    CBaseData封装了财务数据的操作

  以上为股票的静态数据结构

  以下为股票的动态数据结构

  class CReport

  ::行情信息数据数组类

    REPORT行情刷新数据结构

    CReport封装了行情信息数据的操作
  class CMinute

  ::行情分时数据数组类

    MINUTE行情分时数据结构

    CMinute封装了行情分时数据的操作
  class COutline

  ::行情额外信息数据数组类

    OUTLINE行情额外数据结构

    COutline封装了行情额外信息数据操作
  ////////////////////////////////////

  class CStockInfo

  ::单个股票信息类
  class CStock

  ::单个股票的数据,包括股票信息,K线数据,基本资料,除权除息数据等

  *********以上类是在stock.h中定义的,主要是股票数据结构的定义***********

 

  **********以下类是股票信息数据CStockInfo的数组类,在container.h中定义*********

  class CStockInfoArray

  ::CStockInfo数阻类

    typedef CSPArray<CStockInfo, CStockInfo &> CStockInfoArray; 

  class CStockContainer: public CStockInfoArray

  ::股票信息数组类

    有一个股票信息数组的全局对象AfxGetStockContainer()保存所有股票的信息
  class CDomain: public CSPStringArray

  ::板块类,包含板块名称、板块中的股票代码

  class CDomainArray

  ::板块数组类

    typedef CSPArray<CDomain, CDomain &> CDomainArray;

  class CDomainContainer : public CDomainArray
  ::板块数组类

 

2.股票数据库相关的类

  class IStStore

  ::读取K线数据的通用接口,各种格式的读取K线数据类必须从此类继承

  class CStDatabase : public Object

  ::本地数据类,提供对磁盘数据的操作接口,包括股票信息,各种周期K线数据,基本资料,权息资料的读取和安装。

  class CQianlong : public IStStore

  ::钱龙数据格式的读取类

  class CClkFile

  ::文件操作

  class CSelfDB : public CQianlong

  ::自有格式数据的读取,除了除权除息数据、行情数据外,其余与钱龙格式数据相同。

 

3.技术指标类

  class CTechnique

  ::技术指标基类

    其他的技术指标类是从基类继承的

 

4.股票列表视图的列变量定义,以及自定义列的表达式计算

  class CExpress

  ::表达式,可以包含变量
  class CIndex

  ::新建指标,包含含有变量的表达式,在股票列表上显示为一列
  class CIndexContainer

  ::新建指标数组 

5.策略定义

  class CRateParam

  ::交易税费设置类
  class CSPTimeContainer

  ::CSPTimeContainer : public CSPTimeArray

    typedef CSPArray<CSPTime, CSPTime &> CSPTimeArray;
  class COpParam

  ::策略模拟操作条件类
  class CStockOwnContainer

  ::拥有股票数组
  class COpRecordContainer

  ::操作记录数组
  class CAssetSerialContainer

  ::资产数组
  class CTechStock

  ::一只待操作的股票,包含股票的信息,K线数据,长周期K线数据,所需技术指标,所需长周期技术指标
  class CTechStockContainer

  ::CTechStock数组
  class CStrategy
  ::策略

6.软件的用户配置

  class CTechParameters

  ::技术指标参数,包含所有技术指标的参数设定
  class CColorRefContainer

  ::CSPArray<COLORREF, COLORREF> CColorRefArray;

    class STKLIB_API CColorRefContainer : public CColorRefArray
  class CColorClass

  ::界面配色方案
  class CColorClassContainer

  ::配色方案数组
  class CStProfile

  ::系统设置 

 

STKNET中的类及其继承关系

STKNET--这个工程是实现网络数据自动下载功能的动态连接库:

 

1.数据包类和数据库类

  class CPackage

  ::数据包类,表示一个数据包

  class CPackages

  ::数据包数组

  class CDownloadServer

  ::产品服务器信息类,表示一个产品服务器

  class CServers

  ::产品服务器数组

  class CNetDatabase : public CStDatabase

  ::网络数据类,提供对磁盘数据的操作接口,包括股票信息,各种周期K线数据,基本资料,权息资料的 读取和安装。

  class CStDatabase

  ::本地数据类,提供对磁盘数据的操作接口,包括股票信息,各种周期K线数据,基本资料,权息资料的读取和安装。

 

view、StkReveiver、stockdrv、NetTs.DLL三者之间的关系梳理

 

1.StkReveiver类负责接收处理通视驱动的消息和行情服务器的消息,然后向视图发送消息

定义了收到上述两者发来的WM_APP_STKRECEIVER_TSDATA消息的处理函数OnStkReceiverTsdata()

G:\stock\TskingVS2019\src\Client\StkNet\Src\StkReceiver.cpp

BEGIN_MESSAGE_MAP(CStkReceiver, CWnd)
	//{{AFX_MSG_MAP(CStkReceiver)
	ON_WM_CREATE()
	ON_WM_DESTROY()
	//}}AFX_MSG_MAP
	ON_MESSAGE(WM_APP_STKRECEIVER_CONNECTSERVER,OnStkReceiverConnectserver)
	ON_MESSAGE(WM_APP_STKRECEIVER_DISCONNECTSERVER,OnStkReceiverDisconnectserver)
	ON_MESSAGE(WM_APP_STKRECEIVER_INIT,OnStkReceiverInit)
	ON_MESSAGE(WM_APP_STKRECEIVER_SETUP,OnStkReceiverSetup)
	ON_MESSAGE(WM_APP_STKRECEIVER_QUIT,OnStkReceiverQuit)
	ON_MESSAGE(WM_APP_STKRECEIVER_TSDATA,OnStkReceiverTsdata)  //收到消息的处理函数
END_MESSAGE_MAP()

消息的处理函数OnStkReceiverTsdata()

G:\stock\TskingVS2019\src\Client\StkNet\Src\StkReceiver.cpp

// 通视处理数据,行情服务器也发送过来
LRESULT CStkReceiver::OnStkReceiverTsdata(
		UINT wFileType,				// 文件类型, 参见 StockDrv.H
		LONG lPara)
{
	int	i = 0;
	PBYTE pFileBuf = NULL;
	PBYTE pBuffx = NULL;
	PGZLXBINDATA pGZLX = NULL;
	RCV_DATA *	pHeader = (RCV_DATA *) lPara;

	// 检查参数
	ASSERT(pHeader && pHeader->m_pData);
	if (!pHeader || !pHeader->m_pData)
		return -1L;
	// ASSERT(pHeader->m_nPacketNum > 0 || pHeader->m_bDISK);
	if (pHeader->m_nPacketNum <= 0 && !pHeader->m_bDISK)
		return -1L;

	//	对于处理较慢的数据类型,建议将数据备份,另创建一线程处理
	switch(wFileType)
	{
	case RCV_REPORT:
		{
			// 检查参数
			//ASSERT(pHeader->m_nPacketNum > 0 && !pHeader->m_bDISK);
			if (pHeader->m_nPacketNum <= 0 || pHeader->m_bDISK)
				return -1L;
			
			// 分配备份数据存储空间
			COMMPACKET * pCommPacket = AllocCommPacket(CStock::dataReport, pHeader->m_nPacketNum);
			if (NULL == pCommPacket)
				return -1L;

			// 修改AfxGetStockContainer()
			int nBufSize = pHeader->m_pReport[0].m_cbSize;
			PBYTE pBaseBuf = (PBYTE)&pHeader->m_pReport[0];
			for(i=0; i<pHeader->m_nPacketNum; i++)
			{
				PRCV_REPORT_STRUCTEx pReport = (PRCV_REPORT_STRUCTEx)(pBaseBuf + nBufSize*i);
				if (convert_TSREPORT_to_REPORT(pReport, &(pCommPacket->m_pReport[i])))
				{
					/* 以下代码转移到新建线程中执行 */
					// AfxGetStkReceiver().OnReceiveReport(&(pCommPacket->m_pReport[i]));
				}
			}
			
			{
				CSingleLock		lock(&g_mutexCommPacket,TRUE);
				g_aptrCommPacket.Add(pCommPacket);
			}

			/* 以下代码转移到新建线程中执行
			// 保存至本地文件
			AfxGetDB().StoreReport(pCommPacket->m_pReport, pCommPacket->m_dwCount, FALSE);

			// 通知各股票信息显示窗口,刷新行情数据
			for(i=0; i<m_awndRcvData.GetSize(); i++)
				::SendMessage(m_awndRcvData[i], WM_APP_STKRECEIVER_DATA, CStock::dataReport, (LPARAM)pCommPacket);

			// 释放备份数据存储空间
			FreeCommPacket(pCommPacket);
			*/ 
		}
		break;
	
	case RCV_FILEDATA:
		switch(pHeader->m_wDataType)
		{
		case FILE_HISTORY_EX:						// 补日线数据
			{
				RCV_HISTORY_STRUCTEx * pDay = pHeader->m_pDay;
				int	nPacketNum	=	pHeader->m_nPacketNum;
				CKData	kdata(CKData::ktypeDay);
				CString	sCode;
				DWORD	dwMarket = CStock::marketUnknown;

				// 读取文件
				if (pHeader->m_bDISK)
				{
					pDay	=	NULL;
					CFile	file;
					if (file.Open(pHeader->m_File.m_szFileName,CFile::modeRead))
					{
						ASSERT(file.GetLength() == pHeader->m_File.m_dwLen);
						nPacketNum	=	(int)(file.GetLength()/sizeof(RCV_HISTORY_STRUCTEx));
						if (nPacketNum > 0)
							pDay = new RCV_HISTORY_STRUCTEx[nPacketNum];
						if (pDay)
							file.Read(pDay, sizeof(RCV_HISTORY_STRUCTEx)*nPacketNum);
						file.Close();
					}
				}

				// 分配备份数据存储空间
				COMMPACKET * pCommPacket = AllocCommPacket(CStock::dataK, nPacketNum);
				if (NULL == pCommPacket)
					return -1L;

				// 处理数据
				DWORD	dwCount	=	0;
				for(i=0; i<nPacketNum && pDay; i++)
				{
					if (pDay[i].m_head.m_dwHeadTag == EKE_HEAD_TAG)
					{
						if (kdata.GetSize() > 0)
						{
							kdata.AutoSetKType();
							UpdateStockContainerByKData(AfxGetStockContainer(), sCode, kdata);
							AfxGetDB().InstallKData(kdata);
							kdata.RemoveAll();
						}
						sCode		=	pDay[i].m_head.m_szLabel;
						dwMarket	=	TSMarket_to_Market(pDay[i].m_head.m_wMarket);
						continue;
					}
					convert_TSHISTORY_to_KDATA(dwMarket, sCode, &(pDay[i]), &(pCommPacket->m_pKdata[dwCount]));
					kdata.Add(pCommPacket->m_pKdata[dwCount]);
					dwCount	++;
				}
				pCommPacket->m_dwCount	=	dwCount;
				if (pHeader->m_bDISK && pDay)
					delete [] pDay;
				if (kdata.GetSize() > 0)
				{
					kdata.AutoSetKType();
					UpdateStockContainerByKData(AfxGetStockContainer(), sCode, kdata);
					AfxGetDB().InstallKData(kdata);
				}

				// 通知各股票信息显示窗口,刷新行情数据
				for(i=0; i<m_awndRcvData.GetSize(); i++)
					::SendMessage(m_awndRcvData[i], WM_APP_STKRECEIVER_DATA, CStock::dataK, (LPARAM)pCommPacket);
	
				// 释放备份数据存储空间
				FreeCommPacket(pCommPacket);
			}
			break;

		case FILE_MINUTE_EX:						// 补分钟线数据
		case 83:	// 补分笔数据
			{
				RCV_MINUTE_STRUCTEx * pMin = pHeader->m_pMinute;
				ASSERT(pMin->m_head.m_dwHeadTag == EKE_HEAD_TAG);
				CMinute	minute;
				BOOL bAutoSaveKDataMin = AfxGetProfile().GetAutoSaveKDataMin(); // 作为分钟K线保存
				CString	sCode;
				DWORD	dwMarket = CStock::marketUnknown;
				
				// 分配备份数据存储空间
				COMMPACKET * pCommPacket = AllocCommPacket(CStock::dataMinute, pHeader->m_nPacketNum);
				if (NULL == pCommPacket)
					return -1L;

				DWORD	dwCount	=	0;
				for(i=0; i<pHeader->m_nPacketNum; i++)
				{
					if (pMin[i].m_head.m_dwHeadTag == EKE_HEAD_TAG)
					{
						if (minute.GetSize() > 0)
						{
							CKData	kdMin(CKData::ktypeMin5);
							if (minute.ToKData(kdMin))
								AfxGetDB().InstallKData(kdMin);
							minute.RemoveAll();
						}
						sCode		=	pMin[i].m_head.m_szLabel;
						dwMarket	=	TSMarket_to_Market(pMin[i].m_head.m_wMarket);
						continue;
					}
					convert_TSMINUTE_to_MINUTE(dwMarket, sCode, &(pMin[i]), &(pCommPacket->m_pMinute[dwCount]));
					if (bAutoSaveKDataMin)
						minute.Add(pCommPacket->m_pMinute[dwCount]);
					dwCount	++;
				}
				pCommPacket->m_dwCount	=	dwCount;
				if (minute.GetSize() > 0)
				{
					CKData	kdMin(CKData::ktypeMin5);
					if (minute.ToKData(kdMin))
						AfxGetDB().InstallKData(kdMin);
				}

				// 保存至本地文件
				AfxGetDB().StoreMinute(pCommPacket->m_pMinute, pCommPacket->m_dwCount);

				// 通知各股票信息显示窗口,刷新行情数据
				for(i=0; i<m_awndRcvData.GetSize(); i++)
					::SendMessage(m_awndRcvData[i], WM_APP_STKRECEIVER_DATA, CStock::dataMinute, (LPARAM)pCommPacket);

				// 释放备份数据存储空间
				FreeCommPacket(pCommPacket);
			}
			break;

		case FILE_POWER_EX:							// 补充除权数据
			{
				RCV_POWER_STRUCTEx * pPower = pHeader->m_pPower;
				int	nPacketNum	=	pHeader->m_nPacketNum;
				CDRData	drdata;
				CString	sCode;
				DWORD	dwMarket = CStock::marketUnknown;

				if (pHeader->m_bDISK)
				{
					pPower	=	NULL;
					CFile	file;
					if (file.Open(pHeader->m_File.m_szFileName,CFile::modeRead))
					{
						ASSERT(file.GetLength() == pHeader->m_File.m_dwLen);
						nPacketNum	=	(int)(file.GetLength()/sizeof(RCV_POWER_STRUCTEx));
						if (nPacketNum > 0)
							pPower = new RCV_POWER_STRUCTEx[nPacketNum];
						if (pPower)
							file.Read(pPower, sizeof(RCV_POWER_STRUCTEx)*nPacketNum);
						file.Close();
					}
				}

				// 分配备份数据存储空间
				COMMPACKET * pCommPacket = AllocCommPacket(CStock::dataDR, nPacketNum);
				if (NULL == pCommPacket)
					return -1L;

				DWORD	dwCount	=	0;
				for(i=0; i<nPacketNum && pPower; i++)
				{
					if (pPower[i].m_head.m_dwHeadTag == EKE_HEAD_TAG)
					{
						if (drdata.GetSize() > 0)
							AfxGetDB().InstallDRData(drdata);
						drdata.RemoveAll();
						sCode		=	pPower[i].m_head.m_szLabel;
						dwMarket	=	TSMarket_to_Market(pPower[i].m_head.m_wMarket);
						continue;
					}
					convert_TSPOWER_to_DRDATA(dwMarket, sCode, &(pPower[i]), &(pCommPacket->m_pDrdata[dwCount]));
					drdata.Add(pCommPacket->m_pDrdata[dwCount]);
					dwCount	++;
				}
				if (pHeader->m_bDISK && pPower)
					delete [] pPower;
				if (drdata.GetSize() > 0)
					AfxGetDB().InstallDRData(drdata);
				pCommPacket->m_dwCount	=	dwCount;

				// 通知各股票信息显示窗口,刷新行情数据
				for(i=0; i<m_awndRcvData.GetSize(); i++)
					::SendMessage(m_awndRcvData[i], WM_APP_STKRECEIVER_DATA, CStock::dataDR, (LPARAM)pCommPacket);

				// 释放备份数据存储空间
				FreeCommPacket(pCommPacket);
			}
			break;

		case FILE_MULTISORT_EX:					// 综合排名
			{
				RCV_MULTISORT_STRUCTEx * pMultisort = pHeader->m_pMultisort;
				
				// 分配备份数据存储空间
				COMMPACKET * pCommPacket = AllocCommPacket(CStock::dataMultisort, pHeader->m_nPacketNum);
				if (NULL == pCommPacket)
					return -1L;

				for(i=0; i<pHeader->m_nPacketNum; i++)
				{
					convert_TSMULTISORT_to_MULTISORT(&(pMultisort[i]), &(pCommPacket->m_pMultisort[i]));
				}
				pCommPacket->m_dwCount	=	pHeader->m_nPacketNum;

				// 通知各股票信息显示窗口,刷新行情数据
				for(i=0; i<m_awndRcvData.GetSize(); i++)
					::SendMessage(m_awndRcvData[i], WM_APP_STKRECEIVER_DATA, CStock::dataMultisort, (LPARAM)pCommPacket);

				// 释放备份数据存储空间
				FreeCommPacket(pCommPacket);
			}
			break;

		case FILE_BASE_EX:						// 钱龙兼容基本资料文件,m_szFileName仅包含文件名
			{
				if (pHeader->m_bDISK)
				{
					AfxGetDB().InstallBaseText(pHeader->m_File.m_szFileName, AfxGetFileTitle(pHeader->m_File.m_szFileName));
				}
				else
				{
					AfxGetDB().InstallBaseText(LPCTSTR(pHeader->m_pData), pHeader->m_File.m_dwLen, AfxGetFileTitle(pHeader->m_File.m_szFileName));
				}

				// 分配备份数据存储空间
				COMMPACKET * pCommPacket = AllocCommPacket(CStock::dataCode, 1);
				if (NULL == pCommPacket)
					return -1L;
				CString	sTemp	=	AfxGetFileTitleNoExt(pHeader->m_File.m_szFileName);
				strncpy(pCommPacket->m_pStockcode[0].m_szCode, sTemp, min(sizeof(pCommPacket->m_pStockcode[0].m_szCode)-1,sTemp.GetLength()));
				pCommPacket->m_pStockcode[0].m_dwMarket	=	CStock::marketUnknown;

				// 通知各股票信息显示窗口,刷新行情数据
				for(i=0; i<m_awndRcvData.GetSize(); i++)
					::SendMessage(m_awndRcvData[i], WM_APP_STKRECEIVER_DATA, CStock::dataBasetext, (LPARAM)pCommPacket);

				// 释放备份数据存储空间
				FreeCommPacket(pCommPacket);
			}
			break;

		case FILE_NEWS_EX:						// 新闻类,其类型由m_szFileName中子目录名来定
			if (pHeader->m_bDISK)
			{
				AfxGetDB().InstallNewsText(pHeader->m_File.m_szFileName, AfxGetFileTitle(pHeader->m_File.m_szFileName));
			}
			else
			{
				AfxGetDB().InstallNewsText(LPCTSTR(pHeader->m_pData), pHeader->m_File.m_dwLen, AfxGetFileTitle(pHeader->m_File.m_szFileName));
			}
			// 通知各股票信息显示窗口,刷新行情数据
			for(i=0; i<m_awndRcvData.GetSize(); i++)
				::SendMessage(m_awndRcvData[i], WM_APP_STKRECEIVER_DATA, CStock::dataNews, NULL);
			break;

		case FILE_HTML_EX:						// HTML文件,m_szFileName为URL
			AfxGetProfile().AddHTMLURLToExplorer(pHeader->m_File.m_szFileName);
			break;

		case FILE_SOFTWARE_EX:
			TRACE("%s\n",pHeader->m_File.m_szFileName);
			TRACE("%d\n",pHeader->m_File.m_dwLen);
			pBuffx = (PBYTE)pHeader->m_pData;
			break;

		case FILE_SHAZQDATA_EX:		//h上海国债净价交易
			break;
		case FILE_TYPE_RES:
			TRACE("MSG: CStkReceiver::OnStkDataOK, Replaced data \n");
			break;
		default:
			TRACE("Msg: CStkReceiver::OnStkReceiverData,Unkonw data type\n");
		}
		break;
	}

	return 0L;
}

通知各窗口处理

// 通知各股票信息显示窗口,刷新行情数据
			for(i=0; i<m_awndRcvData.GetSize(); i++)
				::SendMessage(m_awndRcvData[i], WM_APP_STKRECEIVER_DATA, CStock::dataReport, (LPARAM)pCommPacket);

 

消息来源

1.由NetTS.DLL发出

BOOL CStkReceiver::NetEngineBeginWorking(LPCTSTR lpszAddress, UINT nPort, LPCTSTR lpszUser, LPCTSTR lpszPasswd)
{
	if (gNetTSDLL.LoadDriver("NetTS.dll")
		&& gNetTSDLL.Stock_Init_Nodialog(m_hWnd,WM_APP_STKRECEIVER_TSDATA,RCV_WORK_SENDMSG,
					lpszAddress,nPort,lpszUser,lpszPasswd) > 0)
		return TRUE;
	return FALSE;
}

点击连接行情服务器时

LRESULT CStkReceiver::OnStkReceiverConnectserver(WPARAM wParam, LPARAM lParam)
{
	if (gNetTSDLL.LoadDriver("NetTS.dll")
		&& gNetTSDLL.Stock_Init(m_hWnd,WM_APP_STKRECEIVER_TSDATA,RCV_WORK_SENDMSG) > 0)
		return TRUE;
	return FALSE;
}

 

 

2.由通视发出

/通视驱动初始化
void CSelectEngineDlg::OnSetupreceiver() 
{
	int	nSel = m_listEngine.GetCurSel();
	if( LB_ERR == nSel )
	{
		AfxMessageBox( AfxModuleLoadString(IDS_SELECTENGINE_ERRSELECT), MB_OK );
		return;
	}

	int	nData = (int)m_listEngine.GetItemData(nSel);
	if( nData >= 0 && nData<m_astrDriver.GetSize() )
	{
		m_drv.Stock_Quit(GetSafeHwnd());
		m_drv.UnloadDriver();

		if( m_drv.LoadDriver( m_astrDriver[nData] )
			&& m_drv.Stock_Init(GetSafeHwnd(),WM_APP_STKRECEIVER_TSDATA,RCV_WORK_SENDMSG) )
		{
			m_drv.SetupReceiver(TRUE);
		}
		else
			AfxMessageBox( AfxModuleLoadString(IDS_SELECTENGINE_ERRLOAD), MB_OK );
	}
	m_btnSetup.EnableWindow( FALSE );
}