본문 바로가기
C | C++ | VC++

주식종목 리스트업(sort)

by 두루물 2025. 2. 22.

대체거래소 오픈대비,로직개편
DlgBookmark.cpp
0.10MB
DlgBookmark.h
0.00MB

   
// DlgBookmark.cpp : 구현 파일입니다.
//

#include "stdafx.h"
#include "Homi.h"
#include "DlgBookmark.h"
#include <HMMainFrm.h>

#include <iostream>
#include <map>

#include "HMSiseInfo.h"
#include "Common.h"
#include "kxNSMenu.h"

#ifdef USE_EBEST_API
#include "T1102.h"
#include "T1101.h"
#else
#include "T1004.h"
#ifdef USE_STOCKLIST_ONESHOT
#include "T3086.h"
#include "T1001.h"
#endif
#endif

#define SISECOL_DRATE      7
#define SISECOL_COUNT      8
#define SISECOL_UPTIME     9
#define SISECOL_EXCEPT    10

#define COMBOSEL_BOOKMARK         1
#define COMBOSEL_JANGO            2
#define COMBOSEL_VOLUMEUP         3  //우선매수대상 (당일볼륨통과 매수대기종목)
#define COMBOSEL_HIGHRATE         4
#define COMBOSEL_LOWRATE          5
#define COMBOSEL_RECENTLISTON     6
#define COMBOSEL_TOPVOLUME        7
#define COMBOSEL_LOWVOLUME        8//
#define COMBOSEL_STATICVI         9//
#define COMBOSEL_STOPMAN         10//관리,거래정지
#define COMBOSEL_DONGSIUP        11//장마감 동시호가 상승
#define COMBOSEL_CLOSEDOWN       12//정규장종료후 시간외 하락

BOOL DlgBookmark::m_bTwiceGrid = 0;
IMPLEMENT_DYNCREATE(DlgBookmark, DlgResizeBaseEx)
enum ENUM_SHOWMODE {
    SHOW_ALL = 0x00,
    SHOW_BOOKMARK = 0x01,
    SHOW_EXCEPT = 0x10,
    SHOW_BIDSTOP = 0x20,
    SHOW_VOLUMEFLAG_V1 = 0x04,
    SHOW_VOLUMEFLAG_V2 = 0x08,
    SHOW_DAILYSISE_AVG = 0x20,
    SHOW_GONGMEDO = 0x40,
};

DlgBookmark::DlgBookmark(CWnd* pParent /*=NULL*/)
    : DlgResizeBaseEx(DlgBookmark::IDD, pParent)
{
    m_hFontBold = NULL;
    m_brush = NULL;
    m_bAddMode = FALSE;
    m_nTimerMode = 0;
    memset(&m_querytime, 0, sizeof(m_querytime));
    m_fixedcolor = RGB(245, 245, 245);//GetSysColor(COLOR_3DFACE)+RGB(10,10,10);//RGB(112,110,112);
    m_crtext = RGB(0, 0, 0);
    m_sortcolumn = 6;
    m_uplimitmap_count = 0;
    m_nLastRefreshTick = 0;
    m_nSelWhat = COMBOSEL_BOOKMARK;
    m_bTwiceGrid = 0;
}

DlgBookmark::~DlgBookmark()
{
    if (m_hFontBold)
        DeleteObject(m_hFontBold);
    m_hFontBold = NULL;
}

void DlgBookmark::DoDataExchange(CDataExchange* pDX)
{
    DlgResizeBaseEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_COMBO_WHAT, m_mcboxcode);
    DDX_GridControl(pDX, IDC_GRID, m_Grid[0]);
    //DDX_GridControl(pDX, IDC_GRID2, m_Grid[1]);
    DDX_Control(pDX, IDC_CMD_LOADBOOKMARK, m_btnList[0]);
    DDX_Control(pDX, IDC_CMD_SAVEBOOKMARK, m_btnList[1]);
}

BEGIN_MESSAGE_MAP(DlgBookmark, DlgResizeBaseEx)
    ON_MESSAGE(XM_API_RECEIVE_DATA, OnXMRecvData)
    ON_MESSAGE(WM_SISETHREAD_SISE, OnSiseEvent)
    ON_WM_SIZE()
    ON_WM_ACTIVATE()
    ON_WM_TIMER()
    ON_WM_DESTROY()
    //ON_WM_CTLCOLOR()
    ON_WM_LBUTTONDOWN()
    ON_CBN_SELENDOK(IDC_COMBO_WHAT, OnCbnSelchangeWhat)
    ON_BN_CLICKED(IDC_CMD_REFRESH, OnClickRefresh)
    ON_BN_CLICKED(IDC_CMD_ADD, OnClickAdd)
    ON_BN_CLICKED(IDC_CMD_REMOVE, OnClickRemove)
    ON_BN_CLICKED(IDC_CMD_LOADBOOKMARK, OnClickLoadBookmark)
    ON_BN_CLICKED(IDC_CMD_SAVEBOOKMARK, OnClickSaveBookmark)
    ON_BN_CLICKED(IDC_CMD_QUERYSISE, OnClickQuerySise)
    ON_BN_CLICKED(IDC_CMD_ADDREAL, OnClickAddReal)
    ON_BN_CLICKED(IDC_CMD_ADDVOLUME, OnClickAddVolumue)
    ON_BN_CLICKED(IDC_CHECK_DAILYSISE, OnCheckDailysise)
    ON_BN_CLICKED(IDC_CHECK_POLLING, OnCheckPolling)

    ON_NOTIFY_RANGE(GVN_LBUTTONCLICK, IDC_GRID, IDC_GRID2, OnGvnClick)
    ON_NOTIFY_RANGE(GVN_RBUTTONUP, IDC_GRID, IDC_GRID2, OnGvnRClick)
    ON_NOTIFY_RANGE(GVN_COLUMNSORT, IDC_GRID, IDC_GRID2, OnGvnColumnSort)
    ON_NOTIFY_RANGE(GVN_QUERYLABELEDIT, IDC_GRID, IDC_GRID2, OnGvnQueryEdit)
    ON_NOTIFY_RANGE(GVN_ENDLABELEDIT, IDC_GRID, IDC_GRID2, OnGvnEditEnd)

    ON_BN_CLICKED(IDC_CMD_BIDHALT, OnClickBidhalt)
    ON_BN_CLICKED(IDC_CMD_EXCEPT, OnClickExcept)
    ON_COMMAND_RANGE(IDM_BIDSPECIAL, IDM_BIDEXCEPT, OnMenuPopup)
END_MESSAGE_MAP()

//DlgBookmark 메시지 처리기입니다.
LRESULT DlgBookmark::OnSiseEvent(WPARAM wParam, LPARAM lParam)
{
    LRESULT rc = 0L;
    CString strtemp;
    char strcode[8] = { 0, };
    char *pcode = (char*)lParam;
    if (wParam & SISE_NOTIFYID_HOGA) { //호가업데이트
    }
    else if (wParam & SISE_NOTIFYID_TICK) { //체결업데이트
        HMSiseInfo* pSiseItem = (HMSiseInfo*)lParam;
        
        KEYLIST_STRING* pItemList = &m_itemlist;
        KEYLIST_STRING::iterator it;
        BOOL bPoll = IsDlgButtonChecked(IDC_CHECK_POLLING);
        if (bPoll)
            return rc;
        if (GetTickCount64() < m_nLastTick + 1000)
            return rc;
        m_nLastTick = GetTickCount64();

        it = std::find(pItemList->begin(), pItemList->end(),pSiseItem->psm->shtcode);// 싱글 Key 요소 찾기.
        if (it != pItemList->end()) {
            GDCtrl* pGrid = NULL;
            for (int igrid = 0; igrid <= 1; igrid++) {
                pGrid = &m_Grid[igrid];
                for (int irow = pGrid->GetFixedRowCount(); irow < pGrid->GetRowCount(); irow++) {
                    int ncode = (int)pGrid->GetItemData(irow, 0);
                    if (pSiseItem->psm->ncode == ncode) {
                        SetListItem(pGrid, pSiseItem,pSiseItem->psm,irow);
                        return rc;
                    }
                }
            }
        }
        if (m_nSelWhat == COMBOSEL_HIGHRATE) { //상한가 갯수변동
            if (m_uplimitmap_count != g_datacenter.m_uplimitmap.Count()
                && GetTickCount64() >= m_nLastRefreshTick + 60000) {
                m_nLastRefreshTick = GetTickCount64();
                RefreshList();
            }
        }
    }
    return rc;
}

// DlgBookmark 메시지 처리기입니다.
//******************************************************************************
//*
//******************************************************************************
BOOL DlgBookmark::OnInitDialog()
{
    DlgResizeBaseEx::OnInitDialog();
    HICON hIcon = AfxGetApp()->LoadIcon(IDI_HOMI);
    GetParent()->SetIcon(hIcon, FALSE);

    SetBackgroundColor(g_conf.m_bkcolor[0]);
    InitControls(0);
    //AddControl(IDC_LIST_STOCK, sizeResize, sizeResize);
    AddControl(IDC_GRID, sizeNone, sizeResize);
    AddControl(IDC_GRID2, sizeResize, sizeResize);
    AddControl(IDC_CMD_REFRESH, sizeNone, sizeNone);
    AddControl(IDC_CMD_LOADBOOKMARK, sizeNone, sizeNone);
    AddControl(IDC_CMD_SAVEBOOKMARK, sizeNone, sizeNone);
    AddControl(IDC_CMD_ADD, sizeNone, sizeNone);
    AddControl(IDC_CMD_REMOVE, sizeNone, sizeNone);
    AddControl(IDC_CHECK_POLLING, sizeRepos, sizeNone);

    SetTooltipText(IDC_CMD_REFRESH, "새로고침");
    SetTooltipText(IDC_CMD_QUERYSISE, "시세조회");
    SetTooltipText(IDC_CMD_ADD, "신규종목 추가");
    SetTooltipText(IDC_CMD_REMOVE, "선택종목 삭제");
    SetTooltipText(IDC_CMD_BIDHALT,"멀티선택 매수 ON/OFF");
    SetTooltipText(IDC_CMD_EXCEPT, "멀티선택 제외 ON/OFF");
    SetTooltipText(IDC_CMD_PREDAY, "전일상승 공략");
    SetTooltipText(IDC_CMD_BIZDAY, "당일상승 공략");
    SetTooltipText(IDC_CMD_SETREAL, "멀티선택 리얼시세(R+) 추가");
    SetTooltipText(IDC_CHECK_DAILYSISE, "클릭시 일시세 보기");
    SetTooltipText(IDC_CHECK_POLLING, "자동갱신(폴링)");
    SetTooltipText(IDC_CMD_ADDVOLUME, "당일볼륨통과 대기");
#if 0
    SetTooltipText(IDC_CHECK_VOLUMEFLAG, "거래량(V1) 미달");
    SetTooltipText(IDC_CHECK_VOLUMEFLAG2, "거래량통과(V2)");
    SetTooltipText(IDC_CHECK_DAILYSISE, "CAPE:서버에서 DBPickup,EBEST:FromDB");
    SetTooltipText(IDC_CHECK_RESETMASTER, "종료시 종목정보 리셋(다음번에 서버수신)");
    SetTooltipText(IDC_CMD_VOLUME, "거래량,거래율,갱신시간표시 토글");
    SetTooltipText(IDC_CMD_ADDALL, "모두추가:대기나 제외종목 모두해제(일시적,저장안함)");
    SetTooltipText(IDC_CHECK_RESETREAL, "볼륨미달종목 리얼해제");
    SetTooltipText(IDC_CMD_RESETBIDSTOP, "매수중지종목 리얼해제");
    SetTooltipText(IDC_CMD_RESETALL, "모두추가:매수중지나 제외종목 모두해제(저장)");
    SetTooltipText(IDC_CHECK_EXPCEPTSISE, "제외종목 시세조회");
    SetTooltipText(IDC_CMD_LOADFILTER, "중지/제외 필터다시읽기");
    SetTooltipText(IDC_CMD_SAVEFILTER, "중지/제외/관심 필터저장");
    SetTooltipText(IDC_CMD_RESETWARN,"투자경고종목 리얼해제");
#endif
    CBitmap bitmap;
    CImageList imglist;
    bitmap.LoadBitmap(IDB_BITMAP1);//IDB_BROWSINGBAR);
    imglist.Create(16, 16, ILC_COLORDDB | ILC_MASK, 10, 1);
    imglist.Add(&bitmap, RGB(255, 0, 255));
    bitmap.Detach();

    hIcon = imglist.ExtractIcon(17);
    GetParent()->SetIcon(hIcon, FALSE);

    hIcon = imglist.ExtractIcon(8);
    HICON hIcon2 = imglist.ExtractIcon(9);


    for (int i = 0; m_btnList[i].m_hWnd && i < sizeof(m_btnList) / sizeof(m_btnList[0]); i++) {
        m_btnList[i].SetWindowText("");
        if (i % 2 == 0) {
            m_btnList[i].SetTooltipText("가져오기");
            m_btnList[i].SetIcon(hIcon, 0);
        }
        else {
            m_btnList[i].SetTooltipText("저장하기");
            m_btnList[i].SetIcon(hIcon2, 0);
        }
    }

    VERIFY(m_brush = (HBRUSH)GetStockObject(HOLLOW_BRUSH));

    CFont *cFont = GetFont();
    LOGFONT lf;
    cFont->GetLogFont(&lf);
    lf.lfWeight = FW_BOLD;
    m_hFontBold = CreateFontIndirect(&lf);
    cFont->Detach();
    //::SendMessage(::GetDlgItem(GetSafeHwnd(), IDC_STATIC_HOGA), WM_SETFONT, (WPARAM)m_hFontBold, TRUE);
    //::SendMessage(::GetDlgItem(GetSafeHwnd(), IDC_STATIC_CHEGYUL), WM_SETFONT, (WPARAM)m_hFontBold, TRUE);
    //FORWARD_WM_SETFONT(::GetDlgItem(GetSafeHwnd(), IDC_STATIC_HOGA), m_hFontBold, TRUE, ::SendMessage);
    CheckDlgButton(IDC_CHECK_DAILYSISE, TRUE);
    OnCheckDailysise();
    CheckDlgButton(IDC_CHECK_POLLING, FALSE);
    OnCheckPolling();

    //HWND hwndCtrl = ::GetDlgItem(GetSafeHwnd(), IDC_COMBO_MARKET);
    //ComboBox_AddString(hwndCtrl, TEXT("코스피"));//marketid 1
    //ComboBox_AddString(hwndCtrl, TEXT("코스닥"));//marketid 2
    //ComboBox_SetCurSel(hwndCtrl, 0);
    m_mcboxcode.ModifyStyle(0, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE| CBS_HASSTRINGS);
    m_mcboxcode.FormatList(1, DT_LEFT, FALSE, NORMAL);
    m_mcboxcode.SendMessage(CB_SETDROPPEDWIDTH, 150, 0);
    m_mcboxcode.LimitText(46);
    m_mcboxcode.ResetContent();
    int nItem;
    nItem = m_mcboxcode.AddString("관심종목", COMBOSEL_BOOKMARK);
    m_mcboxcode.AddString("보유잔고", COMBOSEL_JANGO); //전일+당일(+15%상승포함)
    m_mcboxcode.AddString("최근상장(90일↓)", COMBOSEL_RECENTLISTON);
    m_mcboxcode.AddString("우선매수(당일볼륨↑)", COMBOSEL_VOLUMEUP); //당일볼륨통과
    m_mcboxcode.AddString("거래량상위", COMBOSEL_TOPVOLUME);
    m_mcboxcode.AddString("상한가(+15%상승)", COMBOSEL_HIGHRATE); //전일+당일(+15%상승포함)
    m_mcboxcode.AddString("하한가(-15%하락)", COMBOSEL_LOWRATE); //전일+당일(-15%하락포함)
    //m_mcboxcode.AddString("상승테마주", COMBOSEL_TOPVOLUME);
    //m_mcboxcode.AddString("하락테마주", COMBOSEL_TOPVOLUME);
    m_mcboxcode.AddString("관리/거래정지", COMBOSEL_STOPMAN);
    m_mcboxcode.AddString("VI종목", COMBOSEL_STATICVI);
    m_mcboxcode.AddString("동시호가 상승", COMBOSEL_DONGSIUP);
    m_mcboxcode.AddString("시간외 하락", COMBOSEL_CLOSEDOWN);
    m_mcboxcode.SetCurSel(0);
    CString strmsg;
    //strmsg.Format("제외(%d)", g_conf.m_blacklistmap.size());
    //SetDlgItemText(IDC_CHECK_EXCEPT, strmsg);
    //strmsg.Format("관심(%d)", g_conf.m_bookmarkmap.size());
    //SetDlgItemText(IDC_CHECK_FAVORITE, strmsg);

    //HWND hName = ::GetDlgItem(GetSafeHwnd(), IDC_EDIT_NAME);
    //LoadRecentCodeList(&m_mcboxcode, hName);
    
    //m_mcboxcode.GetWindowText(m_strselcode);
    //CheckDlgButton(IDC_CHECK_ALL, (m_nShowMode == SHOW_ALL));
    //CheckDlgButton(IDC_CHECK_DAILYAVG, (m_nShowMode & SHOW_DAILYSISE_AVG));
    //CheckDlgButton(IDC_CHECK_GONGMEDO, (m_nShowMode & SHOW_GONGMEDO));
    //if (g_conf.uisetting.volumelimit > 0) {
    //    strmsg.Format("볼륨제외(%dM)", g_conf.uisetting.volumelimit / 10000);
    //    SetDlgItemText(IDC_CHECK_RESETREAL, strmsg);
    //}
    //SetDlgItemText(IDC_CMD_VOLUME, (m_nShowVolume == 1) ? "거" : (m_nShowVolume == 2) ? "%" : "업");
    g_pSiseThread->SetSiseUIWnd(ENUM_SISEUID::SISEUID_BOOKMARK, GetSafeHwnd());

    //LISTPAIR_BOOKMARK* pItemList = &g_conf.m_bookmarkmap;
    GDCtrl* pGrid = &m_Grid[0];
    CRect rcc;
    CRect rccell;
    CRect rcgrid;
    pGrid->GetWindowRect(&rcgrid);
    ScreenToClient(&rcgrid);
    GetClientRect(&rcc);

    return TRUE;  // return TRUE unless you set the focus to a control
    // 예외: OCX 속성 페이지는 FALSE를 반환해야 합니다.
}

//******************************************************************************
//*
//******************************************************************************
void DlgBookmark::InitControls(int mode)
{
    int col = 0;
#if 0
    m_listctrl.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP);
    CHeaderCtrl *pHeaderCtrl = m_listctrl.GetHeaderCtrl();
    /*CMFCHeaderCtrl & pHdr = m_listctrl.GetHeaderCtrl();*/
    //pHeaderCtrl = m_listctrl.GetHeaderCtrl();
    int nCount = pHeaderCtrl->GetItemCount();
    //while (m_listctrl.DeleteColumn(0));

    m_listctrl.InsertColumn(col++, " ", LVCFMT_LEFT, 38);
    m_listctrl.InsertColumn(col++, "코드 ", LVCFMT_LEFT, 56);
    m_listctrl.InsertColumn(col++, "종목명 ", LVCFMT_LEFT, 80);
    m_listctrl.InsertColumn(col++, "장", LVCFMT_CENTER, 24);
    m_listctrl.InsertColumn(col++, "현재가", LVCFMT_RIGHT, 60);
    m_listctrl.InsertColumn(col++, "대비", LVCFMT_RIGHT, 50);
    m_listctrl.InsertColumn(col++, "등락율", LVCFMT_RIGHT, 60);
    m_listctrl.InsertColumn(col++, "시세", LVCFMT_RIGHT, 60);
    m_listctrl.InsertColumn(col++, "매매", LVCFMT_RIGHT, 40);
    m_listctrl.InsertColumn(col++, (m_nShowVolume) ? "거래량" : (m_nShowVolume == 2) ? "거래율" : "갱신시간", LVCFMT_RIGHT, 66);
    m_listctrl.InsertColumn(col++, "X", LVCFMT_CENTER, 21);
    m_listctrl.InsertColumn(col++, "F", LVCFMT_CENTER, 21);

    CListCtrlEx::Sort sortflag = (CListCtrlEx::Sort)(CListCtrlEx::Sort::Auto | CListCtrlEx::Sort::Ascending);
    m_listctrl.SetColumnSorting(0, CListCtrlEx::Sort::Auto, CListCtrlEx::Comparer::Int);
    m_listctrl.SetColumnSorting(1, CListCtrlEx::Sort::Auto, CListCtrlEx::Comparer::Int);
    m_listctrl.SetColumnSorting(2, CListCtrlEx::Sort::Auto, CListCtrlEx::Comparer::String);
    m_listctrl.SetColumnSorting(4, sortflag, CListCtrlEx::Comparer::Int);
    m_listctrl.SetColumnSorting(5, sortflag, CListCtrlEx::Comparer::Int);
    m_listctrl.SetColumnSorting(6, sortflag, CListCtrlEx::Comparer::Double);
    m_listctrl.SetColumnSorting(7, CListCtrlEx::Sort::Auto, CListCtrlEx::Comparer::String);
    m_listctrl.SetColumnSorting(8, sortflag, CListCtrlEx::Comparer::String);
    m_listctrl.SetColumnSorting(9, CListCtrlEx::Sort::Auto, CListCtrlEx::Comparer::Int);//거래량
    m_listctrl.SetColumnSorting(10, CListCtrlEx::Sort::Auto, CListCtrlEx::Comparer::String);
    m_listctrl.SetColumnSorting(11, CListCtrlEx::Sort::Auto, CListCtrlEx::Comparer::Int);

    EnableWindowTheme(m_listctrl.GetSafeHwnd(), L"ListView", L"Explorer", NULL);
    m_listctrl.SetAutoUnSelect(TRUE);
#else
    initgrid(&m_Grid[0]);
    //initgrid(&m_Grid[1]);
#endif
    //m_mcboxcode.FormatList(2, DT_LEFT, FALSE, NORMAL);
    //m_mcboxcode.SendMessage(CB_SETDROPPEDWIDTH, 200, 0);
    //m_mcboxcode.LimitText(6);
}

void DlgBookmark::initgrid(GDCtrl* pGrid)
{
    //OninitDialog 에서 ADDControl 하지않으면 style가 0x50081000 처럼 테두리ㅏㄱ설정된다.
    pGrid->ModifyStyleEx(WS_EX_STATICEDGE | WS_EX_CLIENTEDGE, 0);/*효과없애기*/
    /*pGrid->ModifyStyleEx(0,WS_EX_CLIENTEDGE); 효과주기*/
    COLORREF m_bkcolor = RGB(255, 255, 255);
    /*pGrid->SetBkColor(COLOR_WINDOW);*/
    pGrid->SetBkColor(m_bkcolor);
    pGrid->SetListMode(true, true);
    pGrid->SetEditable(false);
    pGrid->EnableDragAndDrop(false);
    pGrid->SetTextBkColor(RGB(0xFF, 0xFF, 0xFF));
    pGrid->SetTextColor(RGB(0x0, 0x0, 0x0));
    //pGrid->SetFocusRectColor(RGB(0,78,152));
    pGrid->SetRowResize(false);
    pGrid->SetColumnResize(true);
    pGrid->EnableSelection(true);
    pGrid->EnableToolTip(true);
    pGrid->AutoUnselect(true); //개별코드로 종목등록위해 15초후 자동선택해제
    //pGrid->AutoSize();
    CFont* Font = GetFont();
    LOGFONT lf;
    Font->GetLogFont(&lf);
    CFont f;
    lf.lfHeight = -12;
    f.CreateFontIndirect(&lf);
    pGrid->SetFont(&f);

    try {
        //pGrid->SetRowCount(DAYLIST_NUM + 2);
        pGrid->SetRowCount(1); //동적인서트시 갯수를 헤더+1 최소 1개더미행 추가 20230825
        pGrid->SetColumnCount(7);
        pGrid->SetFixedRowCount(1);
        pGrid->SetFixedColumnCount(1);
    }
    catch (CMemoryException* e)
    {
        e->ReportError();
        e->Delete();
        return;
    }

    struct {
        char* name;
        int width;
        UINT nFormat;
    }columninfo[13] = {
        { " ",22,DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS},
        { "종목명",60,DT_RIGHT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS },
        { "",3,DT_RIGHT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS },
        { "현재가",50,DT_RIGHT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS },
        { "대비",40,DT_RIGHT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS },
        { "등락",40,DT_RIGHT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS },
        { "거래량",55,DT_RIGHT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS },
        { "",0,0}
    };
    int cols = 0, fcolw = 0;
    pGrid->SetFixedBkColor(m_fixedcolor);//GetSysColor(COLOR_3DFACE));
    pGrid->SetRowHeight(0, m_rowheight);

    for (int i = 0; i < sizeof(columninfo) / sizeof(columninfo[0]) && columninfo[i].width > 0; i++)
    {
        pGrid->SetColumnWidth(i, columninfo[i].width);
        fcolw += columninfo[i].width;
        pGrid->SetItemFormat(0, i, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);// columninfo[i].nFormat);
        pGrid->SetItemText(0, i, columninfo[i].name);
        pGrid->SetItemTextColor(0, i, RGB(96, 96, 96));
        cols++;
    }
    GDCtrl::Sort sortflag = (GDCtrl::Sort)(GDCtrl::Sort::Auto | GDCtrl::Sort::Ascending);
    pGrid->SetColumnSorting(0, sortflag, GDCtrl::Comparer::String);
    pGrid->SetColumnSorting(1, GDCtrl::Sort::Auto, GDCtrl::Comparer::String);
    pGrid->SetColumnSorting(3, sortflag, GDCtrl::Comparer::Int);
    pGrid->SetColumnSorting(4, sortflag, GDCtrl::Comparer::Int);
    pGrid->SetColumnSorting(5, sortflag, GDCtrl::Comparer::Double);
    pGrid->SetColumnSorting(6, GDCtrl::Sort::Auto, GDCtrl::Comparer::Int);//거래량
#if 0
    RECT rcw;
    pGrid->GetWindowRect(&rcw);
    rcw.right = rcw.left + fcolw + 16;
    CRect rcnew = rcw;
    pGrid->SetWindowPos(NULL, 0, 0, rcnew.right - rcnew.left, rcnew.bottom - rcnew.top,
        SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
#endif
    ////pGrid->SetColumnWidth(2, 100);
    //for (int i = 1; i < DAYLIST_NUM + 2; i++) {
    // pGrid->SetRowHeight(i, m_rowheight);
    // pGrid->SetItemBkColour(i, 0, m_fixedcolor + RGB(5, 5, 5));
    // for (int j = 0; j < cols; j++)
    // pGrid->SetItemFormat(i, j, columninfo[j].nFormat);
    //}

    ////CRect rcw;
    ////pGrid->SetWindowPos(NULL,0,0,rcnew.right-rcnew.left,rcnew.bottom-rcnew.top,
    //// SWP_NOMOVE| SWP_NOACTIVATE|SWP_NOZORDER);
    ////bugfix scroll refresh 2019.11.10 KRKIM
    ////pGrid->ExpandToFit();
    ////pGrid->Invalidate();

    //pGrid->SetItemFormat(DAYLIST_NUM + 1, 2, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);// columninfo[i].nFormat);
    //pGrid->SetItemFormat(DAYLIST_NUM + 1, 3, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);// columninfo[i].nFormat);
    //pGrid->SetItemFgColour(DAYLIST_NUM + 1, 0, RGB(96, 96, 96));
    //pGrid->SetItemFgColour(DAYLIST_NUM + 1, 2, RGB(96, 96, 96));
    //pGrid->SetItemFgColour(DAYLIST_NUM + 1, 3, RGB(96, 96, 96));
    //pGrid->SetItemFgColour(DAYLIST_NUM + 1, 4, RGB(96, 96, 96));
    //pGrid->SetItemFgColour(DAYLIST_NUM + 1, 8, RGB(96, 96, 96));
    pGrid->SetRedrawNow(TRUE, TRUE);
    pGrid->SetActionProc(OnGridAction);
    pGrid->SetAutoSizeColumn(pGrid->GetColumnCount() - 1, true);
    m_pGridFocus = pGrid;
}

//******************************************************************************
//*
//******************************************************************************
//void DlgBookmark::OnNMDblclkList(NMHDR *pNMHDR, LRESULT *pResult)
//{
//    LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
//    // TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
//    *pResult = 0;
//
//    //CString strCode;
//
//    //strCode = m_listctrl.GetItemText(pNMItemActivate->iItem, 1);
//
//    //DlgT1001 dlg;
//    //dlg.m_szCode = strCode;
//    //dlg.DoModal();
//}


void DlgBookmark::OnSize(UINT nType, int cx, int cy)
{
    DlgResizeBaseEx::OnSize(nType, cx, cy);
    //  ::SetWindowPos(this->m_listctrl.GetSafeHwnd(), 0, 0, 0, cx-16, cy-60,
          //SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER);
}

HBRUSH DlgBookmark::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
#if 1
    HBRUSH hbr = DlgResizeBaseEx::OnCtlColor(pDC, pWnd, nCtlColor);
    return hbr;
#else
    if (nCtlColor == CTLCOLOR_STATIC) {
        COLORREF crback = GetSysColor(COLOR_WINDOW);
        COLORREF crback2 = RGB(64, 0, 0);//
        COLORREF crback3 = RGB(0, 0, 64);//
        static CBrush newBrush(crback);
        static CBrush newBrush2(crback2);
        static CBrush newBrush3(crback3);
        if (pWnd->m_hWnd == GetDlgItem(IDC_STATIC_HOGA)->m_hWnd) {
            pDC->SetBkMode(TRANSPARENT);
            pDC->SetBkColor(crback2);
            pDC->SetTextColor(RGB(255, 255, 0));
            return newBrush2;
        }
        if (pWnd->m_hWnd == GetDlgItem(IDC_STATIC_CHEGYUL)->m_hWnd) {
            pDC->SetBkMode(TRANSPARENT);
            crback = RGB(0, 0, 128);//
            pDC->SetBkColor(crback3);
            pDC->SetTextColor(RGB(255, 255, 0));
            return newBrush3;
        }
        else
            pDC->SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
        //if (pWnd->m_hWnd == GetDlgItem(IDC_STATIC_TITLE)->m_hWnd)
        // return m_brush;
        return newBrush;
    }
    if (nCtlColor == CTLCOLOR_DLG) {
        COLORREF crback = GetSysColor(COLOR_WINDOW);
        static CBrush newBrush(crback);
        pDC->SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
        /*pDC->SetBkMode(TRANSPARENT);*/
        pDC->SetBkColor(crback);
        return newBrush;
    }
    HBRUSH hbr = CResizingDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
    return hbr;
#endif

}

void DlgBookmark::OnLButtonDown(UINT nFlags, CPoint point)
{
    DlgResizeBaseEx::OnLButtonDown(nFlags, point);
    GetParent()->PostMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x, point.y));
}

void DlgBookmark::OnCancel()
{
    //CResizingDialogEx::OnCancel();
}

int CALLBACK DlgBookmark::OnGridAction(int row, int col, byte action,LPARAM uParam)
{
    int rc = 0;
    LPGVITEM pCell = (LPGVITEM)uParam;
    if (action == GV_ACTION_DELETE) {
        if (pCell && pCell->lParam) {
#if 0 //일별시세창에 적용할것
            void* p = (void* )pCell->lParam;
            delete p;
            rc = 1;
#endif
        }
    }
    return rc;
}

void DlgBookmark::SetListItem(GDCtrl* pGrid, HMSiseInfo* pSiseItem, HMStockInfo* pMI, int irow, bool fredraw)
{
    //CListCtrlEx *pList = &m_listctrl;
    int topindex = 0;
    char shtname[10] = { 0, };
    CString strcode;
    CString strtemp;
    COLORREF crtext, crback = (COLORREF)CLR_DEFAULT;
    int sub = 0;
    char sztemp[60];
    HMStockInfo* psm = NULL;
    psm = (pSiseItem) ? pSiseItem->psm : pMI; // g_datacenter.GetStockMaster(pSiseItem->psm->shtcode);// 종목마스터에서 조회
    if (!psm)
        return;
    if (fredraw)
        pGrid->SetRedrawNow(FALSE, FALSE);

    sprintf(sztemp, "%d", irow);
    //pGrid->SetItemColors(irow, sub, m_fixedcolor, (COLORREF)CLR_DEFAULT);
    pGrid->SetItemColors(irow, sub, m_fixedcolor, (COLORREF)RGB(96, 96, 96));
    if (pSiseItem) {
        if (pSiseItem->volumeflag) {
            sprintf(sztemp, "v%d", pSiseItem->volumeflag);
            pGrid->SetItemColors(irow, sub, (pSiseItem->volumeflag >= 0x02) ?
                RGB(255, 128, 40) : RGB(121, 128, 192), RGB(153, 217, 234));
        }
        if (pSiseItem->isreal == 0)
            pGrid->SetItemColors(irow, sub, RGB(220, 220, 220), RGB(96, 96, 96));
    }
    else
        pGrid->SetItemColors(irow, sub, RGB(220, 220, 220), RGB(96, 96, 96));
    if (psm->si.preuplmtprice > 0 &&
        psm->si.preclose >= psm->si.preuplmtprice) {
        sprintf(sztemp, "전"); //전일상한가
        pGrid->SetItemColors(irow, sub, RGB(121, 128, 192), RGB(153, 217, 234));
    }
    else if (psm->ds.days[1].ndate == g_conf.m_preday &&
        psm->ds.days[1].drate >= HIGHRATE) {
        sprintf(sztemp, "전"); //전일상승세
        pGrid->SetItemColors(irow, sub, CLR_DEFAULT, RGB(121, 128, 192));
    }
    if ((psm->si.uplmtprice > 0 &&
        psm->si.price >= psm->si.uplmtprice) ||
        (pSiseItem && pSiseItem->hoga.bid[0].price >= psm->si.uplmtprice)) {
        sprintf(sztemp, "상"); //당일상한가
        pGrid->SetItemColors(irow, sub, RGB(255, 174, 201), (COLORREF)RGB(200, 0, 0));
        if (psm->si.price < psm->si.uplmtprice) //현재가가 미달이고 매수호가가 초과시
            pGrid->SetItemBackColor(irow, sub, RGB(255, 200, 218));
    }

    pGrid->SetItemText(irow, sub++, sztemp);
    mbcscopy(shtname, psm->hname, sizeof(shtname) - 1);
    if(m_bShowCode)
        pGrid->SetItemText(irow, sub, psm->shtcode);
    else
        pGrid->SetItemText(irow, sub, shtname);

    crback = (COLORREF)RGB(255, 255, 255);
    crtext = RGB(48, 48, 48);
    if (pSiseItem) {
        if (pSiseItem->addexcept) {
            crtext = RGB(0, 0, 96);
            crback = RGB(160, 160, 160);
        }
        else {
            if (pSiseItem->bid_enable <= 0) {
                crback = RGB(230, 230, 230);
            }
            if (pSiseItem->bidspecial) {
                crback = RGB(255, 174, 200);
            }
        }
    }
    else if(psm->noerror)
        crtext = RGB(128, 0, 0);
    if (psm->si.stopped || psm->si.managed || psm->si.warning) {
        crtext = RGB(128, 0, 0);
    }
    pGrid->SetItemColors(irow, sub++, crback, crtext);//종목색상
    //시장구분색상(주황=코스피,파랑=코스닥)
    if (psm->marketid == (int)ENUM_MARKETID::KOSPI) {
        strtemp = "P";
        pGrid->SetItemColors(irow, sub, RGB(255,127,40), (COLORREF)CLR_DEFAULT);
    }
    else if (psm->marketid == (int)ENUM_MARKETID::KOSPI200) {
        strtemp = "P+";
        pGrid->SetItemColors(irow, sub, RGB(128, 64, 64), (COLORREF)CLR_DEFAULT);
    }
    else {
        strtemp = "D";
        pGrid->SetItemColors(irow, sub, RGB(0, 110, 220), (COLORREF)CLR_DEFAULT);
    }
    strtemp = "";
    pGrid->SetItemText(irow, sub++, strtemp);
    crback = (COLORREF)CLR_DEFAULT;
    crtext = RGB(0, 0, 0);
    if (pSiseItem) {
        if (pSiseItem->ticksise[0].price > pSiseItem->ticksise[1].price)
            crtext = RGB(200, 0, 0);
        else if (pSiseItem->ticksise[0].price < pSiseItem->ticksise[1].price)
            crtext = RGB(0, 0, 200);
        if (pSiseItem->staticvi) {
            crback = RGB(220, 220, 220);
        }
    }
    pGrid->SetItemColors(irow, sub, crback, crtext);

    strtemp.Format("%ld", psm->si.price);
    pGrid->SetItemText(irow, sub++, strtemp);

    strtemp.Format("%ld", psm->si.dchange);
    pGrid->SetItemText(irow, sub++, strtemp);
    if (psm->si.drate > 0) {
        if (psm->si.drate >= 10)
            pGrid->SetItemColors(irow, sub, RGB(255, 0, 0), RGB(255, 255, 0));
        else
            pGrid->SetItemColors(irow, sub, (COLORREF)CLR_DEFAULT, RGB(255, 0, 0));
    }
    else
        pGrid->SetItemColors(irow, sub, (COLORREF)CLR_DEFAULT, RGB(0, 0, 255));
    //if(((int)(psm->si.drate * 10.0f) % 10) > 0) //소수점0이면 정수로 표시
    //    strtemp.Format("%.1f%%", psm->si.drate);
    //else
    //    strtemp.Format("%.f%%", psm->si.drate);
    strtemp.Format("%.1f%%", psm->si.drate);
    pGrid->SetItemText(irow, sub++, strtemp);

    crtext = (psm->si.todayvolume >= 200000) ? RGB(255, 0, 0) : RGB(0, 0, 0);
    crback = RGB(255, 255, 255);// (COLORREF)CLR_DEFAULT;
    //케이프는 외인매도 없는 종목이 간간이 있다. 20221227
    if (psm->ds.foreignask < 0)
        crtext = RGB(0, 0, 250);
    pGrid->SetItemColors(irow, sub, crback, crtext);
    if(psm->si.todayvolume >= 1000)
        strtemp.Format("%.fK", psm->si.todayvolume / 1000.);
    else
        strtemp.Format("%d", psm->si.todayvolume);
    pGrid->SetItemText(irow, sub++, strtemp);
    pGrid->InvalidateRow(irow);
    if (fredraw)
        pGrid->SetRedrawNow(TRUE, FALSE);
}

int DlgBookmark::AddToList(GDCtrl* pGrid,HMSiseInfo *pSiseItem, HMStockInfo* pMI,int irow)
{
    HMStockInfo* psm = NULL;
    int iRow = pGrid->InsertRow("", irow);
    pGrid->SetRowHeight(iRow, m_rowheight);
    psm = (pSiseItem) ? pSiseItem->psm : pMI;
    pGrid->SetItemData(iRow, 0, (LPARAM)(psm)? psm->ncode : 0);
    pGrid->SetItemFormat(iRow, 0, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
    pGrid->SetItemFormat(iRow, 1, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
    pGrid->SetItemFormat(iRow, 2, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
    pGrid->SetItemFormat(iRow, 3, DT_RIGHT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
    pGrid->SetItemFormat(iRow, 4, DT_RIGHT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
    pGrid->SetItemFormat(iRow, 5, DT_RIGHT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
    pGrid->SetItemFormat(iRow, 6, DT_RIGHT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
    SetListItem(pGrid,pSiseItem, pMI, iRow, false);
    return iRow;
}

int DlgBookmark::UnRealList()
{
    int count = 0;
    string shtcode;
    HMSiseInfo* pSiseItem;
    KEYLIST_STRING* pItemList = &m_itemlist;
    KEYLIST_STRING::iterator it;
    for (it = pItemList->begin(); it != pItemList->end(); ++it) {
        shtcode = *it;
        HMStockInfo* psm = NULL;
        pSiseItem = g_datacenter.m_stocklist.GetItem(shtcode);
        if (pSiseItem && pSiseItem->isreal == 4) {
            if (::IsWindow(g_pSiseThread->m_pSiseWnd->GetSafeHwnd())) {
                g_pSiseThread->ResetReal(pSiseItem);
                count++;
            }
        }
    }
    return count;
}

void DlgBookmark::RefreshList()
{
    GDCtrl* pGrid = NULL;
    for (int i = 0; i < 2; i++) {
        pGrid = &m_Grid[i];
        if (!pGrid)
            continue;
        if(::IsWindow(pGrid->GetSafeHwnd()) == FALSE)
            continue;
        pGrid->SetRedrawNow(FALSE, FALSE);
        pGrid->DeleteRows(1, -1);//해더제외한 나머지삭제
        pGrid->SetRedrawNow(TRUE, TRUE);
        pGrid->ResetScrollBars();
        pGrid->Invalidate();
    }
    int unrealed = UnRealList();
    if (m_nSelWhat == COMBOSEL_BOOKMARK)
        RefreshBookmark();
    else {
        RefreshOther();
    }
}

void DlgBookmark::RefreshBookmark()
{
    int onepanel = 1; //20240831
    int count = 0;
    char sztooltip[196];
    HMSiseInfo* pSiseItem;
    LISTPAIR_BOOKMARK* pItemList = &g_conf.m_bookmarkmap;
    LISTPAIR_BOOKMARK::iterator it;
    string shtcode;
    CString msg;
    GDCtrl* pGrid = &m_Grid[0];
    LARGE_INTEGER dwstopwatch = { 0, };
    if (m_nTimerMode == 0) {
        stopwatch(0, &dwstopwatch);
    }

    //for (it = pItemList2->begin(); it != pItemList2->end(); ++it) {
    //    pItemList->insert(SORTMAP_STRING::value_type(it->first, "0"));//당일
    //}
    int irow = 0;
    //pItemList->Lock();
    int changegrid = 0;
    CRect rcc;
    CRect rccell;
    CRect rcgrid;
    pGrid->GetWindowRect(&rcgrid);
    ScreenToClient(&rcgrid);
    GetClientRect(&rcc);
    count = pItemList->size();
    //TODO 자동크기조정

    int expect_height = ((count / 2) + 1) * m_rowheight + (count % 2) * m_rowheight;
    int diffh = expect_height - rcgrid.Height();
    if (diffh > 1) {
        CRect rcdlg;
        GetParent()->GetWindowRect(&rcdlg);
        rcdlg.bottom += diffh + 1;
        GetParent()->SetWindowPos(NULL, 0, 0, rcdlg.Width(), rcdlg.Height(), SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);

        pGrid->GetWindowRect(&rcgrid);
        ScreenToClient(&rcgrid);
        GetClientRect(&rcc);
    }

    m_itemlist.clear();
    short vol_level = 0;
    for (it = pItemList->begin(); it != pItemList->end(); ++it) {
        shtcode = it->first;
        STBookMark* pbook = (STBookMark*)&(it->second);
        HMStockInfo* psm = NULL;
        pSiseItem = g_datacenter.m_stocklist.GetItem(shtcode);
        if (!pSiseItem) {
            psm = g_datacenter.GetStockMaster(shtcode.c_str());
        }
        else
            psm = pSiseItem->psm;
        if (!psm)
            continue;
        vol_level = 0;
        if(g_conf.m_hhmmss >= 110000 && pSiseItem && pSiseItem->market.volume < 200000)
            vol_level = 1; //continue;
        if (g_conf.m_hhmmss >= 100000 && pSiseItem && pSiseItem->market.volume < 100000)
            vol_level = 2; //continue;
        if(1 == 0 && vol_level)
            continue;
        if (irow == 0) {
            pGrid->SetRedrawNow(FALSE, FALSE);
            pGrid->DeleteRows(1, -1);//해더제외한 나머지삭제
        }
        //보정 20231003
        if (pbook->addmode > (byte)ENUM_ADDBOOK::BOOKMARK)
            pbook->addmode = (byte)ENUM_ADDBOOK::BOOKMARK;
        if (pbook->shtname == "") {
            if (pSiseItem && pSiseItem->psm)
                pbook->shtname = pSiseItem->psm->hname;
            else if (psm)
                pbook->shtname = psm->hname;
        }
        irow++;
        int nRow = AddToList(pGrid,pSiseItem, psm, irow);
#if 1
        //char sztemp[10] = { 0, };
        //sprintf(sztemp, "%d", irow);
        //pGrid->SetItemText(irow,0, sztemp);
        if (vol_level) {
            pGrid->SetItemTextColor(nRow, 1, RGB(98, 98, 98));
        }
#endif
        memset(sztooltip, 0, sizeof(sztooltip));
        int len = 0;
        len = SiseLogic::GetSiseTooltip(psm, sztooltip+len, sizeof(sztooltip) - 1);
        if(pbook->regdate > 0)
            len += sprintf(sztooltip+len, "\n\n관심등록일:%ld", pbook->regdate);
        pGrid->SetTooltipText(irow, 1, sztooltip);
        pGrid->GetCellRect(irow, 0, &rccell);
        if (onepanel > 1) {
            if (irow > 30 || rccell.bottom > (rcgrid.bottom - rcgrid.top) - m_rowheight) {
                if (changegrid == 0) {
                    pGrid->SetRedrawNow(TRUE, TRUE);
                    pGrid->ResetScrollBars();
                    pGrid->Invalidate();
                    if (m_sortcolumn >= 0)
                        pGrid->SortOnColumn(m_sortcolumn, FALSE);

                    irow = 0;
                    //if (m_bTwiceGrid == 1 && IsWindow(m_Grid[1].GetSafeHwnd())) {
                    //    pGrid = &m_Grid[1];
                    //    changegrid++;
                    //}
                }
            }
        }
        m_itemlist.push_back(shtcode);
        if (pSiseItem && pSiseItem->isreal == 0) {
            if (::IsWindow(g_pSiseThread->m_pSiseWnd->GetSafeHwnd())) {
                g_pSiseThread->SetReal(pSiseItem);
                pSiseItem->isreal = 4;
            }
        }
    }
    if (m_nTimerMode == 0) {
#ifdef _DEBUG
        float etime;
        etime = stopwatch(1, &dwstopwatch);
        //sprintf(sztemp, "종목리스트 경과시간 %5.3f 초 종목수 %ld", etime, count);
        //AddToMainLog(sztemp, 0x02);
#endif
    }
    if (changegrid == 0 || pGrid != &m_Grid[0]) {
        pGrid->SetRedrawNow(TRUE, TRUE);
        pGrid->ResetScrollBars();
        pGrid->Invalidate();
        if (m_sortcolumn >= 0)
            pGrid->SortOnColumn(m_sortcolumn, FALSE);
    }

    msg.Format("관심종목(%d)", count);
    if(GetParent())
        GetParent()->SetWindowText(msg);
}

void DlgBookmark::RefreshOther()
{
    int count = 0;
    int row = 0;
    char sztooltip[196];
    HMSiseInfo* pSiseItem;
    //SORTMAP_STRING codelist;
    //SORTMAP_ULONG  codelist_volume;
    STOCK_UPLIMITLIST* pItemList = &g_datacenter.m_preuplimitmap; //전일상한가
    STOCK_UPLIMITLIST::HASHMAP* pMap = pItemList->GetHashMap();
    //SORTMAP_STRING* pItemList2 = &g_datacenter.m_uplimitmap; //당일상한가
    //MYVECTOR_FLOAT::iterator it;
    STOCK_UPLIMITLIST::HASHMAP::iterator it;
    STOCK_UPLIMITLIST* pItemList2 = &g_datacenter.m_uplimitmap;
    STOCK_UPLIMITLIST::HASHMAP* pMap2 = pItemList2->GetHashMap();
    STOCK_UPLIMITLIST::HASHMAP::iterator it2;
    MYVECTOR_FLOAT codevolume;
    MYVECTOR_FLOAT::iterator vit;
    //LISTPAIR_BOOKMARK* pItemList = &g_conf.m_bookmarkmap;
    //LISTPAIR_BOOKMARK::iterator it;

    string shtcode;
    CString msg;
    GDCtrl* pGrid = &m_Grid[0];
    LARGE_INTEGER dwstopwatch = { 0, };
    if (m_nTimerMode == 0) {
        stopwatch(0, &dwstopwatch);
    }

    MYSTOCK_MASTER::iterator itmst;
    HMStockInfo* psm = NULL;

    m_itemlist.clear();
    //for (itmst = std::next(g_datacenter.m_stockmaster.begin(), 0); itmst != g_datacenter.m_stockmaster.end(); ++itmst) {
    //    shtcode = itmst->first;
    //    psm = &itmst->second;
    //    if (!psm)
    //        continue;
    //    if(psm->si.preuplmtprice > 0 && 
    //        psm->si.preclose >= psm->si.preuplmtprice)
    //        m_itemlist.push_back(shtcode);
    //}
    //당일미만은 삭제
#if 0
    for (it = pItemList2->begin(); it != pItemList2->end();) {
        shtcode = it->first;
        pSiseItem = g_datacenter.m_stocklist.GetItem(shtcode);
        if (pSiseItem && pSiseItem->market.drate < HIGHRATE)
            pItemList2->erase(it++);
        else
            ++it;
    }
#endif
    m_sortcolumn = 5;
    if (m_nSelWhat == COMBOSEL_HIGHRATE) {
        m_uplimitmap_count = g_datacenter.m_uplimitmap.Count();
        //codelist = *pMap2;
        pItemList2->Lock();
        m_sortcolumn = 5;//등락율
        count = 0;
        for (it = pMap2->begin(); it != pMap2->end(); ++it) {
            shtcode = it->first;
            HMStockInfo* psm = NULL;
            pSiseItem = g_datacenter.m_stocklist.GetItem(shtcode);
            if (!pSiseItem) {
                psm = g_datacenter.GetStockMaster(shtcode.c_str());
            }
            else
                psm = pSiseItem->psm;
            if (!psm)
                continue;
            //if (g_conf.m_hhmmss >= 110000 && psm->si.todayvolume < 100000)
            //    continue;
            //if (g_conf.m_hhmmss >= 100000 && psm->si.todayvolume < 50000)
            //    continue;
            if (psm->si.drate < 8.f)
                continue;
            if (count++ > 50)
                break;
            //codelist.insert(SORTMAP_STRING::value_type(it->first, it->second));//당일
            codevolume.push_back(MYVECTOR_ULONG::value_type(shtcode, psm->si.drate));
        }
        //값으로 정렬(내림차순)
        //vector<pair<string, ULONG>> vec(codelist_volume.begin(), codelist_volume.end());
        sort(codevolume.begin(), codevolume.end(), [](MYPAIR_ULONG a, MYPAIR_ULONG b) {
            if (a.second == b.second) return a.first < b.first;//종목코드 오름차순
            return a.second > b.second;//내림차순
            });
        pItemList2->Unlock();
    }
    else if (m_nSelWhat == COMBOSEL_LOWRATE) {
        MYSTOCK_LIST* pStockList = &g_datacenter.m_stocklist;
        MYSTOCK_LIST::HASHMAP* pMap = pStockList->GetHashMap();
        MYSTOCK_LIST::HASHMAP::iterator it;
        string shtcode;
        pStockList->Lock();
        m_sortcolumn = 5;//등락율
        for (it = pMap->begin(); it != pMap->end(); ++it) {
            shtcode = it->first;
            pSiseItem = &it->second;
            psm = pSiseItem->psm;
            if (!psm)
                continue;
            if(psm->si.drate >= -6.f)
                continue;
            codevolume.push_back(MYVECTOR_ULONG::value_type(shtcode, psm->si.drate));
        }
        //값으로 정렬(올림차순)
        sort(codevolume.begin(), codevolume.end(), [](MYPAIR_ULONG a, MYPAIR_ULONG b) {
            if (a.second == b.second) return a.first >= b.first;//종목코드 올림차순
            return a.second < b.second;//올림차순
            });
        pStockList->Unlock();
    }
    else if (m_nSelWhat == COMBOSEL_JANGO) {
        MYSTOCK_JANGOLEDGER* pItemList3 = &(g_datacenter.m_jangoledger);
        MYSTOCK_JANGOLEDGER::HASHMAP* pMap = pItemList3->GetHashMap();
        MYSTOCK_JANGOLEDGER::HASHMAP::iterator it3;
        //STJangoInfo* pFItem;
        pItemList3->Lock();
        m_uplimitmap_count = g_datacenter.m_jangoledger.Count();
        for (it3 = pMap->begin(); it3 != pMap->end(); ++it3)
        {
            //pFItem = &it3->second;//데이터가 주소자체임
            codevolume.push_back(MYVECTOR_ULONG::value_type(shtcode, psm->si.drate));
        }
        //값으로 정렬(내림차순)
        //vector<pair<string, ULONG>> vec(codelist_volume.begin(), codelist_volume.end());
        sort(codevolume.begin(), codevolume.end(), [](MYPAIR_ULONG a, MYPAIR_ULONG b) {
            if (a.second == b.second) return a.first < b.first;//종목코드 오름차순
            return a.second > b.second;//내림차순
            });
        pItemList3->Unlock();
    }
    else if (m_nSelWhat == COMBOSEL_RECENTLISTON) {
        MYSTOCK_LIST* pStockList = &g_datacenter.m_stocklist;
        MYSTOCK_LIST::HASHMAP* pMap = pStockList->GetHashMap();
        MYSTOCK_LIST::HASHMAP::iterator it;
        string shtcode;
        pStockList->Lock();
        for (it = pMap->begin(); it != pMap->end(); ++it) {
            shtcode = it->first;
            pSiseItem = &it->second;
            //m_uplimitmap_count = g_datacenter.m_uplimitmap.Count();
            //codelist = *pMap;
            //pItemList2->Lock();
            //for (it = pMap2->begin(); it != pMap2->end(); ++it) {
                //shtcode = it->first;
                //HMStockInfo* psm = NULL;
                //pSiseItem = g_datacenter.m_stocklist.GetItem(shtcode);
                //if (!pSiseItem) {
                //    psm = g_datacenter.GetStockMaster(shtcode.c_str());
                //}
                //else
            psm = pSiseItem->psm;
            if (!psm)
                continue;
            CTime currTime = CTime::GetCurrentTime();
            CTimeSpan timeDelta(-90, 0, 0, 0);
            currTime += timeDelta;
            CString predate = currTime.Format("%Y%m%d");
            if (psm->si.listdate[0] && (psm->si.listdate > predate ||
                (g_conf.xml.setting.szListOnDate[0] &&
                    strnicmp(psm->si.listdate, g_conf.xml.setting.szListOnDate, 8) >= 0))) {//20220224 버그수정
                codevolume.push_back(MYVECTOR_ULONG::value_type(shtcode, atoi(psm->si.listdate)));
            }
            //값으로 정렬(내림차순)
            //vector<pair<string, ULONG>> vec(codelist_volume.begin(), codelist_volume.end());
            sort(codevolume.begin(), codevolume.end(), [](MYPAIR_ULONG a, MYPAIR_ULONG b) {
                if (a.second == b.second) return a.first < b.first;//종목코드 오름차순
                return a.second > b.second;//내림차순
                });
        }
        pStockList->Unlock();
    }
    //20250215 전일거래량은 젬병였으나 당일거래량 상승종목 매수대기중인 종목(수동으로 매수에 추가한다)
    else if (m_nSelWhat == COMBOSEL_VOLUMEUP) {
    MYSTOCK_LIST* pStockList = &g_datacenter.m_stocklist;
    MYSTOCK_LIST::HASHMAP* pMap = pStockList->GetHashMap();
    MYSTOCK_LIST::HASHMAP::iterator it;
    pStockList->Lock();
    m_sortcolumn = 6;//거래량
    count = 0;
    for (it = pMap->begin(); it != pMap->end(); ++it) {
        shtcode = it->first;
        pSiseItem = &it->second;
        psm = pSiseItem->psm;
        if (!psm || !pSiseItem)
            continue;
        //20250215 전일거래량은 미달이나 당일거래량 통과
        if (pSiseItem->market.volume > 300000 && pSiseItem->volumeflag > 0
            && pSiseItem->market.volume > pSiseItem->market.jdsvolume * 5
            && pSiseItem->market.jdsvolume >= 80000) {
            ////codelist.insert(SORTMAP_STRING::value_type(shtcode, psm->shtname));
            //codevolume.push_back(MYVECTOR_ULONG::value_type(shtcode, atoi(psm->si.listdate)));
            codevolume.push_back(MYVECTOR_ULONG::value_type(shtcode, psm->si.todayvolume));
            if (count++ > 100)
                break;
        }
    }
    pStockList->Unlock();
    }
    //20250114 거래량 소트(회전율이나 전일대비 증감율 높은것만)
    else if (m_nSelWhat == COMBOSEL_TOPVOLUME) {
        MYSTOCK_LIST* pStockList = &g_datacenter.m_stocklist;
        MYSTOCK_LIST::HASHMAP* pMap = pStockList->GetHashMap();
        MYSTOCK_LIST::HASHMAP::iterator it;
        pStockList->Lock();
        m_sortcolumn = 6;
        count = 0;
        for (it = pMap->begin(); it != pMap->end(); ++it) {
            shtcode = it->first;
            pSiseItem = &it->second;
            psm = pSiseItem->psm;
            if (!psm || !pSiseItem)
                continue;
            //20250114 거래량 회전율 목록구성 리얼시세 매수추가버튼
            if (pSiseItem->market.volume > 800000 || 
                (pSiseItem->market.volume > 50000 && 
                    pSiseItem->market.volume > pSiseItem->market.jdsvolume * 5)) {//전일동시간대 거래량 5배상승각
                codevolume.push_back(MYVECTOR_ULONG::value_type(shtcode, psm->si.todayvolume));
                if (count++ > 100)
                    break;
            }
        }
        //값으로 정렬(내림차순)
        sort(codevolume.begin(), codevolume.end(), [](MYPAIR_ULONG a, MYPAIR_ULONG b) {
            if (a.second == b.second) return a.first < b.first;//종목코드 오름차순
            return a.second > b.second;//내림차순
        });
        pStockList->Unlock();
    }
    else if (m_nSelWhat == COMBOSEL_STATICVI) {
    MYSTOCK_LIST* pStockList = &g_datacenter.m_stocklist;
    MYSTOCK_LIST::HASHMAP* pMap = pStockList->GetHashMap();
    MYSTOCK_LIST::HASHMAP::iterator it;
    pStockList->Lock();
    m_sortcolumn = 6;
    count = 0;
    for (it = pMap->begin(); it != pMap->end(); ++it) {
        shtcode = it->first;
        pSiseItem = &it->second;
        psm = pSiseItem->psm;
        if (!psm || !pSiseItem)
            continue;
        if ((pSiseItem->hoga.ask[3].price == 0 && pSiseItem->hoga.bid[3].price == 0) ||
            pSiseItem->staticvi) {
            codevolume.push_back(MYVECTOR_ULONG::value_type(shtcode, pSiseItem->staticvi));
            if (count++ > 100)
                break;
        }
    }
    //값으로 정렬(내림차순)
    sort(codevolume.begin(), codevolume.end(), [](MYPAIR_ULONG a, MYPAIR_ULONG b) {
        if (a.second == b.second) return a.first < b.first;//종목코드 오름차순
        return a.second > b.second;//내림차순
        });
    pStockList->Unlock();
    }
    else if (m_nSelWhat == COMBOSEL_DONGSIUP) {
    MYSTOCK_LIST* pStockList = &g_datacenter.m_stocklist;
    MYSTOCK_LIST::HASHMAP* pMap = pStockList->GetHashMap();
    MYSTOCK_LIST::HASHMAP::iterator it;
    pStockList->Lock();
    m_sortcolumn = 6;
    count = 0;
    for (it = pMap->begin(); it != pMap->end(); ++it) {
        shtcode = it->first;
        pSiseItem = &it->second;
        psm = pSiseItem->psm;
        if (!psm || !pSiseItem)
            continue;
        if (pSiseItem->hoga.bid[0].price > psm->si.price) {
            //codelist.insert(SORTMAP_STRING::value_type(shtcode, psm->shtname));
            codevolume.push_back(MYVECTOR_ULONG::value_type(shtcode, psm->si.price));
            if (count++ > 50)
                break;
        }
    }
    //값으로 정렬(내림차순)
    sort(codevolume.begin(), codevolume.end(), [](MYPAIR_ULONG a, MYPAIR_ULONG b) {
        if (a.second == b.second) return a.first < b.first;//종목코드 오름차순
        return a.second > b.second;//내림차순
        });
    pStockList->Unlock();
    }
    else if (m_nSelWhat == COMBOSEL_CLOSEDOWN) {
    MYSTOCK_LIST* pStockList = &g_datacenter.m_stocklist;
    MYSTOCK_LIST::HASHMAP* pMap = pStockList->GetHashMap();
    MYSTOCK_LIST::HASHMAP::iterator it;
    pStockList->Lock();
    m_sortcolumn = 6;
    count = 0;
    for (it = pMap->begin(); it != pMap->end(); ++it) {
        shtcode = it->first;
        pSiseItem = &it->second;
        psm = pSiseItem->psm;
        if (!psm || !pSiseItem)
            continue;
        if (pSiseItem->ticksise[0].price < psm->si.price) {
            //codelist.insert(SORTMAP_STRING::value_type(shtcode, psm->shtname));
            codevolume.push_back(MYVECTOR_ULONG::value_type(shtcode, pSiseItem->ticksise[0].price));
            if (count++ > 50)
                break;
        }
    }
    //값으로 정렬(내림차순)
    sort(codevolume.begin(), codevolume.end(), [](MYPAIR_ULONG a, MYPAIR_ULONG b) {
        if (a.second == b.second) return a.first < b.first;//종목코드 오름차순
        return a.second > b.second;//내림차순
        });
    pStockList->Unlock();
    }

    else if (m_nSelWhat == COMBOSEL_STOPMAN) {
    MYSTOCK_LIST* pStockList = &g_datacenter.m_stocklist;
    MYSTOCK_LIST::HASHMAP* pMap = pStockList->GetHashMap();
    MYSTOCK_LIST::HASHMAP::iterator it;
    pStockList->Lock();
    m_sortcolumn = 1;
    count = 0;
    for (it = pMap->begin(); it != pMap->end(); ++it) {
        shtcode = it->first;
        pSiseItem = &it->second;
        psm = pSiseItem->psm;
        if (!psm || !pSiseItem)
            continue;
        if (psm->si.stopped || psm->si.managed) {
            int stopped = psm->si.stopped ? 0x01:0x00;
            int managed = psm->si.managed ? 0x10 : 0x00;
            //codelist.insert(SORTMAP_STRING::value_type(shtcode, psm->shtname));
            codevolume.push_back(MYVECTOR_ULONG::value_type(shtcode,stopped || managed));
            if (count++ > 100)
                break;
        }
    }
    pStockList->Unlock();
    }

    int irow = 0;
    //pItemList->Lock();
    int changegrid = 0;
    CRect rcc;
    CRect rccell;
    CRect rcgrid;
    pGrid->GetWindowRect(&rcgrid);
    ScreenToClient(&rcgrid);
    GetClientRect(&rcc);
    count = codevolume.size();
    //TODO 자동크기조정

    int expect_height = ((count / 2) + 1) * m_rowheight + (count % 2) * m_rowheight;
    int diffh = expect_height - rcgrid.Height();
    if (diffh > 1) {
        CRect rcdlg;
        GetParent()->GetWindowRect(&rcdlg);
        rcdlg.bottom += diffh + 1;
        GetParent()->SetWindowPos(NULL, 0, 0, rcdlg.Width(), rcdlg.Height(), SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);

        pGrid->GetWindowRect(&rcgrid);
        ScreenToClient(&rcgrid);
        GetClientRect(&rcc);
    }

    for (vit = codevolume.begin(); vit != codevolume.end(); ++vit) {
        shtcode = vit->first;
        //STBookMark* pbook = (STBookMark*)&(it->second);
        psm = NULL;
        pSiseItem = g_datacenter.m_stocklist.GetItem(shtcode);
        if (!pSiseItem) {
            psm = g_datacenter.GetStockMaster(shtcode.c_str());
        }
        else
            psm = pSiseItem->psm;
        if (!psm)
            continue;

        if (irow == 0) {
            pGrid->SetRedrawNow(FALSE, FALSE);
            pGrid->DeleteRows(1, -1);//해더제외한 나머지삭제
        }
        irow++;
        row = AddToList(pGrid, pSiseItem, psm, irow);
        int len = SiseLogic::GetSiseTooltip(psm, sztooltip, sizeof(sztooltip) - 1);
        pGrid->SetTooltipText(irow, 1, sztooltip);
        pGrid->GetCellRect(irow, 0, &rccell);

        if (irow > 50 || rccell.bottom > (rcgrid.bottom - rcgrid.top) - m_rowheight) {
            if (changegrid == 0) {
                pGrid->SetRedrawNow(TRUE, TRUE);
                pGrid->ResetScrollBars();
                pGrid->Invalidate();
                if (m_sortcolumn >= 0)
                    pGrid->SortOnColumn(m_sortcolumn, FALSE);
#if 1 //오른쪽그리드에 추가
                if (m_bTwiceGrid == 1 && IsWindow(m_Grid[1].GetSafeHwnd())) {
                    irow = 0;
                    pGrid = &m_Grid[1];
                    changegrid++;
                }
#endif
            }
        }
        m_itemlist.push_back(shtcode);
        if (pSiseItem && pSiseItem->isreal == 0) {
            if (::IsWindow(g_pSiseThread->m_pSiseWnd->GetSafeHwnd())) {
                g_pSiseThread->SetReal(pSiseItem);
                pSiseItem->isreal = 4;
            }
        }
    }

    if (m_nTimerMode == 0) {
#ifdef _DEBUG
        float etime;
        etime = stopwatch(1, &dwstopwatch);
        //sprintf(sztemp, "종목리스트 경과시간 %5.3f 초 종목수 %ld", etime, count);
        //AddToMainLog(sztemp, 0x02);
#endif
    }
    if (changegrid == 0 || pGrid != &m_Grid[0]) {
        pGrid->SetRedrawNow(TRUE, TRUE);
        pGrid->ResetScrollBars();
        pGrid->Invalidate();
        if (m_nSelWhat == COMBOSEL_HIGHRATE)
            //pGrid->SetSortAscending(FALSE);
            pGrid->SetColumnSort(m_sortcolumn, GDCtrl::Sort::Descending);
        if (m_nSelWhat == COMBOSEL_LOWRATE)
            pGrid->SetColumnSort(m_sortcolumn, GDCtrl::Sort::Ascending);

        if (m_sortcolumn >= 0)
            pGrid->SortOnColumn(m_sortcolumn, FALSE);
    }
    CString cbtext;
    int sel = m_mcboxcode.GetCurSel();
    m_mcboxcode.GetLBText(sel,1, cbtext);
    msg.Format("%s(%d)", cbtext.GetBuffer(), count);
    if (GetParent())
        GetParent()->SetWindowText(msg);
}

void DlgBookmark::OnClickRefresh()
{
    MYSTOCK_LIST  *pStockList = &g_datacenter.m_stocklist;
    if (m_nTimerMode) {
        m_nTimerMode = 0;
    }
    RefreshList();
}

//새행개행후 종목코드입력모드
void DlgBookmark::OnClickAdd()
{
    int irow = 0, icol = 1;
    int ncode;
    char szcode[10];
    GDCtrl* pGrid = m_pGridFocus;
    HMSiseInfo *pSiseItem = NULL;
    char shtcode[8];
    CString stritem;
    if (!pGrid)
        return;
    
    GDCell selcell = pGrid->GetNextItem(GDCell(0, 1), GVNI_BELOW | GVNI_SELECTED);// | GVNI_FOCUSED);
    if (pGrid->IsValid(selcell)) {
        irow = selcell.row;
    }
    else {
        irow = pGrid->GetRowCount();
    }
    int iaddrow = AddToList(pGrid, NULL, NULL, irow);
    pGrid->InvalidateRow(iaddrow);
    pGrid->SetEditable(true);
    pGrid->SetEditCell(iaddrow, 1);
    pGrid->SetEditable(false);
}

void DlgBookmark::OnClickAddVolumue()
{
    HMSiseInfo* pSiseItem;
    CWnd* pFocus = GetFocus();
    GDCtrl* pGrid = m_pGridFocus;
    int irow = 0, icol = 1;
    int ncode;
    char szcode[10];
    int apply = 0;
    if (!pGrid)
        return;
    while (1) {
        GDCell selcell = pGrid->GetNextItem(GDCell(irow, icol), GVNI_BELOW | GVNI_SELECTED);// | GVNI_FOCUSED);
        if (!pGrid->IsValid(selcell)) {
            AddToMainLog("선택행이 없음", 0x02);
            break;
        }
        irow = selcell.row;
        ncode = (int)pGrid->GetItemData(irow, 0);
        //주의할 점은 sprintf 함수는 자동적으로 str 맨 마지막에 NULL 문자를 붙이기 때문에 항상 한 칸의 여유가 있어야 한다. 
        sprintf(szcode, "%06d", ncode);
        string shtcode(szcode);
        pSiseItem = g_datacenter.m_stocklist.GetItem(shtcode);
        if (pSiseItem) {
            if (pSiseItem->volumeflag >= 1) {
                pSiseItem->volumeflag++;
                if (pSiseItem->volumeflag > 2) {
                    pSiseItem->volumeflag = 0;
                    pSiseItem->bid_enable = 2;
                    if (pSiseItem->isreal == 0)
                        g_pSiseThread->SetReal(pSiseItem);
                    HASHMAP_HOLDLIST::iterator holdit;
                    holdit = g_conf.m_bidhaltmap.find(pSiseItem->psm->shtcode);
                    if (holdit != g_conf.m_bidhaltmap.end()) {
                        g_conf.m_bidhaltmap.erase(holdit);
                    }
                    apply++;
                }
            }
        }
    }
    if (apply > 0) {
        RefreshList();
    }
}

void DlgBookmark::OnClickAddReal()
{
    HMSiseInfo* pSiseItem;
    CWnd* pFocus = GetFocus();
    GDCtrl* pGrid = m_pGridFocus;
    int irow = 0,icol = 1;
    int ncode;
    char szcode[10];

    if (!pGrid)
        return;
    while (1) {
        GDCell selcell = pGrid->GetNextItem(GDCell(irow, icol), GVNI_BELOW | GVNI_SELECTED);// | GVNI_FOCUSED);
        if (!pGrid->IsValid(selcell)) {
            AddToMainLog("선택행이 없음", 0x02);
            break;
        }
        irow = selcell.row;
        ncode = (int)pGrid->GetItemData(irow, 0);
        //주의할 점은 sprintf 함수는 자동적으로 str 맨 마지막에 NULL 문자를 붙이기 때문에 항상 한 칸의 여유가 있어야 한다. 
        sprintf(szcode, "%06d", ncode);
        string shtcode(szcode);
        pSiseItem = g_datacenter.m_stocklist.GetItem(shtcode);
        if (pSiseItem) {
            if (pSiseItem->bid_enable <= 0)
                pSiseItem->bid_enable = 5;
            if (pSiseItem->isreal == 0)
                g_pSiseThread->SetReal(pSiseItem);
            HASHMAP_HOLDLIST::iterator holdit;
            holdit = g_conf.m_bidhaltmap.find(pSiseItem->psm->shtcode);
            if (holdit != g_conf.m_bidhaltmap.end()) {
                g_conf.m_bidhaltmap.erase(holdit);
            }
        }
    }
}

void DlgBookmark::OnClickRemove()
{
    HMSiseInfo *pSiseItem;
    CWnd* pFocus = GetFocus();
    GDCtrl* pGrid = m_pGridFocus;
    int irow = -1;
    if (!pGrid)
        return;
    GDCell selcell = pGrid->GetNextItem(GDCell(0, 1), GVNI_BELOW | GVNI_SELECTED);// | GVNI_FOCUSED);
    if (pGrid->IsValid(selcell)) {
        irow = selcell.row;
    }
    else
        return;
    //CString strcode = pGrid->GetItemText(irow, 1);
    //pSiseItem = (HMSiseInfo*)pGrid->GetItemData(irow,0);
    int ncode = (int)pGrid->GetItemData(irow, 0);
    char szcode[8]; sprintf(szcode, "%06d", ncode);
    string shtcode(szcode);
    pSiseItem = g_datacenter.m_stocklist.GetItem(shtcode);
    if (pSiseItem) {
        if (pSiseItem->addfavor & (byte)ENUM_ADDBOOK::BOOKMARK) {
            pSiseItem->addfavor &= ~(byte)ENUM_ADDBOOK::BOOKMARK;
            //20231003 입력순서 보장위해
            LISTPAIR_BOOKMARK::iterator holdit = g_conf.FindBookmark(pSiseItem->psm->shtcode);
            if (holdit != g_conf.m_bookmarkmap.end()) {
                g_conf.m_bookmarkmap.erase(holdit);
                RefreshList();
            }
        }
    }
}

void DlgBookmark::OnClickBidhalt()
{
    HMSiseInfo* pSiseItem;
    CWnd* pFocus = GetFocus();
    GDCtrl* pGrid = m_pGridFocus;
    int irow = -1;
    if (!pGrid)
        return;
    GDCell selcell = pGrid->GetNextItem(GDCell(0, 1), GVNI_BELOW | GVNI_SELECTED);// | GVNI_FOCUSED);
    if (pGrid->IsValid(selcell)) {
        irow = selcell.row;
    }
    else
        return;
    //CString strcode = pGrid->GetItemText(irow, 1);
    //pSiseItem = (HMSiseInfo*)pGrid->GetItemData(irow, 0);
    int ncode = (int)pGrid->GetItemData(irow, 0);
    char szcode[8]; sprintf(szcode, "%06d", ncode);
    string shtcode(szcode);
    pSiseItem = g_datacenter.m_stocklist.GetItem(shtcode);

    if (pSiseItem) {
        if (pSiseItem->bid_enable >= 1)
            pSiseItem->bid_enable = 0;
        else
            pSiseItem->bid_enable = 1;
        if (pSiseItem->bid_enable <= 0) { //매수홀딩
            STHoldInfo hi(pSiseItem->psm->shtcode, pSiseItem->psm->hname, pSiseItem->bid_enable);
            g_conf.m_bidhaltmap.insert(HASHMAP_HOLDLIST::value_type(pSiseItem->psm->shtcode, hi));
        }
        else {
            HASHMAP_HOLDLIST::iterator holdit;
            holdit = g_conf.m_bidhaltmap.find(pSiseItem->psm->shtcode);
            if (holdit != g_conf.m_bidhaltmap.end()) {
                g_conf.m_bidhaltmap.erase(holdit);
            }
            if(pSiseItem->isreal == 0)
                g_pSiseThread->SetReal(pSiseItem);
        }
        SetListItem(pGrid, pSiseItem, pSiseItem->psm, irow);
        //pGrid->UnSelect();
    }
}

void DlgBookmark::OnClickExcept()
{
    HMSiseInfo* pSiseItem;
    CWnd* pFocus = GetFocus();
    GDCtrl* pGrid = m_pGridFocus;
    int irow = -1;
    if (!pGrid)
        return;
    GDCell selcell = pGrid->GetNextItem(GDCell(0, 1), GVNI_BELOW | GVNI_SELECTED);// | GVNI_FOCUSED);
    if (pGrid->IsValid(selcell)) {
        irow = selcell.row;
    }
    else
        return;
    //CString strcode = pGrid->GetItemText(irow, 1);
    //pSiseItem = (HMSiseInfo*)pGrid->GetItemData(irow, 0);
    int ncode = (int)pGrid->GetItemData(irow, 0);
    char szcode[8]; sprintf(szcode, "%06d", ncode);
    string shtcode(szcode);
    pSiseItem = g_datacenter.m_stocklist.GetItem(shtcode);
    if (pSiseItem) {
        if (pSiseItem->addexcept == (short)ENUM_EXCEPT::EXCEPT_NONE)
            pSiseItem->addexcept |= (short)ENUM_EXCEPT::EXCEPT_BYCODE;
        else
            pSiseItem->addexcept = (short)ENUM_EXCEPT::EXCEPT_NONE;
        if (pSiseItem->addexcept > (short)ENUM_EXCEPT::EXCEPT_NONE) {
            SYSTEMTIME curtime;
            GetLocalTime(&curtime);
            CString strcomment;
            strcomment.Format("%s %04d%02d%02d %02d",
                pSiseItem->psm->hname, curtime.wYear, curtime.wMonth, curtime.wDay, curtime.wHour);
            g_conf.m_blacklistmap.insert(SORTMAP_STRING::value_type(pSiseItem->psm->shtcode, strcomment));
            if (pSiseItem->isreal == 1) {
                g_pSiseThread->ResetReal(pSiseItem);
                ////pSiseItem->oldreal = 1;
                //pSiseItem->isreal = 2;
                //pSiseItem->oldreal = 0;
            }
        }
        else {
            SORTMAP_STRING::iterator strit;
            strit = g_conf.m_blacklistmap.find(pSiseItem->psm->shtcode);
            if (strit != g_conf.m_blacklistmap.end()) {
                g_conf.m_blacklistmap.erase(strit);
            }
            //20230320 임시리얼모드에서 리얼제외해제(리얼수신등록)
            if (pSiseItem->isreal != 1 && g_pSiseThread) {
                g_pSiseThread->SetReal(pSiseItem);
                pSiseItem->isreal = 1;//20230324 호가창종료나 종목변경시 UnReal 못하게 2로세팅
                pSiseItem->oldreal = 0;
                pSiseItem->noerror = 0; //20230322 에러없앰
            }
        }
        SetListItem(pGrid, pSiseItem, pSiseItem->psm, irow);
        //pGrid->UnSelect();
    }
}

//******************************************************************************
//*
//******************************************************************************
LRESULT DlgBookmark::OnXMRecvData(WPARAM wParam, LPARAM lParam)
{
    int nDataType = wParam;
    if (nDataType == XM_CMD_REQUEST_DATA)// Data 수신
    {
#ifdef USE_EBEST_API    
        LPRECV_PACKET pRpData = (LPRECV_PACKET)lParam;
        if (pRpData->nDataLength <= 0)
            return 0;//error
        else if (strncmp((char*)pRpData->szTrCode, NAME_t1102, lstrlen(NAME_t1102)) == 0) {
            OnRecvTick(pRpData);
        }
        else if (strncmp((char*)pRpData->szTrCode, NAME_t1101, lstrlen(NAME_t1101)) == 0) {
            OnRecvHoga(pRpData);
        }
#else
        LPRP_DATA_INFO  lpOutData = (LPRP_DATA_INFO)lParam;
        if (lpOutData->nDataLength <= 0)
            return 0;//error
        else if (strncmp((char*)lpOutData->Header.szTrCode, NAME_T1001, lstrlen(NAME_T1001)) == 0) {
            OnRecvTick(lpOutData);
        }
        else if (strncmp((char*)lpOutData->Header.szTrCode, NAME_T1004, lstrlen(NAME_T1004)) == 0) {
            OnRecvHoga(lpOutData);
        }
#endif
    }
    // Message 수신
    else if (nDataType == XM_CMD_MESSAGE_DATA)
    {
        LPMSG_PACKET pMsg = (LPMSG_PACKET)lParam;
        //SetMessage( ( LPCTSTR )pMsg->lpszMessageData, pMsg->nMsgLength );
        TCAPI_ReleaseMessageData(lParam);
    }
    // System Error 수신
    else if (nDataType == XM_CMD_SYSTEM_ERROR_DATA)
    {
        LPMSG_PACKET pMsg = (LPMSG_PACKET)lParam;
        //SetMessage((LPCTSTR)pMsg->lpszMessageData, pMsg->nMsgLength);
        CString strMsg;
        strMsg.SetString((LPCTSTR)pMsg->lpszMessageData, pMsg->nMsgLength);
        AddToMainLog(strMsg, 0x03);
        Sleep(100);
        KillTimer(200);
        TCAPI_ReleaseMessageData(lParam);
    }
    // Release Data 수신
    else if (nDataType == XM_CMD_RELEASE_DATA)
    {
        int nRQID = (int)lParam;
        TCAPI_ReleaseRequestData(nRQID);
    }
    return 1;
}

//시세
int DlgBookmark::OnRecvTick(LPVOID lpData)
{
    int rc = 0;
    int passOKCount = 0;
#ifdef USE_EBEST_API
    LPRECV_PACKET pRpData = (LPRECV_PACKET)lpData;
    int count = pRpData->nDataLength / sizeof(t1102OutBlock);
    t1102OutBlock* pOut = (t1102OutBlock*)pRpData->lpData;
#else
    LPRP_DATA_INFO lpOutData = (LPRP_DATA_INFO)lpData;
    int count = lpOutData->nDataLength / sizeof(T1001OutBlock);
    T1001OutBlock* pOut = (T1001OutBlock*)lpOutData->lpData;
#endif
    CString strerror;
    CString strCode;
    //char sztemp[30];
    int sub = 0;
    int noerror = 0;//기본값 모두 대상에 포함
    //float fPreVolumeRate;
    MYSTOCK_LIST  *pStockList = &g_datacenter.m_stocklist;
    HMSiseInfo *pSiseItem;//change mode;
    HMStockInfo* psm;
    char *strcode;

    for (register int i = 0; i < count; i++)
    {
        BizCommIF::fixdummysisepacket(pOut);
        strCode = GET_TRIMDATA(pOut->shcode);
        strcode = strCode.GetBuffer(strCode.GetLength());
        //keycount = m_stocklist.Count(strcode);// Key 요소 찾기.
        //__try{
        pSiseItem = pStockList->GetItem(strcode);
        psm = g_datacenter.GetStockMaster(strcode);// 종목마스터에서 조회

        if (m_bAddMode) {
            if (!pSiseItem) {
                //TODO::전일종가와 etf 여부 가져오기 20201231
                HMSiseInfo siseitem;
                //siseitem.ncode = atoi(strcode);
                //STRCOPYDATASIZE(siseitem.shtcode, strcode);
                siseitem.psm = psm;
                pStockList->AddItem(strcode, siseitem);
                pSiseItem = pStockList->GetItem(strcode);
                pSiseItem->addfavor |= (byte)ENUM_ADDBOOK::BOOKMARK;
                psm->psi = pSiseItem;
            }
            if (!psm) {
                HMStockInfo mi;
                mi.ncode = pSiseItem->psm->ncode;
                STRCOPYDATASIZE(mi.shtcode, strcode);
                STRCOPYDATASIZE(mi.hname, GET_TRIMDATA(pOut->hname));
                mbcscopy(mi.shtname, mi.hname, sizeof(mi.shtname) - 1);
                //STRCOPYDATASIZE(pItem->excode, GET_TRIMDATA(pOut->excode));
                STRCOPYDATASIZE(mi.marketgb, GET_TRIMDATA(pOut->janginfo));
                if (!strnicmp(mi.marketgb, "KOSPI",5))
                    mi.marketid = (int)ENUM_MARKETID::KOSPI;
                else if (!strnicmp(mi.marketgb, "KOSPI200",8))
                    mi.marketid = (int)ENUM_MARKETID::KOSPI;// KOSPI200;
                else
                    mi.marketid = (int)ENUM_MARKETID::KOSDAQ;
                if (!psm) {
                    g_datacenter.m_stockmaster.insert(MYSTOCK_MASTER::value_type(pSiseItem->psm->shtcode, mi));
                    psm = g_datacenter.GetStockMaster(pSiseItem->psm->shtcode);
                }
            }
            pSiseItem->psm = psm;
        }
        //개별 일별시세 조회
        if (psm && psm->ds.daycount == 0) {
            HWND hSiseWnd = g_pSiseThread->m_pSiseWnd ? g_pSiseThread->m_pSiseWnd->GetSafeHwnd() : NULL;
            g_bizmoncenter.queryBizNow(strcode, hSiseWnd);
        }

        SYSTEMTIME cur_time;
        GetLocalTime(&cur_time);
        pSiseItem->uptime = cur_time;
        if(psm)
            psm->uptime = cur_time;
        pSiseItem->market.uptime = cur_time;

        //현재가 시세만
        pSiseItem->market.price = _ttoi(GET_TRIMDATA(pOut->price));
        pSiseItem->market.jdsvolume = _ttoi(GET_TRIMDATA(pOut->jvolume)); //전일동시간대 거래량
        pSiseItem->psm->si.jnilvolume = _ttoi(GET_TRIMDATA(pOut->jnilvolume));
        pSiseItem->psm->si.listing = _ttoi(GET_TRIMDATA(pOut->listing));
        pSiseItem->psm->si.listing *= 1000;//상장주식수 (1000단위)
        pSiseItem->psm->si.abscnt = _ttoi(GET_TRIMDATA(pOut->abscnt));
        pSiseItem->psm->si.abscnt *= 1000;//유동주식수 (1000단위, 환경설정은 1단위)
        pSiseItem->psm->si.capital = _ttoi(GET_TRIMDATA(pOut->capital));
        pSiseItem->psm->si.total = _ttoi(GET_TRIMDATA(pOut->total));
        STRCOPYDATASIZE(pSiseItem->psm->si.listdate, GET_TRIMDATA(pOut->listdate));//상장일

        STRCOPYDATASIZE(pSiseItem->market.sign, GET_TRIMDATA(pOut->sign));//전일대비 구분 char(1) 1: 상한, 2: 상승, 3: 보합, 4: 하한, 5: 하락
        pSiseItem->market.change = _ttoi(GET_TRIMDATA(pOut->change));//전일대비 long(8) 기호는 안들어옴 위에 sign으로 판단해야함
        pSiseItem->market.drate = (float)_tstof(GET_TRIMDATA(pOut->diff));//등락율 foat(6.2) 기호있는 숫자로 들옴 백분율로 환산해야함
        if (pSiseItem->market.sign[0] == '4' || pSiseItem->market.sign[0] == '5') {
            if (pSiseItem->market.change > 0)
                pSiseItem->market.change *= -1;
        }
        if(psm)
            psm->si.preclose = pSiseItem->market.price - pSiseItem->market.change;
#ifdef USE_EBEST_API
        char tempdiff[10];
        strncpy(tempdiff, pOut->diff, sizeof(pOut->diff));
        if (strchr(tempdiff, '.'))
            pSiseItem->market.drate = pSiseItem->market.drate; //백분율로 들어온다.
        else
            pSiseItem->market.drate = pSiseItem->market.drate / 100; //백분율 없이 정수로 들어온다.
#else
        pSiseItem->market.drate = pSiseItem->market.drate / 100; //백분율 없이 정수로 들어온다.
#endif
        pSiseItem->market.volume = _ttoi(GET_TRIMDATA(pOut->volume));
        pSiseItem->market.value = _ttoi(GET_TRIMDATA(pOut->value));
        pSiseItem->market.open = _ttoi(GET_TRIMDATA(pOut->open));
        pSiseItem->market.high = _ttoi(GET_TRIMDATA(pOut->high));
        pSiseItem->market.low = _ttoi(GET_TRIMDATA(pOut->low));
        if (psm)
            pSiseItem->market.orate = BizLogic::calcDrate(psm->si.preclose, pSiseItem->market.open);
        pSiseItem->market.brate = BizLogic::calcDrate(pSiseItem->market.open, pSiseItem->market.price);
#if 0
        //20231219
        if (pSiseItem->market.open > 0) {
            if (pSiseItem->market.high > 0)
                pSiseItem->market.hrate = BizLogic::calcDrate(pSiseItem->market.open, pSiseItem->market.high);
            if (pSiseItem->market.low > 0)
                pSiseItem->market.hrate = BizLogic::calcDrate(pSiseItem->market.open, pSiseItem->market.low);
        }
#endif
        STRCOPYDATASIZE(pSiseItem->market.opentime, GET_TRIMDATA(pOut->opentime));
        STRCOPYDATASIZE(pSiseItem->market.hightime, GET_TRIMDATA(pOut->hightime));
        STRCOPYDATASIZE(pSiseItem->market.lowtime, GET_TRIMDATA(pOut->lowtime));
        pSiseItem->market.trate = BizLogic::calcDrate(pSiseItem->market.low, pSiseItem->market.high);
        int arrow = strnicmp(pSiseItem->market.lowtime, pSiseItem->market.hightime, 6);
        if (arrow > 0)
            pSiseItem->market.trate *= -1;

        STRCOPYDATASIZE(pSiseItem->psm->si.manage, GET_TRIMDATA(pOut->info2));
        STRCOPYDATASIZE(pSiseItem->psm->si.stop, GET_TRIMDATA(pOut->info3));
        STRCOPYDATASIZE(pSiseItem->psm->si.warn, GET_TRIMDATA(pOut->info4));
        STRCOPYDATASIZE(pSiseItem->psm->si.care, GET_TRIMDATA(pOut->info5));
        STRCOPYDATASIZE(pSiseItem->psm->marketgb, GET_TRIMDATA(pOut->janginfo));
#ifndef USE_EBEST_API
        if (psm) {
            STRCOPYDATATRIM(psm->si.szinvestatt, pOut->investatt);
            psm->si.etftcrate = _tstof(GET_TRIMDATA(pOut->etftcrate));
            if (psm->si.szinvestatt[0] == 'Y') {
                psm->si.investatt = true;
                STRCOPYDATASIZE(psm->si.care, "투자환기");
            }
            else
                psm->si.investatt = false;
        }
#endif
        //nextstep:
        pSiseItem->noerror |= noerror;
        if (noerror == 0) {
#ifdef USE_EBEST_API
            t1101InBlock stIn;
            memset(&stIn, 0x00, sizeof(stIn));
            strncpy(stIn.shcode, strcode, sizeof(stIn.shcode));
            int slen = sizeof(stIn);
            int nReqID = BizCommIF::SendRequest(GetSafeHwnd(), NAME_t1101, &stIn, slen, 0, "", 10);
#else
            T1004InBlock stIn;
            memset(&stIn, 0x00, sizeof(stIn));
            strncpy(stIn.shcode, strcode, sizeof(stIn.shcode));
            int slen = sizeof(stIn);
            int nReqID = BizCommIF::SendRequest(GetSafeHwnd(), NAME_T1004, &stIn, slen, 0, "", 10);
#endif
            if (nReqID == -1) {//error
                strerror.Format("%6s %-8.8s 종목등록 실패", strcode, pSiseItem->psm->shtname);
                AddToMainLog(strerror);
            }
        }
        pOut++;
        m_irecvquery++;
    }
    if (m_bAddMode) {
        RefreshList();
    }
    else if (m_irecvquery >= m_iquery) {
        m_irecvquery = 0;
        RefreshList();
    }
    //}
    //__finally{
    return rc;
}

//주식현재가(호가)조회
int DlgBookmark::OnRecvHoga(LPVOID lpData)
{
    int rc = 0;
    int passOKCount = 0;
#ifdef USE_EBEST_API    
    LPRECV_PACKET pRpData = (LPRECV_PACKET)lpData;
    int count = pRpData->nDataLength / sizeof(t1101OutBlock);
    t1101OutBlock* pOut = (t1101OutBlock*)pRpData->lpData;
#else
    LPRP_DATA_INFO lpOutData = (LPRP_DATA_INFO)lpData;
    int count = lpOutData->nDataLength / sizeof(T1004OutBlock);
    T1004OutBlock* pOut = (T1004OutBlock*)lpOutData->lpData;
#endif
    CString strtemp;
    CString strerror;
    CString strCode;
    HMSiseInfo *pSiseItem;//change mode;
    char *strcode;
    CString strmsg;
    char *offerrem1 = pOut->offerrem1;
    char *offerho1 = pOut->offerho1;
    char *bidrem1 = pOut->bidrem1;
    char * bidho1 = pOut->bidho1;
    int diffpos1 = pOut->offerho2 - offerho1;
    int diffpos2 = pOut->bidho2 - bidho1;
    char sztempval[4][15 + 1] = { 0, };

    SYSTEMTIME cur_time = { 0, };
    GetLocalTime(&cur_time);
    MYSTOCK_LIST  *pStockList = &g_datacenter.m_stocklist;

    for (register int i = 0; i < count; i++)
    {
        BizCommIF::fixdummyhogapacket(pOut);

        //m_nT1004Count++;//호가 수신수
        strCode = GET_TRIMDATA(pOut->shcode);
        strcode = strCode.GetBuffer(strCode.GetLength());
        //keycount = m_pStockList->Count(strcode);// Key 요소 찾기.
        //__try{
        //it = m_pStockList->find(strcode);// Key 요소 찾기.
        //if (it != m_pStockList->end()){
        pSiseItem = pStockList->GetItem(strcode);
        int codetest = atoi(strcode);
        if (pSiseItem) {
            ////pItem = &it->second;
            ////STRCOPYDATASIZE(pItem->orderprice.shtcode, GET_TRIMDATA(pOut->shcode));
            //STRCOPYDATASIZE(pSiseItem->order.hotime, GET_TRIMDATA(pOut->hotime));
            //HHMMSSToTime(pSiseItem->order.hotime, &cur_time);
            //pSiseItem->uptime = cur_time;
            pSiseItem->hoga.uptime = cur_time;
            pSiseItem->uptime = cur_time;
            STRCOPYDATASIZE(pSiseItem->hoga.hotime, GET_TRIMDATA(pOut->hotime));
            //리얼타임 서버시간 전문의 시간이라 디버깅시 로컬시간이랑 비교하면 안됨!
            //if(cur_time.wHour < 16)
#if 0 //20231003 서버시간으로 엎어치기금지
            HHMMSSToTime(pSiseItem->hoga.hotime, &cur_time);
            pSiseItem->uptime = cur_time;
#endif
            for (register int ipos = 0; ipos < 10; ipos++) {
                STRCOPYDATASIZE(sztempval[0], offerrem1); sztempval[0][sizeof(pOut->offerrem1)] = 0x00;
                STRCOPYDATASIZE(sztempval[1], offerho1);  sztempval[1][sizeof(pOut->offerho1)] = 0x00;
                STRCOPYDATASIZE(sztempval[2], bidrem1);   sztempval[2][sizeof(pOut->bidrem1)] = 0x00;
                STRCOPYDATASIZE(sztempval[3], bidho1);    sztempval[3][sizeof(pOut->bidho1)] = 0x00;
                pSiseItem->hoga.ask[ipos].qty = _ttoi(sztempval[0]);//중앙,최우선 매도호가
                pSiseItem->hoga.ask[ipos].price = _ttoi(GET_TRIMDATA(sztempval[1]));
                pSiseItem->hoga.bid[ipos].qty = _ttoi(GET_TRIMDATA(sztempval[2]));//중앙,최우선 매도호가
                pSiseItem->hoga.bid[ipos].price = _ttoi(GET_TRIMDATA(sztempval[3]));

                offerho1 += diffpos1;
                offerrem1 = offerho1 + (pOut->offerrem1 - pOut->offerho1);
                bidho1 += diffpos2;
                bidrem1 = bidho1 + (pOut->bidrem1 - pOut->bidho1);
            }

            pSiseItem->staticvi = (pSiseItem->hoga.bid[3].price <= 0) ? 1 : 0;

            if (/*pSiseItem->except == 0 && */pSiseItem->isreal == 0 || pSiseItem->oldreal == 0) {
                if (::IsWindow(g_pSiseThread->m_pSiseWnd->GetSafeHwnd())) {
                    g_pSiseThread->SetReal(pSiseItem);
                    //20230321 현재추가한 예외종목 리얼등록
                    if (m_bAddMode)
                        pSiseItem->isreal = 3;

                }
            }
        }
        pOut++;
    }
    if (g_pSiseThread->m_pSiseWnd->IsInService() == TRUE) {
        g_pMainWnd->m_pFrmLedger->m_pDlgLedger->ShowStockCount();
    }
    return rc;
}

void DlgBookmark::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
    DlgResizeBaseEx::OnActivate(nState, pWndOther, bMinimized);
    if (m_nActivate == 1) {
        SendMessage(WM_COMMAND, MAKEWPARAM(IDC_CMD_REFRESH, 0), 0L);
    }
}

//콤보선택
void DlgBookmark::OnCbnSelchangeWhat()
{
    ULONG_PTR itemdata = 0;
    int nItem = m_mcboxcode.GetCurSel(&itemdata);
    if (nItem != CB_ERR) {
        ::SetFocus(::GetDlgItem(GetSafeHwnd(), IDC_GRID));
        m_nSelWhat = itemdata;
        RefreshList();
    }
}

void DlgBookmark::OnTimer(UINT_PTR nIDEvent)
{
    if (nIDEvent == 100) {
        m_nTimerMode = 1;
        SendMessage(WM_COMMAND, (WPARAM)MAKELONG(IDC_CMD_REFRESH, BN_CLICKED), (LPARAM)0L);
    }
    if (nIDEvent == 200) {
        KEYLIST_STRING* pItemList = &m_itemlist;
        KEYLIST_STRING::iterator it;
        HMSiseInfo *pSiseItem;
        string shtcode;
        int count = 0;
        int ok = 0;
        int nReqID = 0;
        time_t timeover;
        if (m_bInTimer == 1)
            return;
        m_bInTimer = 1;
        for (it = std::next(pItemList->begin(), m_iquery); it != pItemList->end(); ++it) {
            shtcode = *it;
            pSiseItem = g_datacenter.m_stocklist.GetItem(shtcode);
            if (pSiseItem)
                timeover = GetElapsedTime(pSiseItem->uptime);
            else
                timeover = -1;
            if (timeover == -1 || timeover > 1000 * 30 * 1) {//30초 경과시
                ok++;
#ifdef USE_EBEST_API
                t1102InBlock stIn;
                memset(&stIn, 0x00, sizeof(stIn));
                strncpy(stIn.shcode, shtcode.c_str(), sizeof(stIn.shcode));
                int slen = sizeof(stIn);
                // 메세지 받을 윈도우,TR 명,IN Param,다음조회 여부 : 다음 조회일 경우 세팅,다음조회 Key,Timeout(초)
                nReqID = BizCommIF::SendRequest(GetSafeHwnd(), NAME_t1102, &stIn, slen, 0, "", 10);
                if (nReqID != -1) {//error
                    count++;
                    Sleep(50);
                    if (count % 10 == 0) {
                        Sleep(1080);//1초당 10건 시세제한
                        break;
                    }
                }
#else
                T1001InBlock stIn;
                memset(&stIn, 0x00, sizeof(stIn));
                strncpy(stIn.shcode, shtcode.c_str(), sizeof(stIn.shcode));
                int slen = sizeof(stIn);
                // 메세지 받을 윈도우,TR 명,IN Param,다음조회 여부 : 다음 조회일 경우 세팅,다음조회 Key,Timeout(초)
                nReqID = BizCommIF::SendRequest(GetSafeHwnd(), NAME_T1001, &stIn, slen, 0, "", 10);
                if (nReqID != -1) {//error
                    count++;
                }
#endif
            }
            m_iquery++;
        }
        if (count == 0 || m_iquery >= pItemList->size())
            KillTimer(200);
        m_bInTimer = 0;
    }
}

void DlgBookmark::OnCheckPolling()
{
    BOOL bPoll = IsDlgButtonChecked(IDC_CHECK_POLLING);
    if (bPoll)
        SetTimer(100, 10000, NULL);
    else
        KillTimer(100);
}

void DlgBookmark::OnCheckDailysise()
{
    //TODO 20231003 오래된것 조회하기
    //EBEST는 속도가 초당3건이라 98분이상 걸리므로 그냥 DB에서 읽는다.
    BOOL bc = IsDlgButtonChecked(IDC_CHECK_DAILYSISE);
    m_bShowDailySise = bc;
}

void DlgBookmark::OnClickQuerySise()
{
    MYSTOCK_LIST  *pStockList = &g_datacenter.m_stocklist;
    MYSTOCK_LIST::HASHMAP *pMap = pStockList->GetHashMap();
    MYSTOCK_LIST::HASHMAP::iterator it;
    string shtcode;
    int count = 0;
    time_t timeover;
    if (m_bInTimer == 1)
        return;
    m_bAddMode = FALSE;
    if (m_querytime.wYear != 0) {
        timeover = GetElapsedTime(m_querytime);
        if (timeover < 1000 * 5)
            return;
    }
    GetLocalTime(&m_querytime);
    ////순서대로 소트표시(해시맵은 순서보장안받음)
    //pKeyList = pStockList->GetKeyList();
    ///*pKeyList->sort();*/
    m_iquery = 0;
    m_irecvquery = 0;
    KillTimer(200);
    int interval = 250;
#ifdef USE_EBEST_API
    interval = 1080;
#endif
    SetTimer(200, interval, NULL);
}

void DlgBookmark::OnClickSaveBookmark()
{
    g_conf.SaveBookmark();
    g_conf.SaveBidStop();
    g_conf.SaveBlackList();
}

void DlgBookmark::OnClickLoadBookmark()
{
    //TODO fileopen
    char szlogfile[MAX_PATH];
    g_conf.GetLogFilePath(szlogfile, "Bookmark",0, ".xml");
    static TCHAR szPath[_MAX_PATH];
    CString strFile;
    CFileDialog oFileDialog(TRUE, _T(""), _T(""), OFN_FILEMUSTEXIST | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_ENABLEHOOK,
        _T("Bookmark(Bookmark*.xml)|Bookmark*.xml|Text Files(*.txt)|*.txt|All Files(*.*)|*.*||"), AfxGetMainWnd());
    if (szPath[0] == 0x00)
        strncpy(szPath, g_conf.m_confdir, sizeof(szPath) - 1);
    oFileDialog.m_ofn.lpstrInitialDir = szPath;
    /*oFileDialog.m_ofn.lpstrFile = NULL;*/
    if (oFileDialog.DoModal() != IDOK)
        return;
    strFile = oFileDialog.GetPathName();
    strncpy(szlogfile, strFile.GetBuffer(), sizeof(szlogfile) - 1);
    g_conf.LoadBookmark(szlogfile);
    RefreshList();
}

void DlgBookmark::OnGvnClick(UINT idCtrl,NMHDR* pNMHDR, LRESULT* pResult)
{
    NM_GRIDVIEW* pnmgv = (NM_GRIDVIEW*)pNMHDR;
    GV_DISPINFO* pgvDispInfo = (GV_DISPINFO*)pnmgv->param;
    GDCtrl* pGrid = NULL;
    *pResult = FALSE;
    NMHDR nmhdr = pnmgv->hdr;
    if (nmhdr.hwndFrom == m_Grid[0].GetSafeHwnd())
        pGrid = &m_Grid[0];
    else if (nmhdr.hwndFrom == m_Grid[1].GetSafeHwnd())
        pGrid = &m_Grid[1];
    else
        return;
    //20231003 이전 그리드 선택해제
    if (m_pGridFocus && pGrid != m_pGridFocus) {
        m_pGridFocus->UnSelect();
        m_pGridFocus->Invalidate();
    }
    m_pGridFocus = pGrid;

    if (pnmgv->iRow < pGrid->GetFixedRowCount()) {
        if (pnmgv->iRow < 0) {
            m_sortcolumn = -1;
            m_Grid[0].UnSelect();//EnableSelection
            m_Grid[0].Invalidate();
            //m_Grid[1].UnSelect();//EnableSelection
            //m_Grid[1].Invalidate();
        }
        return;
    }
    int irow = pnmgv->iRow;
    if (irow >= pGrid->GetFixedRowCount()) {
        //HMSiseInfo* pSiseItem = (HMSiseInfo * )pGrid->GetItemData(irow,0);
        int ncode = (int)pGrid->GetItemData(irow, 0);
        char szcode[8]; sprintf(szcode, "%06d", ncode);
        string shtcode(szcode);
        HMSiseInfo* pSiseItem = g_datacenter.m_stocklist.GetItem(shtcode);
        if (pSiseItem) {
            if (g_pMainWnd->m_pFrmHogaClick && ::IsWindow(g_pMainWnd->m_pFrmHogaClick->GetSafeHwnd())) {
                HWND hHogaWnd = g_pMainWnd->m_pFrmHogaClick->m_pDlg->GetSafeHwnd();
                if (hHogaWnd && IsWindow(hHogaWnd))
                    ::PostMessage(hHogaWnd, WM_SISETHREAD_HOGA, (WPARAM)SISE_NOTIFYID_CHGCODE, (LPARAM)pSiseItem->psm->shtcode);
                //::SetWindowPos(g_pMainWnd->m_pFrmHogaClick->GetSafeHwnd(), NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
            }
            if (g_pMainWnd->m_pFrmStockInfo && ::IsWindow(g_pMainWnd->m_pFrmStockInfo->GetSafeHwnd())) {
                HWND hTargetWnd = g_pMainWnd->m_pFrmStockInfo->m_pDlg->GetSafeHwnd();
                if (hTargetWnd && IsWindow(hTargetWnd))
                    ::PostMessage(hTargetWnd, WM_SISETHREAD_SISE, (WPARAM)SISE_NOTIFYID_CHGCODE, (LPARAM)pSiseItem->psm->shtcode);
                //::SetWindowPos(g_pMainWnd->m_pFrmStockInfo->GetSafeHwnd(), NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
            }
            if (g_pMainWnd->m_pFrmDailySise && ::IsWindow(g_pMainWnd->m_pFrmDailySise->GetSafeHwnd())) {
                if (m_bShowDailySise) {
                    HWND hHogaWnd = g_pMainWnd->m_pFrmDailySise->m_pDlg->GetSafeHwnd();
                    if (hHogaWnd && IsWindow(hHogaWnd))
                        ::PostMessage(hHogaWnd, WM_SISETHREAD_SISE, (WPARAM)SISE_NOTIFYID_CHGCODE, (LPARAM)pSiseItem->psm->shtcode);
                    //::SetWindowPos(g_pMainWnd->m_pFrmDailySise->GetSafeHwnd(),NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
                }
            }
            if (g_pMainWnd->m_pFrmBunSise && ::IsWindow(g_pMainWnd->m_pFrmBunSise->GetSafeHwnd())) {
                HWND hBunsiseWnd = g_pMainWnd->m_pFrmBunSise->m_pDlg->GetSafeHwnd();
                if (hBunsiseWnd && IsWindow(hBunsiseWnd))
                    ::PostMessage(hBunsiseWnd, WM_SISETHREAD_SISE, (WPARAM)SISE_NOTIFYID_CHGCODE, (LPARAM)pSiseItem->psm->shtcode);
                //::SetWindowPos(g_pMainWnd->m_pFrmBunSise->GetSafeHwnd(), NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
            }
        }
    }
}

void DlgBookmark::OnGvnRClick(UINT idCtrl, NMHDR* pNMHDR, LRESULT* pResult)
{
    NM_GRIDVIEW* pnmgv = (NM_GRIDVIEW*)pNMHDR;
    GV_DISPINFO* pgvDispInfo = (GV_DISPINFO*)pnmgv->param;
    GDCtrl* pGrid = NULL;
    *pResult = FALSE;
    NMHDR nmhdr = pnmgv->hdr;
    if (nmhdr.hwndFrom == m_Grid[0].GetSafeHwnd())
        pGrid = &m_Grid[0];
    //else if (nmhdr.hwndFrom == m_Grid[1].GetSafeHwnd())
    //    pGrid = &m_Grid[1];
    else
        return;
    if (pnmgv->iRow < pGrid->GetFixedRowCount()) {
        if (pnmgv->iColumn == 1) {
            m_bShowCode ^= 1;
            RefreshList();
        }
        return;
    }
    POINT pt;
    GetCursorPos(&pt);
    HMENU hMenuLoad = NULL, hMenu = NULL;
    hMenuLoad = LoadMenu(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDM_CONTEXT_MENU));
    hMenu = GetSubMenu(hMenuLoad, 3);
    int ncode = (int)pGrid->GetItemData(pnmgv->iRow, 0);
    char szcode[8]; sprintf(szcode, "%06d", ncode);
    string shtcode(szcode);
    HMSiseInfo* pSiseItem = g_datacenter.m_stocklist.GetItem(shtcode);
    if (pSiseItem){
        if(pSiseItem->bidspecial)
            CheckMenuItem(hMenu, IDM_BIDSPECIAL, MF_CHECKED);
        if(pSiseItem->bid_enable <= 0)
            CheckMenuItem(hMenu, IDM_BIDHALT, MF_CHECKED);
        if (pSiseItem->addexcept)
            CheckMenuItem(hMenu, IDM_BIDEXCEPT, MF_CHECKED);
    }
#ifdef USE_KXMENU
    kxNSMenu menu;
    menu.LoadMenu(hMenu);
    menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, GetSafeHwnd(), NULL);
    menu.Detach();
#else
    TrackPopupMenu(hMenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, 0, GetSafeHwnd(), NULL);
#endif
#if 0
    //if (hMenu)
    // TrackPopupMenu(hMenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, 0, GetSafeHwnd(), NULL);
    //if (hMenuLoad)
    // DestroyMenu(hMenuLoad);
    //m_gvitem = *pnmgv;
    DWORD lParam = GetMessagePos();
    //POINT pt;
    //pt.x = GET_X_LPARAM(lParam);
    //pt.y = GET_Y_LPARAM(lParam);
    g_pMainWnd->m_pFrmLedger->m_pDlg->SendMessage(WM_CONTEXTMENU, (WPARAM)pNMHDR->hwndFrom, lParam);
#endif
}

//두그리드 소트동기화
void DlgBookmark::OnGvnColumnSort(UINT idCtrl, NMHDR* pNMHDR, LRESULT* pResult)
{
    NM_GRIDVIEW* pnmgv = (NM_GRIDVIEW*)pNMHDR;
    GV_DISPINFO* pgvDispInfo = (GV_DISPINFO*)pnmgv->param;
    GDCtrl* pGrid = NULL;// , * pGrid2 = NULL;;
    *pResult = FALSE;
    NMHDR nmhdr = pnmgv->hdr;
    if (nmhdr.hwndFrom == m_Grid[0].GetSafeHwnd()) {
        pGrid = &m_Grid[0];
        //pGrid2 = &m_Grid[1];
    }
    else if (nmhdr.hwndFrom == m_Grid[1].GetSafeHwnd()) {
        pGrid = &m_Grid[1];
        //pGrid2 = &m_Grid[0];
    }
    else
        return;
    if (pnmgv->iRow < pGrid->GetFixedRowCount()) {
        int reverse = pnmgv->param;
        m_sortcolumn = pnmgv->iColumn;
        if (m_sortcolumn >= 0) {
            BOOL bAscending = pGrid->GetSortAscending();
            pGrid->SortOnColumn(m_sortcolumn, FALSE);// reverse);
            //if (reverse)
            //    pGrid->SetSortAscending(bAscending);
        }
    }
}

void DlgBookmark::OnGvnQueryEdit(UINT idCtrl, NMHDR* pNMHDR, LRESULT* pResult)
{
    NM_GRIDVIEW* pnmgv = (NM_GRIDVIEW*)pNMHDR;
    GV_DISPINFO* pgvDispInfo = (GV_DISPINFO*)pnmgv->param;
    *pResult = FALSE; //편집적용이면 FALSE
    GDCtrl* pGrid = NULL;
    NMHDR nmhdr = pnmgv->hdr;
    if (nmhdr.hwndFrom == m_Grid[0].GetSafeHwnd())
        pGrid = &m_Grid[0];
    //else if (nmhdr.hwndFrom == m_Grid[1].GetSafeHwnd())
    //    pGrid = &m_Grid[1];
    else
        return;
}

void DlgBookmark::OnGvnEditEnd(UINT idCtrl, NMHDR* pNMHDR, LRESULT* pResult)
{
    int addpos = 0;
    NM_GRIDVIEW* pnmgv = (NM_GRIDVIEW*)pNMHDR;
    GV_DISPINFO* pgvDispInfo = (GV_DISPINFO*)pnmgv->param;
    *pResult = FALSE;
    GDCtrl* pGrid = NULL;
    NMHDR nmhdr = pnmgv->hdr;
    if (nmhdr.hwndFrom == m_Grid[0].GetSafeHwnd()) {
        pGrid = &m_Grid[0];
        addpos = pnmgv->iRow - 1;
    }
    else
        return;
    if (pnmgv->iRow < pGrid->GetFixedRowCount()) {
        return;
    }
    if (pnmgv->iColumn == 0) {
        CString strcode = pGrid->GetItemText(pnmgv->iRow, pnmgv->iColumn);
        string szkeycode = strcode;
        char sztemp[10] = { 0, };
        if (strcode.GetLength() < 6) {
            pGrid->DeleteRow(pnmgv->iRow);
            pGrid->Invalidate();
            RefreshList();
            return;
        }
        HMSiseInfo* pSiseItem = g_datacenter.m_stocklist.GetItem(strcode.GetBuffer());
        if (pSiseItem) {
            LISTPAIR_BOOKMARK* pItemList = &g_conf.m_bookmarkmap;
            LISTPAIR_BOOKMARK::iterator holdit = g_conf.FindBookmark(szkeycode.c_str());
            if (holdit == g_conf.m_bookmarkmap.end()) {
                if (addpos >= g_conf.m_bookmarkmap.size())
                    addpos = max(0,g_conf.m_bookmarkmap.size() - 1);
                STBookMark hi(strcode.GetBuffer(), pSiseItem->psm->hname, (byte)ENUM_ADDBOOK::BOOKMARK);
                pItemList->insert(std::next(pItemList->begin(), addpos), LISTPAIR_BOOKMARK::value_type(szkeycode, hi));
                pSiseItem->addfavor |= (byte)ENUM_ADDBOOK::BOOKMARK;
                RefreshList();
            }
        }
        else {
            HMStockInfo* psm = g_datacenter.GetStockMaster(szkeycode.c_str());// 종목마스터에서 조회
            if (psm) {
                m_bAddMode = TRUE;
#ifdef USE_EBEST_API
                t1102InBlock stIn;
                memset(&stIn, 0x00, sizeof(stIn));
                strncpy(stIn.shcode, szkeycode.c_str(), sizeof(stIn.shcode));
                int slen = sizeof(stIn);
                //char *testcode = pStockItem->code.GetBuffer(pStockItem->code.GetLength());
                // 메세지 받을 윈도우,TR 명,IN Param,다음조회 여부 : 다음 조회일 경우 세팅,다음조회 Key,Timeout(초)
                int nReqID = BizCommIF::SendRequest(GetSafeHwnd(), NAME_t1102, &stIn, slen, 0, "", 10);
#else
                T1001InBlock stIn;
                memset(&stIn, 0x00, sizeof(stIn));
                strncpy(stIn.shcode, szkeycode.c_str(), sizeof(stIn.shcode));
                int slen = sizeof(stIn);
                //char *testcode = pStockItem->code.GetBuffer(pStockItem->code.GetLength());
                // 메세지 받을 윈도우,TR 명,IN Param,다음조회 여부 : 다음 조회일 경우 세팅,다음조회 Key,Timeout(초)
                int nReqID = BizCommIF::SendRequest(GetSafeHwnd(), NAME_T1001, &stIn, slen, 0, "", 10);

#endif
                if (nReqID == -1) {//error

                }
            }
            else
                RefreshList();
        }
    }
}

void DlgBookmark::OnMenuPopup(UINT nCmdID)
{
    HMSiseInfo* pSiseItem;
    CWnd* pFocus = GetFocus();
    GDCtrl* pGrid = m_pGridFocus;
    int irow = -1;
    if (!pGrid)
        return;
    GDCell selcell = pGrid->GetNextItem(GDCell(0, 1), GVNI_BELOW | GVNI_SELECTED);// | GVNI_FOCUSED);
    if (pGrid->IsValid(selcell)) {
        irow = selcell.row;
    }
    else
        return;
    //CString strcode = pGrid->GetItemText(irow, 1);
    //pSiseItem = (HMSiseInfo*)pGrid->GetItemData(irow, 0);
    int ncode = (int)pGrid->GetItemData(irow, 0);
    char szcode[8]; sprintf(szcode, "%06d", ncode);
    string shtcode(szcode);
    pSiseItem = g_datacenter.m_stocklist.GetItem(shtcode);
    if (!pSiseItem)
        return;
    if (nCmdID == IDM_BIDSPECIAL) {
        if (pSiseItem->bidspecial)
            pSiseItem->bidspecial = 0;
        else
            pSiseItem->bidspecial = 1;
    }
    else if (nCmdID == IDM_BIDHALT) {
        OnClickBidhalt();
    }
    else if (nCmdID == IDM_BIDEXCEPT) {
        OnClickExcept();
    }
}

//엔터방지
void DlgBookmark::OnOK()
{

}

void DlgBookmark::OnDestroy()
{
    UnRealList();
    m_itemlist.clear();
    if (g_pSiseThread) {
        g_pSiseThread->SetSiseUIWnd(ENUM_SISEUID::SISEUID_BOOKMARK, NULL);
    }
    DlgResizeBaseEx::OnDestroy();
}



결과아웃풋(output via UI)


 

 

설명안해

 

'C | C++ | VC++' 카테고리의 다른 글

.rc 에서 사용되고 있습니다.  (0) 2025.02.16
마소는 visual studio 버그안고치냐  (5) 2024.12.19
외산SW의 잠식  (0) 2024.04.10
시스템트레이딩  (2) 2024.03.06
[OLEDB] DataTable에서 ROWSTATE 삭제 row 찾는법  (0) 2021.11.14