admin
2024-03-04 9be57d2f294687a9283e6d3ed8599def4faf1fec
'功能修改'
31个文件已修改
28个文件已添加
4874 ■■■■■ 已修改文件
FloatTrade/CAutoFocusButton.cpp 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/CAutoFocusButton.h 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/CBuyDlg.cpp 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/CBuyDlg.h 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/CImgButton.cpp 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/CImgButton.h 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/ConfigUtil.cpp 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/ConfigUtil.h 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/FloatTrade.aps 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/FloatTrade.cpp 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/FloatTrade.rc 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/FloatTrade.vcxproj 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/FloatTrade.vcxproj.filters 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/FloatTradeDlg.cpp 1255 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/FloatTradeDlg.h 110 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/RCa18592 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/RDa18592 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/SellDlg.cpp 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/SellDlg.h 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/SellManager.cpp 316 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/SellManager.h 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/SellRuleDlg.cpp 784 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/SellRuleDlg.h 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/SellStruct.h 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/TipDlg.cpp 25 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/TipDlg.h 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/config.cfg 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/res/ic_bg.bmp 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/res/ic_close_red.png 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/resource.h 71 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
TradeRecord/ConfigUtil.cpp 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
TradeRecord/ConfigUtil.h 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
TradeRecord/TradeRecord.aps 补丁 | 查看 | 原始文档 | blame | 历史
TradeRecord/TradeRecord.rc 补丁 | 查看 | 原始文档 | blame | 历史
TradeRecord/TradeRecord.vcxproj 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
TradeRecord/TradeRecord.vcxproj.filters 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
TradeRecord/TradeRecord.vcxproj.user 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
TradeRecord/TradeRecordDlg.cpp 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
TradeRecord/config.cfg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
TradeRecord/lib_config.zip 补丁 | 查看 | 原始文档 | blame | 历史
TradeRecord/lib_config/include/libconfig.h 355 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
TradeRecord/lib_config/include/libconfig.h++ 574 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
TradeRecord/libconfig++.dll 补丁 | 查看 | 原始文档 | blame | 历史
TradeRecord/res/TradeRecord.ico 补丁 | 查看 | 原始文档 | blame | 历史
TradeRecord/res/TradeRecord.png 补丁 | 查看 | 原始文档 | blame | 历史
TradeRecord/resource.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
TradeRecordSetup/TradeRecordSetup.vdproj 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
TradeRecordSetup/dependency/GdiPlus.dll 补丁 | 查看 | 原始文档 | blame | 历史
TradeRecordSetup/dependency/mfc140ud.dll 补丁 | 查看 | 原始文档 | blame | 历史
TradeRecordSetup/dependency/msvcp140d.dll 补丁 | 查看 | 原始文档 | blame | 历史
TradeRecordSetup/dependency/ucrtbased.dll 补丁 | 查看 | 原始文档 | blame | 历史
TradeRecordSetup/dependency/vcruntime140_1d.dll 补丁 | 查看 | 原始文档 | blame | 历史
TradeRecordSetup/dependency/vcruntime140d.dll 补丁 | 查看 | 原始文档 | blame | 历史
common/NetworkApi.cpp 223 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common/NetworkApi.h 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common/SocketManager.cpp 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common/SocketManager.h 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common/StringUtil.h 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
common/TimeUtil.h 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
FloatTrade/CAutoFocusButton.cpp
New file
@@ -0,0 +1,14 @@
#include "common/pch.h"
#include "CAutoFocusButton.h"
BEGIN_MESSAGE_MAP(CAutoFocusButton, CMFCButton)
    ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()
void CAutoFocusButton::OnMouseMove(UINT nFlags, CPoint point)
{
    // 调用父类的消息处理函数
    SetForegroundWindow();
    CButton::OnMouseMove(nFlags, point);
}
FloatTrade/CAutoFocusButton.h
New file
@@ -0,0 +1,14 @@
#pragma once
#include <afxext.h>
class CAutoFocusButton : public CMFCButton
{
public:
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    DECLARE_MESSAGE_MAP()
};
FloatTrade/CBuyDlg.cpp
@@ -37,6 +37,8 @@
BEGIN_MESSAGE_MAP(CBuyDlg, CDialogEx)
    ON_BN_CLICKED(btn_sure, &CBuyDlg::OnBnClickedsure)
    ON_WM_COPYDATA()
    ON_CBN_SELCHANGE(IDC_COMBO_SELL_FIRST, &CBuyDlg::OnCbnSelchangeComboSellFirst)
    ON_CBN_SELCHANGE(IDC_COMBO_SELL_LEFT, &CBuyDlg::OnCbnSelchangeComboSellLeft)
END_MESSAGE_MAP()
@@ -138,3 +140,15 @@
    return TRUE;  // return TRUE unless you set the focus to a control
                  // 异常: OCX 属性页应返回 FALSE
}
void CBuyDlg::OnCbnSelchangeComboSellFirst()
{
    // TODO: 在此添加控件通知处理程序代码
}
void CBuyDlg::OnCbnSelchangeComboSellLeft()
{
    // TODO: 在此添加控件通知处理程序代码
}
FloatTrade/CBuyDlg.h
@@ -30,4 +30,6 @@
    afx_msg void OnBnClickedsure();
    afx_msg BOOL OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct);
    virtual BOOL OnInitDialog();
    afx_msg void OnCbnSelchangeComboSellFirst();
    afx_msg void OnCbnSelchangeComboSellLeft();
};
FloatTrade/CImgButton.cpp
New file
@@ -0,0 +1,57 @@
#include "common/pch.h"
#include "CImgButton.h"
CImgButton::CImgButton()
{
}
CImgButton::~CImgButton()
{
}
// BEGIN_MESSAGE_MAP(CImgButton, CBitmapButton)
// END_MESSAGE_MAP()
void CImgButton::SetTextColor(COLORREF crColor)
{
    TextColor = crColor;
}
void CImgButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    CRect rect = lpDrawItemStruct->rcItem;
    CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
    int nSaveDC = pDC->SaveDC();
    UINT state = lpDrawItemStruct->itemState;
    TCHAR strText[MAX_PATH + 1];
    ::GetWindowText(m_hWnd, strText, MAX_PATH);
    CBitmapButton::DrawItem(lpDrawItemStruct);
   // pDC->SetTextColor(TextColor);
   /* if (strText != NULL)
    {
        CFont* hFont = GetFont();
        CFont* hOldFont = pDC->SelectObject(hFont);
        CSize szExtent = pDC->GetTextExtent(strText, lstrlen(strText));
        CPoint pt(rect.CenterPoint().x - szExtent.cx / 2, rect.CenterPoint().y - szExtent.cy / 2);
        if (state & ODS_SELECTED)
        {
            pt.Offset(1, 1);
        }
        int nMode = pDC->SetBkMode(TRANSPARENT);
        if (state & ODS_DISABLED)
        {
            pDC->DrawState(pt, szExtent, strText, DSS_DISABLED, TRUE, 0, (HBRUSH)NULL);
        }
        else
        {
            pDC->DrawState(pt, szExtent, strText, DSS_NORMAL, TRUE, 0, (HBRUSH)NULL);
        }
        pDC->SelectObject(hOldFont);
        pDC->SetBkMode(nMode);
    }*/
    pDC->RestoreDC(nSaveDC);
}
FloatTrade/CImgButton.h
New file
@@ -0,0 +1,19 @@
#pragma once
#include <afxext.h>
class CImgButton: public CBitmapButton
{
public:
    CImgButton();
    virtual ~CImgButton();
protected:
    //DECLARE_MESSAGE_MAP()
public:
public:
    COLORREF TextColor;
    void SetTextColor(COLORREF crColor);
    virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
};
FloatTrade/ConfigUtil.cpp
@@ -92,6 +92,26 @@
    writeConfig(mConfig);
}
list<string> ConfigUtil::getKeys()
{
    libconfig::Config mConfig;
    readConfig(mConfig);
    libconfig::Setting& root = mConfig.getRoot();
    list<string> keys;
    for (auto iter = root.begin(); iter != root.end(); ++iter) {
        keys.push_back(iter->getName());
    }
    return keys;
}
void ConfigUtil::delKey(string key)
{
    libconfig::Config mConfig;
    readConfig(mConfig);
    libconfig::Setting& root = mConfig.getRoot();
    root.remove(key);
}
bool ConfigUtil::isTradeRefresh()
{
    try {
@@ -137,6 +157,28 @@
    return false;
}
int* ConfigUtil::getSellRuleDialogShowPos()
{
    int* pos = (int*)malloc(sizeof(int) * 2);
    pos[0] = 0;
    pos[1] = 0;
    try {
        string str =    readStringConfig("sell_rule_show_pos");
        // 分隔字符串
        int split_index = str.find(",");
        int x= stoi( str.substr(0, split_index));
        int y = stoi(str.substr(split_index + 1, str.length() - (split_index+1)));
        pos[0] = x;
        pos[1] = y;
    }
    catch (...) {
    }
    return pos;
}
void ConfigUtil::setTradeRefresh(bool enable)
{
    setIntConfig("trade_refresh", enable ? 1 : 0);
@@ -154,6 +196,13 @@
    setIntConfig("trade_quick_key", enable ? 1 : 0);
}
void ConfigUtil::setSellRuleDialogShowPos(int x, int y)
{
    string pos = "";
    pos.append(to_string(x)).append(",").append(to_string(y));
    setStringConfig("sell_rule_show_pos", pos);
}
POINT ConfigUtil::getWindowPos()
{
    
FloatTrade/ConfigUtil.h
@@ -9,24 +9,32 @@
    static void readConfig(libconfig::Config& config);
    static void writeConfig(libconfig::Config& config);
    static int readIntConfig(const char * key);
    static string readStringConfig(const char* key);
    static void setIntConfig(const char* key,int val);
    static void setStringConfig(const char* key,string val);
public:
    static int readIntConfig(const char* key);
    static string readStringConfig(const char* key);
    static void setIntConfig(const char* key, int val);
    static void setStringConfig(const char* key, string val);
    static list<string> getKeys();
    static void delKey(string key);
    static bool isTradeRefresh();
    static bool isGroupRefresh();
    static bool isAutoFocus();
    static bool isTradeQuickKey();
    // 获取卖出规则弹框显示的位置
    static int* getSellRuleDialogShowPos();
    static void setTradeRefresh(bool enable);
    static void setGroupRefresh(bool enable);
    static void setAutoFocus(bool enable);
    static void setTradeQuickKey(bool enable);
    static void setSellRuleDialogShowPos(int x, int y);
    // 窗口位置
    static POINT getWindowPos();
FloatTrade/FloatTrade.aps
Binary files differ
FloatTrade/FloatTrade.cpp
@@ -7,6 +7,7 @@
#include "FloatTradeDlg.h"
#include "SellRuleDlg.h"
#include "TipDlg.h"
#include "SellDlg.h"
@@ -64,7 +65,7 @@
BOOL CFloatTradeApp::InitInstance()
{
    SetUnhandledExceptionFilter(CFloatTradeApp::unhandledExceptionFilter);
    //SetUnhandledExceptionFilter(CFloatTradeApp::unhandledExceptionFilter);
    // 如果一个运行在 Windows XP 上的应用程序清单指定要
    // 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
    //则需要 InitCommonControlsEx()。  否则,将无法创建窗口。
FloatTrade/FloatTrade.rc
Binary files differ
FloatTrade/FloatTrade.vcxproj
@@ -221,16 +221,22 @@
    <ClInclude Include="..\common\SocketManager.h" />
    <ClInclude Include="..\common\StringUtil.h" />
    <ClInclude Include="..\common\targetver.h" />
    <ClInclude Include="..\common\TimeUtil.h" />
    <ClInclude Include="..\common\Win32Util.h" />
    <ClInclude Include="CBuyDlg.h" />
    <ClInclude Include="CColorStatic.h" />
    <ClInclude Include="CImgButton.h" />
    <ClInclude Include="CAutoFocusButton.h" />
    <ClInclude Include="ConfigUtil.h" />
    <ClInclude Include="CSettingDlg.h" />
    <ClInclude Include="FloatTrade.h" />
    <ClInclude Include="FloatTradeDlg.h" />
    <ClInclude Include="MyButton.h" />
    <ClInclude Include="Resource.h" />
    <ClInclude Include="SellDlg.h" />
    <ClInclude Include="SellManager.h" />
    <ClInclude Include="SellRuleDlg.h" />
    <ClInclude Include="SellStruct.h" />
    <ClInclude Include="ThsUtil.h" />
    <ClInclude Include="TipDlg.h" />
  </ItemGroup>
@@ -244,6 +250,8 @@
    <ClCompile Include="base64.cpp" />
    <ClCompile Include="CBuyDlg.cpp" />
    <ClCompile Include="CColorStatic.cpp" />
    <ClCompile Include="CImgButton.cpp" />
    <ClCompile Include="CAutoFocusButton.cpp" />
    <ClCompile Include="ConfigUtil.cpp" />
    <ClCompile Include="CSettingDlg.cpp" />
    <ClCompile Include="FloatTrade.cpp" />
@@ -252,6 +260,8 @@
    <ClCompile Include="json_value.cpp" />
    <ClCompile Include="json_writer.cpp" />
    <ClCompile Include="MyButton.cpp" />
    <ClCompile Include="SellDlg.cpp" />
    <ClCompile Include="SellManager.cpp" />
    <ClCompile Include="SellRuleDlg.cpp" />
    <ClCompile Include="ThsUtil.cpp" />
    <ClCompile Include="TipDlg.cpp" />
@@ -265,7 +275,10 @@
  </ItemGroup>
  <ItemGroup>
    <Image Include="icon.ico" />
    <Image Include="res\bitmap1.bmp" />
    <Image Include="res\ic_bg.bmp" />
    <Image Include="res\FloatTrade.ico" />
    <Image Include="res\ic_close_red.png" />
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
FloatTrade/FloatTrade.vcxproj.filters
@@ -87,6 +87,24 @@
    <ClInclude Include="TipDlg.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="..\common\TimeUtil.h">
      <Filter>头文件\common</Filter>
    </ClInclude>
    <ClInclude Include="SellDlg.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="CImgButton.h">
      <Filter>头文件\common</Filter>
    </ClInclude>
    <ClInclude Include="SellStruct.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="CAutoFocusButton.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="SellManager.h">
      <Filter>头文件</Filter>
    </ClInclude>
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="FloatTrade.cpp">
@@ -149,6 +167,18 @@
    <ClCompile Include="TipDlg.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="SellDlg.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="CImgButton.cpp">
      <Filter>源文件\common</Filter>
    </ClCompile>
    <ClCompile Include="CAutoFocusButton.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="SellManager.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="FloatTrade.rc">
@@ -168,5 +198,14 @@
    <Image Include="icon.ico">
      <Filter>资源文件</Filter>
    </Image>
    <Image Include="res\ic_bg.bmp">
      <Filter>资源文件</Filter>
    </Image>
    <Image Include="res\ic_close_red.png">
      <Filter>资源文件</Filter>
    </Image>
    <Image Include="res\bitmap1.bmp">
      <Filter>资源文件</Filter>
    </Image>
  </ItemGroup>
</Project>
FloatTrade/FloatTradeDlg.cpp
@@ -20,16 +20,11 @@
#include <codecvt>
#include <thread>
#include "../common/Win32Util.h"
#include "../common/TimeUtil.h"
#include "ThsUtil.h"
#include "CSettingDlg.h"
#include "CBuyDlg.h"
#include "SellRuleDlg.h"
#include "TipDlg.h"
using namespace std;
// CFloatTradeDlg 对话框
@@ -84,9 +79,9 @@
}
void CFloatTradeDlg::showTips(CString message, int msgType)
void CFloatTradeDlg::showTips(CString message, int msgType, int delayMs, int position)
{
    TipDlg* p_MsgWindow = new TipDlg(this);
    TipDlg* p_MsgWindow = new TipDlg(delayMs, position, this);
    p_MsgWindow->Create(IDD_DIALOG_TIPS, this);
    if (msgType == MSG_TYPE_INFO) {
        msgColor = COLOR_BLACK;
@@ -99,6 +94,9 @@
    }
    else if (msgType == MSG_TYPE_FAIL) {
        msgColor = COLOR_GREEN;
    }
    else if (msgType == MSG_TYPE_WARNING) {
        msgColor = COLOR_ORANGE;
    }
    p_MsgWindow->setMsg(message, msgColor);
    p_MsgWindow->ShowWindow(SW_SHOW);
@@ -119,6 +117,38 @@
    }
    catch (...) {
        context->setMsg(L"获取交易状态失败", MSG_TYPE_FAIL);
    }
}
void CFloatTradeDlg::getAutoCancelSellMode(CFloatTradeDlg* context)
{
    try {
        int mode = NetworkApi::get_auto_cancel_sell_mode();
        if (mode == 0) {
            context->checkAutoCancelSell.SetCheck(TRUE);
        }
        else {
            context->checkAutoCancelSell.SetCheck(FALSE);
        }
    }
    catch (...) {
        context->setMsg(L"获取交易状态失败", MSG_TYPE_FAIL);
    }
}
void CFloatTradeDlg::getMarketSituation(CFloatTradeDlg* context)
{
    try {
        int situation = NetworkApi::get_market_situation();
        if (situation == 2) {
            context->checkMarketSituation.SetCheck(TRUE);
        }
        else {
            context->checkMarketSituation.SetCheck(FALSE);
        }
    }
    catch (...) {
    }
}
@@ -183,40 +213,33 @@
    }
}
void CFloatTradeDlg::selectSellVolume(string code, int percent)
void CFloatTradeDlg::selectSellRateIndex(string code, int percent)
{
    if (code.length() != 6) {
        return;
    }
    int  v_ids[] = { IDC_BUTTON_SELL_VOLUME_1,IDC_BUTTON_SELL_VOLUME_2,IDC_BUTTON_SELL_VOLUME_3,IDC_BUTTON_SELL_VOLUME_4,IDC_BUTTON_SELL_VOLUME_5,IDC_BUTTON_SELL_VOLUME_6,IDC_BUTTON_SELL_VOLUME_7,IDC_BUTTON_SELL_VOLUME_8,IDC_BUTTON_SELL_VOLUME_9,IDC_BUTTON_SELL_VOLUME_10 };
    int  v_ids[] = { IDC_BUTTON_SELL_VOLUME_1,IDC_BUTTON_SELL_VOLUME_2,IDC_BUTTON_SELL_VOLUME_3,IDC_BUTTON_SELL_VOLUME_4,IDC_BUTTON_SELL_VOLUME_5 };
    int length = sizeof(v_ids) / sizeof(v_ids[0]);
    // 选中当前的数据
    for (int i = 0; i < length; i++) {
        CButton* pButton = (CButton*)GetDlgItem(v_ids[i]);
        CString st;
        st.Append(L"1/");
        st.Append(to_wstring(i + 1).c_str());
        if (i + 1 == percent) {
        st.Append(to_wstring((i + 1)).c_str());
        if ((i + 1) == percent) {
            st.Append(L"※");
        }
        pButton->SetWindowTextW(st);
    }
    sellPercentMap[code] = percent;
    if (codePosition.available <= 0) {
        editLeftVolume.SetWindowTextW(L"0");
        return;
    }
    int total_count = codePosition.total / 100;
    int sell_count = total_count / percent;
    if (codePosition.available < sell_count * 100 * 2) {
        sell_count = codePosition.available / 100;
    }
    sellManager->init(code);
    if (sell_count < 1) {
        sell_count = 1;
    }
    editLeftVolume.SetWindowTextW(std::to_wstring(sell_count * 100).c_str());
    (sellManager->getSellSetting(code))->mode1_rate_index = percent;
    sellManager->syncSettingToFile(code);
    int money = sellManager->computeCurrentMoney(code);
    editSellMoney.SetWindowTextW(to_wstring( money).c_str());
}
@@ -225,23 +248,68 @@
    if (delayMs > 0) {
        Sleep(delayMs);
    }
    context->codePosition.total = 0;
    context->codePosition.available = 0;
    context->codePosition.sell_rules_count = 0;
    context->sellManager->init(code);
    try {
        string result = NetworkApi::get_code_position_info(code);
        auto doc = JsonUtil::parseUTF16(result);
        if (doc.IsObject()) {
            context->codePosition.total = doc[L"data"][L"total"].GetInt();
            context->codePosition.available = doc[L"data"][L"available"].GetInt();
            context->codePosition.sell_rules_count = doc[L"data"][L"sell_rules_count"].GetInt();
            if (doc[_T("data")].HasMember(L"code_info"))
            {
                auto data = doc[_T("data")].GetObjectW();
                CString c = data[_T("code_info")].GetArray()[0].GetString();
                wstring name = L"";
                // 获取输入框的内容
                if (context != nullptr) {
                    CString realCode;
                    context->editCode.GetWindowTextW(realCode);
                    if (c != realCode) {
                        return;
                    }
                }
            }
            int total = doc[L"data"][L"total"].GetInt();
            int available = doc[L"data"][L"available"].GetInt();
            CodePosition* codePosition = context->sellManager->getCodePosition(code);
            codePosition->total = total;
            codePosition->available = available;
            codePosition->sell_rules_count = doc[L"data"][L"sell_rules_count"].GetInt();
            codePosition->costPrice = doc[L"data"][L"cost_price"].GetFloat();
            list<int> sellVolumes;
            if (doc[L"data"].HasMember(L"sell_orders")) {
                auto sell_orders_array = doc[L"data"][L"sell_orders"].GetArray();
                for (int i = 0; i < sell_orders_array.Size(); i++) {
                    sellVolumes.push_back(sell_orders_array[i].GetInt());
                }
            }
            codePosition->sell_orders = sellVolumes;
            // TODO 测试
            //codePosition->sell_orders.clear();
            //codePosition->sell_orders.push_back(900);
            //codePosition->available = 900;
            // 设置卖框显示的内容
            if (context->sellDlgMap.find(code) != context->sellDlgMap.end()) {
                context->sellDlgMap[code]->SetPositionInfo(total, available);
            }
            //设置内容
            context->showCodePositionInfo();
            context->initSellSettingView();
            if (showCodeDesc && doc[_T("data")].HasMember(L"code_info"))
            {
                auto data = doc[_T("data")].GetObjectW();
                wstring c = data[_T("code_info")].GetArray()[0].GetString();
                CString c = data[_T("code_info")].GetArray()[0].GetString();
                wstring name = L"";
                if (!data[_T("code_info")].GetArray()[1].IsNull()) {
                    name = data[_T("code_info")].GetArray()[1].GetString();
@@ -253,13 +321,36 @@
                    CString resultC(fresult.c_str());
                    context->setMsg(resultC, MSG_TYPE_INFO, FALSE);
                }
            }
        }
    }
    catch (wstring st) {
        context->setMsg(CString(st.c_str()), MSG_TYPE_FAIL);
    }
    // 设置数据请求完毕
    if (context->requestingCode == code) {
        context->requestingCode = "";
    }
    string nowTime = TimeUtil::getNowTime("%H%M%S");
    // 09:26:00之前都是跌停价卖
    if (stoi(nowTime) < stoi("092500")) {
        context->comboSellPriceType.SetCurSel(1);
    }
    else {
        context->comboSellPriceType.SetCurSel(0);
    }
    if ((context->sellManager->getSellSetting(code))->lock) {
        context->checkLockVolume.SetCheck(TRUE);
    }
    else {
        context->checkLockVolume.SetCheck(FALSE);
    }
    int money = context->sellManager->computeCurrentMoney(code);
    context->editSellMoney.SetWindowTextW(to_wstring(money).c_str());
}
void CFloatTradeDlg::requestSellResult(int order_ref, CFloatTradeDlg* context, int delayMs)
@@ -285,11 +376,8 @@
                    msgType = MSG_TYPE_FAIL;
                }
                FloatMsg params;
                params.msg = StringUtil::cstring2String(msg);
                params.msgType = msgType;
                LPARAM lm = (LPARAM)&params;
                ::SendMessage(context->GetSafeHwnd(), WM_FLOAT_MSG, 0, lm);
                showFloatMsg(context, msg, msgType);
                CString code;
                context->editCode.GetWindowText(code);
@@ -298,51 +386,244 @@
                }
            }
            else {
                FloatMsg params;
                params.msg = StringUtil::cstring2String(doc[L"msg"].GetString());
                params.msgType = MSG_TYPE_FAIL;
                LPARAM lm = (LPARAM)&params;
                ::SendMessage(context->GetSafeHwnd(), WM_FLOAT_MSG, 0, lm);
                showFloatMsg(context,doc[L"msg"].GetString(), MSG_TYPE_FAIL);
            }
        }
    }
    catch (wstring st) {
        FloatMsg params;
        params.msg = StringUtil::cstring2String(st.c_str());
        params.msgType = MSG_TYPE_FAIL;
        LPARAM lm = (LPARAM)&params;
        ::SendMessage(context->GetSafeHwnd(), WM_FLOAT_MSG, 0, lm);
        showFloatMsg(context, st.c_str(), MSG_TYPE_FAIL);
    }
}
void CFloatTradeDlg::regularUpdatePositionInfo(CFloatTradeDlg* context)
{
    while (TRUE) {
        try {
            string nowTime = TimeUtil::getNowTime("%H%M%S");
            // 09:26:00之前都是跌停价卖
            if (stoi(nowTime) >= stoi("093000") && stoi(nowTime) <= stoi("093003")) {
                //if (stoi(nowTime) >= stoi("154000") && stoi(nowTime) <= stoi("155000")) {
                CString codew;
                context->editCode.GetWindowTextW(codew);
                if (codew.GetLength() == 6) {
                    string code = StringUtil::cstring2String(codew);
                    // 更新持仓
                    requestCodePosition(code, context, FALSE);
                }
            }
        }
        catch (...) {
        }
        Sleep(1000);
    }
}
void CFloatTradeDlg::runPushMsgHeart(CFloatTradeDlg* context, SOCKET socket)
{
    while (TRUE) {
        rapidjson::StringBuffer buf;
        rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
        writer.StartObject();
        writer.Key("type");
        writer.String("heart");
        writer.Key("data");
        writer.StartObject();
        writer.EndObject();
        writer.EndObject();
        string json_content = buf.GetString();
        string data = NetworkApi::load_request_data(json_content);
        try {
            int result = send(socket, data.c_str(), strlen(data.c_str()), 0);
            if (result < 0) {
                throw string("发送失败");
            }
        }
        catch (...) {
            break;
        }
        Sleep(5*1000);
    }
}
void CFloatTradeDlg::runPushMsgReceiver(CFloatTradeDlg* context)
{
    while (TRUE) {
        try {
            SOCKET socket = SocketManager::createSocket();
            rapidjson::StringBuffer buf;
            rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
            writer.StartObject();
            writer.Key("type");
            writer.String("register_msg_receiver");
            writer.Key("data");
            writer.StartObject();
            writer.Key("types");
            writer.StartArray();
            writer.String("order_almost_deal");
            writer.String("delegate_order_danger");
            writer.EndArray();
            writer.EndObject();
            writer.EndObject();
            string json_content = buf.GetString();
            string data = NetworkApi::load_request_data(json_content);
            SocketManager::sendMsg(socket, data.c_str());
            std::thread t1(runPushMsgHeart, context, socket);
            t1.detach();
            // 注册成功
            while (TRUE) {
                // 接收消息
                string result = SocketManager::receiveMsg(socket);
                auto doc = JsonUtil::parseUTF16(result);
                if (doc.IsObject() && doc[L"code"] == 0) {
                    if (doc.HasMember(L"data")) {
                        CString type = doc[L"data"][L"type"].GetString();
                        if (type == L"order_almost_deal") {
                            auto data = doc[L"data"][L"data"].GetObjectW();
                            if (data.HasMember(L"code") && data.HasMember(L"code_name"))
                            {
                                CString st;
                                st.Append(data[L"code"].GetString());
                                st.Append(L" ");
                                st.Append(data[L"code_name"].GetString());
                                st.Append(L" 即将买入:");
                                st.Append(data[L"msg"].GetString());
                                std::thread t1(context->showFloatMsg, context, st, MSG_TYPE_WARNING,5000, TipDlg::POSITION_RIGHT_BOTTOM);
                                t1.detach();
                            }
                        }
                        else if (type == L"delegate_order_danger") {
                            auto data = doc[L"data"][L"data"].GetObjectW();
                            if (data.HasMember(L"code") && data.HasMember(L"code_name"))
                            {
                                CString st;
                                st.Append(data[L"code"].GetString());
                                st.Append(L" ");
                                st.Append(data[L"code_name"].GetString());
                                st.Append(L" 封单不足:");
                                st.Append(data[L"msg"].GetString());
                                std::thread t1(context->showFloatMsg, context, st, MSG_TYPE_WARNING, 5000, TipDlg::POSITION_RIGHT_BOTTOM);
                                t1.detach();
                            }
                        }
                    }
                }
                cout << result << endl;
            }
        }
        catch (...) {
            Sleep(1000);
        }
    }
}
void CFloatTradeDlg::startShake(CFloatTradeDlg* context, CString text)
{
    context->mfcBtnFlashInfo.SetWindowTextW(text);
    COLORREF colors[] = { RGB(255, 0, 0),RGB(0, 255, 0),RGB(0, 0, 255) };
    for (int i = 0; i < 100; i++) {
        COLORREF color = colors[i % 3];
        context->mfcBtnFlashInfo.SetTextColor(color);
        context->mfcBtnFlashInfo.Invalidate();
        Sleep(100);
    }
    context->mfcBtnFlashInfo.SetWindowTextW(L"");
}
void CFloatTradeDlg::showCodePositionInfo()
{
    labelTotalPosition.SetWindowTextW(std::to_wstring(codePosition.total).c_str());
    labelSelledVolume.SetWindowTextW(std::to_wstring(codePosition.total - codePosition.available).c_str());
    editLeftVolume.SetWindowTextW(std::to_wstring(codePosition.available).c_str());
    if (codePosition.sell_rules_count > 0) {
        btnSellRule.SetWindowTextW(L"盯板上卖※");
    string code = getInputCode();
    sellManager->init(code);
    CodePosition* codePosition = sellManager->getCodePosition(code);
    SellSetting* sellSetting = sellManager->getSellSetting(code);
    if (codePosition->sell_rules_count > 0) {
        btnSellRule.SetWindowTextW(L"条件单※");
    }
    else {
        btnSellRule.SetWindowTextW(L"盯板上卖");
        btnSellRule.SetWindowTextW(L"条件单");
    }
    CString codew;
    editCode.GetWindowTextW(codew);
    string code = StringUtil::cstring2String(codew);
    CString totalStr ;
    totalStr.Append(L"¥");
    totalStr.Append(std::to_wstring((int)(codePosition->total * codePosition->costPrice * 100) / 100).c_str());
    labelTotalPosition.SetWindowTextW(totalStr);
    if (sellPercentMap.find(code) != sellPercentMap.end()) {
        selectSellVolume(code, sellPercentMap[code]);
    CString availableStr;
    availableStr.Append(L"¥");
    availableStr.Append(std::to_wstring((int)(codePosition->available * codePosition->costPrice * 100) / 100).c_str());
    labelSelledVolume.SetWindowTextW(availableStr);
    fillSellMoney(code, codePosition->available);
    if (sellSetting->setting_mode == SETTING_MODE_RATE) {
        selectSellRateIndex(code, sellSetting->mode1_rate_index);
        radioSell1.SetCheck(TRUE);
        radioSell2.SetCheck(FALSE);
    }
    else {
        if (codePosition.total - codePosition.available > 0)
        {
            selectSellVolume(code, 1);
        int money = sellManager->computeCurrentMoney(code);
        editSellMoney.SetWindowTextW(to_wstring(money).c_str());
        comboSellFirst.SetCurSel(sellSetting->mode2_first_index);
        comboSellLeft.SetCurSel(sellSetting->mode2_left_index);
        radioSell1.SetCheck(FALSE);
        radioSell2.SetCheck(TRUE);
    }
    checkLockBuyVolume.SetCheck(sellSetting->lockBuy);
    if (sellSetting->lockBuy) {
        if (sellSetting->lockBuyMoney > 0) {
            editBuyMoney.SetWindowTextW(to_wstring(sellSetting->lockBuyMoney).c_str());
        }
    }
    else {
        string nowTime = TimeUtil::getNowTime("%H%M%S");
        // 09:25:00之前都是跌停价卖
        if (stoi(nowTime) < stoi("093000")) {
            editBuyMoney.SetWindowTextW(std::to_wstring((int)(codePosition->total * codePosition->costPrice * 100) / 100).c_str());
        }
        else {
            selectSellVolume(code, 2);
            editBuyMoney.SetWindowTextW(L"");
        }
    }
}
list<UINT> CFloatTradeDlg::distributeVolume(UINT total, UINT percent)
{
    list<UINT> volumeList;
    UINT base = total / percent;
    UINT left = total % percent;
    for (UINT i = 0; i < percent; i++) {
        if (i + 1 <= left) {
            volumeList.push_back(base + 1);
        }
        else {
            volumeList.push_back(base);
        }
    }
    return volumeList;
}
UINT CFloatTradeDlg::computeSellVolume(list<UINT> volumeList, list<int> sell_volumes)
{
    if (sell_volumes.size() >= volumeList.size()) {
        return 0;
    }
    list<UINT>::iterator el = volumeList.begin();
    advance(el, sell_volumes.size());
    if (el != volumeList.end()) {
        return *el;
    }
    return 0;
}
CFloatTradeDlg::CFloatTradeDlg(CWnd* pParent /*=nullptr*/)
@@ -360,7 +641,7 @@
    //DDX_Control(pDX, btn_buy_mode_want, btnBuyModeWant);
    //DDX_Control(pDX, btn_buy_mode_all, btnBuyModeAll);
    DDX_Control(pDX, check_auto_refresh, checkAutoRefresh);
    DDX_Control(pDX, check_auto_click, checkAutoClick);
    DDX_Control(pDX, check_auto_click, checkAutoCancelSell);
    DDX_Control(pDX, check_trade_quick_key, checkTradeQuickKey);
    DDX_Control(pDX, btn_white_list, whiteList);
    DDX_Control(pDX, btn_black_list, blackList);
@@ -372,9 +653,18 @@
    //DDX_Control(pDX, btn_buy, btnBuy);
    DDX_Control(pDX, IDC_STATIC_TOTAL_POSITION, labelTotalPosition);
    DDX_Control(pDX, IDC_STATIC_ALREADY_SELL, labelSelledVolume);
    DDX_Control(pDX, IDC_EDIT_SELL_VOLUME, editLeftVolume);
    DDX_Control(pDX, IDC_EDIT_SELL_VOLUME, editSellMoney);
    DDX_Control(pDX, IDC_COMBO_SELL_PRICE, comboSellPriceType);
    DDX_Control(pDX, btn_code_trade_info, btnSellRule);
    DDX_Control(pDX, IDC_CHECK_LOCK_SELL_VOLUME, checkLockVolume);
    DDX_Control(pDX, IDC_COMBO_SELL_FIRST, comboSellFirst);
    DDX_Control(pDX, IDC_COMBO_SELL_LEFT, comboSellLeft);
    DDX_Control(pDX, IDC_RADIO1, radioSell1);
    DDX_Control(pDX, IDC_RADIO2, radioSell2);
    DDX_Control(pDX, IDC_CHECK_MARKET_SITUATION, checkMarketSituation);
    DDX_Control(pDX, IDC_MFCBUTTON_FLASH_INFO, mfcBtnFlashInfo);
    DDX_Control(pDX, IDC_CHECK_LOCK_BUY_VOLUME, checkLockBuyVolume);
    DDX_Control(pDX, IDC_EDIT_BUY_VOLUME, editBuyMoney);
}
BEGIN_MESSAGE_MAP(CFloatTradeDlg, CDialogEx)
@@ -387,8 +677,8 @@
    ON_BN_CLICKED(btn_buy_mode_want, &CFloatTradeDlg::OnClickedBtnBuyModeWant)
    ON_BN_CLICKED(btn_close_buy, &CFloatTradeDlg::OnClickedBtnCloseBuy)
    ON_BN_CLICKED(btn_open_buy, &CFloatTradeDlg::OnClickedBtnOpenBuy)
    ON_BN_CLICKED(btn_pause_buy, &CFloatTradeDlg::OnClickedBtnPauseBuy)
    ON_BN_CLICKED(btn_pause_buy_remove, &CFloatTradeDlg::OnClickedBtnPauseBuyRemove)
    //ON_BN_CLICKED(btn_pause_buy, &CFloatTradeDlg::OnClickedBtnPauseBuy)
    //ON_BN_CLICKED(btn_pause_buy_remove, &CFloatTradeDlg::OnClickedBtnPauseBuyRemove)
    ON_BN_CLICKED(btn_remove_black, &CFloatTradeDlg::OnClickedBtnRemoveBlack)
    ON_BN_CLICKED(btn_remove_white, &CFloatTradeDlg::OnClickedBtnRemoveWhite)
    ON_BN_CLICKED(btn_sell, &CFloatTradeDlg::OnClickedBtnSell)
@@ -400,7 +690,7 @@
    ON_BN_CLICKED(check_trade_quick_key, &CFloatTradeDlg::OnClickedCheckTradeQuickKey)
    ON_WM_COPYDATA()
    ON_BN_CLICKED(btn_want_list, &CFloatTradeDlg::OnBnClickedwantlist)
    ON_BN_CLICKED(btn_pause_buy_list, &CFloatTradeDlg::OnBnClickedpausebuylist)
    //ON_BN_CLICKED(btn_pause_buy_list, &CFloatTradeDlg::OnBnClickedpausebuylist)
    ON_BN_CLICKED(btn_black_list, &CFloatTradeDlg::OnBnClickedblacklist)
    ON_BN_CLICKED(btn_white_list, &CFloatTradeDlg::OnBnClickedwhitelist)
    ON_WM_CLOSE()
@@ -413,14 +703,26 @@
    ON_BN_CLICKED(IDC_BUTTON_SELL_VOLUME_3, &CFloatTradeDlg::OnBnClickedButtonSellVolume1)
    ON_BN_CLICKED(IDC_BUTTON_SELL_VOLUME_4, &CFloatTradeDlg::OnBnClickedButtonSellVolume1)
    ON_BN_CLICKED(IDC_BUTTON_SELL_VOLUME_5, &CFloatTradeDlg::OnBnClickedButtonSellVolume1)
    ON_BN_CLICKED(IDC_BUTTON_SELL_VOLUME_6, &CFloatTradeDlg::OnBnClickedButtonSellVolume1)
    ON_BN_CLICKED(IDC_BUTTON_SELL_VOLUME_7, &CFloatTradeDlg::OnBnClickedButtonSellVolume1)
    ON_BN_CLICKED(IDC_BUTTON_SELL_VOLUME_8, &CFloatTradeDlg::OnBnClickedButtonSellVolume1)
    ON_BN_CLICKED(IDC_BUTTON_SELL_VOLUME_9, &CFloatTradeDlg::OnBnClickedButtonSellVolume1)
    ON_BN_CLICKED(IDC_BUTTON_SELL_VOLUME_10, &CFloatTradeDlg::OnBnClickedButtonSellVolume1)
    ON_BN_CLICKED(IDC_BUTTON_REFRESH, &CFloatTradeDlg::OnBnClickedButtonRefresh)
    ON_BN_CLICKED(IDC_BUTTON_MUST_LIST, &CFloatTradeDlg::OnBnClickedmustlist)
    ON_BN_CLICKED(IDC_BUTTON_ADD_MUST, &CFloatTradeDlg::OnBnClickedmust)
    ON_BN_CLICKED(IDC_BUTTON_REMOVE_MUST, &CFloatTradeDlg::OnBnClickedremovefrommust)
    ON_MESSAGE(WM_FLOAT_MSG, &CFloatTradeDlg::OnFloatMsg)
END_MESSAGE_MAP()
    ON_BN_CLICKED(IDC_CHECK_LOCK_SELL_VOLUME, &CFloatTradeDlg::OnBnClickedCheckLockSellVolume)
    ON_BN_CLICKED(IDC_RADIO2, &CFloatTradeDlg::OnBnClickedRadio2)
    ON_BN_CLICKED(IDC_RADIO1, &CFloatTradeDlg::OnBnClickedRadio1)
    ON_BN_CLICKED(IDC_CHECK_MARKET_SITUATION, &CFloatTradeDlg::OnBnClickedCheckMarketSituation)
    ON_CBN_SELCHANGE(IDC_COMBO_SELL_FIRST, &CFloatTradeDlg::OnCbnSelchangeComboSellFirst)
    ON_CBN_SELCHANGE(IDC_COMBO_SELL_LEFT, &CFloatTradeDlg::OnCbnSelchangeComboSellLeft)
    ON_BN_CLICKED(IDC_BUTTON_ADD_WANT, &CFloatTradeDlg::OnBnClickedButtonAddWant)
    ON_BN_CLICKED(IDC_BUTTON_REMOVE_WANT, &CFloatTradeDlg::OnBnClickedButtonRemoveWant)
    ON_BN_CLICKED(IDC_BUTTON_WANT_LIST, &CFloatTradeDlg::OnBnClickedButtonWantList)
    ON_BN_CLICKED(IDC_BUTTON_GET_POSITIONS, &CFloatTradeDlg::OnBnClickedButtonGetPositions)
    ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_VOLUME, &CFloatTradeDlg::OnDeltaposSpinVolume)
    ON_BN_CLICKED(IDC_CHECK_LOCK_BUY_VOLUME, &CFloatTradeDlg::OnBnClickedCheckLockBuyVolume)
    ON_WM_KEYDOWN()
END_MESSAGE_MAP()
// CFloatTradeDlg 消息处理程序
@@ -442,24 +744,20 @@
    btnSell.SetFont(&bigFont, FALSE);
    //btnBuy.SetFont(&bigFont, FALSE);
    mfcBtnFlashInfo.SetTextColor(RGB(255, 0, 0));
}
void CFloatTradeDlg::initData()
{
    sellManager = new SellManager();
    buyWin = 0;
    requestingCode = "";
    if (ConfigUtil::isTradeRefresh()) {
        checkAutoRefresh.SetCheck(TRUE);
    }
    else {
        checkAutoRefresh.SetCheck(FALSE);
    }
    if (ConfigUtil::isGroupRefresh()) {
        checkAutoClick.SetCheck(TRUE);
    }
    else {
        checkAutoClick.SetCheck(FALSE);
    }
    if (ConfigUtil::isTradeQuickKey()) {
@@ -469,19 +767,26 @@
        checkTradeQuickKey.SetCheck(FALSE);
    }
    // 初始化刷新频率
    HWND hWnd = CWnd::GetSafeHwnd();
    //设置热键
    RegisterHotKey(hWnd, HOT_KEY_SELL_ALL, MOD_SHIFT, VK_F1);
    RegisterHotKey(hWnd, HOT_KEY_SELL_ALL, MOD_SHIFT, VK_F10);
    RegisterHotKey(hWnd, HOT_KEY_CANCEL, MOD_SHIFT, VK_F5);
    RegisterHotKey(hWnd, HOT_KEY_BUY, MOD_SHIFT, VK_F12);
    RegisterHotKey(hWnd, HOT_KEY_BUY, MOD_SHIFT, VK_F9);
    //置顶
    SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
    //请求网络数据
    std::thread t1(getTradeState, this);
    t1.detach();
    std::thread t2(getTradeMode, this);
    t2.detach();
    std::thread t22(getAutoCancelSellMode, this);
    t22.detach();
    //启动交易刷新
    std::thread t3(ThsUtil::run_trade_refresh);
@@ -490,6 +795,10 @@
    //启动分组刷新
    std::thread t4(ThsUtil::run_group_refresh);
    t4.detach();
    // 获取市场行情
    std::thread t5(getMarketSituation, this);
    t5.detach();
    // 设置位置
@@ -504,9 +813,33 @@
    comboSellPriceType.AddString(_T("买5价"));
    comboSellPriceType.SetCurSel(0);
    codePosition.available = 0;
    codePosition.total = 0;
    codePosition.sell_rules_count = 0;
    for (int i = 0; i < 10; i++) {
        CString st = L"";
        st.Append(to_wstring((i + 1) * 10).c_str());
        st.Append(L"%");
        comboSellFirst.AddString(st);
    }
    comboSellFirst.SetCurSel(4);
    for (int i = 0; i < 10; i++) {
        CString st = L"";
        st.Append(to_wstring((i + 1)).c_str());
        st.Append(L"笔卖");
        comboSellLeft.AddString(st);
    }
    comboSellLeft.SetCurSel(1);
    radioSell2.SetCheck(TRUE);
    comboSellFirst.EnableWindow(FALSE);
    radioSell1.EnableWindow(FALSE);
    radioSell2.EnableWindow(FALSE);
    std::thread thread_ru(regularUpdatePositionInfo, this);
    thread_ru.detach();
    std::thread thread_push_msg_receive(runPushMsgReceiver, this);
    thread_push_msg_receive.detach();
}
@@ -554,7 +887,7 @@
    }
    else if (nHotKeyId == HOT_KEY_BUY) {
        cout << "买入" << endl;
        OnBnClickedbuy();
        buy();
    }
}
@@ -599,6 +932,9 @@
void CFloatTradeDlg::OnClickedBtnAlreadyCanceled()
{
    // showTips(L"这是条测试消息~~~~~~~", MSG_TYPE_FAIL,1000);
    //list<HWND> hwnds = Win32Util::searchWindow("副屏1");
    //HWND hwnd = *(hwnds.begin());
    //::SetWindowPos(hwnd, HWND_TOPMOST,0,0,0,0, SWP_NOMOVE | SWP_NOSIZE);
@@ -792,37 +1128,20 @@
void CFloatTradeDlg::OnClickedBtnSell()
{
    bool IS_TEST = FALSE;
    if (codePosition.total <= 0) {
        setMsg(L"无持仓", MSG_TYPE_FAIL);
    if (requestingCode.size() >= 6) {
        showTips(L"持仓请求未结束(150ms以后才能卖)", MSG_TYPE_FAIL, 1000);
        return;
    }
    if (codePosition.available <= 0) {
        setMsg(L"已卖完", MSG_TYPE_FAIL);
    CString sell_money;
    editSellMoney.GetWindowTextW(sell_money);
    if (!StringUtil::isNumber(StringUtil::cstring2String(sell_money))) {
        showTips(L"卖金额输入错误", MSG_TYPE_FAIL, 1000);
        return;
    }
    CString sell_volume;
    editLeftVolume.GetWindowTextW(sell_volume);
    if (!StringUtil::isNumber(StringUtil::cstring2String(sell_volume))) {
        setMsg(L"卖量输入错误", MSG_TYPE_FAIL);
        return;
    }
    int sell_volume_int = stoi(StringUtil::cstring2String(sell_volume));
    if (sell_volume_int <= 0) {
        setMsg(L"卖量不能为0", MSG_TYPE_FAIL);
        return;
    }
    if (sell_volume_int % 100 != 0) {
        setMsg(L"卖量必须为100的整数倍", MSG_TYPE_FAIL);
        return;
    }
    //0-价格笼子 1-跌停价  2-涨停价 3-现价
    int sellPriceType = comboSellPriceType.GetCurSel();
    if (sellPriceType < 0 || sellPriceType > 10) {
        setMsg(L"请选择卖价类型", MSG_TYPE_FAIL);
    int sell_money_int = stoi(StringUtil::cstring2String(sell_money));
    if (sell_money_int <= 0) {
        showTips(L"卖金额不能为0", MSG_TYPE_FAIL, 1000);
        return;
    }
@@ -830,40 +1149,24 @@
    // 卖
    try {
        string code = getCode();
        string result = NetworkApi::sell(code, sell_volume_int, sellPriceType, true);
        /*string result = string(StringUtil::cstring2String(L"{\"code\":0,\"data\":{\"sinfo\": \"b_600088_1701739811583\", \"securityID\": \"600088\", \"orderLocalID\": \"0190000205\", \"direction\": \"1\", \"orderSysID\": \"110010190000205\", \"insertTime\": \"09:30 : 11\", \"insertDate\": \"20231205\", \"acceptTime\": \"09 : 30 : 11\", \"cancelTime\": \"\", \"limitPrice\": 15.0, \"accountID\": \"38800001334901\", \"orderRef\": 81740, \"turnover\": 0.0, \"volume\": 200, \"volumeTraded\": 0, \"orderStatus\": \"2\", \"orderSubmitStatus\": \"1\", \"statusMsg\": \"\"}}"));*/
        CString msg(code.c_str());
        msg.Append(L":");
        auto doc = JsonUtil::parseUTF16(result);
        if (doc.IsObject() && doc.HasMember(L"code")) {
            if (doc[L"code"] == 0) {
                if (doc[L"data"].HasMember(L"orderRef")) {
                    msg.Append(_T("提交卖成功"));
                    setMsg(msg, MSG_TYPE_SUCCESS);
                    int orderRef = doc[L"data"][L"orderRef"].GetInt();
                    std::thread t1(requestSellResult, orderRef, this, 2000);
                    t1.detach();
                }
                else if (doc[L"data"].HasMember(L"orderStatusMsg")) {
                    msg.Append(doc[L"data"][L"orderStatusMsg"].GetString());
                    setMsg(msg, MSG_TYPE_FAIL);
                }
            }
            else {
                if (doc.HasMember(L"msg")) {
                    msg.Append(doc[L"msg"].GetString());
                    setMsg(msg, MSG_TYPE_FAIL);
                }
        int sell_volume_int = sellMoneyToVolume(code, sell_money_int);
        if (sell_volume_int == 0) {
            sell_volume_int = 100;
        }
        // 获取持仓
        CodePosition*  pos = sellManager->getCodePosition(code);
        if (pos != nullptr) {
            if (pos->available > 0 && sell_volume_int > pos->available) {
                // 卖剩余的所有
                sell_volume_int = pos->available;
            }
        }
        else {
            msg.Append(L"解析结果出错");
            setMsg(msg, MSG_TYPE_FAIL);
        }
        sell(code, sell_volume_int, this);
    }
    catch (wstring st) {
        CString msg(st.c_str());
        setMsg(msg, MSG_TYPE_FAIL);
        //setMsg(msg, MSG_TYPE_FAIL);
        showTips(msg, MSG_TYPE_FAIL, 1000);
    }
}
@@ -918,12 +1221,77 @@
    }
}
void CFloatTradeDlg::OnBnClickedmustlist()
{
    try {
        std::list<wstring> wlist = NetworkApi::list_must_buy();
        MessageBox(formatListResult(wlist), TEXT("红名单"), MB_TASKMODAL);
    }
    catch (wstring st) {
        CString cs(st.c_str());
        AfxMessageBox(cs);
    }
}
void CFloatTradeDlg::OnBnClickedmust()
{
    try {
        string code = getCode();
        NetworkApi::add_must_buy(code);
        CString msg(code.c_str());
        msg.Append(_T("加入红名单成功"));
        setMsg(msg, MSG_TYPE_SUCCESS);
    }
    catch (wstring st) {
        CString msg(st.c_str());
        setMsg(msg, MSG_TYPE_FAIL);
    }
}
void CFloatTradeDlg::OnBnClickedremovefrommust()
{
    // 移除白名单
    try {
        string code = getCode();
        NetworkApi::remove_must_buy(code);
        CString msg(code.c_str());
        msg.Append(_T("移除红名单成功"));
        setMsg(msg, MSG_TYPE_SUCCESS);
    }
    catch (wstring st) {
        CString msg(st.c_str());
        setMsg(msg, MSG_TYPE_FAIL);
    }
}
void CFloatTradeDlg::OnClickedCheckAutoClick()
{
    // 分组刷新
    ConfigUtil::setGroupRefresh(checkAutoClick.GetCheck());
    if (checkAutoCancelSell.GetCheck()) {
        // 撤所有
        try {
            NetworkApi::set_auto_cancel_sell_mode(0);
        }
        catch (wstring msg) {
            checkAutoCancelSell.SetCheck(FALSE);
            AfxMessageBox(msg.c_str());
        }
    }
    else {
        // 撤机器
        try {
            NetworkApi::set_auto_cancel_sell_mode(1);
        }
        catch (wstring msg) {
            checkAutoCancelSell.SetCheck(TRUE);
            AfxMessageBox(msg.c_str());
        }
    }
}
@@ -946,14 +1314,14 @@
    FloatMsg* pData = (FloatMsg*)lParam;
    showTips(CString(pData->msg.c_str()), pData->msgType);
    showTips(CString(pData->msg.c_str()), pData->msgType, pData->showMS, pData->position);
    return LRESULT();
}
CString formatListResult(std::list<wstring> wlist) {
CString CFloatTradeDlg::formatListResult(std::list<wstring> wlist) {
    CString st;
    int index = 0;
    for (std::list<wstring>::iterator ele = wlist.begin(); ele != wlist.end(); ++ele) {
@@ -969,6 +1337,249 @@
        index++;
    }
    return st;
}
void CFloatTradeDlg::initSellSettingView()
{
    SellSettingView sellSettingView;
    int mode = 0;
    if (radioSell1.GetCheck()) {
        mode = 1;
    }
    else if (radioSell2.GetCheck()) {
        mode = 2;
    }
    string code = "";
    try {
        code = getInputCode();
    }
    catch (...) {
        return;
    }
    // ---设置UI参数---
    CodePosition* codePosition = sellManager->getCodePosition(code);
    if (codePosition->sell_orders.size() > 0) {
        sellSettingView.mode = FALSE;
    }
    else {
        sellSettingView.mode = TRUE;
    }
    if (codePosition->sell_orders.size() >= 1 || mode != 2) {
        sellSettingView.mode2_first = FALSE;
    }
    else {
        sellSettingView.mode2_first = TRUE;
    }
    if (codePosition->sell_orders.size() >= 2 || mode != 2) {
        sellSettingView.mode2_left = FALSE;
    }
    else {
        sellSettingView.mode2_left = TRUE;
    }
    if (mode != 1 || codePosition->sell_orders.size() > 0) {
        sellSettingView.mode1_percent = FALSE;
    }
    else {
        sellSettingView.mode1_percent = TRUE;
    }
    // ---更新UI---
    if (sellSettingView.mode) {
        radioSell1.EnableWindow(TRUE);
        radioSell2.EnableWindow(TRUE);
    }
    else {
        radioSell1.EnableWindow(FALSE);
        radioSell2.EnableWindow(FALSE);
    }
    int  v_ids[] = { IDC_BUTTON_SELL_VOLUME_1,IDC_BUTTON_SELL_VOLUME_2,IDC_BUTTON_SELL_VOLUME_3,IDC_BUTTON_SELL_VOLUME_4,IDC_BUTTON_SELL_VOLUME_5 };
    int length = sizeof(v_ids) / sizeof(v_ids[0]);
    for (int i = 0; i < length; i++) {
        CWnd* pButtonWnd = GetDlgItem(v_ids[i]);
        if (sellSettingView.mode1_percent) {
            pButtonWnd->EnableWindow(TRUE);
        }
        else {
            pButtonWnd->EnableWindow(FALSE);
        }
    }
    if (sellSettingView.mode2_first) {
        comboSellFirst.EnableWindow(TRUE);
    }
    else {
        comboSellFirst.EnableWindow(FALSE);
    }
    if (sellSettingView.mode2_left) {
        comboSellLeft.EnableWindow(TRUE);
    }
    else {
        comboSellLeft.EnableWindow(FALSE);
    }
}
string CFloatTradeDlg::getInputCode()
{
    CString codew;
    editCode.GetWindowTextW(codew);
    if (codew.GetLength() != 6) {
        throw wstring(L"代码输入错误");
    }
    return StringUtil::cstring2String(codew);
}
void CFloatTradeDlg::OnSellCallback(string code, CWnd* context)
{
    CFloatTradeDlg* dlg = ((CFloatTradeDlg*)context);
    try {
        dlg->sell(code, dlg);
    }
    catch (wstring msg) {
        dlg->showTips(msg.c_str(), MSG_TYPE_FAIL);
    }
}
void CFloatTradeDlg::OnSellCloseCallback(string code, CWnd* context)
{
    SellDlg* dlg = ((CFloatTradeDlg*)context)->sellDlgMap[code];
    dlg->CloseWindow();
    delete dlg;
    ((CFloatTradeDlg*)context)->sellDlgMap.erase(code);
}
void CFloatTradeDlg::sell(string code, int volume, CFloatTradeDlg* context)
{
    //0-价格笼子 1-跌停价  2-涨停价 3-现价
    int sellPriceType = context->comboSellPriceType.GetCurSel();
    if (sellPriceType < 0 || sellPriceType > 10) {
        context->showTips(L"请选择卖价类型", MSG_TYPE_FAIL, 1000);
        return;
    }
    string nowTime = TimeUtil::getNowTime("%H%M%S");
    // 09:25:00之前都是跌停价卖
    if (stoi(nowTime) >= stoi("092500")) {
        if (sellPriceType == 1) {
            sellPriceType = 0;
            context->comboSellPriceType.SetCurSel(0);
        }
    }
    // 卖
    try {
        int orderRef = context->sellManager->sell(code, volume, sellPriceType);
        std::thread t1(context->requestSellResult, orderRef, context, 2000);
        t1.detach();
        context->showTips(L"卖提交成功", MSG_TYPE_SUCCESS, 1000);
    }
    catch (wstring st) {
        CString msg(st.c_str());
        //setMsg(msg, MSG_TYPE_FAIL);
        context->showTips(msg, MSG_TYPE_FAIL, 1000);
    }
}
void CFloatTradeDlg::sell(string code, CFloatTradeDlg* dlg)
{
    //0-价格笼子 1-跌停价  2-涨停价 3-现价
    int sellPriceType = dlg->comboSellPriceType.GetCurSel();
    if (sellPriceType < 0 || sellPriceType > 10) {
        dlg->showTips(L"请选择卖价类型", MSG_TYPE_FAIL, 1000);
        return;
    }
    string nowTime = TimeUtil::getNowTime("%H%M%S");
    // 09:25:00之前都是跌停价卖
    if (stoi(nowTime) >= stoi("092500")) {
        if (sellPriceType == 1) {
            sellPriceType = 0;
            dlg->comboSellPriceType.SetCurSel(0);
        }
    }
    // 卖
    try {
        int orderRef = dlg->sellManager->sell(code, sellPriceType);
        std::thread t1(dlg->requestSellResult, orderRef, dlg, 2000);
        t1.detach();
        dlg->showTips(L"卖提交成功", MSG_TYPE_SUCCESS, 1000);
    }
    catch (wstring st) {
        CString msg(st.c_str());
        dlg->showTips(msg, MSG_TYPE_FAIL, 1000);
    }
}
void CFloatTradeDlg::fillSellMoney(string code, int volume)
{
    CodePosition* codePosition = sellManager->getCodePosition(code);
    editSellMoney.SetWindowTextW(to_wstring( (int)(codePosition->costPrice * volume * 100) / 100).c_str());
}
int CFloatTradeDlg::sellMoneyToVolume(string code, int money)
{
    CodePosition* codePosition = sellManager->getCodePosition(code);
    int volume = ((int)round((money / codePosition->costPrice) * 100)) / 100;
    return SellManager::sellMoneyToVolume(money, codePosition->costPrice);
}
void CFloatTradeDlg::buy()
{
    try {
        string code = getInputCode();
        CString buyMoneyw;
        editBuyMoney.GetWindowTextW(buyMoneyw);
        if (buyMoneyw.GetLength() < 1) {
            throw wstring(L"请输入买入金额");
        }
        CodePosition* pos = sellManager->getCodePosition(code);
        if (pos == nullptr) {
            throw wstring(L"没有获取到现价");
        }
        int buyMoney = stoi(StringUtil::cstring2String(buyMoneyw));
        if (round(pos->costPrice) <= 0) {
            throw wstring(L"未获取到现价");
        }
        int volume = SellManager::sellMoneyToVolume(buyMoney, pos->costPrice);
        if (volume <= 0) {
            CString msg = L"买入量不能小于100(单价:";
            msg.Append(to_wstring(pos->costPrice).c_str());
            msg.Append(L")");
            throw wstring(msg);
        }
        NetworkApi::buy(code, volume, "");
        showTips(L"买入提交成功", MSG_TYPE_SUCCESS, 1000);
    }
    catch (wstring st) {
        showTips(st.c_str(), MSG_TYPE_FAIL, 1000);
    }
}
void CFloatTradeDlg::showFloatMsg(CFloatTradeDlg* context, CString msg, MSG_TYPE msgType, int showMS, int position)
{
    FloatMsg params;
    params.msg = StringUtil::cstring2String(msg);
    params.msgType = msgType;
    params.showMS = showMS;
    params.position = position;
    LPARAM lm = (LPARAM)&params;
    ::SendMessage(context->GetSafeHwnd(), WM_FLOAT_MSG, 0, lm);
}
@@ -1063,6 +1674,8 @@
            wstring codew = root[_T("data")][_T("code")].GetString();
            editCode.SetWindowTextW(codew.c_str());
            string code = StringUtil::wstringToString(codew);
            // 设置正在请求的代码
            requestingCode = code;
            //请求网络获取消息
            //std::thread t1(getCodeDesc, code, this);
@@ -1130,6 +1743,9 @@
        case label_atrribute:
            pDC->SetTextColor(msgColor);
            break;
        case IDC_STATIC_ALREADY_SELL:
            pDC->SetTextColor(RGB(255, 0, 0));
            break;
        }
    }
    return hbr;
@@ -1140,9 +1756,7 @@
{
    CString code;
    editCode.GetWindowText(code);
    CString volume;
    editLeftVolume.GetWindowText(volume);
    SellRuleDlg dlg(code, volume);
    SellRuleDlg dlg(code, 0);
    //dlg.Create(IDD_BUY,this);
    //dlg.ShowWindow(SW_SHOW);
    //return;
@@ -1153,15 +1767,346 @@
void CFloatTradeDlg::OnBnClickedButtonSellVolume1()
{
    int nID = ((CButton*)GetFocus())->GetDlgCtrlID();
    int  v_ids[] = { IDC_BUTTON_SELL_VOLUME_1,IDC_BUTTON_SELL_VOLUME_2,IDC_BUTTON_SELL_VOLUME_3,IDC_BUTTON_SELL_VOLUME_4,IDC_BUTTON_SELL_VOLUME_5,IDC_BUTTON_SELL_VOLUME_6,IDC_BUTTON_SELL_VOLUME_7,IDC_BUTTON_SELL_VOLUME_8,IDC_BUTTON_SELL_VOLUME_9,IDC_BUTTON_SELL_VOLUME_10 };
    int  v_ids[] = { IDC_BUTTON_SELL_VOLUME_1,IDC_BUTTON_SELL_VOLUME_2,IDC_BUTTON_SELL_VOLUME_3,IDC_BUTTON_SELL_VOLUME_4,IDC_BUTTON_SELL_VOLUME_5 };
    int length = sizeof(v_ids) / sizeof(v_ids[0]);
    for (int i = 0; i < length; i++) {
        if (v_ids[i] == nID) {
            CString codew;
            editCode.GetWindowTextW(codew);
            selectSellVolume(StringUtil::cstring2String(codew), i + 1);
            selectSellRateIndex(getInputCode(), i + 1);
            break;
        }
    }
}
}
void CFloatTradeDlg::OnBnClickedButtonRefresh()
{
    try {
        requestCodePosition(getInputCode(), this, TRUE);
    }
    catch (wstring msg) {
        AfxMessageBox(msg.c_str());
    }
}
void CFloatTradeDlg::OnBnClickedCheckLockSellVolume()
{
    // 锁量,
    // 判断代码是否填充
    try {
        string code = getInputCode();
        sellManager->init(code);
        if (!checkLockVolume.GetCheck()) {
            SellSetting* sellSetting = sellManager->getSellSetting(code);
            sellSetting->lock = FALSE;
            sellSetting->lockMoney = 0;
            sellManager->syncSettingToFile(code);
            return;
        }
        // 判断量是否输入
        CString sellMoneyw;
        editSellMoney.GetWindowTextW(sellMoneyw);
        string sellMoney = StringUtil::cstring2String(sellMoneyw);
        if (!StringUtil::isNumber(sellMoney)) {
            throw wstring(L"请输入正确的金额");
        }
        int sellMoney_int = stoi(sellMoney);
        SellSetting* sellSetting = sellManager->getSellSetting(code);
        sellSetting->lock = TRUE;
        sellSetting->lockMoney = sellMoney_int;
        sellManager->syncSettingToFile(code);
    }
    catch (wstring msg) {
        checkLockVolume.SetCheck(!checkLockVolume.GetCheck());
        AfxMessageBox(msg.c_str());
    }
}
void CFloatTradeDlg::OnBnClickedRadio2()
{
    radioSell1.SetCheck(FALSE);
    initSellSettingView();
    try {
        string code = getInputCode();
        sellManager->init(code);
        SellSetting* sellSetting = sellManager->getSellSetting(code);
        comboSellFirst.SetCurSel(sellSetting->mode2_first_index);
        comboSellLeft.SetCurSel(sellSetting->mode2_left_index);
        sellSetting->setting_mode = SETTING_MODE_PERCENT;
        sellManager->syncSettingToFile(code);
        showCodePositionInfo();
    }
    catch (wstring msg) {
        AfxMessageBox(msg.c_str());
    }
}
void CFloatTradeDlg::OnBnClickedRadio1()
{
    radioSell2.SetCheck(FALSE);
    initSellSettingView();
    try {
        string code = getInputCode();
        sellManager->init(code);
        SellSetting* sellSetting = sellManager->getSellSetting(code);
        sellSetting->setting_mode = SETTING_MODE_RATE;
        selectSellRateIndex(code, sellSetting->mode1_rate_index);
    }
    catch (wstring msg) {
        AfxMessageBox(msg.c_str());
    }
}
void CFloatTradeDlg::OnBnClickedCheckMarketSituation()
{
    try {
        if (checkMarketSituation.GetCheck()) {
            NetworkApi::set_market_situation(2);
        }
        else {
            NetworkApi::set_market_situation(0);
        }
    }
    catch (wstring msg) {
        checkMarketSituation.SetCheck(!checkMarketSituation.GetCheck());
        AfxMessageBox(msg.c_str());
    }
}
void CFloatTradeDlg::OnCbnSelchangeComboSellFirst()
{
    try {
        string code = getInputCode();
        sellManager->init(code);
        SellSetting* sellSetting = sellManager->getSellSetting(code);
        sellSetting->mode2_first_index = comboSellFirst.GetCurSel();
        sellManager->syncSettingToFile(code);
        showCodePositionInfo();
    }
    catch (wstring msg) {
        AfxMessageBox(msg.c_str());
    }
}
void CFloatTradeDlg::OnCbnSelchangeComboSellLeft()
{
    try {
        string code = getInputCode();
        sellManager->init(code);
        SellSetting* sellSetting = sellManager->getSellSetting(code);
        sellSetting->mode2_left_index = comboSellLeft.GetCurSel();
        sellManager->syncSettingToFile(code);
        showCodePositionInfo();
    }
    catch (wstring msg) {
        AfxMessageBox(msg.c_str());
    }
}
void CFloatTradeDlg::OnBnClickedButtonAddWant()
{
    try {
        string code = getCode();
        NetworkApi::add_want_buy(code);
        CString msg(code.c_str());
        msg.Append(_T("加入想买单成功"));
        setMsg(msg, MSG_TYPE_SUCCESS);
    }
    catch (wstring st) {
        CString msg(st.c_str());
        setMsg(msg, MSG_TYPE_FAIL);
    }
}
void CFloatTradeDlg::OnBnClickedButtonRemoveWant()
{
    try {
        string code = getCode();
        NetworkApi::remove_want_buy(code);
        CString msg(code.c_str());
        msg.Append(_T("移除想买单成功"));
        setMsg(msg, MSG_TYPE_SUCCESS);
    }
    catch (wstring st) {
        CString msg(st.c_str());
        setMsg(msg, MSG_TYPE_FAIL);
    }
}
void CFloatTradeDlg::OnBnClickedButtonWantList()
{
    try {
        std::list<wstring> wlist = NetworkApi::list_want_buy();
        MessageBox(formatListResult(wlist), TEXT("想买单"), MB_TASKMODAL);
    }
    catch (wstring st) {
        CString cs(st.c_str());
        AfxMessageBox(cs);
    }
}
void CFloatTradeDlg::OnBnClickedButtonGetPositions()
{
    string result = NetworkApi::get_all_positions();
    auto doc = JsonUtil::parseUTF16(result);
    if (doc.IsObject() && doc[L"code"] == 0) {
        auto array = doc[L"data"].GetArray();
        for (int i = 0; i < array.Size(); i++) {
            auto  data = array[i].GetObjectW();
            CString codew = data[L"code"].GetString();
            string code = StringUtil::cstring2String(codew);
            CString codeName = data[L"code_name"].GetString();
            CodePosition position;
            position.total = data[L"total"].GetInt();
            position.available = data[L"available"].GetInt();
            if (sellDlgMap.find(code) == sellDlgMap.end())
            {
                SellDlg* dlg = new SellDlg(code, codeName, position, OnSellCallback, OnSellCloseCallback, this);
                dlg->Create(IDD_DIALOG_SELL, this);
                dlg->ShowWindow(SW_SHOW);
                sellDlgMap[code] = dlg;
            }
            else {
                sellDlgMap[code]->ShowWindow(SW_SHOW);
            }
        }
    }
    cout << result << endl;
}
void CFloatTradeDlg::OnDeltaposSpinVolume(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
    try {
        CString st;
        editSellMoney.GetWindowTextW(st);
        int old = stoi(StringUtil::cstring2String(st));
        if (pNMUpDown->iDelta < 0) {
            st = std::to_wstring(old + 1000).c_str();
        }
        else {
            if (old >= 1000)
            {
                st = std::to_wstring(old - 1000).c_str();
            }
            else {
                st = std::to_wstring(0).c_str();
            }
        }
        editSellMoney.SetWindowTextW(st);
    }
    catch (...) {
    }
    *pResult = 0;
}
void CFloatTradeDlg::OnBnClickedCheckLockBuyVolume()
{
    // 锁量,
    // 判断代码是否填充
    try {
        string code = getInputCode();
        sellManager->init(code);
        if (!checkLockBuyVolume.GetCheck()) {
            SellSetting* sellSetting = sellManager->getSellSetting(code);
            sellSetting->lockBuy = FALSE;
            sellSetting->lockBuyMoney = 0;
            sellManager->syncSettingToFile(code);
            return;
        }
        // 判断量是否输入
        CString buyMoneyw;
        editBuyMoney.GetWindowTextW(buyMoneyw);
        string buyMoney = StringUtil::cstring2String(buyMoneyw);
        if (buyMoney.length()==0|| !StringUtil::isNumber(buyMoney)) {
            throw wstring(L"请输入正确的金额");
        }
        int buyMoney_int = stoi(buyMoney);
        SellSetting* sellSetting = sellManager->getSellSetting(code);
        sellSetting->lockBuy = TRUE;
        sellSetting->lockBuyMoney = buyMoney_int;
        sellManager->syncSettingToFile(code);
    }
    catch (wstring msg) {
        checkLockBuyVolume.SetCheck(!checkLockBuyVolume.GetCheck());
        AfxMessageBox(msg.c_str());
    }
}
BOOL CFloatTradeDlg::PreTranslateMessage(MSG* pMsg)
{
    if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN) // 按下 Enter 键
    {
        // 关闭窗口
        // EndDialog(IDOK);
        if (CWnd::GetFocus() == GetDlgItem(IDC_EDIT_SELL_VOLUME)) {
            if (checkLockVolume.GetCheck()) {
                // 保存锁定的金额
                try {
                    string code = getInputCode();
                    CString sellMoneyw;
                    editSellMoney.GetWindowTextW(sellMoneyw);
                    string sellMoney = StringUtil::cstring2String(sellMoneyw);
                    if (!StringUtil::isNumber(sellMoney)) {
                        throw wstring(L"请输入正确的金额");
                    }
                    int sellMoney_int = stoi(sellMoney);
                    SellSetting* sellSetting = sellManager->getSellSetting(code);
                    sellSetting->lockMoney = sellMoney_int;
                    sellManager->syncSettingToFile(code);
                }
                catch (wstring msg) {
                    AfxMessageBox(msg.c_str());
                }
            }
        }
        else if (CWnd::GetFocus() == GetDlgItem(IDC_EDIT_BUY_VOLUME))
        {
            if (checkLockBuyVolume.GetCheck()) {
                // 保存锁定的金额
                try {
                    string code = getInputCode();
                    CString buyMoneyw;
                    editBuyMoney.GetWindowTextW(buyMoneyw);
                    string buyMoney = StringUtil::cstring2String(buyMoneyw);
                    if (!StringUtil::isNumber(buyMoney)) {
                        throw wstring(L"请输入正确的金额");
                    }
                    int buyMoney_int = stoi(buyMoney);
                    SellSetting* sellSetting = sellManager->getSellSetting(code);
                    sellSetting->lockBuyMoney = buyMoney_int;
                    sellManager->syncSettingToFile(code);
                }
                catch (wstring msg) {
                    AfxMessageBox(msg.c_str());
                }
            }
        }
        return TRUE;
    }
    return CDialogEx::PreTranslateMessage(pMsg);
}
FloatTrade/FloatTradeDlg.h
@@ -8,7 +8,12 @@
#include <string>
#include <thread>
#include <map>
using namespace std;
#include <list>
#include "SellDlg.h"
#include "SellStruct.h"
#include "SellManager.h"
#include "TipDlg.h"
#define WM_FLOAT_MSG (WM_USER + 100)
@@ -16,6 +21,9 @@
#define COLOR_GREEN RGB(0,230,0)
#define COLOR_BLUE RGB(25,6,173)
#define COLOR_BLACK RGB(0,0,0)
#define COLOR_ORANGE RGB(255,128,32)
using namespace std;
enum MSG_TYPE{
@@ -23,18 +31,15 @@
MSG_TYPE_SUCCESS,
MSG_TYPE_SELL_SUCCESS,
MSG_TYPE_FAIL,
};
struct CodePosition{
    int total;//总持仓
    int available;//可用持仓
    int sell_rules_count;//卖出规则数量
MSG_TYPE_WARNING,
};
// 悬浮消息
struct FloatMsg {
    string msg;
    MSG_TYPE msgType;
    int position;
    int showMS;// 显示的ms数
};
// CFloatTradeDlg 对话框
@@ -47,12 +52,15 @@
    COLORREF msgColor;
    std::thread* cancelMsgThread;
    static bool breakCancelMsg;
    // 正在请求的代码
    string requestingCode;
    // 下单窗口
    HWND buyWin;
    CodePosition codePosition;
    map<string, int> sellPercentMap;
    SellManager* sellManager;
    map<string, SellDlg*> sellDlgMap;
    void initView();
@@ -62,10 +70,15 @@
    void setMsg(CString msg, MSG_TYPE msgType,  bool autoCancel=TRUE);
    void showTips(CString str, int textColorType);
    void showTips(CString str, int textColorType,  int delayMs=2000, int position = TipDlg::POSITION_NORMAL);
    // 获取交易状态
    static void getTradeState(CFloatTradeDlg* context);
    static void getAutoCancelSellMode(CFloatTradeDlg* context);
    // 获取市场行情
    static void getMarketSituation(CFloatTradeDlg* context);
    //获取交易模式
    static void getTradeMode(CFloatTradeDlg* context);
@@ -75,7 +88,7 @@
    static void getCodeDesc(string code,CFloatTradeDlg* context);
    //选择卖量
    void selectSellVolume(string code, int percent);
    void selectSellRateIndex(string code, int percent);
    // 获取代码持仓状态 
    static void requestCodePosition(string code, CFloatTradeDlg* context,bool showCodeDesc, int delayMs=0);
@@ -83,8 +96,51 @@
    // 获取卖结果 
    static void requestSellResult(int order_ref, CFloatTradeDlg* context, int delayMs = 0);
    //定时更新持仓信息
    static void regularUpdatePositionInfo(CFloatTradeDlg* context);
    // 消息接收器心跳包发送
    static void runPushMsgHeart(CFloatTradeDlg* context, SOCKET socket);
    // 运行推送消息接收器
    static void runPushMsgReceiver(CFloatTradeDlg* context);
    // 开始震动
    static void startShake(CFloatTradeDlg* context,CString text);
    // 展示持仓数据
    void showCodePositionInfo();
    // 量的分配
    list<UINT> distributeVolume(UINT total, UINT percent);
    // 计算量索引
    UINT computeSellVolume(list<UINT> volumeList, list<int> sell_volumes);
    CString formatListResult(std::list<wstring> wlist);
    // 设置卖视图
    void initSellSettingView();
    // 获取输入的代码
    string getInputCode();
    // 卖回调
    static void OnSellCallback(string code, CWnd* context);
    // 关闭卖回调
    static void OnSellCloseCallback(string code, CWnd* context);
    static void sell(string code,int volume, CFloatTradeDlg* context);
    static void sell(string code, CFloatTradeDlg* context);
    // 填充卖资金根据量
    void fillSellMoney(string code, int volume);
    int sellMoneyToVolume(string code, int money);
    void buy();
    static void showFloatMsg(CFloatTradeDlg *context, CString msg,MSG_TYPE msgType,int showMS=2000, int position=TipDlg::POSITION_NORMAL);
// 构造
@@ -110,6 +166,7 @@
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnClickedBtnAlreadyCanceled();
    afx_msg void OnClickedBtnBlack();
@@ -128,7 +185,6 @@
    afx_msg void OnClickedCheckAutoClick();
    afx_msg void OnClickedCheckAutoRefresh();
    afx_msg void OnClickedCheckTradeQuickKey();
    afx_msg LRESULT OnFloatMsg(WPARAM wParam, LPARAM lParam);
    CStatic labelAtrribute;
@@ -139,7 +195,7 @@
    //CButton btnBuyModeWant;
    //CButton btnBuyModeAll;
    CButton checkAutoRefresh;
    CButton checkAutoClick;
    CButton checkAutoCancelSell;
    CButton checkTradeQuickKey;
    CButton whiteList;
    CButton blackList;
@@ -158,7 +214,33 @@
    afx_msg void OnBnClickedButtonSellVolume1();
    CStatic labelTotalPosition;
    CStatic labelSelledVolume;
    CEdit editLeftVolume;
    CEdit editSellMoney;
    CComboBox comboSellPriceType;
    CButton btnSellRule;
    afx_msg void OnBnClickedButtonRefresh();
    afx_msg void OnBnClickedmustlist();
    afx_msg void OnBnClickedmust();
    afx_msg void OnBnClickedremovefrommust();
    CButton checkLockVolume;
    afx_msg void OnBnClickedCheckLockSellVolume();
    CComboBox comboSellFirst;
    CComboBox comboSellLeft;
    CButton radioSell1;
    CButton radioSell2;
    afx_msg void OnBnClickedRadio2();
    afx_msg void OnBnClickedRadio1();
    CButton checkMarketSituation;
    afx_msg void OnBnClickedCheckMarketSituation();
    afx_msg void OnCbnSelchangeComboSellFirst();
    afx_msg void OnCbnSelchangeComboSellLeft();
    CMFCButton mfcBtnFlashInfo;
    afx_msg void OnBnClickedButtonAddWant();
    afx_msg void OnBnClickedButtonRemoveWant();
    afx_msg void OnBnClickedButtonWantList();
    afx_msg void OnBnClickedButtonGetPositions();
    afx_msg void OnDeltaposSpinVolume(NMHDR* pNMHDR, LRESULT* pResult);
    CButton checkLockBuyVolume;
    CEdit editBuyMoney;
    afx_msg void OnBnClickedCheckLockBuyVolume();
    virtual BOOL PreTranslateMessage(MSG* pMsg);
};
FloatTrade/RCa18592
Binary files differ
FloatTrade/RDa18592
Binary files differ
FloatTrade/SellDlg.cpp
New file
@@ -0,0 +1,110 @@
// SellDlg.cpp: 实现文件
//
#include "common/pch.h"
#include "FloatTrade.h"
#include "SellDlg.h"
#include "afxdialogex.h"
#include "../common/NetworkApi.h"
#include <thread>
// SellDlg 对话框
IMPLEMENT_DYNAMIC(SellDlg, CDialogEx)
void SellDlg::initView(SellDlg* context)
{
    //context->btnSell.SetTextColor(RGB(0, 255, 0));
    //context->btnSell.SetFaceColor(RGB(0, 0, 0), TRUE);
    //btnSell.Invalidate();
    //context->btnClose.SubclassDlgItem(IDC_BUTTON_CLOSE, context);
    HBITMAP hBitmap = ::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_PNG_CLOSE));   //IDB_BITMAP1 为BITMAP资源
    context->btnClose.SetBitmap(hBitmap);
}
void SellDlg::SetBtnSellText()
{
    // 设置卖信息
    CString st = L"卖-";
    st.Append(codeName);
    st.Append(L"-");
    st.Append(to_wstring(position.total - position.available).c_str());
    st.Append(L"/");
    st.Append(to_wstring(position.total).c_str());
    btnSell.SetWindowTextW(st);
}
SellDlg::SellDlg(string code, CString name, CodePosition position, SellCallbackFunc callback, CloseCallbackFunc closeCallback, CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_DIALOG_SELL, pParent)
{
    this->pParent = pParent;
    this->code = code;
    this->codeName = name;
    this->position = position;
    this->sellCallback = callback;
    this->closeCallback = closeCallback;
}
SellDlg::~SellDlg()
{
}
void SellDlg::SetPositionInfo(int total, int avaiable)
{
    this->position.total = total;
    this->position.available = avaiable;
    SetBtnSellText();
}
void SellDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_MFCBUTTON_SELL, btnSell);
    DDX_Control(pDX, IDC_BUTTON_CLOSE, btnClose);
}
BEGIN_MESSAGE_MAP(SellDlg, CDialogEx)
    ON_WM_NCHITTEST()
    ON_BN_CLICKED(IDC_BUTTON_CLOSE, &SellDlg::OnBnClickedButtonClose)
    ON_BN_CLICKED(IDC_MFCBUTTON_SELL, &SellDlg::OnBnClickedMfcbuttonSell)
END_MESSAGE_MAP()
// SellDlg 消息处理程序
LRESULT SellDlg::OnNcHitTest(CPoint point)
{
    return HTCAPTION;
}
BOOL SellDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    // 设置对话框背景颜色
    //SetBackgroundColor(RGB(0,0,0));
    SetBtnSellText();
    std::thread t1(initView, this);
    t1.detach();
    return TRUE;
}
void SellDlg::OnBnClickedButtonClose()
{
    this->closeCallback(code, this->pParent);
}
void SellDlg::OnBnClickedMfcbuttonSell()
{
    this->sellCallback(code, this->pParent);
}
FloatTrade/SellDlg.h
New file
@@ -0,0 +1,59 @@
#pragma once
#include <string>
#include <list>
#include "CImgButton.h"
#include "CAutoFocusButton.h"
#include "SellStruct.h"
using namespace std;
typedef void (*SellCallbackFunc)(string, CWnd*);
typedef void (*CloseCallbackFunc)(string, CWnd*);
// SellDlg 对话框
class SellDlg : public CDialogEx
{
    DECLARE_DYNAMIC(SellDlg)
private:
    string code;
    CString codeName;
    CodePosition position;
    SellCallbackFunc sellCallback;
    CloseCallbackFunc closeCallback;
    CWnd* pParent;
    static void initView(SellDlg *context);
    void SetBtnSellText();
public:
    SellDlg(string code, CString name, CodePosition position, SellCallbackFunc callback, CloseCallbackFunc closeCallback, CWnd* pParent = nullptr);   // 标准构造函数
    virtual ~SellDlg();
    // 设置持仓信息
    void SetPositionInfo(int total,int avaiable);
// 对话框数据
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_DIALOG_SELL };
#endif
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
    DECLARE_MESSAGE_MAP()
public:
    afx_msg LRESULT OnNcHitTest(CPoint point);
    virtual BOOL OnInitDialog();
    CAutoFocusButton btnSell;
    CButton  btnClose;
    afx_msg void OnBnClickedMfcbuttonClose();
    afx_msg void OnBnClickedButtonClose();
    afx_msg void OnBnClickedMfcbuttonSell();
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    afx_msg void OnNcMouseMove(UINT nHitTest, CPoint point);
};
FloatTrade/SellManager.cpp
New file
@@ -0,0 +1,316 @@
#include "common/pch.h"
#include "SellManager.h"
#include "../common/NetworkApi.h"
#include "../common/JsonUtil.h"
#include "ConfigUtil.h"
#include "../common/JsonUtil.h"
#include <iostream>
#include <ctime>
SellSetting* SellManager::getSellSetting(string code)
{
    if (sellSettingMap.find(code) != sellSettingMap.end())
    {
        return sellSettingMap[code];
    }
    return nullptr;
}
CodePosition* SellManager::getCodePosition(string code)
{
    if (codePositionMap.find(code) != codePositionMap.end())
    {
        return codePositionMap[code];
    }
    return nullptr;
}
int SellManager::sell(string code, int sellPriceType)
{
    if (sellSettingMap.find(code) == sellSettingMap.end()) {
        throw wstring(L"尚未设置卖出规则");
    }
    //获取持仓信息
    if (codePositionMap.find(code) == codePositionMap.end()) {
        throw wstring(L"尚未获取到持仓");
    }
    int money = computeCurrentMoney(code);
    if (money <= 0) {
        throw wstring(L"可卖出量为0");
    }
    int volume = sellMoneyToVolume(money, codePositionMap[code]->costPrice);
    if (volume > codePositionMap[code]->available) {
        volume = codePositionMap[code]->available;
    }
    return    sell(code, volume, sellPriceType);
}
int SellManager::sell(string code, int volume, int sellPriceType)
{
    string result = NetworkApi::sell(code, volume, sellPriceType, true);
    CString msg(code.c_str());
    msg.Append(L":");
    auto doc = JsonUtil::parseUTF16(result);
    if (doc.IsObject() && doc.HasMember(L"code")) {
        if (doc[L"code"] == 0) {
            if (doc[L"data"].HasMember(L"orderRef")) {
                msg.Append(_T("提交卖成功"));
                int orderRef = doc[L"data"][L"orderRef"].GetInt();
                return orderRef;
            }
            else if (doc[L"data"].HasMember(L"orderStatusMsg")) {
                msg.Append(doc[L"data"][L"orderStatusMsg"].GetString());
                throw wstring(msg);
            }
        }
        else {
            if (doc.HasMember(L"msg")) {
                msg.Append(doc[L"msg"].GetString());
                throw wstring(msg);
            }
        }
    }
    else {
        msg.Append(L"解析结果出错");
        throw wstring(msg);
    }
}
void SellManager::lockVolume(string code, int volume)
{
}
void SellManager::unLockVolume(string code)
{
}
int SellManager::computeCurrentMoney(string code)
{
    SellSetting* sellSetting = sellSettingMap[code];
    CodePosition* pos = codePositionMap[code];
    //if (pos->available <= 0) {
    //    return 0;
    //}
    int sell_count_100 = 0;
    int available_100 = pos->available / 100;
    if (!sellSetting->lock)
    {
        if (sellSetting->setting_mode == SETTING_MODE_RATE) {
            list<UINT> volumeList = distributeVolume(pos->total / 100, sellSetting->mode1_rate_index);
            sell_count_100 = computeSellVolume(volumeList, pos->sell_orders);
        }
        else {
            int first_percent = (sellSetting->mode2_first_index + 1) * 10;
            int second_count = (sellSetting->mode2_left_index + 1);
            int total_100 = pos->total / 100;
            if (pos->sell_orders.size() == 0) {
                sell_count_100 = total_100 * first_percent / 100;
                if (total_100 * first_percent % 100 != 0) {
                    sell_count_100 += 1;
                }
            }
            else {
                // 总持仓减去第一次的持仓
                list<UINT> volumeList = distributeVolume(total_100 - *(pos->sell_orders.begin()) / 100, second_count);
                list<UINT>::iterator el = volumeList.begin();
                advance(el, pos->sell_orders.size() - 1);
                if (el != volumeList.end()) {
                    sell_count_100 = *el;
                }
                else {
                    sell_count_100 = 0;
                }
            }
        }
    }
    else {
        if (sellSetting->lockMoney <= 0) {
            CString msg = L"锁定量错误:";
            msg.Append(to_wstring(sellSetting->lockMoney).c_str());
            throw wstring(msg);
        }
        return sellSetting->lockMoney;
    }
    if (sell_count_100 > available_100) {
        sell_count_100 = available_100;
    }
    return (int) round(sell_count_100 * 100 * pos->costPrice);
}
void SellManager::syncSettingToFile(string code)
{
    // 对象转为json
    if (sellSettingMap.find(code)== sellSettingMap.end())
    {
        return;
    }
    SellSetting* sellSetting = sellSettingMap[code];
    auto nowDate = getNowDate();
    string key = string("sell_setting-").append(nowDate).append("-").append(code);
    rapidjson::StringBuffer buf;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
    writer.StartObject();
    writer.Key("setting_mode");
    writer.Int(sellSetting->setting_mode);
    writer.Key("lock");
    writer.Bool(sellSetting->lock);
    writer.Key("lockMoney");
    writer.Int(sellSetting->lockMoney);
    writer.Key("lockBuy");
    writer.Bool(sellSetting->lockBuy);
    writer.Key("lockBuyMoney");
    writer.Int(sellSetting->lockBuyMoney);
    writer.Key("mode1_rate_index");
    writer.Int(sellSetting->mode1_rate_index);
    writer.Key("mode2_first_index");
    writer.Int(sellSetting->mode2_first_index);
    writer.Key("mode2_left_index");
    writer.Int(sellSetting->mode2_left_index);
    writer.EndObject();
    const char* json_content = buf.GetString();
    ConfigUtil::setStringConfig(key.c_str(), json_content);
}
void SellManager::clearPreSettings()
{
    list<string> keys = ConfigUtil::getKeys();
    auto nowDate = getNowDate();
    string prefix = string("sell_setting-");
    string prefix_today = string("sell_setting-").append(nowDate);
    for (list<string>::iterator e = keys.begin(); e != keys.end(); e++) {
        string key = *e;
        if (key.find(prefix) == 0 && key.find(prefix_today) < 0) {
            ConfigUtil::delKey(key);
        }
    }
}
string SellManager::getNowDate()
{
    std::time_t now = std::time(nullptr);
    // 使用本地时间转换当前时间
    std::tm currentDate;
    localtime_s(&currentDate,&now);
    // 定义日期格式
    char buffer[80];
    std::strftime(buffer, sizeof(buffer), "%Y%m%d", &currentDate);
    return string(buffer);
}
SellSetting* SellManager::loadSettingFromFile(string code)
{
    auto nowDate = getNowDate();
    string key = string("sell_setting-").append(nowDate).append("-").append(code);
    try {
        string result = ConfigUtil::readStringConfig(key.c_str());
        auto doc = JsonUtil::parseUTF8(result);
        SellSetting* setting = new SellSetting();
        setting->lock = doc["lock"].GetBool();
        setting->lockMoney = doc["lockMoney"].GetInt();
        setting->lockBuy = doc["lockBuy"].GetBool();
        setting->lockBuyMoney = doc["lockBuyMoney"].GetInt();
        setting->setting_mode = doc["setting_mode"].GetInt()==0? SETTING_MODE_RATE: SETTING_MODE_PERCENT;
        setting->mode2_first_index = doc["mode2_first_index"].GetInt();
        setting->mode2_left_index = doc["mode2_left_index"].GetInt();
        setting->mode1_rate_index = doc["mode1_rate_index"].GetInt();
        return setting;
    }
    catch (...) {
    }
    return nullptr;
}
list<UINT> SellManager::distributeVolume(UINT total, UINT percent)
{
    list<UINT> volumeList;
    UINT base = total / percent;
    UINT left = total % percent;
    for (UINT i = 0; i < percent; i++) {
        if (i + 1 <= left) {
            volumeList.push_back(base + 1);
        }
        else {
            volumeList.push_back(base);
        }
    }
    return volumeList;
}
UINT SellManager::computeSellVolume(list<UINT> volumeList, list<int> sell_volumes)
{
    if (sell_volumes.size() >= volumeList.size()) {
        return 0;
    }
    list<UINT>::iterator el = volumeList.begin();
    advance(el, sell_volumes.size());
    if (el != volumeList.end()) {
        return *el;
    }
    return 0;
}
int SellManager::sellMoneyToVolume(int money, double price)
{
    int volume = ((int)round((money / price) * 100)) / 100;
    volume = volume < 0 ? 0 : volume;
    return volume / 100 * 100;
}
void SellManager::init(string code)
{
    // 初始化代码
    if (getSellSetting(code) == nullptr) {
        SellSetting* setting = loadSettingFromFile(code);
        if (setting == nullptr) {
            setting = new SellSetting();
            setting->lock = true;
            setting->lockMoney = 5000;
            setting->lockBuy = false;
            setting->lockBuyMoney = 0;
            setting->setting_mode = SETTING_MODE_RATE;
            setting->mode1_rate_index = 4;
        }
        sellSettingMap[code] = setting;
    }
    if (getCodePosition(code) == nullptr) {
        CodePosition* codePosition = new CodePosition();
        codePosition->available = 0;
        codePosition->costPrice = 0.0f;
        codePosition->total = 0;
        codePosition->sell_rules_count = 0;
        codePosition->sell_orders = list<int>();
        codePositionMap[code] = codePosition;
    }
}
FloatTrade/SellManager.h
New file
@@ -0,0 +1,49 @@
#pragma once
#include "SellStruct.h"
#include <map>
#include <string>
using namespace std;
class SellManager
{
private:
    map<string, SellSetting*> sellSettingMap;
    map<string, CodePosition*> codePositionMap;
    string getNowDate();
    SellSetting* loadSettingFromFile(string code);
    list<UINT> distributeVolume(UINT total, UINT percent);
    UINT computeSellVolume(list<UINT> volumeList, list<int> sell_volumes);
public:
    void init(string code);
    SellSetting* getSellSetting(string code);
    CodePosition* getCodePosition(string code);
    // 卖出
    int sell(string code, int sellPriceType);
    // 卖出
    // 返回orderRef
    int sell(string code, int volume, int sellPriceType);
    // 锁定量
    void lockVolume(string code, int volume);
    // 解锁量
    void unLockVolume(string code);
    // 计算当前需要的卖出量
    int computeCurrentMoney(string code);
    // 将设置保存到文件中
    void syncSettingToFile(string code);
    // 清除之前的设置
    void clearPreSettings();
    static int sellMoneyToVolume(int money, double price);
};
FloatTrade/SellRuleDlg.cpp
@@ -3,11 +3,16 @@
#include "common/pch.h"
#include "FloatTrade.h"
#include "SellRuleDlg.h"
#include "../common/Win32Util.h"
#include "../common/NetworkApi.h"
#include "../common/StringUtil.h"
#include "../common/JsonUtil.h"
#include "afxdialogex.h"
#include <thread>
#include "ConfigUtil.h"
#include <ctime>
#include <cstring>
#include "../common/TimeUtil.h"
// SellRuleDlg 对话框
@@ -38,8 +43,20 @@
    DDX_Control(pDX, IDC_BUTTON_DELETE, btnDel);
    DDX_Control(pDX, IDC_BUTTON_ADD, btnAdd);
    DDX_Control(pDX, IDC_LIST_RULES, listRules);
    DDX_Control(pDX, IDC_EDIT_BUY1_PRICE, editBuy1Price);
    DDX_Control(pDX, IDC_COMBO_SELL_PRICE_TYPE, comboSellPriceType);
    DDX_Control(pDX, IDC_EDIT_CODE2, editCode1);
    DDX_Control(pDX, IDC_EDIT_BUY1_PRICE2, editBuy1Price1);
    DDX_Control(pDX, IDC_EDIT_SELL_VOLUME2, editSellVolume1);
    DDX_Control(pDX, IDC_COMBO_SELL_PRICE_TYPE2, comboSellPriceType1);
    DDX_Control(pDX, IDC_EDIT_END_TIME2, editEndTime1);
    DDX_Control(pDX, IDC_STATIC_ID2, labelId1);
    DDX_Control(pDX, IDC_STATIC_ID3, labelID3);
    DDX_Control(pDX, IDC_EDIT_CODE3, editCode3);
    DDX_Control(pDX, IDC_EDIT_BUY1_VOLUME2, editBuy1Volume3);
    DDX_Control(pDX, IDC_EDIT_END_TIME3, editEndTime3);
    DDX_Control(pDX, IDC_STATIC_POSITION, labelPosition);
    DDX_Control(pDX, IDC_STATIC_POSITION2, labelPosition1);
    DDX_Control(pDX, IDC_STATIC_BUY1_MONEY, labelBuy1Money);
}
@@ -49,6 +66,20 @@
    ON_BN_CLICKED(IDC_BUTTON_ADD, &SellRuleDlg::OnBnClickedButtonAdd)
    ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_RULES, &SellRuleDlg::OnLvnItemchangedListRules)
    ON_NOTIFY(NM_CUSTOMDRAW, IDC_LIST_RULES, &SellRuleDlg::OnNMCustomdrawListRules)
    ON_BN_CLICKED(IDC_BUTTON_CLEAR2, &SellRuleDlg::OnBnClickedButtonClear2)
    ON_BN_CLICKED(IDC_BUTTON_DELETE2, &SellRuleDlg::OnBnClickedButtonDelete2)
    ON_BN_CLICKED(IDC_BUTTON_ADD2, &SellRuleDlg::OnBnClickedButtonAdd2)
    ON_WM_CLOSE()
    ON_BN_CLICKED(IDC_BUTTON_UPDATE, &SellRuleDlg::OnBnClickedButtonUpdate)
    ON_BN_CLICKED(IDC_BUTTON_UPDATE2, &SellRuleDlg::OnBnClickedButtonUpdate2)
    ON_BN_CLICKED(IDC_BUTTON_FILL_VOLUME, &SellRuleDlg::OnBnClickedButtonFillVolume)
    ON_BN_CLICKED(IDC_BUTTON_CLEAR3, &SellRuleDlg::OnBnClickedButtonClear3)
    ON_BN_CLICKED(IDC_BUTTON_DELETE4, &SellRuleDlg::OnBnClickedButtonDelete4)
    ON_BN_CLICKED(IDC_BUTTON_UPDATE3, &SellRuleDlg::OnBnClickedButtonUpdate3)
    ON_BN_CLICKED(IDC_BUTTON_ADD3, &SellRuleDlg::OnBnClickedButtonAdd3)
    ON_BN_CLICKED(IDC_BUTTON_FILL_VOLUME2, &SellRuleDlg::OnBnClickedButtonFillVolume2)
    ON_BN_CLICKED(IDC_BUTTON_GET_POSITION, &SellRuleDlg::OnBnClickedButtonGetPosition)
    ON_BN_CLICKED(IDC_BUTTON_GET_POSITION2, &SellRuleDlg::OnBnClickedButtonGetPosition2)
END_MESSAGE_MAP()
@@ -58,14 +89,33 @@
BOOL SellRuleDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    // 设置显示的位置
    int* pos = ConfigUtil::getSellRuleDialogShowPos();
    int x = pos[0];
    int y = pos[1];
    free(pos);
    if (x > 0 || y > 0)
    {
        HWND hwnd = GetSafeHwnd();
        RECT rect;
        Win32Util::getWindowRect(hwnd, &rect);
        ::SetWindowPos(hwnd, nullptr, x, y, rect.right - rect.left + 1, rect.bottom - rect.top + 1, SWP_SHOWWINDOW);
    }
    if (this->initCode) {
        editCode.SetWindowTextW(this->initCode);
        editCode1.SetWindowTextW(this->initCode);
        editCode3.SetWindowTextW(this->initCode);
    }
    if (this->initVolume) {
        editSellVolume.SetWindowTextW(this->initVolume);
        editSellVolume1.SetWindowTextW(this->initVolume);
    }
    editEndTime.SetWindowTextW(L"14:56:55");
    editEndTime.SetWindowTextW(L"14:56:58");
    editEndTime1.SetWindowTextW(L"09:24:59");
    initEndTime3();
    initView();
    std::thread    t1(requestListRules, this);
    t1.detach();
@@ -81,48 +131,69 @@
    editBuy1Volume.SetWindowTextW(L"");
    editCode.SetWindowTextW(L"");
    editSellVolume.SetWindowTextW(L"");
    editEndTime.SetWindowTextW(L"14:56:55");
    editEndTime.SetWindowTextW(L"14:56:58");
    labelPosition.SetWindowTextW(L"");
}
void SellRuleDlg::initView()
{
    //初始化列表
    listRules.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES| WS_HSCROLL);
    listRules.SetExtendedStyle(ES_MULTILINE | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | WS_HSCROLL);
    listRules.ModifyStyle(LVS_SINGLESEL, LVS_REPORT);
    listRules.SetRowHeigt(24);
    listRules.SetRowHeigt(48);
    CRect rect;
    listRules.GetClientRect(&rect);
    int unitSize = (rect.Width() - 5) / 7.5f;
    listRules.InsertColumn(0, _T("代码"), LVCFMT_LEFT, unitSize*1, 0);
    listRules.InsertColumn(1, _T("买1量(手)"), LVCFMT_LEFT, unitSize * 1.1, 1);
    listRules.InsertColumn(2, _T("买1价"), LVCFMT_LEFT, unitSize * 1, 2);
    listRules.InsertColumn(3, _T("卖量(股)"), LVCFMT_LEFT, unitSize * 1.1, 3);
    listRules.InsertColumn(4, _T("卖价类型"), LVCFMT_LEFT, unitSize * 1.2, 4);
    listRules.InsertColumn(5, _T("结束时间"), LVCFMT_LEFT, unitSize * 1.3, 5);
    listRules.InsertColumn(6, _T("状态"), LVCFMT_LEFT, unitSize * 0.8, 6);
//    listRules.InsertColumn(7, _T("ID"), LVCFMT_LEFT, 50, 7);
//    listRules.InsertColumn(8, _T("创建时间"), LVCFMT_LEFT, 50, 8);
    listRules.InsertColumn(0, _T("代码"), LVCFMT_LEFT, unitSize * 1, 0);
    listRules.InsertColumn(1, _T("条件"), LVCFMT_LEFT, unitSize * 3, 1);
    listRules.InsertColumn(2, _T("卖出量(股)"), LVCFMT_LEFT, unitSize * 1.1, 2);
    listRules.InsertColumn(3, _T("结束时间"), LVCFMT_LEFT, unitSize * 1.3, 3);
    listRules.InsertColumn(4, _T("状态"), LVCFMT_LEFT, unitSize * 0.8, 4);
    //    listRules.InsertColumn(7, _T("ID"), LVCFMT_LEFT, 50, 7);
    //    listRules.InsertColumn(8, _T("创建时间"), LVCFMT_LEFT, 50, 8);
    listRules.AutoColumn();
    list<string> types = get_price_types();
    for (list<string>::iterator e = types.begin(); e != types.end();++e) {
    for (list<string>::iterator e = types.begin(); e != types.end(); ++e) {
        comboSellPriceType.AddString(CString((*e).c_str()));
        comboSellPriceType1.AddString(CString((*e).c_str()));
    }
    comboSellPriceType.SetCurSel(0);
    comboSellPriceType.SetCurSel(0);
    comboSellPriceType1.SetCurSel(1);
}
void SellRuleDlg::showDetail(SellRule rule) {
    labelID.SetWindowTextW(rule.id_);
    editBuy1Volume.SetWindowTextW(CString(std::to_wstring(rule.buy1_volume).c_str()));
    editBuy1Price.SetWindowTextW(rule.buy1_price);
    editCode.SetWindowTextW(rule.code);
    editSellVolume.SetWindowTextW(CString(std::to_wstring(rule.sell_volume).c_str()));
    comboSellPriceType.SetCurSel(rule.sell_price_type);
    editEndTime.SetWindowTextW(rule.end_time);
    OnBnClickedButtonClear();
    OnBnClickedButtonClear2();
    OnBnClickedButtonClear3();
    if (rule.type == 2) {
        if (rule.buy1_volume > 0) {
            labelID.SetWindowTextW(rule.id_);
            editBuy1Volume.SetWindowTextW(CString(std::to_wstring(rule.buy1_volume).c_str()));
            editCode.SetWindowTextW(rule.code);
            editSellVolume.SetWindowTextW(CString(std::to_wstring(rule.sell_volume).c_str()));
            comboSellPriceType.SetCurSel(rule.sell_price_type);
            editEndTime.SetWindowTextW(rule.end_time);
        }
        else {
            labelId1.SetWindowTextW(rule.id_);
            editCode1.SetWindowTextW(rule.code);
            editSellVolume1.SetWindowTextW(CString(std::to_wstring(rule.sell_volume).c_str()));
            comboSellPriceType1.SetCurSel(rule.sell_price_type);
            editEndTime1.SetWindowTextW(rule.end_time);
            editBuy1Price1.SetWindowTextW(rule.buy1_price);
        }
    }
    else if (rule.type == 1) {
        labelID3.SetWindowTextW(rule.id_);
        editBuy1Volume3.SetWindowTextW(CString(std::to_wstring(rule.buy1_volume).c_str()));
        editCode3.SetWindowTextW(rule.code);
        editEndTime3.SetWindowTextW(rule.end_time);
    }
}
void SellRuleDlg::requestListRules(SellRuleDlg* app)
@@ -144,6 +215,7 @@
                rule.create_time = array[i][L"create_time"].GetString();
                rule.excuted = array[i][L"excuted"].GetInt();
                rule.end_time = array[i][L"end_time"].GetString();
                rule.type = array[i][L"type"].GetInt();
                rules.push_back(rule);
            }
            app->listRules.SetRedraw(false);
@@ -153,17 +225,40 @@
            list<string> TYPES = get_price_types();
            for (list<SellRule>::iterator ele = app->ruleList.begin(); ele != app->ruleList.end(); ++ele) {
                SellRule rule = *ele;
                app->listRules.InsertItem(index, rule.id_);
                app->listRules.SetItemText(index, 0, rule.code);
                app->listRules.SetItemText(index, 1, std::to_wstring(rule.buy1_volume).c_str());
                app->listRules.SetItemText(index, 2, rule.buy1_price);
                app->listRules.SetItemText(index, 3, std::to_wstring(rule.sell_volume).c_str());
                list<string>::iterator its = TYPES.begin();
                std::advance(its, rule.sell_price_type);
                string price_type = *its;
                app->listRules.SetItemText(index, 4, CString(price_type.c_str()));
                app->listRules.SetItemText(index, 5, rule.end_time);
                app->listRules.SetItemText(index, 6, rule.excuted ? L"已执行" : L"未执行");
                CString conditionDesc = L"";
                //通过量来卖
                if (rule.type == 2) {
                    if (rule.buy1_volume > 0) {
                        conditionDesc.Append(L"当【买1】低于【");
                        conditionDesc.Append(to_wstring(rule.buy1_volume).c_str());
                        conditionDesc.Append(L"】手,以【");
                        conditionDesc.Append(CString(price_type.c_str()));
                        conditionDesc.Append(L"】卖");
                    }
                    else {
                        conditionDesc.Append(L"当【最新价】低于【");
                        conditionDesc.Append(rule.buy1_price);
                        conditionDesc.Append(L"】,以【");
                        conditionDesc.Append(CString(price_type.c_str()));
                        conditionDesc.Append(L"】卖");
                    }
                }
                else if (rule.type == 1) {
                    conditionDesc.Append(L"当【买1】低于【");
                    conditionDesc.Append(to_wstring(rule.buy1_volume).c_str());
                    conditionDesc.Append(L"】手,撤买");
                }
                app->listRules.SetItemText(index, 1, conditionDesc);
                app->listRules.SetItemText(index, 2, std::to_wstring(rule.sell_volume).c_str());
                app->listRules.SetItemText(index, 3, rule.end_time);
                app->listRules.SetItemText(index, 4, rule.excuted ? L"已执行" : L"未执行");
                //app->listRules.SetItemText(index, 7, rule.id_);
                //app->listRules.SetItemText(index, 8, rule.create_time);
                if (rule.excuted) {
@@ -171,13 +266,102 @@
                }
                index++;
            }
        }
        app->listRules.SetRedraw(true);
    }
    else {
        AfxMessageBox(doc[L"msg"].GetString());
    }
}
void SellRuleDlg::initEndTime3()
{
    // 初始化结束时间
    std::time_t now = std::time(nullptr);
    string nowday = TimeUtil::toFormatString(now, "%Y-%m-%d");
    nowday.append(" 14:50:00");
    time_t max_t = TimeUtil::toTimestamp(nowday, "%Y-%m-%d %H:%M:%S");
    now += 60 * 10;
    if (now > max_t) {
        now = max_t;
    }
    // 将时间戳转换为本地时间
    std::tm local_time;
    localtime_s(&local_time, &now);
    char buffer[20];
    //%Y-%m-%d %H:%M:%S
    std::strftime(buffer, sizeof(buffer), "%H:%M:%S", &local_time);
    CString time_str = CString(buffer);
    editEndTime3.SetWindowTextW(time_str);
}
CodePosition SellRuleDlg::getCodePosition(string code)
{
    string result = NetworkApi::get_code_position_info(code);
    auto doc = JsonUtil::parseUTF16(result);
    if (doc.IsObject()) {
        int total = doc[L"data"][L"total"].GetInt();
        int available = doc[L"data"][L"available"].GetInt();
        CodePosition codePosition;
        codePosition.total = total;
        codePosition.available = available;
        codePosition.sell_rules_count = doc[L"data"][L"sell_rules_count"].GetInt();
        codePosition.costPrice = doc[L"data"][L"cost_price"].GetFloat();
        list<int> sellVolumes;
        if (doc[L"data"].HasMember(L"sell_orders")) {
            auto sell_orders_array = doc[L"data"][L"sell_orders"].GetArray();
            for (int i = 0; i < sell_orders_array.Size(); i++) {
                sellVolumes.push_back(sell_orders_array[i].GetInt());
            }
        }
        codePosition.sell_orders = sellVolumes;
        return codePosition;
    }
    throw wstring(L"尚未获取到持仓");
}
void SellRuleDlg::showBuy1Money(string code)
{
    if (code.length() != 6) {
        return;
    }
    CString volume_str;
    editBuy1Volume.GetWindowTextW(volume_str);
    if (volume_str.GetLength() <= 0) {
        return;
    }
    if (codePriceMap.find(code) == codePriceMap.end()) {
        return;
    }
    int volume = stoi(StringUtil::cstring2String(volume_str).c_str());
    string price_str = codePriceMap[code];
    double price = stod(price_str.c_str());
    this->editBuy1Volume.SetWindowTextW(to_wstring(volume).c_str());
    int money = (int)(volume * 100 * price);
    CString money_str;
    if (money > 100000000) {
        double money_f = money / 1000000 / 100.0f;
        money_str.Append(CString(StringUtil::toString(money_f, 2).c_str()));
        money_str.Append(L"亿");
    }
    else {
        double money_f = round(money / 100.0f) / 100;
        money_str.Append(CString(StringUtil::toString(money_f, 2).c_str()));
        money_str.Append(L"万");
    }
    this->labelBuy1Money.SetWindowTextW(money_str);
}
@@ -207,13 +391,12 @@
    CString id;
    CString code;
    CString buy1Volume;
    CString buy1Price;
    CString buy1Price = L"";
    CString sellVolume;
    int sellPriceType = comboSellPriceType.GetCurSel();
    CString endTime;
    this->labelID.GetWindowTextW(id);
    this->editBuy1Volume.GetWindowTextW(buy1Volume);
    this->editBuy1Price.GetWindowTextW(buy1Price);
    this->editCode.GetWindowTextW(code);
    this->editSellVolume.GetWindowTextW(sellVolume);
    this->editEndTime.GetWindowTextW(endTime);
@@ -260,6 +443,10 @@
    writer.Key("end_time");
    writer.String(StringUtil::cstring2String(endTime).c_str());
    writer.Key("type");
    writer.Int(2);
    writer.EndObject();
    const char* json_content = buf.GetString();
    string result = NetworkApi::add_sell_rule(JsonUtil::parseUTF8(json_content));
@@ -272,6 +459,80 @@
        AfxMessageBox(doc[L"msg"].GetString());
    }
}
void SellRuleDlg::OnBnClickedButtonUpdate()
{
    CString id;
    CString code;
    CString buy1Volume;
    CString buy1Price = L"";
    CString sellVolume;
    int sellPriceType = comboSellPriceType.GetCurSel();
    CString endTime;
    this->labelID.GetWindowTextW(id);
    this->editBuy1Volume.GetWindowTextW(buy1Volume);
    this->editCode.GetWindowTextW(code);
    this->editSellVolume.GetWindowTextW(sellVolume);
    this->editEndTime.GetWindowTextW(endTime);
    if (id.GetLength() == 0) {
        AfxMessageBox(L"请先选择数据");
        return;
    }
    if (code.GetLength() != 6) {
        AfxMessageBox(L"代码输入不正确");
        return;
    }
    if (buy1Volume.GetLength() < 1) {
        AfxMessageBox(L"请输入买1量");
        return;
    }
    if (sellVolume.GetLength() < 1) {
        AfxMessageBox(L"请输入卖量");
        return;
    }
    if (endTime.GetLength() < 1) {
        AfxMessageBox(L"请输入生效截止时间");
        return;
    }
    int buy1Volume_int = stoi(StringUtil::cstring2String(buy1Volume));
    rapidjson::StringBuffer buf;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
    writer.StartObject();
    writer.Key("id");
    writer.String(StringUtil::cstring2String(id).c_str());
    writer.Key("code");
    writer.String(StringUtil::cstring2String(code).c_str());
    writer.Key("buy1_volume");
    writer.Int(buy1Volume_int * 100);
    writer.Key("buy1_price");
    writer.String(StringUtil::cstring2String(buy1Price).c_str());
    writer.Key("sell_volume");
    writer.Int(stoi(StringUtil::cstring2String(sellVolume)));
    writer.Key("sell_price_type");
    writer.Int(sellPriceType);
    writer.Key("end_time");
    writer.String(StringUtil::cstring2String(endTime).c_str());
    writer.EndObject();
    const char* json_content = buf.GetString();
    string result = NetworkApi::update_sell_rule(JsonUtil::parseUTF8(json_content));
    rapidjson::GenericDocument<rapidjson::UTF16<>> doc = JsonUtil::parseUTF16(result);
    if (doc[L"code"].GetInt() == 0) {
        MessageBox(L"修改成功", L"提示", MB_TASKMODAL);
        requestListRules(this);
    }
    else {
        AfxMessageBox(doc[L"msg"].GetString());
    }
}
void SellRuleDlg::OnLvnItemchangedListRules(NMHDR* pNMHDR, LRESULT* pResult)
{
@@ -321,7 +582,7 @@
        // 暂时不处理每一列
        return;
    }
}
std::list<string> SellRuleDlg::get_price_types()
@@ -335,3 +596,458 @@
    return types;
}
void SellRuleDlg::OnBnClickedButtonClear2()
{
    labelId1.SetWindowTextW(L"");
    editBuy1Price1.SetWindowTextW(L"");
    editCode1.SetWindowTextW(L"");
    editSellVolume1.SetWindowTextW(L"");
    editEndTime1.SetWindowTextW(L"09:24:59");
    labelPosition1.SetWindowTextW(L"");
}
void SellRuleDlg::OnBnClickedButtonDelete2()
{
    CString id;
    this->labelId1.GetWindowTextW(id);
    if (id.GetLength() < 1) {
        AfxMessageBox(L"尚未选中代码");
        return;
    }
    string result = NetworkApi::del_sell_rule(id);
    rapidjson::GenericDocument<rapidjson::UTF16<>> doc = JsonUtil::parseUTF16(result);
    if (doc[L"code"].GetInt() == 0) {
        MessageBox(L"删除成功", L"提示", MB_TASKMODAL);
        requestListRules(this);
    }
    else {
        AfxMessageBox(doc[L"msg"].GetString());
    }
}
void SellRuleDlg::OnBnClickedButtonAdd2()
{
    CString id;
    CString code;
    CString buy1Volume = L"0";
    CString buy1Price;
    CString sellVolume;
    int sellPriceType = comboSellPriceType1.GetCurSel();
    CString endTime;
    this->labelId1.GetWindowTextW(id);
    this->editBuy1Price1.GetWindowTextW(buy1Price);
    this->editCode1.GetWindowTextW(code);
    this->editSellVolume1.GetWindowTextW(sellVolume);
    this->editEndTime1.GetWindowTextW(endTime);
    if (id.GetLength() > 0) {
        AfxMessageBox(L"请先清除数据");
        return;
    }
    if (code.GetLength() != 6) {
        AfxMessageBox(L"代码输入不正确");
        return;
    }
    if (buy1Volume.GetLength() < 1) {
        AfxMessageBox(L"请输入买1量");
        return;
    }
    if (sellVolume.GetLength() < 1) {
        AfxMessageBox(L"请输入卖量");
        return;
    }
    if (endTime.GetLength() < 1) {
        AfxMessageBox(L"请输入生效截止时间");
        return;
    }
    int buy1Volume_int = stoi(StringUtil::cstring2String(buy1Volume));
    rapidjson::StringBuffer buf;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
    writer.StartObject();
    writer.Key("code");
    writer.String(StringUtil::cstring2String(code).c_str());
    writer.Key("buy1_volume");
    writer.Int(buy1Volume_int * 100);
    writer.Key("buy1_price");
    writer.String(StringUtil::cstring2String(buy1Price).c_str());
    writer.Key("sell_volume");
    writer.Int(stoi(StringUtil::cstring2String(sellVolume)));
    writer.Key("sell_price_type");
    writer.Int(sellPriceType);
    writer.Key("end_time");
    writer.String(StringUtil::cstring2String(endTime).c_str());
    writer.Key("type");
    writer.Int(2);
    writer.EndObject();
    const char* json_content = buf.GetString();
    string result = NetworkApi::add_sell_rule(JsonUtil::parseUTF8(json_content));
    rapidjson::GenericDocument<rapidjson::UTF16<>> doc = JsonUtil::parseUTF16(result);
    if (doc[L"code"].GetInt() == 0) {
        MessageBox(L"添加成功", L"提示", MB_TASKMODAL);
        requestListRules(this);
    }
    else {
        AfxMessageBox(doc[L"msg"].GetString());
    }
}
void SellRuleDlg::OnClose()
{
    HWND hwnd = GetSafeHwnd();
    RECT rect;
    Win32Util::getWindowRect(hwnd, &rect);
    ConfigUtil::setSellRuleDialogShowPos(rect.left, rect.top);
    CDialogEx::OnClose();
}
void SellRuleDlg::OnBnClickedButtonUpdate2()
{
    CString id;
    CString code;
    CString buy1Volume = L"0";
    CString buy1Price;
    CString sellVolume;
    int sellPriceType = comboSellPriceType1.GetCurSel();
    CString endTime;
    this->labelId1.GetWindowTextW(id);
    this->editBuy1Price1.GetWindowTextW(buy1Price);
    this->editCode1.GetWindowTextW(code);
    this->editSellVolume1.GetWindowTextW(sellVolume);
    this->editEndTime1.GetWindowTextW(endTime);
    if (id.GetLength() == 0) {
        AfxMessageBox(L"请先选择数据");
        return;
    }
    if (code.GetLength() != 6) {
        AfxMessageBox(L"代码输入不正确");
        return;
    }
    if (buy1Volume.GetLength() < 1) {
        AfxMessageBox(L"请输入买1量");
        return;
    }
    if (sellVolume.GetLength() < 1) {
        AfxMessageBox(L"请输入卖量");
        return;
    }
    if (endTime.GetLength() < 1) {
        AfxMessageBox(L"请输入生效截止时间");
        return;
    }
    int buy1Volume_int = stoi(StringUtil::cstring2String(buy1Volume));
    rapidjson::StringBuffer buf;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
    writer.StartObject();
    writer.Key("id");
    writer.String(StringUtil::cstring2String(id).c_str());
    writer.Key("code");
    writer.String(StringUtil::cstring2String(code).c_str());
    writer.Key("buy1_volume");
    writer.Int(buy1Volume_int * 100);
    writer.Key("buy1_price");
    writer.String(StringUtil::cstring2String(buy1Price).c_str());
    writer.Key("sell_volume");
    writer.Int(stoi(StringUtil::cstring2String(sellVolume)));
    writer.Key("sell_price_type");
    writer.Int(sellPriceType);
    writer.Key("end_time");
    writer.String(StringUtil::cstring2String(endTime).c_str());
    writer.EndObject();
    const char* json_content = buf.GetString();
    string result = NetworkApi::update_sell_rule(JsonUtil::parseUTF8(json_content));
    rapidjson::GenericDocument<rapidjson::UTF16<>> doc = JsonUtil::parseUTF16(result);
    if (doc[L"code"].GetInt() == 0) {
        MessageBox(L"修改成功", L"提示", MB_TASKMODAL);
        requestListRules(this);
    }
    else {
        AfxMessageBox(doc[L"msg"].GetString());
    }
}
void SellRuleDlg::OnBnClickedButtonFillVolume()
{
    CString code;
    this->editCode.GetWindowTextW(code);
    string result = NetworkApi::get_buy1_info(StringUtil::cstring2String(code));
    auto doc = JsonUtil::parseUTF16(result);
    if (doc.IsObject()) {
        if (doc[L"code"].GetInt() == 0) {
            if (doc.HasMember(L"data")) {
                int volume = doc[L"data"][L"volume"].GetInt();
                double price = doc[L"data"][L"price"].GetDouble();
                codePriceMap[StringUtil::cstring2String(code)] = StringUtil::toString(price, 2);
                volume = volume / 100 / 3;
                this->editBuy1Volume.SetWindowTextW(to_wstring(volume).c_str());
                showBuy1Money(StringUtil::cstring2String(code));
            }
        }
        else {
            AfxMessageBox(doc[L"msg"].GetString());
        }
    }
}
BOOL SellRuleDlg::PreTranslateMessage(MSG* pMsg)
{
    if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN) // 按下 Enter 键
    {
        if (CWnd::GetFocus() == GetDlgItem(IDC_EDIT_BUY1_VOLUME)) {
            // 处理该控件内的回车事件
            CString code;
            this->editCode.GetWindowTextW(code);
            showBuy1Money(StringUtil::cstring2String(code));
        }
        return TRUE;
    }
    return CDialogEx::PreTranslateMessage(pMsg);
}
void SellRuleDlg::OnBnClickedButtonClear3()
{
    labelID3.SetWindowTextW(L"");
    editBuy1Volume3.SetWindowTextW(L"");
    editCode3.SetWindowTextW(L"");
    initEndTime3();
}
void SellRuleDlg::OnBnClickedButtonDelete4()
{
    CString id;
    this->labelID3.GetWindowTextW(id);
    if (id.GetLength() < 1) {
        AfxMessageBox(L"尚未选中代码");
        return;
    }
    string result = NetworkApi::del_sell_rule(id);
    rapidjson::GenericDocument<rapidjson::UTF16<>> doc = JsonUtil::parseUTF16(result);
    if (doc[L"code"].GetInt() == 0) {
        MessageBox(L"删除成功", L"提示", MB_TASKMODAL);
        requestListRules(this);
    }
    else {
        AfxMessageBox(doc[L"msg"].GetString());
    }
}
void SellRuleDlg::OnBnClickedButtonUpdate3()
{
    CString id;
    CString code;
    CString buy1Volume;
    CString buy1Price = L"";
    CString endTime;
    this->labelID3.GetWindowTextW(id);
    this->editBuy1Volume3.GetWindowTextW(buy1Volume);
    this->editCode3.GetWindowTextW(code);
    this->editEndTime3.GetWindowTextW(endTime);
    if (id.GetLength() == 0) {
        AfxMessageBox(L"请先选择数据");
        return;
    }
    if (code.GetLength() != 6) {
        AfxMessageBox(L"代码输入不正确");
        return;
    }
    if (buy1Volume.GetLength() < 1) {
        AfxMessageBox(L"请输入买1量");
        return;
    }
    if (endTime.GetLength() < 1) {
        AfxMessageBox(L"请输入生效截止时间");
        return;
    }
    int buy1Volume_int = stoi(StringUtil::cstring2String(buy1Volume));
    rapidjson::StringBuffer buf;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
    writer.StartObject();
    writer.Key("id");
    writer.String(StringUtil::cstring2String(id).c_str());
    writer.Key("code");
    writer.String(StringUtil::cstring2String(code).c_str());
    writer.Key("buy1_volume");
    writer.Int(buy1Volume_int * 100);
    writer.Key("buy1_price");
    writer.String(StringUtil::cstring2String(buy1Price).c_str());
    writer.Key("end_time");
    writer.String(StringUtil::cstring2String(endTime).c_str());
    writer.EndObject();
    const char* json_content = buf.GetString();
    string result = NetworkApi::update_sell_rule(JsonUtil::parseUTF8(json_content));
    rapidjson::GenericDocument<rapidjson::UTF16<>> doc = JsonUtil::parseUTF16(result);
    if (doc[L"code"].GetInt() == 0) {
        MessageBox(L"修改成功", L"提示", MB_TASKMODAL);
        requestListRules(this);
    }
    else {
        AfxMessageBox(doc[L"msg"].GetString());
    }
}
void SellRuleDlg::OnBnClickedButtonAdd3()
{
    CString id;
    CString code;
    CString buy1Volume;
    CString buy1Price = L"";
    CString endTime;
    this->labelID3.GetWindowTextW(id);
    this->editBuy1Volume3.GetWindowTextW(buy1Volume);
    this->editCode3.GetWindowTextW(code);
    this->editEndTime3.GetWindowTextW(endTime);
    if (id.GetLength() > 0) {
        AfxMessageBox(L"请先清除数据");
        return;
    }
    if (code.GetLength() != 6) {
        AfxMessageBox(L"代码输入不正确");
        return;
    }
    if (buy1Volume.GetLength() < 1) {
        AfxMessageBox(L"请输入买1量");
        return;
    }
    if (endTime.GetLength() < 1) {
        AfxMessageBox(L"请输入生效截止时间");
        return;
    }
    int buy1Volume_int = stoi(StringUtil::cstring2String(buy1Volume));
    rapidjson::StringBuffer buf;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
    writer.StartObject();
    writer.Key("code");
    writer.String(StringUtil::cstring2String(code).c_str());
    writer.Key("buy1_volume");
    writer.Int(buy1Volume_int * 100);
    writer.Key("buy1_price");
    writer.String(StringUtil::cstring2String(buy1Price).c_str());
    writer.Key("end_time");
    writer.String(StringUtil::cstring2String(endTime).c_str());
    writer.Key("type");
    writer.Int(1);
    writer.EndObject();
    const char* json_content = buf.GetString();
    string result = NetworkApi::add_sell_rule(JsonUtil::parseUTF8(json_content));
    rapidjson::GenericDocument<rapidjson::UTF16<>> doc = JsonUtil::parseUTF16(result);
    if (doc[L"code"].GetInt() == 0) {
        MessageBox(L"添加成功", L"提示", MB_TASKMODAL);
        requestListRules(this);
    }
    else {
        AfxMessageBox(doc[L"msg"].GetString());
    }
}
void SellRuleDlg::OnBnClickedButtonFillVolume2()
{
    CString code;
    this->editCode3.GetWindowTextW(code);
    string result = NetworkApi::get_buy1_info(StringUtil::cstring2String(code));
    auto doc = JsonUtil::parseUTF16(result);
    if (doc.IsObject()) {
        if (doc[L"code"].GetInt() == 0) {
            if (doc.HasMember(L"data")) {
                int volume = doc[L"data"][L"volume"].GetInt();
                volume = volume / 100 / 2;
                this->editBuy1Volume3.SetWindowTextW(to_wstring(volume).c_str());
            }
        }
        else {
            AfxMessageBox(doc[L"msg"].GetString());
        }
    }
}
void SellRuleDlg::OnBnClickedButtonGetPosition()
{
    try {
        CString code;
        this->editCode.GetWindowTextW(code);
        if (code.GetLength() != 6) {
            throw wstring(L"代码输入错误");
        }
        CodePosition codePosition = getCodePosition(StringUtil::cstring2String(code));
        CString st;
        st.Append(to_wstring(codePosition.available).c_str());
        st.Append(L"/");
        st.Append(to_wstring(codePosition.total).c_str());
        labelPosition.SetWindowTextW(st);
    }
    catch (wstring msg) {
        AfxMessageBox(msg.c_str());
    }
}
void SellRuleDlg::OnBnClickedButtonGetPosition2()
{
    try {
        CString code;
        this->editCode1.GetWindowTextW(code);
        if (code.GetLength() != 6) {
            throw wstring(L"代码输入错误");
        }
        CodePosition codePosition = getCodePosition(StringUtil::cstring2String(code));
        CString st;
        st.Append(to_wstring(codePosition.available).c_str());
        st.Append(L"/");
        st.Append(to_wstring(codePosition.total).c_str());
        labelPosition1.SetWindowTextW(st);
    }
    catch (wstring msg) {
        AfxMessageBox(msg.c_str());
    }
}
FloatTrade/SellRuleDlg.h
@@ -2,6 +2,7 @@
#include "../common/CMyListCtrl.h"
#include <list>
#include <string>
#include "SellManager.h"
using namespace std;
#define COLOR_RED 2
#define COLOR_DEFAULT 0
@@ -21,6 +22,8 @@
    int excuted;
    CString day;
    CString end_time;
    // 0-买 1-买撤 2-卖 3-卖撤
    int type;
};
@@ -52,9 +55,15 @@
    CString initCode;
    CString initVolume;
    list<SellRule> ruleList;
    map<string, string> codePriceMap;
    void showDetail(SellRule rule);
    void initView();
    static void requestListRules(SellRuleDlg *app);
    void initEndTime3();
    CodePosition getCodePosition(string code);
    // 显示买1的金额
    void showBuy1Money(string code);
public:
@@ -73,8 +82,35 @@
    CMyListCtrl listRules;
    afx_msg void OnLvnItemchangedListRules(NMHDR* pNMHDR, LRESULT* pResult);
    afx_msg void OnNMCustomdrawListRules(NMHDR* pNMHDR, LRESULT* pResult);
    CEdit editBuy1Price;
    CComboBox comboSellPriceType;
    static std::list<string> get_price_types();
    CEdit editCode1;
    CEdit editBuy1Price1;
    CEdit editSellVolume1;
    CComboBox comboSellPriceType1;
    CEdit editEndTime1;
    CStatic labelId1;
    afx_msg void OnBnClickedButtonClear2();
    afx_msg void OnBnClickedButtonDelete2();
    afx_msg void OnBnClickedButtonAdd2();
    afx_msg void OnClose();
    afx_msg void OnBnClickedButtonUpdate();
    afx_msg void OnBnClickedButtonUpdate2();
    afx_msg void OnBnClickedButtonFillVolume();
    CStatic labelID3;
    CEdit editCode3;
    CEdit editBuy1Volume3;
    CEdit editEndTime3;
    afx_msg void OnBnClickedButtonClear3();
    afx_msg void OnBnClickedButtonDelete4();
    afx_msg void OnBnClickedButtonUpdate3();
    afx_msg void OnBnClickedButtonAdd3();
    afx_msg void OnBnClickedButtonFillVolume2();
    CStatic labelPosition;
    CStatic labelPosition1;
    afx_msg void OnBnClickedButtonGetPosition();
    afx_msg void OnBnClickedButtonGetPosition2();
    CStatic labelBuy1Money;
    virtual BOOL PreTranslateMessage(MSG* pMsg);
};
FloatTrade/SellStruct.h
New file
@@ -0,0 +1,38 @@
#pragma once
#include <list>
using namespace std;
enum SELL_SETTING_MODE {
    SETTING_MODE_RATE,
    SETTING_MODE_PERCENT
};
struct SellSetting {
    // 设置模式  1-分数  2-百分数
    SELL_SETTING_MODE setting_mode;
    int lockMoney;// 锁定的金额
    bool lock;//是否锁定
    int lockBuyMoney;// 锁定的金额
    bool lockBuy;//是否锁定
    int mode2_first_index;// 第一笔卖的百分比索引
    int mode2_left_index;// 剩下卖的百分比索引
    int mode1_rate_index;// 几笔卖的比例
};
struct SellSettingView {
    // 选择模式
    bool mode;
    bool mode2_first;
    bool mode2_left;
    bool mode1_percent;
};
struct CodePosition {
    int total;//总持仓
    int available;//可用持仓
    int sell_rules_count;//卖出规则数量
    list<int> sell_orders;// 已卖的订单数量
    float costPrice; // 成本价格
};
FloatTrade/TipDlg.cpp
@@ -3,6 +3,7 @@
#include "common/pch.h"
#include "FloatTrade.h"
#include "../common/Win32Util.h"
#include "TipDlg.h"
#include "afxdialogex.h"
#include <thread>
@@ -12,10 +13,11 @@
IMPLEMENT_DYNAMIC(TipDlg, CDialogEx)
TipDlg::TipDlg(CWnd* pParent /*=nullptr*/)
TipDlg::TipDlg(int delayMs, int position, CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_DIALOG_TIPS, pParent)
{
    this->delayMs = delayMs;
    this->position = position;
}
TipDlg::~TipDlg()
@@ -46,8 +48,19 @@
    int screenHeight = GetSystemMetrics(SM_CYSCREEN);
    CRect windowRect;
    GetWindowRect(&windowRect);
    SetWindowPos(NULL, screenWidth - windowRect.Width(), screenHeight - windowRect.Height(), 0, 0, SWP_NOSIZE | SWP_NOZORDER);
    std::thread t1(closeTip, this);
    int x = screenWidth - windowRect.Width();
    int y = screenHeight - windowRect.Height();
    list<HWND>  hwnds =    Win32Util::searchWindow("悬浮盯盘");
    if (hwnds.size() > 0&& position == POSITION_NORMAL) {
        CRect rect;
        GetWindowRect(&rect);
        Win32Util::getWindowRect(*(hwnds.begin()),&rect);
        x = rect.left;
        y = rect.top - windowRect.Height();
    }
    SetWindowPos(NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
    std::thread t1(closeTip, this, this->delayMs);
    t1.detach();
    CFont middleFont;
@@ -80,8 +93,8 @@
    labelMsg.Invalidate();
}
void TipDlg::closeTip(TipDlg* context){
    Sleep(2000);
void TipDlg::closeTip(TipDlg* context,int delayMs){
    Sleep(delayMs);
    if (context != nullptr) {
        context->EndDialog(IDOK);
    }
FloatTrade/TipDlg.h
@@ -8,7 +8,11 @@
    DECLARE_DYNAMIC(TipDlg)
public:
    TipDlg(CWnd* pParent = nullptr);   // 标准构造函数
    const static int POSITION_NORMAL = 0;
    const static int POSITION_RIGHT_BOTTOM = 1;
    TipDlg(int delayMs,int position, CWnd* pParent = nullptr);   // 标准构造函数
    virtual ~TipDlg();
// 对话框数据
@@ -28,7 +32,9 @@
private:
    COLORREF msgColor;
    static void closeTip(TipDlg *context);
    static void closeTip(TipDlg *context,int delayMs = 2000);
    int delayMs;
    int position;
public:
    afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
};
FloatTrade/config.cfg
@@ -1,7 +1,59 @@
trade_refresh = 1;
group_refresh = 0;
window_pos = "[288,316]";
trade_quick_key = 1;
window_pos = "[-792,521]";
ths_auto_click_positions = "[\n    [\n        50,\n        150\n    ],\n    [\n        50,\n        100\n    ],\n    [\n        50,\n        300\n    ]\n]";
ths_auto_click_time_space = 500;
ths_auto_refresh_time_space = 200;
sell_rule_show_pos = "-788,258";
ths_auto_click_time_space = 2000;
ths_auto_refresh_time_space = 2000;
ths_auto_click_positions = "[]";
trade_refresh = 0;
sell_setting-20240221-603767 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240221-000333 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 5,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240222-603767 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 1,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240221-000334 = "{\n    \"setting_mode\": 0,\n    \"lock\": false,\n    \"lockMoney\": 0,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240221-603787 = "{\n    \"setting_mode\": 0,\n    \"lock\": false,\n    \"lockMoney\": 0,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240222-600678 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5500,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240222-601996 = "{\n    \"setting_mode\": 0,\n    \"lock\": false,\n    \"lockMoney\": 0,\n    \"lockBuy\": true,\n    \"lockBuyMoney\": 300,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240222-000514 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240222-002912 = "{\n    \"setting_mode\": 0,\n    \"lock\": false,\n    \"lockMoney\": 0,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240222-600692 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 6000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240222-603607 = "{\n    \"setting_mode\": 0,\n    \"lock\": false,\n    \"lockMoney\": 0,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240222-000717 = "{\n    \"setting_mode\": 0,\n    \"lock\": false,\n    \"lockMoney\": 0,\n    \"lockBuy\": true,\n    \"lockBuyMoney\": 300,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240222-603990 = "{\n    \"setting_mode\": 0,\n    \"lock\": false,\n    \"lockMoney\": 0,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240222-603860 = "{\n    \"setting_mode\": 0,\n    \"lock\": false,\n    \"lockMoney\": 0,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240222-603536 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-002587 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-002868 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": true,\n    \"lockBuyMoney\": 2000,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-002164 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-603109 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-002725 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-002611 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-002819 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": true,\n    \"lockBuyMoney\": 3000,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-000518 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-000020 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-000593 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-000802 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-000862 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-002094 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-002280 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-002902 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-002975 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-002990 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-003029 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-600088 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-600193 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-600321 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-600636 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-600783 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-601107 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-601127 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-603135 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-603629 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-002308 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-002435 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-002579 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-002882 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-601966 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240223-601996 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240228-600053 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240228-600830 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240228-603798 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
sell_setting-20240228-002902 = "{\n    \"setting_mode\": 0,\n    \"lock\": true,\n    \"lockMoney\": 5000,\n    \"lockBuy\": false,\n    \"lockBuyMoney\": 0,\n    \"mode1_rate_index\": 4,\n    \"mode2_first_index\": 0,\n    \"mode2_left_index\": 0\n}";
FloatTrade/res/ic_bg.bmp
FloatTrade/res/ic_close_red.png
FloatTrade/resource.h
@@ -9,18 +9,19 @@
#define IDD_BUY                         135
#define IDD_DIALOG_SELL_RULE            141
#define IDD_DIALOG_TIPS                 143
#define IDD_DIALOG_SELL                 147
#define IDB_BITMAP_BG                   152
#define IDB_PNG1                        153
#define IDB_PNG_CLOSE                   153
#define btn_already_canceled            1000
#define btn_sell                        1001
#define btn_white                       1002
#define btn_remove_white                1003
#define btn_pause_buy_list              1004
#define label_atrribute                 1005
#define btn_black                       1006
#define btn_remove_black                1007
#define btn_white_list                  1008
#define btn_black_list                  1009
#define btn_pause_buy                   1010
#define btn_pause_buy_remove            1011
#define btn_want_list                   1012
#define btn_want_buy                    1013
#define btn_want_buy_remove             1014
@@ -35,9 +36,9 @@
#define btn_buy                         1023
#define btn_config                      1024
#define edit_trade_refresh_space_time   1025
#define btn_code_trade_info             1025
#define edit_trade_group_space_time     1026
#define edit_group_pos                  1027
#define btn_code_trade_info             1028
#define btn_sure                        1029
#define edit_price                      1031
#define edit_money                      1032
@@ -45,36 +46,82 @@
#define IDC_EDIT_BUY1_VOLUME            1049
#define IDC_EDIT_SELL_VOLUME            1050
#define IDC_EDIT_END_TIME               1051
#define IDC_EDIT_BUY_VOLUME             1051
#define IDC_EDIT_BUY1_PRICE             1052
#define IDC_EDIT_CODE3                  1052
#define IDC_BUTTON_CLEAR                1053
#define IDC_BUTTON_DELETE               1054
#define IDC_STATIC_ID                   1055
#define IDC_BUTTON_ADD                  1056
#define IDC_LIST_RULES                  1057
#define IDC_EDIT_CODE2                  1058
#define IDC_COMBO_SELL_PRICE            1059
#define IDC_STATIC_ID2                  1059
#define IDC_BUTTON_SELL_VOLUME_1        1060
#define IDC_BUTTON_SELL_VOLUME_10       1061
#define IDC_BUTTON_SELL_VOLUME_9        1062
#define IDC_BUTTON_CLEAR2               1060
#define IDC_EDIT_SELL_VOLUME2           1061
#define IDC_EDIT_END_TIME2              1062
#define IDC_BUTTON_SELL_VOLUME_3        1063
#define IDC_BUTTON_SELL_VOLUME_8        1064
#define IDC_BUTTON_SELL_VOLUME_7        1065
#define IDC_BUTTON_SELL_VOLUME_6        1066
#define IDC_EDIT_BUY1_PRICE2            1063
#define IDC_BUTTON_DELETE2              1064
#define IDC_BUTTON_ADD2                 1065
#define IDC_BUTTON_UPDATE               1066
#define IDC_BUTTON_SELL_VOLUME_4        1067
#define IDC_BUTTON_UPDATE2              1067
#define IDC_BUTTON_SELL_VOLUME_2        1068
#define IDC_BUTTON_DELETE3              1068
#define IDC_BUTTON_FILL_VOLUME          1068
#define IDC_BUTTON_SELL_VOLUME_5        1069
#define IDC_STATIC_ID3                  1069
#define IDC_EDIT_BUY1_VOLUME2           1070
#define IDC_STATIC_TOTAL_POSITION       1071
#define IDC_BUTTON_FILL_VOLUME2         1071
#define IDC_STATIC_ALREADY_SELL         1072
#define IDC_EDIT_END_TIME3              1072
#define IDC_STATIC_MSG                  1073
#define IDC_COMBO1                      1074
#define IDC_BUTTON_CLEAR3               1073
#define IDC_COMBO_SELL_PRICE_TYPE       1074
#define IDC_BUTTON_REFRESH              1075
#define IDC_COMBO_SELL_PRICE_TYPE2      1075
#define IDC_BUTTON_MUST_LIST            1076
#define IDC_BUTTON_DELETE4              1076
#define IDC_BUTTON_ADD_MUST             1077
#define IDC_BUTTON_ADD3                 1077
#define IDC_BUTTON_REMOVE_MUST          1078
#define IDC_BUTTON_UPDATE3              1078
#define IDC_CHECK_LOCK_SELL_VOLUME      1079
#define IDC_RADIO1                      1080
#define IDC_RADIO2                      1081
#define IDC_COMBO_SELL_FIRST            1082
#define IDC_COMBO2                      1083
#define IDC_BUTTON_ADD_WANT             1083
#define IDC_CHECK_MARKET_SITUATION      1084
#define IDC_COMBO_SELL_LEFT             1085
#define IDC_BUTTON_REMOVE_WANT          1086
#define IDC_BUTTON_WANT_LIST            1087
#define IDC_MFCBUTTON1                  1088
#define IDC_MFCBUTTON2                  1089
#define IDC_CHECK_LOCK_BUY_VOLUME       1089
#define IDC_MFCBUTTON_FLASH_INFO        1090
#define IDC_MFCBUTTON_SELL              1091
#define IDC_BUTTON_CLOSE                1092
#define IDC_BUTTON_GET_POSITIONS        1092
#define IDC_SPIN1                       1093
#define IDC_SPIN_VOLUME                 1093
#define IDC_BUTTON_GET_POSITION         1094
#define IDC_STATIC_POSITION             1095
#define IDC_BUTTON_GET_POSITION2        1096
#define IDC_STATIC_POSITION2            1097
#define IDC_STATIC_POSITION3            1098
#define IDC_STATIC_BUY1_MONEY           1098
// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        145
#define _APS_NEXT_RESOURCE_VALUE        154
#define _APS_NEXT_COMMAND_VALUE         32771
#define _APS_NEXT_CONTROL_VALUE         1075
#define _APS_NEXT_CONTROL_VALUE         1096
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif
TradeRecord/ConfigUtil.cpp
New file
@@ -0,0 +1,119 @@
#include "common/pch.h"
#include "ConfigUtil.h"
#include <iostream>
#include <fstream>
#include "../common/JsonUtil.h"
bool fileExists(const std::string& filename) {
    std::ifstream file(filename);
    return file.good(); // 如果文件成功打开,则返回 true
}
void ConfigUtil::readConfig(libconfig::Config& config)
{
    string strConfPath = "config.cfg";
    if (!fileExists(strConfPath)) {
        std::ofstream file(strConfPath);
        file.is_open();
    }
    //解读配置文件
    try {
        config.readFile(strConfPath.c_str());
    }
    catch (const libconfig::FileIOException& fioex) {
        std::cerr << "I/O exception while reading the file." << std::endl;
    }
    catch (const libconfig::ParseException& pex) {
        std::cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine()
            << " - " << pex.getError() << std::endl;
    }
}
void ConfigUtil::writeConfig(libconfig::Config& config)
{
    config.writeFile("config.cfg");
}
int ConfigUtil::readIntConfig(const char* key)
{
    libconfig::Config mConfig;
    readConfig(mConfig);
    libconfig::Setting& root = mConfig.getRoot();
    if (root.exists(key)) {
        int val;
        root.lookupValue(key, val);
        return val;
    }
    throw string("尚未获取到内容");
}
string ConfigUtil::readStringConfig(const char* key)
{
    libconfig::Config mConfig;
    readConfig(mConfig);
    libconfig::Setting& root = mConfig.getRoot();
    if (root.exists(key)) {
        //string val;
        const char* val;
        root.lookupValue(key, val);
        return string(val);
    }
    throw string("尚未获取到内容");
}
void ConfigUtil::setIntConfig(const char* key, int val) {
    libconfig::Config mConfig;
    readConfig(mConfig);
    libconfig::Setting& root = mConfig.getRoot();
    if (root.exists(key)) {
        root[key] = val;
    }
    else {
        root.add(key, libconfig::Setting::TypeInt) = val;
    }
    writeConfig(mConfig);
}
void ConfigUtil::setStringConfig(const char* key, string val) {
    libconfig::Config mConfig;
    readConfig(mConfig);
    libconfig::Setting& root = mConfig.getRoot();
    if (root.exists(key)) {
        root[key] = val.c_str();
    }
    else {
        root.add(key, libconfig::Setting::TypeString) = val.c_str();
    }
    writeConfig(mConfig);
}
POINT ConfigUtil::getWindowPos()
{
    // 页码位置
    try {
        string data = readStringConfig("window_pos");
        rapidjson::Document root = JsonUtil::parseUTF8(data);
        return     POINT({ root[0].GetInt(), root[1].GetInt() });
    }
    catch (...) {
    }
    return POINT({ 0,0 });
}
void ConfigUtil::setWindowPos(int x, int y)
{
    string st = "[";
    st.append(std::to_string(x)).append(",").append(std::to_string(y)).append("]");
    setStringConfig("window_pos", st);
}
TradeRecord/ConfigUtil.h
New file
@@ -0,0 +1,30 @@
#pragma once
#include<string>
#include <libconfig.h++>
#include<list>
using namespace std;
class ConfigUtil
{
private:
    static void readConfig(libconfig::Config& config);
    static void writeConfig(libconfig::Config& config);
    static int readIntConfig(const char* key);
    static string readStringConfig(const char* key);
    static void setIntConfig(const char* key, int val);
    static void setStringConfig(const char* key, string val);
public:
    // 窗口位置
    static POINT getWindowPos();
    static void setWindowPos(int x, int y);
};
TradeRecord/TradeRecord.aps
Binary files differ
TradeRecord/TradeRecord.rc
Binary files differ
TradeRecord/TradeRecord.vcxproj
@@ -93,9 +93,12 @@
      <SDLCheck>true</SDLCheck>
      <PreprocessorDefinitions>_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <PrecompiledHeaderFile>common/pch.h</PrecompiledHeaderFile>
      <AdditionalIncludeDirectories>D:\workspace\GP\trade_desk_cplus\TradeDesk\TradeRecord\lib_config\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ClCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <AdditionalLibraryDirectories>D:\workspace\GP\trade_desk_cplus\TradeDesk\TradeRecord\lib_config\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
      <AdditionalDependencies>libconfig++.lib;</AdditionalDependencies>
    </Link>
    <Midl>
      <MkTypLibCompatible>false</MkTypLibCompatible>
@@ -193,6 +196,7 @@
    <ClInclude Include="..\common\StringUtil.h" />
    <ClInclude Include="..\common\targetver.h" />
    <ClInclude Include="..\common\Win32Util.h" />
    <ClInclude Include="ConfigUtil.h" />
    <ClInclude Include="Resource.h" />
    <ClInclude Include="TradeRecord.h" />
    <ClInclude Include="TradeRecordDlg.h" />
@@ -204,6 +208,7 @@
    <ClCompile Include="..\common\pch.cpp" />
    <ClCompile Include="..\common\SocketManager.cpp" />
    <ClCompile Include="..\common\Win32Util.cpp" />
    <ClCompile Include="ConfigUtil.cpp" />
    <ClCompile Include="TradeRecord.cpp" />
    <ClCompile Include="TradeRecordDlg.cpp" />
  </ItemGroup>
TradeRecord/TradeRecord.vcxproj.filters
@@ -60,6 +60,9 @@
    <ClInclude Include="..\common\Win32Util.h">
      <Filter>头文件\common</Filter>
    </ClInclude>
    <ClInclude Include="ConfigUtil.h">
      <Filter>头文件</Filter>
    </ClInclude>
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="TradeRecord.cpp">
@@ -86,6 +89,9 @@
    <ClCompile Include="..\common\Win32Util.cpp">
      <Filter>源文件\common</Filter>
    </ClCompile>
    <ClCompile Include="ConfigUtil.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="TradeRecord.rc">
TradeRecord/TradeRecord.vcxproj.user
@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup />
  <PropertyGroup>
    <RESOURCE_FILE>TradeRecord.rc</RESOURCE_FILE>
  </PropertyGroup>
</Project>
TradeRecord/TradeRecordDlg.cpp
@@ -11,6 +11,7 @@
#include <map>
#include "../common/NetworkApi.h"
#include "../common/JsonUtil.h"
#include "ConfigUtil.h"
// TradeRecordDlg 对话框
@@ -25,7 +26,11 @@
void TradeRecordDlg::initView()
{
    // 设置位置
    POINT p = ConfigUtil::getWindowPos();
    RECT re;
    Win32Util::getWindowRect(GetSafeHwnd(), &re);
    Win32Util::moveWin(GetSafeHwnd(), p.x, p.y, (re.right - re.left + 1), (re.bottom - re.top + 1));
    //初始化列表
@@ -66,12 +71,17 @@
                break;
            }
            if (doc.IsObject() && doc[L"code"].GetInt() == 0) {
                if (!doc.HasMember(L"data"))
                    continue;
                if (!doc[L"data"].HasMember(L"list"))
                    continue;
                list<TradeDelegateRecord> tempRecordList;
                //解析结果
               auto dataList =    doc[L"data"][L"list"].GetArray();
               if (dataList.Size() > 0)
               {
                   dlg->updateTime = doc[L"data"][L"updateTime"].GetString();
                   if(doc[L"data"].HasMember(L"updateTime"))
                     dlg->updateTime = doc[L"data"][L"updateTime"].GetString();
               }
                for (int i = 0; i < dataList.Size(); i++) {
                    TradeDelegateRecord record;
@@ -139,8 +149,6 @@
                                }
                            }
                        }
                    }
@@ -511,5 +519,8 @@
    kill = TRUE;
    recordList.clear();
    updateTime = "";
    RECT rect;
    Win32Util::getWindowRect(GetSafeHwnd(), &rect);
    ConfigUtil::setWindowPos(rect.left, rect.top);
    CDialogEx::OnClose();
}
TradeRecord/config.cfg
New file
@@ -0,0 +1 @@
window_pos = "[-725,118]";
TradeRecord/lib_config.zip
Binary files differ
TradeRecord/lib_config/include/libconfig.h
New file
@@ -0,0 +1,355 @@
/* ----------------------------------------------------------------------------
   libconfig - A library for processing structured configuration files
   Copyright (C) 2005-2018  Mark A Lindner
   This file is part of libconfig.
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public License
   as published by the Free Software Foundation; either version 2.1 of
   the License, or (at your option) any later version.
   This library is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.
   You should have received a copy of the GNU Library General Public
   License along with this library; if not, see
   <http://www.gnu.org/licenses/>.
   ----------------------------------------------------------------------------
*/
#ifndef __libconfig_h
#define __libconfig_h
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
#if defined(LIBCONFIG_STATIC)
#define LIBCONFIG_API
#elif defined(LIBCONFIG_EXPORTS)
#define LIBCONFIG_API __declspec(dllexport)
#else /* ! LIBCONFIG_EXPORTS */
#define LIBCONFIG_API __declspec(dllimport)
#endif /* LIBCONFIG_STATIC */
#else /* ! WIN32 */
#define LIBCONFIG_API
#endif /* WIN32 */
#define LIBCONFIG_VER_MAJOR    1
#define LIBCONFIG_VER_MINOR    7
#define LIBCONFIG_VER_REVISION 0
#include <stdio.h>
#define CONFIG_TYPE_NONE    0
#define CONFIG_TYPE_GROUP   1
#define CONFIG_TYPE_INT     2
#define CONFIG_TYPE_INT64   3
#define CONFIG_TYPE_FLOAT   4
#define CONFIG_TYPE_STRING  5
#define CONFIG_TYPE_BOOL    6
#define CONFIG_TYPE_ARRAY   7
#define CONFIG_TYPE_LIST    8
#define CONFIG_FORMAT_DEFAULT  0
#define CONFIG_FORMAT_HEX      1
#define CONFIG_OPTION_AUTOCONVERT                     0x01
#define CONFIG_OPTION_SEMICOLON_SEPARATORS            0x02
#define CONFIG_OPTION_COLON_ASSIGNMENT_FOR_GROUPS     0x04
#define CONFIG_OPTION_COLON_ASSIGNMENT_FOR_NON_GROUPS 0x08
#define CONFIG_OPTION_OPEN_BRACE_ON_SEPARATE_LINE     0x10
#define CONFIG_OPTION_ALLOW_SCIENTIFIC_NOTATION       0x20
#define CONFIG_OPTION_FSYNC                           0x40
#define CONFIG_OPTION_ALLOW_OVERRIDES                 0x80
#define CONFIG_TRUE  (1)
#define CONFIG_FALSE (0)
typedef union config_value_t
{
  int ival;
  long long llval;
  double fval;
  char *sval;
  struct config_list_t *list;
} config_value_t;
typedef struct config_setting_t
{
  char *name;
  short type;
  short format;
  config_value_t value;
  struct config_setting_t *parent;
  struct config_t *config;
  void *hook;
  unsigned int line;
  const char *file;
} config_setting_t;
typedef enum
{
  CONFIG_ERR_NONE = 0,
  CONFIG_ERR_FILE_IO = 1,
  CONFIG_ERR_PARSE = 2
} config_error_t;
typedef struct config_list_t
{
  unsigned int length;
  config_setting_t **elements;
} config_list_t;
typedef const char ** (*config_include_fn_t)(struct config_t *,
                                             const char *,
                                             const char *,
                                             const char **);
typedef struct config_t
{
  config_setting_t *root;
  void (*destructor)(void *);
  int options;
  unsigned short tab_width;
  unsigned short float_precision;
  unsigned short default_format;
  const char *include_dir;
  config_include_fn_t include_fn;
  const char *error_text;
  const char *error_file;
  int error_line;
  config_error_t error_type;
  const char **filenames;
  void *hook;
} config_t;
extern LIBCONFIG_API int config_read(config_t *config, FILE *stream);
extern LIBCONFIG_API void config_write(const config_t *config, FILE *stream);
extern LIBCONFIG_API void config_set_default_format(config_t *config,
                                                    short format);
extern LIBCONFIG_API void config_set_options(config_t *config, int options);
extern LIBCONFIG_API int config_get_options(const config_t *config);
extern LIBCONFIG_API void config_set_option(config_t *config, int option,
                                            int flag);
extern LIBCONFIG_API int config_get_option(const config_t *config, int option);
extern LIBCONFIG_API int config_read_string(config_t *config, const char *str);
extern LIBCONFIG_API int config_read_file(config_t *config,
                                          const char *filename);
extern LIBCONFIG_API int config_write_file(config_t *config,
                                           const char *filename);
extern LIBCONFIG_API void config_set_destructor(config_t *config,
                                                void (*destructor)(void *));
extern LIBCONFIG_API void config_set_include_dir(config_t *config,
                                                 const char *include_dir);
extern LIBCONFIG_API void config_set_include_func(config_t *config,
                                                  config_include_fn_t func);
extern LIBCONFIG_API void config_set_float_precision(config_t *config,
                                                     unsigned short digits);
extern LIBCONFIG_API unsigned short config_get_float_precision(
  const config_t *config);
extern LIBCONFIG_API void config_set_tab_width(config_t *config,
                                               unsigned short width);
extern LIBCONFIG_API unsigned short config_get_tab_width(
  const config_t *config);
extern LIBCONFIG_API void config_set_hook(config_t *config, void *hook);
#define config_get_hook(C) ((C)->hook)
extern LIBCONFIG_API void config_init(config_t *config);
extern LIBCONFIG_API void config_destroy(config_t *config);
extern LIBCONFIG_API void config_clear(config_t *config);
extern LIBCONFIG_API int config_setting_get_int(
  const config_setting_t *setting);
extern LIBCONFIG_API long long config_setting_get_int64(
  const config_setting_t *setting);
extern LIBCONFIG_API double config_setting_get_float(
  const config_setting_t *setting);
extern LIBCONFIG_API int config_setting_get_bool(
  const config_setting_t *setting);
extern LIBCONFIG_API const char *config_setting_get_string(
  const config_setting_t *setting);
extern LIBCONFIG_API int config_setting_lookup_int(
  const config_setting_t *setting, const char *name, int *value);
extern LIBCONFIG_API int config_setting_lookup_int64(
  const config_setting_t *setting, const char *name, long long *value);
extern LIBCONFIG_API int config_setting_lookup_float(
  const config_setting_t *setting, const char *name, double *value);
extern LIBCONFIG_API int config_setting_lookup_bool(
  const config_setting_t *setting, const char *name, int *value);
extern LIBCONFIG_API int config_setting_lookup_string(
  const config_setting_t *setting, const char *name, const char **value);
extern LIBCONFIG_API int config_setting_set_int(config_setting_t *setting,
                                                int value);
extern LIBCONFIG_API int config_setting_set_int64(config_setting_t *setting,
                                                  long long value);
extern LIBCONFIG_API int config_setting_set_float(config_setting_t *setting,
                                                  double value);
extern LIBCONFIG_API int config_setting_set_bool(config_setting_t *setting,
                                                 int value);
extern LIBCONFIG_API int config_setting_set_string(config_setting_t *setting,
                                                   const char *value);
extern LIBCONFIG_API int config_setting_set_format(config_setting_t *setting,
                                                   short format);
extern LIBCONFIG_API short config_setting_get_format(
  const config_setting_t *setting);
extern LIBCONFIG_API int config_setting_get_int_elem(
  const config_setting_t *setting, int idx);
extern LIBCONFIG_API long long config_setting_get_int64_elem(
  const config_setting_t *setting, int idx);
extern LIBCONFIG_API double config_setting_get_float_elem(
  const config_setting_t *setting, int idx);
extern LIBCONFIG_API int config_setting_get_bool_elem(
  const config_setting_t *setting, int idx);
extern LIBCONFIG_API const char *config_setting_get_string_elem(
  const config_setting_t *setting, int idx);
extern LIBCONFIG_API config_setting_t *config_setting_set_int_elem(
  config_setting_t *setting, int idx, int value);
extern LIBCONFIG_API config_setting_t *config_setting_set_int64_elem(
  config_setting_t *setting, int idx, long long value);
extern LIBCONFIG_API config_setting_t *config_setting_set_float_elem(
  config_setting_t *setting, int idx, double value);
extern LIBCONFIG_API config_setting_t *config_setting_set_bool_elem(
  config_setting_t *setting, int idx, int value);
extern LIBCONFIG_API config_setting_t *config_setting_set_string_elem(
  config_setting_t *setting, int idx, const char *value);
extern LIBCONFIG_API const char **config_default_include_func(
    config_t *config, const char *include_dir, const char *path,
    const char **error);
extern LIBCONFIG_API int config_setting_is_scalar(
    const config_setting_t *setting);
extern LIBCONFIG_API int config_setting_is_aggregate(
    const config_setting_t *setting);
#define /* const char * */ config_get_include_dir(/* const config_t * */ C) \
  ((C)->include_dir)
#define /* void */ config_set_auto_convert(/* config_t * */ C, F) \
  config_set_option((C), CONFIG_OPTION_AUTOCONVERT, (F))
#define /* int */ config_get_auto_convert(/* const config_t * */ C) \
  config_get_option((C), CONFIG_OPTION_AUTOCONVERT)
#define /* int */ config_setting_type(/* const config_setting_t * */ S) \
  ((S)->type)
#define /* int */ config_setting_is_group(/* const config_setting_t * */ S) \
  ((S)->type == CONFIG_TYPE_GROUP)
#define /* int */ config_setting_is_array(/* const config_setting_t * */ S) \
  ((S)->type == CONFIG_TYPE_ARRAY)
#define /* int */ config_setting_is_list(/* const config_setting_t * */ S) \
  ((S)->type == CONFIG_TYPE_LIST)
#define /* int */ config_setting_is_number(/* const config_setting_t * */ S) \
  (((S)->type == CONFIG_TYPE_INT)                                       \
   || ((S)->type == CONFIG_TYPE_INT64)                                  \
   || ((S)->type == CONFIG_TYPE_FLOAT))
#define /* const char * */ config_setting_name( \
  /* const config_setting_t * */ S)             \
  ((S)->name)
#define /* config_setting_t * */ config_setting_parent( \
  /* const config_setting_t * */ S)                     \
  ((S)->parent)
#define /* int */ config_setting_is_root(       \
  /* const config_setting_t * */ S)             \
  ((S)->parent ? CONFIG_FALSE : CONFIG_TRUE)
extern LIBCONFIG_API int config_setting_index(const config_setting_t *setting);
extern LIBCONFIG_API int config_setting_length(
  const config_setting_t *setting);
extern LIBCONFIG_API config_setting_t *config_setting_get_elem(
  const config_setting_t *setting, unsigned int idx);
extern LIBCONFIG_API config_setting_t *config_setting_get_member(
  const config_setting_t *setting, const char *name);
extern LIBCONFIG_API config_setting_t *config_setting_add(
  config_setting_t *parent, const char *name, int type);
extern LIBCONFIG_API int config_setting_remove(config_setting_t *parent,
                                               const char *name);
extern LIBCONFIG_API int config_setting_remove_elem(config_setting_t *parent,
                                                    unsigned int idx);
extern LIBCONFIG_API void config_setting_set_hook(config_setting_t *setting,
                                                  void *hook);
#define config_setting_get_hook(S) ((S)->hook)
extern LIBCONFIG_API config_setting_t *config_lookup(const config_t *config,
                                                     const char *path);
extern LIBCONFIG_API config_setting_t *config_setting_lookup(
  config_setting_t *setting, const char *path);
extern LIBCONFIG_API int config_lookup_int(const config_t *config,
                                           const char *path, int *value);
extern LIBCONFIG_API int config_lookup_int64(const config_t *config,
                                             const char *path,
                                             long long *value);
extern LIBCONFIG_API int config_lookup_float(const config_t *config,
                                             const char *path, double *value);
extern LIBCONFIG_API int config_lookup_bool(const config_t *config,
                                            const char *path, int *value);
extern LIBCONFIG_API int config_lookup_string(const config_t *config,
                                              const char *path,
                                              const char **value);
#define /* config_setting_t * */ config_root_setting( \
  /* const config_t * */ C)                           \
  ((C)->root)
#define  /* void */ config_set_default_format(/* config_t * */ C,       \
                                              /* short */ F)            \
  (C)->default_format = (F)
#define /* short */ config_get_default_format(/* config_t * */ C)       \
  ((C)->default_format)
#define /* unsigned short */ config_setting_source_line(   \
  /* const config_setting_t * */ S)                        \
  ((S)->line)
#define /* const char */ config_setting_source_file(    \
  /* const config_setting_t * */ S)                     \
  ((S)->file)
#define /* const char * */ config_error_text(/* const config_t * */ C)  \
  ((C)->error_text)
#define /* const char * */ config_error_file(/* const config_t * */ C)  \
  ((C)->error_file)
#define /* int */ config_error_line(/* const config_t * */ C)   \
  ((C)->error_line)
#define /* config_error_t */ config_error_type(/* const config_t * */ C) \
  ((C)->error_type)
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __libconfig_h */
TradeRecord/lib_config/include/libconfig.h++
New file
@@ -0,0 +1,574 @@
/* ----------------------------------------------------------------------------
   libconfig - A library for processing structured configuration files
   Copyright (C) 2005-2018  Mark A Lindner
   This file is part of libconfig.
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public License
   as published by the Free Software Foundation; either version 2.1 of
   the License, or (at your option) any later version.
   This library is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.
   You should have received a copy of the GNU Library General Public
   License along with this library; if not, see
   <http://www.gnu.org/licenses/>.
   ----------------------------------------------------------------------------
*/
#ifndef __libconfig_hpp
#define __libconfig_hpp
#include <stdio.h>
#include <exception>
#include <string>
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
#if defined(LIBCONFIGXX_STATIC)
#define LIBCONFIGXX_API
#elif defined(LIBCONFIGXX_EXPORTS)
#define LIBCONFIGXX_API __declspec(dllexport)
#else /* ! LIBCONFIGXX_EXPORTS */
#define LIBCONFIGXX_API __declspec(dllimport)
#endif /* LIBCONFIGXX_STATIC */
#else /* ! WIN32 */
#define LIBCONFIGXX_API
#endif /* WIN32 */
#define LIBCONFIGXX_VER_MAJOR    1
#define LIBCONFIGXX_VER_MINOR    7
#define LIBCONFIGXX_VER_REVISION 0
#if __cplusplus < 201103L
#define LIBCONFIGXX_NOEXCEPT throw()
#else
#define LIBCONFIGXX_NOEXCEPT noexcept
#endif
struct config_t; // fwd decl
struct config_setting_t; // fwd decl
namespace libconfig {
class LIBCONFIGXX_API ConfigException : public std::exception { };
class Setting; // fwd decl
class SettingIterator;
class SettingConstIterator;
class LIBCONFIGXX_API SettingException : public ConfigException
{
  public:
  SettingException(const Setting &setting);
  SettingException(const Setting &setting, int idx);
  SettingException(const Setting &setting, const char *name);
  SettingException(const char *path);
  SettingException(const SettingException &other);
  SettingException& operator=(const SettingException &other);
  virtual ~SettingException() LIBCONFIGXX_NOEXCEPT;
  const char *getPath() const;
  virtual const char *what() const LIBCONFIGXX_NOEXCEPT;
  private:
  char *_path;
};
class LIBCONFIGXX_API SettingTypeException : public SettingException
{
  public:
  SettingTypeException(const Setting &setting);
  SettingTypeException(const Setting &setting, int idx);
  SettingTypeException(const Setting &setting, const char *name);
  virtual const char *what() const LIBCONFIGXX_NOEXCEPT;
};
class LIBCONFIGXX_API SettingNotFoundException : public SettingException
{
  public:
  SettingNotFoundException(const char *path);
  SettingNotFoundException(const Setting &setting, int idx);
  SettingNotFoundException(const Setting &setting, const char *name);
  virtual const char *what() const LIBCONFIGXX_NOEXCEPT;
};
class LIBCONFIGXX_API SettingNameException : public SettingException
{
  public:
  SettingNameException(const Setting &setting, const char *name);
  virtual const char *what() const LIBCONFIGXX_NOEXCEPT;
};
class LIBCONFIGXX_API FileIOException : public ConfigException
{
  public:
  virtual const char *what() const LIBCONFIGXX_NOEXCEPT;
};
class LIBCONFIGXX_API ParseException : public ConfigException
{
  public:
  ParseException(const char *file, int line, const char *error);
  ParseException(const ParseException &other);
  virtual ~ParseException() LIBCONFIGXX_NOEXCEPT;
  inline const char *getFile() const
  { return(_file); }
  inline int getLine() const
  { return(_line); }
  inline const char *getError() const
  { return(_error); }
  virtual const char *what() const LIBCONFIGXX_NOEXCEPT;
  private:
  const char *_file;
  int _line;
  const char *_error;
};
class LIBCONFIGXX_API Setting
{
  friend class Config;
  public:
  enum Type
  {
    TypeNone = 0,
    // scalar types
    TypeInt,
    TypeInt64,
    TypeFloat,
    TypeString,
    TypeBoolean,
    // aggregate types
    TypeGroup,
    TypeArray,
    TypeList
  };
  enum Format
  {
    FormatDefault = 0,
    FormatHex = 1
  };
  typedef SettingIterator iterator;
  typedef SettingConstIterator const_iterator;
  public:
  virtual ~Setting();
  inline Type getType() const { return(_type); }
  inline Format getFormat() const { return(_format); }
  void setFormat(Format format);
  operator bool() const;
  operator int() const;
  operator unsigned int() const;
  operator long() const;
  operator unsigned long() const;
  operator long long() const;
  operator unsigned long long() const;
  operator double() const;
  operator float() const;
  operator const char *() const;
  operator std::string() const;
  inline const char *c_str() const
  { return operator const char *(); }
  Setting & operator=(bool value);
  Setting & operator=(int value);
  Setting & operator=(long value);
  Setting & operator=(const long long &value);
  Setting & operator=(const double &value);
  Setting & operator=(float value);
  Setting & operator=(const char *value);
  Setting & operator=(const std::string &value);
  Setting & lookup(const char *path) const;
  inline Setting & lookup(const std::string &path) const
  { return(lookup(path.c_str())); }
  Setting & operator[](const char *name) const;
  inline Setting & operator[](const std::string &name) const
  { return(operator[](name.c_str())); }
  Setting & operator[](int index) const;
  bool lookupValue(const char *name, bool &value) const;
  bool lookupValue(const char *name, int &value) const;
  bool lookupValue(const char *name, unsigned int &value) const;
  bool lookupValue(const char *name, long long &value) const;
  bool lookupValue(const char *name, unsigned long long &value) const;
  bool lookupValue(const char *name, double &value) const;
  bool lookupValue(const char *name, float &value) const;
  bool lookupValue(const char *name, const char *&value) const;
  bool lookupValue(const char *name, std::string &value) const;
  inline bool lookupValue(const std::string &name, bool &value) const
  { return(lookupValue(name.c_str(), value)); }
  inline bool lookupValue(const std::string &name, int &value) const
  { return(lookupValue(name.c_str(), value)); }
  inline bool lookupValue(const std::string &name, unsigned int &value) const
  { return(lookupValue(name.c_str(), value)); }
  inline bool lookupValue(const std::string &name, long long &value) const
  { return(lookupValue(name.c_str(), value)); }
  inline bool lookupValue(const std::string &name,
                          unsigned long long &value) const
  { return(lookupValue(name.c_str(), value)); }
  inline bool lookupValue(const std::string &name, double &value) const
  { return(lookupValue(name.c_str(), value)); }
  inline bool lookupValue(const std::string &name, float &value) const
  { return(lookupValue(name.c_str(), value)); }
  inline bool lookupValue(const std::string &name, const char *&value) const
  { return(lookupValue(name.c_str(), value)); }
  inline bool lookupValue(const std::string &name, std::string &value) const
  { return(lookupValue(name.c_str(), value)); }
  void remove(const char *name);
  inline void remove(const std::string &name)
  { remove(name.c_str()); }
  void remove(unsigned int idx);
  Setting & add(const char *name, Type type);
  inline Setting & add(const std::string &name, Type type)
  { return(add(name.c_str(), type)); }
  Setting & add(Type type);
  bool exists(const char *name) const;
  inline bool exists(const std::string &name) const
  { return(exists(name.c_str())); }
  int getLength() const;
  const char *getName() const;
  std::string getPath() const;
  int getIndex() const;
  const Setting & getParent() const;
  Setting & getParent();
  bool isRoot() const;
  inline bool isGroup() const
  { return(_type == TypeGroup); }
  inline bool isArray() const
  { return(_type == TypeArray); }
  inline bool isList() const
  { return(_type == TypeList); }
  inline bool isAggregate() const
  { return(_type >= TypeGroup); }
  inline bool isScalar() const
  { return((_type > TypeNone) && (_type < TypeGroup)); }
  inline bool isNumber() const
  {
    return((_type == TypeInt) || (_type == TypeInt64) || (_type == TypeFloat));
  }
  inline bool isString() const
  { return(_type == TypeString); }
  unsigned int getSourceLine() const;
  const char *getSourceFile() const;
  iterator begin();
  iterator end();
  const_iterator begin() const;
  const_iterator end() const;
  private:
  config_setting_t *_setting;
  Type _type;
  Format _format;
  Setting(config_setting_t *setting);
  void assertType(Type type) const;
  static Setting & wrapSetting(config_setting_t *setting);
  Setting(const Setting& other); // not supported
  Setting& operator=(const Setting& other); // not supported
};
class LIBCONFIGXX_API SettingIterator
{
  public:
  SettingIterator(Setting &setting, bool endIterator = false);
  SettingIterator(const SettingIterator &other);
  SettingIterator& operator=(const SettingIterator &other);
  // Equality comparison.
  inline bool operator==(SettingIterator const &other) const
  { return((_setting == other._setting) && (_idx == other._idx)); }
  inline bool operator!=(SettingIterator const &other) const
  { return(!operator==(other)); }
  bool operator<(SettingIterator const &other) const;
  // Dereference operators.
  inline Setting & operator*()
  { return((*_setting)[_idx]); }
  inline Setting * operator->()
  { return(&(*_setting)[_idx]); }
  inline const Setting & operator*() const
  { return(*_setting)[_idx]; }
  inline const Setting * operator->() const
  { return(&(*_setting)[_idx]); }
  // Increment and decrement operators.
  SettingIterator & operator++();
  SettingIterator operator++(int);
  SettingIterator & operator--();
  SettingIterator operator--(int);
  // Arithmetic operators.
  SettingIterator operator+(int offset) const;
  SettingIterator & operator+=(int offset);
  SettingIterator operator-(int offset) const;
  SettingIterator & operator-=(int offset);
  int operator-(const SettingIterator &other) const;
  private:
  Setting *_setting;
  int _count;
  int _idx;
};
SettingIterator operator+(int offset, const SettingIterator &si);
class LIBCONFIGXX_API SettingConstIterator
{
  public:
  SettingConstIterator(const Setting &setting, bool endIterator = false);
  SettingConstIterator(const SettingConstIterator &rhs);
  SettingConstIterator& operator=(const SettingConstIterator &rhs);
  // Equality comparison.
  bool operator==(SettingConstIterator const &other) const
  { return((_setting == other._setting) && (_idx == other._idx)); }
  inline bool operator!=(SettingConstIterator const &other) const
  { return(!operator==(other)); }
  // Dereference operators.
  inline Setting const & operator*()
  { return((*_setting)[_idx]); }
  inline Setting const * operator->()
  { return(&(*_setting)[_idx]); }
  inline const Setting& operator*() const
  { return((*_setting)[_idx]); }
  inline const Setting * operator->() const
  { return(&(*_setting)[_idx]); }
  // Increment and decrement operators.
  SettingConstIterator & operator++();
  SettingConstIterator operator++(int);
  SettingConstIterator & operator--();
  SettingConstIterator operator--(int);
  // Arithmetic operators.
  SettingConstIterator operator+(int offset) const;
  SettingConstIterator & operator+=(int offset);
  SettingConstIterator operator-(int offset) const;
  SettingConstIterator & operator-=(int offset);
  int operator-(const SettingConstIterator &other) const;
  private:
  const Setting *_setting;
  int _count;
  int _idx;
};
SettingConstIterator operator+(int offset, const SettingConstIterator &si);
class LIBCONFIGXX_API Config
{
  public:
  enum Option
  {
    OptionNone = 0,
    OptionAutoConvert = 0x01,
    OptionSemicolonSeparators = 0x02,
    OptionColonAssignmentForGroups = 0x04,
    OptionColonAssignmentForNonGroups = 0x08,
    OptionOpenBraceOnSeparateLine = 0x10,
    OptionAllowScientificNotation = 0x20,
    OptionFsync = 0x40,
    OptionAllowOverrides = 0x80
  };
  Config();
  virtual ~Config();
  void clear();
  void setOptions(int options);
  int getOptions() const;
  void setOption(Config::Option option, bool flag);
  bool getOption(Config::Option option) const;
  inline void setAutoConvert(bool flag)
  { setOption(Config::OptionAutoConvert, flag); }
  inline bool getAutoConvert() const
  { return(getOption(Config::OptionAutoConvert)); }
  void setDefaultFormat(Setting::Format format);
  inline Setting::Format getDefaultFormat() const
  { return(_defaultFormat); }
  void setTabWidth(unsigned short width);
  unsigned short getTabWidth() const;
  void setFloatPrecision(unsigned short digits);
  unsigned short getFloatPrecision() const;
  void setIncludeDir(const char *includeDir);
  const char *getIncludeDir() const;
  virtual const char **evaluateIncludePath(const char *path,
                                           const char **error);
  void read(FILE *stream);
  void write(FILE *stream) const;
  void readString(const char *str);
  inline void readString(const std::string &str)
  { return(readString(str.c_str())); }
  void readFile(const char *filename);
  inline void readFile(const std::string &filename)
  { readFile(filename.c_str()); }
  void writeFile(const char *filename);
  inline void writeFile(const std::string &filename)
  { writeFile(filename.c_str()); }
  Setting & lookup(const char *path) const;
  inline Setting & lookup(const std::string &path) const
  { return(lookup(path.c_str())); }
  bool exists(const char *path) const;
  inline bool exists(const std::string &path) const
  { return(exists(path.c_str())); }
  bool lookupValue(const char *path, bool &value) const;
  bool lookupValue(const char *path, int &value) const;
  bool lookupValue(const char *path, unsigned int &value) const;
  bool lookupValue(const char *path, long long &value) const;
  bool lookupValue(const char *path, unsigned long long &value) const;
  bool lookupValue(const char *path, double &value) const;
  bool lookupValue(const char *path, float &value) const;
  bool lookupValue(const char *path, const char *&value) const;
  bool lookupValue(const char *path, std::string &value) const;
  inline bool lookupValue(const std::string &path, bool &value) const
  { return(lookupValue(path.c_str(), value)); }
  inline bool lookupValue(const std::string &path, int &value) const
  { return(lookupValue(path.c_str(), value)); }
  inline bool lookupValue(const std::string &path, unsigned int &value) const
  { return(lookupValue(path.c_str(), value)); }
  inline bool lookupValue(const std::string &path, long long &value) const
  { return(lookupValue(path.c_str(), value)); }
  inline bool lookupValue(const std::string &path,
                          unsigned long long &value) const
  { return(lookupValue(path.c_str(), value)); }
  inline bool lookupValue(const std::string &path, double &value) const
  { return(lookupValue(path.c_str(), value)); }
  inline bool lookupValue(const std::string &path, float &value) const
  { return(lookupValue(path.c_str(), value)); }
  inline bool lookupValue(const std::string &path, const char *&value) const
  { return(lookupValue(path.c_str(), value)); }
  inline bool lookupValue(const std::string &path, std::string &value) const
  { return(lookupValue(path.c_str(), value)); }
  Setting & getRoot() const;
  private:
  static void ConfigDestructor(void *arg);
  void handleError() const;
  config_t *_config;
  Setting::Format _defaultFormat;
  Config(const Config& other); // not supported
  Config& operator=(const Config& other); // not supported
};
} // namespace libconfig
#endif // __libconfig_hpp
TradeRecord/libconfig++.dll
Binary files differ
TradeRecord/res/TradeRecord.ico

TradeRecord/res/TradeRecord.png
TradeRecord/resource.h
@@ -16,7 +16,7 @@
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        129
#define _APS_NEXT_RESOURCE_VALUE        131
#define _APS_NEXT_COMMAND_VALUE         32771
#define _APS_NEXT_CONTROL_VALUE         1000
#define _APS_NEXT_SYMED_VALUE           101
TradeRecordSetup/TradeRecordSetup.vdproj
@@ -15,6 +15,24 @@
    {
        "Entry"
        {
        "MsmKey" = "8:_0C17DD0BE4FF43DC8F0909F4A031363F"
        "OwnerKey" = "8:_UNDEFINED"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_1FE84B2B16C24D49AFD8F0427C4ACD28"
        "OwnerKey" = "8:_UNDEFINED"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_5622C7E9F6F34B69ACB97F6AE6BF18CC"
        "OwnerKey" = "8:_UNDEFINED"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_5CC6DA3851A04311AAE19163BAA6FCC6"
        "OwnerKey" = "8:_UNDEFINED"
        "MsmSig" = "8:_UNDEFINED"
@@ -22,6 +40,24 @@
        "Entry"
        {
        "MsmKey" = "8:_64C18390F6C048CBB05AB5D5510459D8"
        "OwnerKey" = "8:_UNDEFINED"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_6690B871B8E9452CBB3D7D1AFE63B342"
        "OwnerKey" = "8:_UNDEFINED"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_B380087551834DE9B619118ADE6726FE"
        "OwnerKey" = "8:_UNDEFINED"
        "MsmSig" = "8:_UNDEFINED"
        }
        "Entry"
        {
        "MsmKey" = "8:_E8D363F6037F4BCAAAFEF1D3E6EEEFAF"
        "OwnerKey" = "8:_UNDEFINED"
        "MsmSig" = "8:_UNDEFINED"
        }
@@ -43,6 +79,22 @@
        "PrivateKeyFile" = "8:"
        "TimeStampServer" = "8:"
        "InstallerBootstrapper" = "3:2"
            "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}"
            {
            "Enabled" = "11:TRUE"
            "PromptEnabled" = "11:TRUE"
            "PrerequisitesLocation" = "2:1"
            "Url" = "8:"
            "ComponentsUrl" = "8:"
                "Items"
                {
                    "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:.NETFramework,Version=v4.7.2"
                    {
                    "Name" = "8:Microsoft .NET Framework 4.7.2 (x86 and x64)"
                    "ProductCode" = "8:.NETFramework,Version=v4.7.2"
                    }
                }
            }
        }
        "Release"
        {
@@ -59,6 +111,14 @@
        "PrivateKeyFile" = "8:"
        "TimeStampServer" = "8:"
        "InstallerBootstrapper" = "3:2"
            "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}"
            {
            "Enabled" = "11:TRUE"
            "PromptEnabled" = "11:TRUE"
            "PrerequisitesLocation" = "2:1"
            "Url" = "8:"
            "ComponentsUrl" = "8:"
            }
        }
    }
    "Deployable"
@@ -80,10 +140,130 @@
        }
        "File"
        {
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_0C17DD0BE4FF43DC8F0909F4A031363F"
            {
            "SourcePath" = "8:dependency\\vcruntime140d.dll"
            "TargetName" = "8:vcruntime140d.dll"
            "Tag" = "8:"
            "Folder" = "8:_C878F4C043484E8F96972549E3434C5B"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:FALSE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1FE84B2B16C24D49AFD8F0427C4ACD28"
            {
            "SourcePath" = "8:dependency\\vcruntime140_1d.dll"
            "TargetName" = "8:vcruntime140_1d.dll"
            "Tag" = "8:"
            "Folder" = "8:_C878F4C043484E8F96972549E3434C5B"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:FALSE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_5622C7E9F6F34B69ACB97F6AE6BF18CC"
            {
            "SourcePath" = "8:dependency\\mfc140ud.dll"
            "TargetName" = "8:mfc140ud.dll"
            "Tag" = "8:"
            "Folder" = "8:_C878F4C043484E8F96972549E3434C5B"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:FALSE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_5CC6DA3851A04311AAE19163BAA6FCC6"
            {
            "SourcePath" = "8:..\\TradeRecord\\res\\TradeRecord.ico"
            "TargetName" = "8:TradeRecord.ico"
            "Tag" = "8:"
            "Folder" = "8:_C878F4C043484E8F96972549E3434C5B"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:FALSE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_6690B871B8E9452CBB3D7D1AFE63B342"
            {
            "SourcePath" = "8:dependency\\ucrtbased.dll"
            "TargetName" = "8:ucrtbased.dll"
            "Tag" = "8:"
            "Folder" = "8:_C878F4C043484E8F96972549E3434C5B"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:FALSE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B380087551834DE9B619118ADE6726FE"
            {
            "SourcePath" = "8:dependency\\GdiPlus.dll"
            "TargetName" = "8:GdiPlus.dll"
            "Tag" = "8:"
            "Folder" = "8:_C878F4C043484E8F96972549E3434C5B"
            "Condition" = "8:"
            "Transitive" = "11:FALSE"
            "Vital" = "11:TRUE"
            "ReadOnly" = "11:FALSE"
            "Hidden" = "11:FALSE"
            "System" = "11:FALSE"
            "Permanent" = "11:FALSE"
            "SharedLegacy" = "11:FALSE"
            "PackageAs" = "3:1"
            "Register" = "3:1"
            "Exclude" = "11:FALSE"
            "IsDependency" = "11:FALSE"
            "IsolateTo" = "8:"
            }
            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E8D363F6037F4BCAAAFEF1D3E6EEEFAF"
            {
            "SourcePath" = "8:dependency\\msvcp140d.dll"
            "TargetName" = "8:msvcp140d.dll"
            "Tag" = "8:"
            "Folder" = "8:_C878F4C043484E8F96972549E3434C5B"
            "Condition" = "8:"
@@ -157,7 +337,7 @@
        "Name" = "8:Microsoft Visual Studio"
        "ProductName" = "8:交易列表"
        "ProductCode" = "8:{D1C9675C-AB49-451C-9DFB-4C9FC5231596}"
        "PackageCode" = "8:{39752BD0-4CDB-4AAB-A85A-C5BE43BCF8AB}"
        "PackageCode" = "8:{D1863254-B1FD-4CA8-84B9-507517B20695}"
        "UpgradeCode" = "8:{5668777F-B420-45DA-83DA-42ED0DFE8782}"
        "AspNetVersion" = "8:4.0.30319.0"
        "RestartWWWService" = "11:FALSE"
TradeRecordSetup/dependency/GdiPlus.dll
Binary files differ
TradeRecordSetup/dependency/mfc140ud.dll
Binary files differ
TradeRecordSetup/dependency/msvcp140d.dll
Binary files differ
TradeRecordSetup/dependency/ucrtbased.dll
Binary files differ
TradeRecordSetup/dependency/vcruntime140_1d.dll
Binary files differ
TradeRecordSetup/dependency/vcruntime140d.dll
Binary files differ
common/NetworkApi.cpp
@@ -79,11 +79,11 @@
}
//网络请求
std::string  NetworkApi::base_request(std::string data) {
std::string NetworkApi::load_request_data(std::string data)
{
    rapidjson::Document document;
    document.Parse(data.c_str());
    string requestIdStr =(document["type"].IsInt()? std::to_string(document["type"].GetInt()) : document["type"].GetString()).append(get_rquest_id());
    string requestIdStr = (document["type"].IsInt() ? std::to_string(document["type"].GetInt()) : document["type"].GetString()).append(get_rquest_id());
    rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
    // 添加 request_id 字段
@@ -106,7 +106,12 @@
    ss << std::setw(8) << std::setfill('0') << jsonString.length();
    std::string length_str = string("##").append(ss.str());
    std::string fstr = length_str.append(jsonString);
    return fstr;
}
//网络请求
std::string  NetworkApi::base_request(std::string data) {
    std::string fstr = load_request_data(data);
    try {
        return    SocketManager::sendMsg(_COMMON_SERVER_ADDR, _COMMON_SERVER_PORT, fstr.c_str());
    }
@@ -147,7 +152,7 @@
        return    SocketManager::sendMsg(_TRADE_SERVER_ADDR, _TRADE_SERVER_PORT, fstr.c_str());
    }
    catch (...) {
        throw CString(L"网络请求出错");
        throw wstring(L"网络请求出错");
    }
}
@@ -325,6 +330,121 @@
    }
}
int NetworkApi::get_auto_cancel_sell_mode()
{
    rapidjson::StringBuffer buf;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
    writer.StartObject();
    writer.Key("type");
    writer.String("common");
    writer.Key("data");
    writer.StartObject();
    writer.Key("ctype");
    writer.String("auto_cancel_sell_mode");
    writer.Key("operate");
    writer.Int(3);
    writer.EndObject();
    writer.EndObject();
    const char* json_content = buf.GetString();
    string result = base_request(std::string(json_content));
    //JSON解析
    rapidjson::GenericDocument<rapidjson::UTF16<>> root = JsonUtil::parseUTF16(result);
    if (root[_T("code")].GetInt() != 0) {
        throw wstring(root[_T("msg")].GetString());
    }
    else {
        return    root[_T("data")][_T("mode")].GetInt();
    }
}
void NetworkApi::set_auto_cancel_sell_mode(int mode)
{
    rapidjson::StringBuffer buf;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
    writer.StartObject();
    writer.Key("type");
    writer.String("common");
    writer.Key("data");
    writer.StartObject();
    writer.Key("ctype");
    writer.String("auto_cancel_sell_mode");
    writer.Key("operate");
    writer.Int(1);
    writer.Key("mode");
    writer.Int(mode);
    writer.EndObject();
    writer.EndObject();
    const char* json_content = buf.GetString();
    string result = base_request(std::string(json_content));
    //JSON解析
    rapidjson::GenericDocument<rapidjson::UTF16<>> root = JsonUtil::parseUTF16(result);
    if (root[_T("code")].GetInt() != 0) {
        throw wstring(root[_T("msg")].GetString());
    }
}
int NetworkApi::get_market_situation()
{
    rapidjson::StringBuffer buf;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
    writer.StartObject();
    writer.Key("type");
    writer.String("common");
    writer.Key("data");
    writer.StartObject();
    writer.Key("ctype");
    writer.String("market_situation");
    writer.Key("operate");
    writer.Int(3);
    writer.EndObject();
    writer.EndObject();
    const char* json_content = buf.GetString();
    string result = base_trade_request(std::string(json_content));
    //JSON解析
    rapidjson::GenericDocument<rapidjson::UTF16<>> root = JsonUtil::parseUTF16(result);
    if (!root.IsObject()) {
        throw wstring(L"JSON解析出错");
    }
    if (root[_T("code")].GetInt() != 0) {
        throw wstring(root[_T("msg")].GetString());
    }
    return root[L"data"][L"situation"].GetInt();
}
void NetworkApi::set_market_situation(int situation)
{
    rapidjson::StringBuffer buf;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
    writer.StartObject();
    writer.Key("type");
    writer.String("common");
    writer.Key("data");
    writer.StartObject();
    writer.Key("ctype");
    writer.String("market_situation");
    writer.Key("operate");
    writer.Int(1);
    writer.Key("situation");
    writer.Int(situation);
    writer.EndObject();
    writer.EndObject();
    const char* json_content = buf.GetString();
    string result = base_trade_request(std::string(json_content));
    //JSON解析
    rapidjson::GenericDocument<rapidjson::UTF16<>> root = JsonUtil::parseUTF16(result);
    if (!root.IsObject()) {
        throw wstring(L"JSON解析出错");
    }
    if (root[_T("code")].GetInt() != 0) {
        throw wstring(root[_T("msg")].GetString());
    }
}
// 加白名单 
void NetworkApi::add_white(string code) {
    __request(code, 202);
@@ -340,6 +460,11 @@
//加想买
void NetworkApi::add_want_buy(string code) {
    __request(code, 401);
}
void NetworkApi::add_must_buy(std::string code)
{
    __request(code, 421);
}
// 移除白名单 
@@ -359,6 +484,11 @@
    __request(code, 402);
}
void NetworkApi::remove_must_buy(std::string code)
{
    __request(code, 422);
}
//白名单列表
std::list<wstring> NetworkApi::list_white() {
@@ -375,6 +505,11 @@
//想买列表
std::list<wstring> NetworkApi::list_want_buy() {
    return __request_list(403);
}
std::list<std::wstring> NetworkApi::list_must_buy()
{
    return __request_list(423);
}
@@ -432,8 +567,10 @@
    writer.StartObject();
    writer.Key("code");
    writer.String(code.c_str());
    writer.Key("volume");
    writer.Int(volume);
    if (volume >= 0) {
        writer.Key("volume");
        writer.Int(volume);
    }
    writer.Key("price_type");
    writer.Int(price_type);
    writer.Key("force");
@@ -469,7 +606,15 @@
    writer.EndObject();
    writer.EndObject();
    const char* json_content = buf.GetString();
    string result = base_trade_request(std::string(json_content));
    //string result = "{\"code\": 0, \"data\": {\"code\": \"603200\", \"total\": 1200, \"available\": 1200, \"sell_orders\": [], \"sell_rules_count\": 0, \"code_info\": [\"603200\", \"\\u4e0a\\u6d77\\u6d17\\u9738\"], \"desc\": \"\"}}";
    //JSON解析
    rapidjson::GenericDocument<rapidjson::UTF16<>> root = JsonUtil::parseUTF16(result);
@@ -794,6 +939,34 @@
    return result;
}
string NetworkApi::update_sell_rule(rapidjson::Document doc)
{
    rapidjson::StringBuffer buf;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
    writer.StartObject();
    writer.Key("type");
    writer.String("update_sell_rule");
    writer.Key("data");
    writer.StartObject();
    for (rapidjson::Value::ConstMemberIterator itr = doc.MemberBegin(); itr != doc.MemberEnd(); itr++) {
        string key = itr->name.GetString();
        writer.Key(key.c_str());
        if (itr->value.IsString()) {
            writer.String(itr->value.GetString());
        }
        else if (itr->value.IsNumber()) {
            writer.Int(itr->value.GetInt());
        }
    }
    writer.EndObject();
    writer.EndObject();
    const char* json_content = buf.GetString();
    string result = base_trade_request(std::string(json_content));
    return result;
}
string NetworkApi::del_sell_rule(CString id)
{
    rapidjson::StringBuffer buf;
@@ -812,6 +985,44 @@
    return result;
}
string NetworkApi::get_all_positions()
{
    rapidjson::StringBuffer buf;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
    writer.StartObject();
    writer.Key("type");
    writer.String("common");
    writer.Key("data");
    writer.StartObject();
    writer.Key("ctype");
    writer.String("get_positions");
    writer.EndObject();
    writer.EndObject();
    const char* json_content = buf.GetString();
    string result = base_trade_request(std::string(json_content));
    return result;
}
string NetworkApi::get_buy1_info(string code)
{
    rapidjson::StringBuffer buf;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buf);
    writer.StartObject();
    writer.Key("type");
    writer.String("common");
    writer.Key("data");
    writer.StartObject();
    writer.Key("ctype");
    writer.String("get_buy1_info");
    writer.Key("code");
    writer.String(code.c_str());
    writer.EndObject();
    writer.EndObject();
    const char* json_content = buf.GetString();
    string result = base_trade_request(std::string(json_content));
    return result;
}
string NetworkApi::list_delegate_records(CString updateTime,bool canCancel)
{
    rapidjson::StringBuffer buf;
common/NetworkApi.h
@@ -34,6 +34,7 @@
    // 网络请求
    static std::string base_request(std::string data);
    // 请求交易服务器
    static std::string base_trade_request(std::string data);
@@ -45,6 +46,7 @@
public:
    static std::string load_request_data(std::string data);
    // 获取代码简要信息
    static std::wstring getCodeDesc(std::string code);
@@ -60,6 +62,19 @@
    // 设置买入模式
    static void set_buy_mode(int mode);
    // 获取自动撤卖模式
    static int get_auto_cancel_sell_mode();
    // 设置自动撤卖模式
    static void set_auto_cancel_sell_mode(int mode);
    // 获取市场行情
    static int get_market_situation();
    // 设置市场行情
    static void set_market_situation(int situation);
   
    // 加白名单
    static void add_white(std::string code);
@@ -73,6 +88,9 @@
    // 加想买
    static void add_want_buy(std::string code);
    // 加必买
    static void add_must_buy(std::string code);
    // 移除白名单
    static void remove_white(std::string code);
@@ -85,6 +103,9 @@
    // 移除想买
    static void remove_want_buy(std::string code);
    // 移除必买
    static void remove_must_buy(std::string code);
    // 白名单列表
    static std::list<std::wstring> list_white();
@@ -96,6 +117,9 @@
    // 想买列表
    static std::list<std::wstring> list_want_buy();
    // 必买列表
    static std::list<std::wstring> list_must_buy();
    // 获取委托列表
    static string list_delegate_records(CString updateTime,bool canCancel=FALSE);
@@ -166,8 +190,19 @@
    static string add_sell_rule(rapidjson::Document  doc);
    static string update_sell_rule(rapidjson::Document  doc);
    static string del_sell_rule(CString id);
    //拉取所有持仓
    static string get_all_positions();
    static string get_buy1_info(string code);
};
common/SocketManager.cpp
@@ -52,13 +52,80 @@
            }
        }
    }
    closesocket(m_SockClient);
    if (num < 0) {
        throw string("未接收到信息");
    }
    return data;
}
}
string SocketManager::sendMsg(SOCKET m_SockClient, const char* msg)
{
    char buffer[1024];
    int result = send(m_SockClient, msg, strlen(msg), 0);
    if (result < 0) {
        throw string("发送失败");
    }
    int header_length = 10;
    int num = recv(m_SockClient, buffer, 1024, 0);
    string data = string(buffer, 0, num);
    if (data.find("##") == 0) {
        //带有头文件
        int count = std::stoi(data.substr(2, header_length - 2));
        data = data.substr(header_length);
        while (data.length() < count) {
            char buffer[1024];
            num = recv(m_SockClient, buffer, 1024, 0);
            if (num > 0) {
                data.append(string(buffer, 0, num));
            }
        }
    }
    if (num < 0) {
        throw string("未接收到信息");
    }
    return data;
}
SOCKET SocketManager::createSocket(string addr, int port)
{
    WSADATA wsd;
    WSAStartup(MAKEWORD(2, 2), &wsd);
    SOCKET m_SockClient;
    m_SockClient = socket(AF_INET, SOCK_STREAM, 0);
    sockaddr_in clientaddr;
    clientaddr.sin_family = AF_INET;
    clientaddr.sin_port = htons(port);
    //clientaddr.sin_addr.S_un.S_addr = ;
    inet_pton(AF_INET, addr.c_str(), &clientaddr.sin_addr);
    int c = connect(m_SockClient, (sockaddr*)&clientaddr, sizeof(clientaddr));
    if (c != 0) {
        throw string("socket连接失败");
    }
    return m_SockClient;
}
string SocketManager::receiveMsg(SOCKET m_SockClient)
{
    char buffer[1024];
    int header_length = 10;
    int num = recv(m_SockClient, buffer, 1024, 0);
    if (num <= 0) {
        throw string("连接已断开");
    }
    string data = string(buffer, 0, num);
    if (data.find("##") == 0) {
        //带有头文件
        int count = std::stoi(data.substr(2, header_length - 2));
        data = data.substr(header_length);
        while (data.length() < count) {
            char buffer[1024];
            num = recv(m_SockClient, buffer, 1024, 0);
            if (num > 0) {
                data.append(string(buffer, 0, num));
            }
        }
    }
    return data;
}
common/SocketManager.h
@@ -26,6 +26,10 @@
    ~SocketManager();
    static string sendMsg(const char*);
    static string sendMsg(string addr,int port, const char*);
    static string sendMsg(SOCKET socket, const char*);
    static SOCKET createSocket(string addr= MAIN_HOST, int port = API_PORT);
    // 接收消息
    static string receiveMsg(SOCKET socket);
};
common/StringUtil.h
@@ -48,6 +48,9 @@
    }
    static bool isNumber(const std::string& str) {
        if (str.empty()) {
            return false;
        }
        for (char c : str) {
            if (!isdigit(c)) {
                return false;
@@ -55,4 +58,11 @@
        }
        return true;
    }
    // double转为字符串
    static string toString(double value, int precision) {
        std::ostringstream oss;
        oss << std::fixed << std::setprecision(precision) << value;
        return oss.str();
    }
};
common/TimeUtil.h
New file
@@ -0,0 +1,59 @@
#pragma once
#include <iostream>
#include <ctime>
#include <string>
class TimeUtil {
public:
    static std::string getNowTime() {
        std::time_t now = std::time(nullptr);
        // 将时间戳转换为本地时间
        std::tm local_time;
        localtime_s(&local_time , &now);
        // 格式化时间为字符串
        char time_str[20];
        //%Y-%m-%d %H:%M:%S
        std::strftime(time_str, sizeof(time_str), "%H:%M:%S", &local_time);
        // 输出当前时间
        return std::string(time_str);
    }
    static std::string getNowTime(std::string format) {
        std::time_t now = std::time(nullptr);
        // 将时间戳转换为本地时间
        std::tm local_time;
        localtime_s(&local_time, &now);
        // 格式化时间为字符串
        char time_str[20];
        //%Y-%m-%d %H:%M:%S
        std::strftime(time_str, sizeof(time_str), format.c_str(), &local_time);
        // 输出当前时间
        return std::string(time_str);
    }
    static std::string toFormatString(time_t timestamp ,std::string format) {
        // 将时间戳转换为本地时间
        std::tm local_time;
        localtime_s(&local_time, &timestamp);
        // 格式化时间为字符串
        char time_str[20];
        //%Y-%m-%d %H:%M:%S
        std::strftime(time_str, sizeof(time_str), format.c_str(), &local_time);
        // 输出当前时间
        return std::string(time_str);
    }
    static time_t toTimestamp(string str_time, std::string format) {
        std::tm timeinfo = {};
        std::istringstream ss(str_time);
        ss >> std::get_time(&timeinfo, format.c_str());
        time_t timestamp = mktime(&timeinfo);
        return timestamp;
    }
};