策略为王源码分析-启动通视接口驱动dll

Published

一、策略为王和stock.dll 的交互原理

这里用 网际风提供的stock.dll举例

1、首先第一步要安装网际风客户端,这样在C:\Windows\System32目录下就有了网际风的程序,其中Stock.DLL为数据接口模块(里面有API输出),用户的应用程序只跟Stock.DLL打交道,WJFMain.EXE为网络接口模块,负责与网际风服务器的通讯,至于Stock.DLL和WJFMain.EXE之间的交互,由Stock.DLL自动完成,对用户程序是透明的,无需关心。同时注册表中的[HKEY_LOCAL_MACHINE\SOFTWARE\StockDrv] 下的Driver键值会被网际风安装程序修改为指向网际风的数据接口Stock.DLL位置

2、用户程序读取 [HKEY_LOCAL_MACHINE\SOFTWARE\StockDrv] 下的Driver键值,如 "Driver"="stock.dll" ,这就是网际风数据接口的DLL位置,使用注册表读取函数可以取得上述路径,然后使用LoadLibrary加载上述DLL,再使用GetProcAddress取得Stock_Init、Stock_Quit、GetStockDrvInfo等API的入口。

3、使用远程方式调用上面取得的Stock_Init,并传入3个参数(消息处理窗口句柄、消息号、工作模式),消息处理句柄和消息号是用户程序自定义的,是告诉网际风数据接口的关键数据,相当于注册函数,以后网际风给用户程序发送数据都通过上述消息号来通知,如果有数据要发送给用户程序,Stock.DLL就会向上述句柄发送上述消息号,并在消息参数中有数据标识和对应的数据地址,用户程序只需要在上述消息处理函数中,对传过来的地址指针取数据即可,消息处理范例参考上述的分析家规范。简单说,用户程序只要调用一次Stock_Init,然后就坐等网际风给你发消息了,如果有行情变化,数据就会不请自来,你只对消息参数处理即可,用户主动请求的数据也是以消息模式传送过来。

4、用户程序卸载驱动时,可以调用Stock_Quit,相当于告诉Stock.DLL我不需要数据了。再调用FreeLibrary卸载上述DLL

 

二、

1.E:\x\src\StkUI\StkUI.rc

打开StkUI.rc,找到” IDR_MAINFRAME MENU”,你会发现定义了一系列菜单名和菜单项的对应关系,这个就是当你打开主程序StkUI.exe时的每一项菜单列表。

IDR_MAINFRAME MENU
BEGIN
    POPUP "系统(&S)"
    BEGIN
        MENUITEM "连接Internet服务器(&N)...",        ID_SYS_CONNECTSERVER
        MENUITEM "断开Internet服务器(&D)",           ID_SYS_DISCONNECTSERVER
        MENUITEM SEPARATOR
        MENUITEM "启动通视接收系统(&A)...",             ID_SYS_STARTTONGSHI
        MENUITEM "设置接收(补充数据)(&E)...",           ID_SYS_SETUPTONGSHI
        MENUITEM "停止通视接收系统(&O)",                ID_SYS_STOPTONGSHI
        MENUITEM SEPARATOR
        MENUITEM "复制(&C)\tCtrl+C",              ID_EDIT_COPY
        MENUITEM "全部选择(A)\tCtrl+A",             ID_EDIT_SELECT_ALL
        MENUITEM "查找...(F)\tCtrl+F",            ID_EDIT_FIND
        MENUITEM SEPARATOR
        MENUITEM "打印设置(&R)...",                 ID_FILE_PRINT_SETUP
        MENUITEM "打印预览(&V)...",                 ID_FILE_PRINT_PREVIEW
        MENUITEM "打印(&P)...\tCtrl+P",           ID_FILE_PRINT
        MENUITEM SEPARATOR
        MENUITEM "自动升级(&U)...",                 ID_SYS_AUTOUPGRADE
        MENUITEM "五分钟线数据自动写盘(&S)",              ID_SYS_AUTOSAVE
        MENUITEM "最小化时显示为通知图标(&I)",             ID_SYS_NOTIFYICON
        MENUITEM SEPARATOR
        MENUITEM "退出(&X)",                      ID_APP_EXIT
    END

src\StkUI\MainFrm.cpp

其菜单项为ID_SYS_STARTTONGSHI,然后在MainFrm.cpp下定义了点击该菜单之后所触发的操作:

	ON_UPDATE_COMMAND_UI(ID_SYS_DISCONNECTSERVER, OnUpdateSysDisconnectserver)
	ON_COMMAND(ID_SYS_STARTTONGSHI, OnSysStarttongshi)
	ON_UPDATE_COMMAND_UI(ID_SYS_STARTTONGSHI, OnUpdateSysStarttongshi)
	ON_COMMAND(ID_SYS_SETUPTONGSHI, OnSysSetuptongshi)
	ON_UPDATE_COMMAND_UI(ID_SYS_SETUPTONGSHI, OnUpdateSysSetuptongshi)
	ON_COMMAND(ID_SYS_STOPTONGSHI, OnSysStoptongshi)
	ON_UPDATE_COMMAND_UI(ID_SYS_STOPTONGSHI, OnUpdateSysStoptongshi)

ON_COMMAND函数的作用是MFC中将消息处理函数添加到消息路由表中。所以OnSysStarttongshi就是当你在软件界面上点击"启动通视接收系统(&A)...”所引发的动作。如下:

void CMainFrame::OnSysStarttongshi()
{
	AfxGetStkReceiver().EngineBeginWorking(TRUE);
	AfxGetSListStockContainer().ReRetrieveFromStatic(AfxGetActiveStrategy());
	AfxGetStaticDoc()->UpdateAllViews(NULL, UPDATE_HINT_SLISTVIEW, NULL);
}

3.E:\x\src\StkNet\Src\StkReceiver.cpp

这里发送了消息

BOOL CStkReceiver::EngineBeginWorking(BOOL bShowSelectEngineDialog)
{
	return SendMessage(WM_APP_STKRECEIVER_INIT, !bShowSelectEngineDialog);	// 启动通视接收系统
}

在定义的消息映射表中,OnStkReceiverInit接收消息并处理

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()

这家伙在这里打开驱动程序选择框,\src\StkNet\Src\StkNet.rc

LRESULT CStkReceiver::OnStkReceiverInit(WPARAM wParam, LPARAM lParam)
{
	// 通视及兼容设备
	{
		CStringArray astrProvider, astrDriver;
		if (!wParam)
		{
			CSelectEngineDlg	dlg;
			if (IDOK != dlg.DoModal())
				return -1L;
			dlg.GetSelectedDriver(astrProvider, astrDriver);
		}