效果图

前段时间,因业务需要,写了这样一个软件,同样的页面已经是第2次写了,第1次大约5年前的事情了,因为代码遗失,于是重新写。页面看似复杂,实现起来非常简单。
第一步:参照通达信的公式管理器核心文件TCalc.dll,导出资源文件(TCalc.rc),这样界面基本上显现出来了,接下来就是把这些页面进行整合(页面调用)。
第二步:提取公式列表信息
enum formula_type : unsigned char {
ftFrom,
ftTechnical_Indicator_Formula,// 技术指标公式
ftConditional_Sel_Stock_Formula, // 自选股指标公式
ftExpert_System_Formula, // 系统专家公式
ftColorful_Kline_Formula, // 五彩K线公式
ftTo,
};
typedef struct _Formula_Parameter
{
char _name[16];//参数
union
{
char _value[4][16];
struct
{
char _min[16];//最小
char _max[16];//最大
char _default[16];//默认
char _step[16];//步长
};
};
}Formula_Parameter;
// 技术指标公式
typedef struct _Technical_Indicator_Formula
{
bool is_system;//是否系统公式 1-是 0-否
bool is_common;//是否系统公式 1-是 0-否
char name[32];// 公式名称
bool is_protected;//密码保护
char password[16];//密码
bool type_disable;
char _type;//公式类型
/*
技术指标公式
0 - 大势型
1 - 超买超卖型
2 - 趋势性
3 - 能量型
4 - 成交量型
5 - 均线型
6 - 图表型
7 - 路径型
8 - 停损型
9 - 交易型
10 - 神系
11 - 龙系
12 - 鬼系
13 - 其他系
14 - 特色型
15 - 其他类型
条件选股公式
0 - 指标条件
1 - 基本面
2 - 即时盘中
3 - 走势特征
4 - 形态特征
5 - 其他类型
专家系统公式
0 -
五彩K线公式
*/
bool draw_disable;
char draw_line_method;//画线方法
/*
0 - 副图
1 - 主图叠加
2 - 副图(叠加K线)
3 - 副图(叠加美国线)
4 - 副图(叠加收盘站线)
5 - 主图替换
*/
char desp[64];//公式描述
char version[16];//公式版本
char show_decimal;//显示小数
/*
0 - 缺省位数
1 - 品种小数位数
2 - 品种小数位数 + 1
3 - 固定0位
4 - 固定1位
5 - 固定2位
6 - 固定3位
7 - 固定4位
*/
Formula_Parameter parameters[16];//参数
char formula_text[4096];//公式文本内容
char trade_rules;//交易法则
/*
0 - 无
1 - 左手
2 - 右手
*/
bool coordinate_disable;
char coordinate_position[64];//坐标线位置,最多6个,用分号分隔
bool extract_disable;
char extract_y_axis[4][16];//额外Y轴分界
}Technical_Indicator_Formula;
//条件选股公式
typedef struct _Conditional_Sel_Stock_Formula
{
bool is_system;//是否系统公式 1-是 0-否
bool is_common;//是否系统公式 1-是 0-否
char name[32];// 公式名称
bool is_protected;//密码保护
char password[16];//密码
char _type;//公式类型
/*
条件选股公式
0 - 指标条件
1 - 基本面
2 - 即时盘中
3 - 走势特征
4 - 形态特征
5 - 其他类型
*/
char right_to_use;//使用复权
/*
0 - 缺省设置
1 - 恒不复权
*/
char desp[64];//公式描述
char version[16];//公式版本
Formula_Parameter parameters[16];//参数
char formula_text[4096];//公式文本内容
}Conditional_Sel_Stock_Formula;
//专家系统公式
typedef struct _Expert_System_Formula
{
bool is_system;//是否系统公式 1-是 0-否
bool is_common;//是否系统公式 1-是 0-否
char name[32];// 公式名称
bool is_protected;//密码保护
char password[16];//密码
char desp[64];//公式描述
char version[16];//公式版本
Formula_Parameter parameters[16];//参数
char formula_text[4096];//公式文本内容
}Expert_System_Formula;
//五彩K线公式
typedef struct _Colorful_Kline_Formula
{
bool is_system;//是否系统公式 1-是 0-否
bool is_common;//是否系统公式 1-是 0-否
char name[32];// 公式名称
bool is_protected;//密码保护
char password[16];//密码
char desp[64];//公式描述
char version[16];//公式版本
Formula_Parameter parameters[16];//参数
char formula_text[4096];//公式文本内容
}Colorful_Kline_Formula;
class formula
{
public:
formula();
~formula();
std::vector<Formula_Struct*> m_queFormulas;
private:
void init();
};
void formula::init()
{
// 技术指标公式
Formula_Struct formula_Struct;
//0 - 大势型
memset(&formula_Struct, 0, sizeof(formula_Struct));
formula_Struct.is_root = true;
strcpy_s(formula_Struct.name, "大势型");// 公式名称
formula_Struct.subtype = 1;
formula_Struct.formulatype = formula_type::ftTechnical_Indicator_Formula;
m_queFormulas.push_back(formula_Struct.clone());
memset(&formula_Struct, 0, sizeof(formula_Struct));
formula_Struct.subtype = 0;
formula_Struct.is_system = true;
strcpy_s(formula_Struct.name, "ABI");// 公式名称
formula_Struct.is_protected = false;//密码保护
formula_Struct.draw_line_method = 0;//画线方法
strcpy_s(formula_Struct.desp, "绝对广量指标");//公式描述
strcpy_s(formula_Struct.version, "0");//公式版本
formula_Struct.show_decimal = 0;//显示小数
strcpy_s(formula_Struct.formula_text, "ABI:100*ABS(ADVANCE-DECLINE)/(ADVANCE+DECLINE);\n");//公式文本内容
strcat_s(formula_Struct.formula_text, "MAABI:EMA(ABI,M);");
strcpy_s(formula_Struct.parameters[0]._name, "M");//参数
strcpy_s(formula_Struct.parameters[0]._min, _T("2.00"));
strcpy_s(formula_Struct.parameters[0]._max, _T("100.00"));
strcpy_s(formula_Struct.parameters[0]._default, _T("10.00"));
formula_Struct.trade_rules = 1;//交易法则
strcpy_s(formula_Struct.coordinate_position, "自动");//坐标线位置,最多6个,用分号分隔
formula_Struct.formulatype = formula_type::ftTechnical_Indicator_Formula;
m_queFormulas.push_back(formula_Struct.clone());
memset(&formula_Struct, 0, sizeof(formula_Struct));
formula_Struct.subtype = 0;
formula_Struct.is_system = true;
strcpy_s(formula_Struct.name, "ADL");// 公式名称
formula_Struct.is_protected = false;//密码保护
formula_Struct.draw_line_method = 0;//画线方法
strcpy_s(formula_Struct.desp, "腾落指标");//公式描述
strcpy_s(formula_Struct.version, "0");//公式版本
formula_Struct.show_decimal = 0;//显示小数
strcpy_s(formula_Struct.formula_text, "ADL:SUM(ADVANCE-DECLINE,0);\n");//公式文本内容
strcat_s(formula_Struct.formula_text, "MAADL:MA(ADL,M);");
strcpy_s(formula_Struct.parameters[0]._name, "M");//参数
strcpy_s(formula_Struct.parameters[0]._min, _T("2.00f"));
strcpy_s(formula_Struct.parameters[0]._max, _T("60.00f"));
strcpy_s(formula_Struct.parameters[0]._default, _T("7.00f"));
formula_Struct.trade_rules = 1;//交易法则
strcpy_s(formula_Struct.coordinate_position, "自动");//坐标线位置,最多6个,用分号分隔
formula_Struct.formulatype = formula_type::ftTechnical_Indicator_Formula;
m_queFormulas.push_back(formula_Struct.clone());
memset(&formula_Struct, 0, sizeof(formula_Struct));
formula_Struct.subtype = 0;
formula_Struct.is_system = true;
strcpy_s(formula_Struct.name, "ADR");// 公式名称
formula_Struct.is_protected = false;//密码保护
formula_Struct.draw_line_method = 0;//画线方法
strcpy_s(formula_Struct.desp, "涨跌比率");//公式描述
strcpy_s(formula_Struct.version, "0");//公式版本
formula_Struct.show_decimal = 0;//显示小数
strcpy_s(formula_Struct.formula_text, "ADR:SUM(ADVANCE,N)/SUM(DECLINE,N);\n");//公式文本内容
strcat_s(formula_Struct.formula_text, "MAADR:MA(ADR,M);");
strcpy_s(formula_Struct.parameters[0]._name, "N");//参数
strcpy_s(formula_Struct.parameters[0]._min, _T("2.00f"));
strcpy_s(formula_Struct.parameters[0]._max, _T("100.00f"));
strcpy_s(formula_Struct.parameters[0]._default, _T("10.00f"));
strcpy_s(formula_Struct.parameters[1]._name, "M");//参数
strcpy_s(formula_Struct.parameters[1]._min, _T("2.00f"));
strcpy_s(formula_Struct.parameters[1]._max, _T("60.00"));
strcpy_s(formula_Struct.parameters[1]._default, _T("6.00"));
formula_Struct.trade_rules = 1;//交易法则
strcpy_s(formula_Struct.coordinate_position, "自动");//坐标线位置,最多6个,用分号分隔
strcpy_s(formula_Struct.extract_y_axis[0], "0.50");
strcpy_s(formula_Struct.extract_y_axis[1], "1.00");
strcpy_s(formula_Struct.extract_y_axis[2], "1.50");
formula_Struct.formulatype = formula_type::ftTechnical_Indicator_Formula;
m_queFormulas.push_back(formula_Struct.clone());
......
}
第三步:将提取的公式结构填充显示到列表树
void CTCalcDlg::InitFormulaGroupTree()
{
CTreeCtrl* pTree = reinterpret_cast<CTreeCtrl*>(GetDlgItem(IDC_TREE_2001));
pTree->LockWindowUpdate();
pTree->DeleteAllItems();
HTREEITEM hRoot = pTree->InsertItem(_T("技术指标公式"), 32, 32);
pTree->SetItemData(hRoot, ftTechnical_Indicator_Formula * 1000);
std::vector<Formula_Struct*>::iterator iter = globalFormula.m_queFormulas.begin();
for (; iter != globalFormula.m_queFormulas.end(); iter++)
{
Formula_Struct* pFormula = *iter;
if (pFormula->is_root && pFormula->formulatype == ftTechnical_Indicator_Formula)
{
label_100:
HTREEITEM hChild = pTree->InsertItem(pFormula->name, 3, 3, hRoot);
pTree->SetItemData(hChild, (DWORD)pFormula);
for (++iter; iter != globalFormula.m_queFormulas.end(); iter++)
{
pFormula = *iter;
if (pFormula->formulatype != ftTechnical_Indicator_Formula)
break;
if (pFormula->is_root)
goto label_100;
CString sItemText;
if (pFormula->is_system)
sItemText.Format(_T("%s %s(系统)"), pFormula->name, pFormula->desp);
else
sItemText.Format(_T("%s %s(用户)"), pFormula->name, pFormula->desp);
HTREEITEM hSubChild = NULL;
if (pFormula->is_common)
hSubChild = pTree->InsertItem(sItemText, 30, 30, hChild);
else if (pFormula->is_protected)
hSubChild = pTree->InsertItem(sItemText, 17, 17, hChild);
else
hSubChild = pTree->InsertItem(sItemText, 15, 15, hChild);
pTree->SetItemData(hSubChild, (DWORD)pFormula);
}
break;
}
}
pTree->Expand(hRoot, TVM_EXPAND);
hRoot = pTree->InsertItem(_T("条件选股公式"), 32, 32);
pTree->SetItemData(hRoot, ftConditional_Sel_Stock_Formula * 1000);
iter = globalFormula.m_queFormulas.begin();
for (; iter != globalFormula.m_queFormulas.end(); iter++)
{
Formula_Struct* pFormula = *iter;
if (pFormula->is_root && pFormula->formulatype == ftConditional_Sel_Stock_Formula)
{
label_101:
HTREEITEM hChild = pTree->InsertItem(pFormula->name, 3, 3, hRoot);
pTree->SetItemData(hChild, (DWORD)pFormula);
for (++iter; iter != globalFormula.m_queFormulas.end(); iter++)
{
pFormula = *iter;
if (pFormula->formulatype != ftConditional_Sel_Stock_Formula)
break;
if (pFormula->is_root)
goto label_101;
CString sItemText;
if (pFormula->is_system)
sItemText.Format(_T("%s %s(系统)"), pFormula->name, pFormula->desp);
else
sItemText.Format(_T("%s %s(用户)"), pFormula->name, pFormula->desp);
HTREEITEM hSubChild = NULL;
if (pFormula->is_common)
hSubChild = pTree->InsertItem(sItemText, 30, 30, hChild);
else if (pFormula->is_protected)
hSubChild = pTree->InsertItem(sItemText, 17, 17, hChild);
else
hSubChild = pTree->InsertItem(sItemText, 15, 15, hChild);
pTree->SetItemData(hSubChild, (DWORD)pFormula);
}
break;
}
}
hRoot = pTree->InsertItem(_T("专家系统公式"), 32, 32);
pTree->SetItemData(hRoot, ftExpert_System_Formula * 1000);
iter = globalFormula.m_queFormulas.begin();
for (; iter != globalFormula.m_queFormulas.end(); iter++)
{
Formula_Struct* pFormula = *iter;
if (pFormula->formulatype == ftExpert_System_Formula)
{
for (; iter != globalFormula.m_queFormulas.end(); iter++)
{
Formula_Struct* pFormula = *iter;
if (pFormula->formulatype != ftExpert_System_Formula)
break;
CString sItemText;
if (pFormula->is_system)
sItemText.Format(_T("%s %s(系统)"), pFormula->name, pFormula->desp);
else
sItemText.Format(_T("%s %s(用户)"), pFormula->name, pFormula->desp);
HTREEITEM hChild = NULL;
if (pFormula->is_common)
hChild = pTree->InsertItem(sItemText, 30, 30, hRoot);
else if (pFormula->is_protected)
hChild = pTree->InsertItem(sItemText, 17, 17, hRoot);
else
hChild = pTree->InsertItem(sItemText, 15, 15, hRoot);
pTree->SetItemData(hChild, (DWORD)pFormula);
}
break;
}
}
hRoot = pTree->InsertItem(_T("五彩K线公式"), 32, 32);
pTree->SetItemData(hRoot, ftColorful_Kline_Formula * 1000);
iter = globalFormula.m_queFormulas.begin();
for (; iter != globalFormula.m_queFormulas.end(); iter++)
{
Formula_Struct* pFormula = *iter;
if (pFormula->formulatype == ftColorful_Kline_Formula)
{
for (; iter != globalFormula.m_queFormulas.end(); iter++)
{
Formula_Struct* pFormula = *iter;
if (pFormula->formulatype != ftColorful_Kline_Formula)
break;
CString sItemText;
if (pFormula->is_system)
sItemText.Format(_T("%s %s(系统)"), pFormula->name, pFormula->desp);
else
sItemText.Format(_T("%s %s(用户)"), pFormula->name, pFormula->desp);
HTREEITEM hChild = NULL;
if (pFormula->is_common)
hChild = pTree->InsertItem(sItemText, 30, 30, hRoot);
else if (pFormula->is_protected)
hChild = pTree->InsertItem(sItemText, 17, 17, hRoot);
else
hChild = pTree->InsertItem(sItemText, 15, 15, hRoot);
pTree->SetItemData(hChild, (DWORD)pFormula);
}
break;
}
}
pTree->UnlockWindowUpdate();
}
至此,列表数结构就显示出来了。