核心功能是展示期货合约行情、处理网络消息(行情 / 交易)、管理 K 线图显示、交易面板交互以及自选合约等辅助功能。
一、核心结构与初始化
1. 全局变量与窗体初始化
// 核心成员变量
public ST_HeYueInfo mCurSelectHeYueInfo = null; // 当前选中的合约信息
public TfrmTrade mFrmTrade = new TfrmTrade(); // 交易子窗口
public TFrmKlineStock mFrmKline = new TFrmKlineStock(); // K线子窗口
public Jken JkenWindow = null; // 预警窗口
MemoryStream mArrowDownStream, mArrowUpStream; // 涨跌箭头图片流
初始化逻辑(FrmMain 构造函数):
- 设置全局窗体句柄(用于消息通信)
- 初始化行情面板 / K 线面板的显示状态
- 加载涨跌箭头图片到内存流
- 设置行情列表(DataGridView)的字体样式
2. 窗体加载与子窗口嵌入
private void FrmMain_Load(object sender, EventArgs e)
{
CreateMarketButton(); // 创建市场分类按钮(全部/主力/自选)
FillHQList("ALL"); // 初始化填充全部合约行情
}
private void timer_init_Tick(object sender, EventArgs e)
{
// 交易窗口嵌入到主窗体的Panel中
mFrmTrade.TopLevel = false;
mFrmTrade.Parent = pnlTrade;
mFrmTrade.Dock = DockStyle.Fill;
mFrmTrade.Show();
// 初始化预警窗口
JkenWindow = new Jken();
JkenWindow.MS = this;
}
关键逻辑:
- 通过 TopLevel = false 将子窗体嵌入主窗体的 Panel 控件,实现一体化显示
- 定时器延迟初始化子窗口,避免窗体加载卡顿
二、核心功能模块
1. 消息通信机制(Windows 消息处理)
protected override void DefWndProc(ref System.Windows.Forms.Message m)
{
switch (m.Msg)
{
case Global.WM_NET_MSG: // 交易网络消息
OnNetMsgTrade(m.WParam, m.LParam);
break;
case Global.WM_NET_MSG_HQ: // 行情网络消息
OnNetMsgHQ(m.WParam, m.LParam);
break;
case Global.WM_LOCAL_MSG_KLINE: // 本地K线消息
OnLocalMsgKLine(m.WParam, m.LParam);
break;
default:
base.DefWndProc(ref m);
break;
}
}
核心处理逻辑:
- OnNetMsgTrade:处理交易服务器消息(登录 / 登出 / 密码修改 / 跟单 / 货币转换)
- 登录成功后更新用户信息,解锁交易面板
- 处理货币转换结果,刷新交易面板资金信息
- OnNetMsgHQ:处理行情服务器消息
- 行情连接成功后订阅实时行情
- 接收实时行情推送,更新行情列表(UpdateHQList)
- OnLocalMsgKLine:处理本地 K 线数据消息,转发给 K 线窗口和预警窗口
2. 行情列表管理
(1)市场分类按钮与行情填充
private void CreateMarketButton()
{
// 创建「全部合约/主力合约/自选合约」按钮
// 按钮点击事件绑定 btnMarket_Click
}
private void btnMarket_Click(Object sender,EventArgs e)
{
string marketCode = btn.Tag as string;
FillHQList(marketCode); // 根据分类填充行情列表
// 按钮选中态样式切换(橙色高亮)
}
(2)行情列表填充(FillHQList)
private void FillHQList(string strMarketCode)
{
lvHangQing.Rows.Clear();
foreach (var node in Common.gDictHeYue) // 遍历全局合约字典
{
ST_HeYueInfo info = node.Value;
// 根据分类过滤(ALL/ZHULI/SELF)
if (strMarketCode == "ZHULI" && !info.bIsZhuLi) continue;
if (strMarketCode == "SELF" && !IsInSelfList(info.id)) continue;
// 填充行情列表行数据
int rowindex = lvHangQing.Rows.Add();
DataGridViewRow row = lvHangQing.Rows[rowindex];
row.Tag = info; // 绑定合约信息到行标签
// 设置行情字段(最新价/买一/卖一/涨跌幅/持仓量等)
// 设置行颜色(涨红跌绿,固定列金色/白色)
}
}
(3)实时行情更新(UpdateHQList)
private void UpdateHQList(ST_HeYueInfo info)
{
lvHangQing.SuspendLayout(); // 暂停布局更新,提升性能
try
{
foreach (DataGridViewRow Row in lvHangQing.Rows)
{
ST_HeYueInfo aa = (ST_HeYueInfo)Row.Tag;
if (aa.bh == info.bh) // 匹配合约编码
{
// 更新该行的行情数据(最新价/涨跌幅/成交量等)
// 更新行颜色(涨红跌绿)
break;
}
}
}
finally
{
lvHangQing.ResumeLayout(); // 恢复布局
}
}
3. K 线图显示逻辑
public void ShowKline(int ChartType, string code,string market, string period, string name = "")
{
// K线窗口嵌入到主窗体的pnlKline面板
mFrmKline.TopLevel = false;
mFrmKline.Parent = pnlKline;
mFrmKline.Dock = DockStyle.Fill;
mFrmKline.Show();
// 切换K线合约/周期(分时/15m等)
mFrmKline.ChangeSymbolPeriod(ChartType,code,market, period, name);
// 切换面板显示(隐藏行情,显示K线)
pnlHangQing.Visible = false;
pnlKline.Visible = true;
}
触发场景:
- 行情列表双击(默认 15 分钟 K 线)
- 分时 / K 线按钮点击(分时 = 1m,K 线按钮绑定不同周期:5m/15m/1h 等)
4. 自选合约管理
// 加入自选
private void menuItem_AddSelf_Click(object sender, EventArgs e)
{
ST_HeYueInfo info = (ST_HeYueInfo)lvHangQing.CurrentRow.Tag;
string strIDList = IniHelper.ReadValue("./config.dat", "SelfContract", "IDList");
// 检查是否已存在,不存在则追加到配置文件
if (!strIDList.Contains(info.id.ToString()))
{
strIDList = string.IsNullOrEmpty(strIDList) ? info.id.ToString() : $"{strIDList},{info.id}";
IniHelper.WriteValue("./config.dat", "SelfContract", "IDList", strIDList);
}
}
// 移出自选
private void menuItem_RemoveSelf_Click(object sender, EventArgs e)
{
// 从配置文件中移除当前合约ID,刷新自选列表
}
5. 行情列表自定义绘制
private void lvHangQing_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
// 第一列绘制涨跌箭头
if (e.RowIndex >= 0 && e.ColumnIndex==0)
{
ST_HeYueInfo tagInfo = (ST_HeYueInfo)lvHangQing.Rows[e.RowIndex].Tag;
float zd = tagInfo.latest – tagInfo.yClose;
if (zd > 0)
{
e.Graphics.DrawImage(Image.FromStream(mArrowUpStream), e.CellBounds.Left + 12, e.CellBounds.Top + 4, 12, 20);
}
else if (zd < 0)
{
e.Graphics.DrawImage(Image.FromStream(mArrowDownStream), e.CellBounds.Left + 12, e.CellBounds.Top + 4, 12, 20);
}
e.Handled = true;
}
}
private void lvHangQing_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
{
// 选中行绘制金色边框,第一行绘制红色顶部边框
if (lvHangQing.Rows[e.RowIndex].Selected)
{
using (Pen pen = new Pen(Color.Gold,1))
{
e.Graphics.DrawLine(pen, e.RowBounds.Left, e.RowBounds.Top, e.RowBounds.Right+5, e.RowBounds.Top);
e.Graphics.DrawLine(pen, e.RowBounds.Left, e.RowBounds.Bottom-2, e.RowBounds.Right+5, e.RowBounds.Bottom-2);
}
}
}
三、关键辅助功能
窗体样式自定义
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000; // 开启双缓冲,减少闪烁
return cp;
}
}
// 自定义窗体拖动(无标题栏)
private void Toptaskbar_MouseDown(object sender, MouseEventArgs e)
{
formPoint = new Point(e.X, e.Y);
}
private void Toptaskbar_MouseMov(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
this.Location = new Point(this.Location.X + e.X – formPoint.X, this.Location.Y + e.Y – formPoint.Y);
}
}
总结





