// 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 #include #include #include 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 lock(context->mtx); string result = NetworkApi::get_code_deal_queue(context->code, context->minMoney); auto doc = JsonUtil::parseUTF8(result); list 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::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(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(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::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: 在此添加控件通知处理程序代码 }