// CBuyDlg.cpp: 实现文件
|
//
|
|
#include "common/pch.h"
|
#include "FloatTrade.h"
|
#include "DealQueueDlg.h"
|
#include "afxdialogex.h"
|
#include "../common/StringUtil.h"
|
#include "../common/NetworkApi.h"
|
#include "../common/JsonUtil.h"
|
#include <regex>
|
#include <thread>
|
#include <afxwin.h>
|
#include <windows.h>
|
using namespace std;
|
|
|
// CBuyDlg 对话框
|
|
IMPLEMENT_DYNAMIC(DealQueueDlg, CDialogEx)
|
|
void DealQueueDlg::AddRoundRect(Gdiplus::GraphicsPath& path, Gdiplus::REAL x, Gdiplus::REAL y, Gdiplus::REAL width, Gdiplus::REAL height, Gdiplus::REAL radius)
|
{
|
path.AddArc(x + width - 2 * radius, y, 2 * radius, 2 * radius, 270, 90);
|
path.AddArc(x + width - 2 * radius, y + height - 2 * radius, 2 * radius, 2 * radius, 0, 90);
|
path.AddArc(x, y + height - 2 * radius, 2 * radius, 2 * radius, 90, 90);
|
path.AddArc(x, y, 2 * radius, 2 * radius, 180, 90);
|
path.AddLine(x + radius, y, x + width - radius, y);
|
//path.AddArc(x + radius, y + radius, 2 * radius, 2 * radius, 90, -180);
|
//path.AddArc(x + width - radius, y + radius, 2 * radius, 2 * radius, 90, 180);
|
//path.AddLine(x + radius, y, x + width - radius, y);
|
//path.AddLine(x + radius, y+2*radius, x + width - radius, y + 2 * radius);
|
|
|
}
|
|
DealQueueDlg::DealQueueDlg(CWnd* pParent /*=nullptr*/)
|
: CDialogEx(IDD_DIALOG_DEAL_QUEUE, pParent), m_Pen(Color::MakeARGB(255, 200, 200, 200), 1.0f)
|
{
|
Gdiplus::GdiplusStartupInput startupInput;
|
ULONG_PTR token;
|
Gdiplus::GdiplusStartup(&token, &startupInput, NULL);
|
m_pGraphics = nullptr;
|
m_CornerRadius = -1; // 调整圆角半径
|
}
|
|
DealQueueDlg::~DealQueueDlg()
|
{
|
}
|
|
void DealQueueDlg::setTargetCode(string code)
|
{
|
this->code = code;
|
SetWindowTextW(CString(code.c_str()));
|
if (!code.empty()) {
|
auto t1 = std::thread(requestDealQueue, this);
|
t1.detach();
|
}
|
}
|
|
void DealQueueDlg::startRequestDealQueueTask(DealQueueDlg* context)
|
{
|
|
|
while (TRUE) {
|
try {
|
string code = context->code;
|
if (!code.empty()) {
|
if (context->windowClosed) {
|
break;
|
}
|
requestDealQueue(context);
|
}
|
}
|
|
catch (...) {
|
}
|
Sleep(1000);
|
}
|
}
|
|
void DealQueueDlg::requestDealQueue(DealQueueDlg* context)
|
{
|
std::lock_guard<std::mutex> lock(context->mtx);
|
string result = NetworkApi::get_code_deal_queue(context->code, context->minMoney);
|
auto doc = JsonUtil::parseUTF8(result);
|
list<DealQueueInfo> mLsit;
|
if (doc.IsObject()) {
|
if (doc["code"] == 0) {
|
auto data = doc["data"].GetObjectW();
|
auto deal_list = data["deal_list"].GetArray();
|
for (int i = 0; i < deal_list.Size(); i++) {
|
auto array = deal_list[i].GetArray();
|
DealQueueInfo info;
|
info.type = array[0].GetInt();
|
info.orderNo = array[1].GetInt();
|
info.time_str = array[2].GetString();
|
info.volume = array[3].GetInt();
|
info.money = array[4].GetInt();
|
info.price = array[5].GetString();
|
info.percent = array[6].GetInt();
|
mLsit.push_back(info);
|
}
|
if (data.HasMember("dealing")) {
|
auto dealing = data["dealing"].GetArray();
|
DealQueueInfo info;
|
info.type = dealing[0].GetInt();
|
info.orderNo = dealing[1].GetInt();
|
info.time_str = dealing[2].GetString();
|
info.volume = dealing[3].GetInt();
|
info.money = dealing[4].GetInt();
|
info.price = StringUtil::to_string(dealing[5].GetFloat());
|
info.percent = dealing[6].GetInt();
|
mLsit.push_back(info);
|
}
|
}
|
}
|
if (context->windowClosed) {
|
return;
|
}
|
|
context->listCtrl.SetRedraw(false);
|
bool needReAdd = false;
|
if (mLsit.size() != context->dealQueueList.size() || mLsit.size() == 0) {
|
needReAdd = true;
|
}
|
else if (context->dealQueueList.size() > 0 && mLsit.size() > 0 && context->dealQueueList.back().orderNo != mLsit.back().orderNo) {
|
needReAdd = true;
|
}
|
|
//填充List
|
if (needReAdd) {
|
// 删除原来的数据,然后新增
|
context->listCtrl.DeleteAllItems();
|
int index = 0;
|
for (list<DealQueueInfo>::iterator it = mLsit.begin(); it != mLsit.end(); ++it) {
|
DealQueueInfo info = *it;
|
context->listCtrl.InsertItem(index, L"");
|
context->listCtrl.SetItemText(index, 0, CString(info.time_str.c_str()));
|
context->listCtrl.SetItemText(index, 1, CString(info.price.c_str()));
|
CString money = CString(StringUtil::to_string(info.money / 10000.0f).c_str());
|
money.Append(L"万");
|
context->listCtrl.SetItemText(index, 2, money);
|
CString percent = to_wstring(info.percent).c_str();
|
percent.Append(L"%");
|
context->listCtrl.SetItemText(index, 3, percent);
|
context->listCtrl.SetItemText(index, 4, info.type == 0 ? L"买" : L"卖");
|
index++;
|
}
|
}
|
else {
|
//修改最后一行的数据
|
int index = mLsit.size() - 1;
|
DealQueueInfo oldInfo = context->dealQueueList.back();
|
DealQueueInfo info = mLsit.back();
|
if (oldInfo.percent != info.percent) {
|
context->listCtrl.SetItemText(index, 0, CString(info.time_str.c_str()));
|
context->listCtrl.SetItemText(index, 1, CString(info.price.c_str()));
|
CString money = CString(StringUtil::to_string(info.money / 10000.0f).c_str());
|
money.Append(L"万");
|
context->listCtrl.SetItemText(index, 2, money);
|
CString percent = to_wstring(info.percent).c_str();
|
percent.Append(L"%");
|
context->listCtrl.SetItemText(index, 3, percent);
|
context->listCtrl.SetItemText(index, 4, info.type == 0 ? L"买" : L"卖");
|
}
|
}
|
context->listCtrl.SetRedraw(true);
|
context->dealQueueList = mLsit;
|
}
|
|
void DealQueueDlg::DoDataExchange(CDataExchange* pDX)
|
{
|
|
CDialogEx::DoDataExchange(pDX);
|
DDX_Control(pDX, IDC_LIST_DEAL_QUEUE, listCtrl);
|
DDX_Control(pDX, IDC_EDIT_MIN_MONEY, editMinMoney);
|
}
|
|
BOOL DealQueueDlg::OnInitDialog()
|
{
|
CDialogEx::OnInitDialog();
|
InitializeGDIPlus();
|
minMoney = 50;
|
editMinMoney.SetWindowTextW(to_wstring(minMoney).c_str());
|
listCtrl.InsertColumn(0, _T("时间"), LVCFMT_LEFT, 65, 0);
|
listCtrl.InsertColumn(1, _T("价格"), LVCFMT_LEFT, 50, 1);
|
listCtrl.InsertColumn(2, _T("金额"), LVCFMT_LEFT, 65, 2);
|
listCtrl.InsertColumn(3, _T("手数"), LVCFMT_LEFT, 65, 3);
|
listCtrl.InsertColumn(4, _T("类型"), LVCFMT_LEFT, 40, 4);
|
windowClosed = false;
|
setTargetCode("");
|
auto t1 = std::thread(startRequestDealQueueTask, this);
|
t1.detach();
|
return TRUE;
|
}
|
|
|
BEGIN_MESSAGE_MAP(DealQueueDlg, CDialogEx)
|
|
ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_DEAL_QUEUE, &DealQueueDlg::OnItemchangedListDealQueue)
|
ON_WM_CLOSE()
|
ON_NOTIFY(NM_CUSTOMDRAW, IDC_LIST_DEAL_QUEUE, &DealQueueDlg::OnCustomdrawListDealQueue)
|
ON_EN_CHANGE(IDC_EDIT_MIN_MONEY, &DealQueueDlg::OnChangeEditMinMoney)
|
END_MESSAGE_MAP()
|
|
|
// 设置滚动条始终在底部
|
void DealQueueDlg::OnItemchangedListDealQueue(NMHDR* pNMHDR, LRESULT* pResult)
|
{
|
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
|
// 检查是否有新的项被添加
|
//if (pNMLV->uNewState != 0 && (pNMLV->uNewState & LVIS_FOCUSED) == 0)
|
{
|
// 获取当前列表的项数
|
int nItemCount = listCtrl.GetItemCount();
|
|
// 滚动到最后一项
|
if (nItemCount > 0)
|
{
|
listCtrl.EnsureVisible(nItemCount - 1, FALSE);
|
}
|
}
|
*pResult = 0;
|
}
|
|
|
void DealQueueDlg::OnClose()
|
{
|
windowClosed = TRUE;
|
CDialogEx::OnClose();
|
}
|
|
|
void DealQueueDlg::OnCustomdrawListDealQueue(NMHDR* pNMHDR, LRESULT* pResult)
|
{
|
LPNMLVCUSTOMDRAW pNMCD = reinterpret_cast<LPNMLVCUSTOMDRAW>(pNMHDR);
|
|
switch (pNMCD->nmcd.dwDrawStage)
|
{
|
case CDDS_PREPAINT:
|
*pResult = CDRF_NOTIFYITEMDRAW;
|
return;
|
|
case CDDS_ITEMPREPAINT:
|
*pResult = CDRF_NOTIFYSUBITEMDRAW;
|
return;
|
|
case CDDS_SUBITEM | CDDS_ITEMPREPAINT:
|
if (pNMCD->iSubItem == 3) // 假设进度条在第2列(索引为1)
|
{
|
CDC* pDC = CDC::FromHandle(pNMCD->nmcd.hdc);
|
CRect rect;
|
listCtrl.GetSubItemRect(pNMCD->nmcd.dwItemSpec, pNMCD->iSubItem, LVIR_BOUNDS, rect);
|
|
int padding = 1;
|
int height = rect.Height() - padding * 2;
|
if (height % 2 != 0) {
|
height -= 1;
|
}
|
|
if (m_CornerRadius < 0) {
|
m_CornerRadius = height / 2;
|
}
|
|
|
int index = pNMCD->nmcd.dwItemSpec;
|
list<DealQueueInfo>::iterator e = dealQueueList.begin();
|
advance(e, index);
|
// 获取进度值
|
int nProgress = (*e).percent;
|
|
// 计算进度条的宽度
|
int nWidth = rect.Width();
|
int nProgressWidth = nWidth * nProgress / 100;
|
|
Graphics* pGraphics = Gdiplus::Graphics::FromHDC(pDC->GetSafeHdc());
|
pGraphics->SetSmoothingMode(SmoothingModeAntiAlias);
|
pGraphics->SetTextRenderingHint(TextRenderingHintAntiAlias);
|
|
m_Pen.SetColor(0xFF2A1D);
|
// 绘制背景
|
GraphicsPath path;
|
AddRoundRect(path,
|
(Gdiplus::REAL)rect.left,
|
(Gdiplus::REAL)rect.top + padding,
|
(Gdiplus::REAL)rect.Width(),
|
(Gdiplus::REAL)height,
|
m_CornerRadius
|
);
|
pGraphics->FillPath(m_BackBrush, &path);
|
pGraphics->DrawPath(&m_Pen, &path);
|
|
GraphicsPath progressPath;
|
AddRoundRect(progressPath,
|
(Gdiplus::REAL)rect.left,
|
(Gdiplus::REAL)rect.top + padding,
|
(Gdiplus::REAL)nProgressWidth,
|
(Gdiplus::REAL)height,
|
m_CornerRadius
|
);
|
pGraphics->FillPath(m_ProgressBrush, &progressPath);
|
pGraphics->DrawPath(&m_Pen, &progressPath);
|
CString st = L"";
|
st.Append(to_wstring(nProgress).c_str());
|
st.Append(L"%");
|
|
PointF point(rect.left + 5, rect.top + padding); // 调整文本位置
|
Gdiplus::Font font(L"Arial", 10);
|
SolidBrush textBrush(Color::White);
|
pGraphics->DrawString(st, -1, &font, point, &textBrush);
|
*pResult = CDRF_SKIPDEFAULT;
|
}
|
else
|
{
|
*pResult = CDRF_DODEFAULT;
|
}
|
return;
|
}
|
|
|
*pResult = CDRF_DODEFAULT;
|
}
|
|
void DealQueueDlg::InitializeGDIPlus()
|
{
|
m_pGraphics = Gdiplus::Graphics::FromHDC(nullptr);
|
m_Pen.SetColor(0xFF00FF00);
|
m_BackBrush = new Gdiplus::LinearGradientBrush(
|
PointF(0, 0),
|
PointF(0, 20),
|
0xFF000000,
|
0xFF000000
|
);
|
m_ProgressBrush = new Gdiplus::LinearGradientBrush(
|
PointF(0, 0),
|
PointF(0, 20),
|
0xFFFF2A1D,
|
0xFFFF2A1D
|
);
|
|
|
}
|
|
void DealQueueDlg::CleanupGDIPlus()
|
{
|
delete m_pGraphics;
|
}
|
|
|
BOOL DealQueueDlg::PreTranslateMessage(MSG* pMsg)
|
{
|
// 检测是否是键盘消息
|
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN)
|
{
|
// 处理回车键事件
|
if (CWnd::GetFocus() == GetDlgItem(IDC_EDIT_MIN_MONEY)) {
|
CString money;
|
editMinMoney.GetWindowTextW(money);
|
if (money.IsEmpty()) {
|
minMoney = 0;
|
}
|
else {
|
minMoney = stoi(StringUtil::cstring2String(money));
|
}
|
auto t1 = std::thread(requestDealQueue, this);
|
t1.detach();
|
return TRUE; // 返回 TRUE 表示已经处理了这个消息,不再传递给基类
|
}
|
}
|
|
return CDialogEx::PreTranslateMessage(pMsg);
|
}
|
|
|
void DealQueueDlg::OnChangeEditMinMoney()
|
{
|
// TODO: 如果该控件是 RICHEDIT 控件,它将不
|
// 发送此通知,除非重写 CDialogEx::OnInitDialog()
|
// 函数并调用 CRichEditCtrl().SetEventMask(),
|
// 同时将 ENM_CHANGE 标志“或”运算到掩码中。
|
|
// TODO: 在此添加控件通知处理程序代码
|
}
|