// DlgInput.cpp : implementation file // #include "stdafx.h" #include "hgjson.h" #include "DlgOptJson.h" #include "afxdialogex.h" #include "DlgRange.h" #include ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // known name ... namespace known_name { struct { std::wstring name; std::wstring title; } g_group[] = { {L"base", L"\u57FA\u672C\u8BBE\u7F6E"}, {L"imgp", L"\u56FE\u50CF\u5904\u7406"}, {L"feeder", L"\u9001\u7EB8\u65B9\u5F0F"}, {L"advance", L"\u9AD8\u7EA7\u8BBE\u7F6E"}}, g_cats[] = { {L"imgp", L"\u56FE\u50CF\u5904\u7406"}}; static std::wstring group_name(const wchar_t* grp_title) { for (auto& v : g_group) { if (v.title == grp_title) return v.name; } return grp_title; } static std::wstring group_title(const wchar_t* grp_name) { if (wcscmp(grp_name, L"imgproc") == 0) grp_name = L"imgp"; for (auto& v : g_group) { if (v.name == grp_name) return v.title; } return grp_name; } static std::wstring category_name(const wchar_t* cat_title) { for (auto& v : g_cats) { if (v.title == cat_title) return v.name; } return cat_title; } static std::wstring category_title(const wchar_t* cat_name) { if (wcscmp(cat_name, L"imgproc") == 0) cat_name = L"imgp"; for (auto& v : g_cats) { if (v.name == cat_name) return v.title; } return cat_name; } }; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // CDlgOptJson dialog IMPLEMENT_DYNAMIC(CDlgOptJson, CDialogEx) CDlgOptJson::CDlgOptJson(CWnd* pParent /*=NULL*/) : CDialogEx(CDlgOptJson::IDD, pParent) { } CDlgOptJson::~CDlgOptJson() { } known_file_util::IJsonW* CDlgOptJson::SANEOPT::to_json(void) { known_file_util::IJsonW* jsn = known_file_util::create_jsonW(), *dep = NULL; int nv = 0; jsn->set_key(name.c_str()); jsn->set_value(L"cat", known_name::category_name(category.c_str()).c_str()); jsn->set_value(L"group", known_name::group_name(group.c_str()).c_str()); jsn->set_value(L"title", title.c_str()); jsn->set_value(L"desc", desc.c_str()); jsn->set_value(L"ver", ver); jsn->set_value(L"pos", pos); jsn->set_value(L"fix-id", fix_id); jsn->set_value(L"type", type.c_str()); jsn->set_value(L"unit", unit.c_str()); SANEOPT::affect_str(nv, affect, false); jsn->set_value(L"affect", nv); jsn->set_value(L"readonly", readonly); jsn->set_value(L"visible", open); jsn->set_value(L"enabled", enable); jsn->set_value(L"size", (int)sizeof(int)); if (!auto_restore_default) jsn->set_value(L"auto", auto_restore_default); if (type == L"bool") { jsn->set_value(L"cur", *(bool*)def_val.c_str()); jsn->set_value(L"default", *(bool*)def_val.c_str()); } else if (type == L"int") { known_file_util::IJsonW* rng = NULL; jsn->set_value(L"cur", *(int*)def_val.c_str()); jsn->set_value(L"default", *(int*)def_val.c_str()); if (range_type == L"list") { rng = known_file_util::create_jsonW(); rng->set_as_array(true); for (auto& v : range) *rng += *(int*)v.c_str(); } else if (range_type == L"range" && range.size() == 3) { rng = known_file_util::create_jsonW(); rng->set_value(L"min", *(int*)range[0].c_str()); rng->set_value(L"max", *(int*)range[1].c_str()); rng->set_value(L"step", *(int*)range[2].c_str()); } if (rng) { jsn->set_value(L"range", rng); rng->release(); } } else if (type == L"float") { known_file_util::IJsonW* rng = NULL; jsn->set_value(L"size", (int)sizeof(double)); jsn->set_value(L"cur", *(double*)def_val.c_str()); jsn->set_value(L"default", *(double*)def_val.c_str()); if (range_type == L"list") { rng = known_file_util::create_jsonW(); rng->set_as_array(true); for (auto& v : range) *rng += *(double*)v.c_str(); } else if (range_type == L"range" && range.size() == 3) { rng = known_file_util::create_jsonW(); rng->set_value(L"min", *(double*)range[0].c_str()); rng->set_value(L"max", *(double*)range[1].c_str()); rng->set_value(L"step", *(double*)range[2].c_str()); } if (rng) { jsn->set_value(L"range", rng); rng->release(); } } else if (type == L"string") { int len = def_val.length(); jsn->set_value(L"cur", (const wchar_t*)def_val.c_str()); jsn->set_value(L"default", (const wchar_t*)def_val.c_str()); if (range.size()) { known_file_util::IJsonW* rng = known_file_util::create_jsonW(); rng->set_as_array(true); for (auto& v : range) { *rng += (const wchar_t*)v.c_str(); if (len < v.length()) len = v.length(); } jsn->set_value(L"range", rng); rng->release(); } len += 4; len *= 3; jsn->set_value(L"size", len); } if (depends.size()) { std::wstring oper(L""), n(L""); std::sort(depends.begin(), depends.end()); if (depend_oper == L"and") oper = L"depend_and"; else if (depend_oper == L"or") oper = L"depend_or"; if (!oper.empty()) { dep = known_file_util::create_jsonW(); dep->set_as_array(true); for (auto& v : depends) { std::wstring exp(v), name(coding::name_from_depend_exp(exp)); if (name.empty()) continue; if (n != name) { n = name; } else exp.erase(0, name.length()); *dep += exp.c_str(); } jsn->set_value(oper.c_str(), dep); dep->release(); } } return jsn; } bool CDlgOptJson::SANEOPT::from_json(known_file_util::IJsonW* jsn) { bool ret = true; const wchar_t* strv = NULL; known_file_util::IJsonW* child = NULL; SANEOPT::init(this); name = jsn->key() ? jsn->key() : L""; if (jsn->get_value(L"title", &strv) && strv) title = strv; if (jsn->get_value(L"desc", &strv) && strv) desc = strv; if (jsn->get_value(L"group", &strv) && strv) group = known_name::group_title(strv); if (jsn->get_value(L"cat", &strv) && strv) category = known_name::category_title(strv); else if(jsn->get_value(L"field", &strv) && strv) category = known_name::category_title(strv); if (jsn->get_value(L"unit", &strv) && strv) unit = strv; std::transform(unit.begin(), unit.end(), unit.begin(), tolower); if (jsn->get_value(L"type", &strv) && strv) type = strv; std::transform(type.begin(), type.end(), type.begin(), tolower); if (type == L"bool") { bool v = false; if (!jsn->get_value(L"default", v)) jsn->get_value(L"cur", v); def_val = std::string((char*)&v, sizeof(v)); } else if(type == L"int") { int v = 0; if (!jsn->get_value(L"default", v)) { if (!jsn->get_value(L"cur", v)) { // try uint64 ... unsigned long long n64 = 0; if(jsn->get_value(L"default", n64) || jsn->get_value(L"cur", n64)) def_val = std::string((char*) & n64, sizeof(n64)); } } if(def_val.empty()) def_val = std::string((char*)&v, sizeof(v)); } else if(type == L"float") { double v = false; if (!jsn->get_value(L"default", v)) jsn->get_value(L"cur", v); def_val = std::string((char*)&v, sizeof(v)); } else if(type == L"string") { strv = NULL; if (!jsn->get_value(L"default", &strv)) jsn->get_value(L"cur", &strv); def_val = strv ? std::string((const char*)strv, lstrlenW(strv) * 2 + 2) : ""; } jsn->get_value(L"affect", ver); SANEOPT::affect_str(ver, affect, true); jsn->get_value(L"ver", ver); jsn->get_value(L"pos", pos); jsn->get_value(L"readonly", readonly); jsn->get_value(L"visible", open); jsn->get_value(L"enabled", enable); jsn->get_value(L"fix-id", fix_id); if (!jsn->get_value(L"auto", auto_restore_default)) auto_restore_default = true; if (jsn->get_value(L"range", &child) && child) { if (type == L"int") { int nv = 0; if (child->get_value(L"min", nv)) { range_type = L"range"; range.push_back(std::string((char*)&nv, sizeof(nv))); child->get_value(L"max", nv); range.push_back(std::string((char*)&nv, sizeof(nv))); child->get_value(L"step", nv); range.push_back(std::string((char*)&nv, sizeof(nv))); } else { range_type = L"list"; known_file_util::JSONMEMW m = child->first_member(); while (m.type != known_file_util::JV_UNKNOWN) { range.push_back(std::string((char*)&m.int_val, sizeof(m.int_val))); m = child->next_member(); } } } else if (type == L"float") { double nv = 0; if (child->get_value(L"min", nv)) { range_type = L"range"; range.push_back(std::string((char*)&nv, sizeof(nv))); child->get_value(L"max", nv); range.push_back(std::string((char*)&nv, sizeof(nv))); child->get_value(L"step", nv); range.push_back(std::string((char*)&nv, sizeof(nv))); } else { range_type = L"list"; known_file_util::JSONMEMW m = child->first_member(); while (m.type != known_file_util::JV_UNKNOWN) { range.push_back(std::string((char*)&m.double_val, sizeof(m.double_val))); m = child->next_member(); } } } else if (type == L"string") { range_type = L"list"; known_file_util::JSONMEMW m = child->first_member(); while (m.type != known_file_util::JV_UNKNOWN) { range.push_back(std::string((const char*)m.str_val, lstrlenW(m.str_val) * 2 + 2)); m = child->next_member(); } } child->release(); } if (jsn->get_value(L"depend_and", &child) && child) depend_oper = L"and"; else if (jsn->get_value(L"depend_or", &child) && child) depend_oper = L"or"; if (child) { known_file_util::JSONMEMW m = child->first_member(); std::wstring n(L""); while (m.type != known_file_util::JV_UNKNOWN) { std::wstring exp(m.str_val), nm(coding::name_from_depend_exp(exp)); if (nm.empty()) exp.insert(0, n); else n = nm; depends.push_back(exp); m = child->next_member(); } child->release(); } return ret; } std::wstring CDlgOptJson::get_item_text(UINT id) { int l = GetDlgItem(id)->GetWindowTextLengthW(); wchar_t* buf = new wchar_t[l + 4]; l = GetDlgItem(id)->GetWindowTextW(buf, l + 2); buf[l] = 0; std::wstring ret(buf); delete[] buf; return std::move(ret); } bool CDlgOptJson::is_button_check(UINT id) { return ((CButton*)GetDlgItem(id))->GetCheck() == BST_CHECKED; } void CDlgOptJson::set_button_check(UINT id, bool check) { ((CButton*)GetDlgItem(id))->SetCheck(check ? BST_CHECKED : BST_UNCHECKED); } void CDlgOptJson::from_ui(SANEOPT& sop) { std::wstring val(L""); sop.name = get_item_text(IDC_EDIT_NAME); sop.title = get_item_text(IDC_EDIT_TITLE); sop.desc = get_item_text(IDC_EDIT_DESCRIPTION); sop.group = get_item_text(IDC_COMBO_GROUP); if (group_.FindStringExact(-1, sop.group.c_str()) == -1) group_.AddString(sop.group.c_str()); sop.category = get_item_text(IDC_COMBO_CATEGORY); if (cat_.FindStringExact(-1, sop.category.c_str()) == -1) cat_.AddString(sop.group.c_str()); sop.affect = get_item_text(IDC_COMBO_AFFECT); sop.unit = get_item_text(IDC_COMBO_UNIT); sop.ver = GetDlgItemInt(IDC_EDIT_VER); sop.type = get_item_text(IDC_COMBO_DATA_TYPE); sop.pos = GetDlgItemInt(IDC_EDIT_POSITION); //sop.fix_id = GetDlgItemInt(IDC_EDIT_FIXED_ID); sop.fix_id = fix_id_edit_.value(); sop.readonly = is_button_check(IDC_CHECK_READONLY); sop.open = is_button_check(IDC_CHECK_PUBLIC); sop.range_type = get_item_text(IDC_COMBO_RANGE); if (GetDlgItem(IDC_EDIT_DEFAULT)->IsWindowVisible()) val = get_item_text(IDC_EDIT_DEFAULT); else val = get_item_text(IDC_COMBO_DEFAULT); if (sop.type == L"bool") { bool v = val == L"true"; sop.def_val = std::string((char*)&v, sizeof(v)); } else if (sop.type == L"int") { int v = _wtoi(val.c_str()); sop.def_val = std::string((char*)&v, sizeof(v)); } else if (sop.type == L"float") { double v = _wtof(val.c_str()); sop.def_val = std::string((char*)&v, sizeof(v)); } else if (sop.type == L"string") { sop.def_val = std::string((const char*)val.c_str(), val.length() * 2 + 2); } else sop.def_val = ""; sop.enable = is_button_check(IDC_CHECK_ENABLE); sop.range_type = get_item_text(IDC_COMBO_RANGE); sop.depend_oper = get_item_text(IDC_COMBO_DEPEND); sop.auto_restore_default = is_button_check(IDC_CHECK_AUTO_RESTORE); sop.depends.clear(); if (sop.depend_oper != L"none") { wchar_t buf[256] = { 0 }; for (int i = 0; i < depends_.GetCount(); ++i) { depends_.GetText(i, buf); std::wstring exp(buf), n(coding::name_from_depend_exp(exp)); if (n.empty()) continue; // title to name ... exp.erase(0, n.length()); for (auto& v : opts_) { if (v.title == n) { exp.insert(0, v.name); break; } } sop.depends.push_back(exp); } } } void CDlgOptJson::to_ui(const SANEOPT& sop) { int n = 0; ::SetDlgItemTextW(m_hWnd, IDC_EDIT_NAME, sop.name.c_str()); ::SetDlgItemTextW(m_hWnd, IDC_EDIT_TITLE, sop.title.c_str()); ::SetDlgItemTextW(m_hWnd, IDC_EDIT_DESCRIPTION, sop.desc.c_str()); n = group_.FindStringExact(-1, sop.group.c_str()); if (n == -1) n = group_.AddString(sop.group.c_str()); group_.SetCurSel(n); n = cat_.FindStringExact(-1, sop.category.c_str()); if (n == -1) n = cat_.AddString(sop.category.c_str()); cat_.SetCurSel(n); n = affect_.FindStringExact(-1, sop.affect.c_str()); affect_.SetCurSel(n); n = unit_.FindStringExact(-1, sop.unit.c_str()); unit_.SetCurSel(n); SetDlgItemInt(IDC_EDIT_VER, sop.ver); n = type_.FindStringExact(-1, sop.type.c_str()); type_.SetCurSel(n); SetDlgItemInt(IDC_EDIT_POSITION, sop.pos); //SetDlgItemInt(IDC_EDIT_FIXED_ID, sop.fix_id); fix_id_edit_.set_value(sop.fix_id); set_button_check(IDC_CHECK_READONLY, sop.readonly); set_button_check(IDC_CHECK_PUBLIC, sop.open); set_button_check(IDC_CHECK_ENABLE, sop.enable); set_button_check(IDC_CHECK_AUTO_RESTORE, sop.auto_restore_default); n = range_.FindStringExact(-1, sop.range_type.c_str()); range_.SetCurSel(n); n = depend_.FindStringExact(-1, sop.depend_oper.c_str()); depend_.SetCurSel(n); depends_.ResetContent(); for (auto& v : sop.depends) { std::wstring n(coding::name_from_depend_exp(v)), str(v); if (n.empty()) continue; // name to title ... str.erase(0, n.length()); for (auto& e : opts_) { if (e.name == n) { str.insert(0, e.title); break; } } depends_.AddString(str.c_str()); } // default value ... // depend item ... n = sop.depend_oper != L"none"; parent_.EnableWindow(n); logic_.EnableWindow(n); depends_.EnableWindow(n); GetDlgItem(IDC_BUTTON_ADD)->EnableWindow(n); GetDlgItem(IDC_EDIT_LOW)->EnableWindow(n); GetDlgItem(IDC_EDIT_LOW)->ShowWindow(SW_SHOW); GetDlgItem(IDC_COMBO_LOW)->ShowWindow(SW_HIDE); GetDlgItem(IDC_STATIC_AND)->ShowWindow(SW_HIDE); GetDlgItem(IDC_EDIT_BIG)->ShowWindow(SW_HIDE); GetDlgItem(IDC_COMBO_BIG)->ShowWindow(SW_HIDE); GetDlgItem(IDC_BUTTON_SET)->EnableWindow(sop.range_type != L"none"); parent_.ResetContent(); for (auto& v : opts_) { if (v.name == sop.name) continue; parent_.AddString(v.title.c_str()); } OnCbnDataTypeSelchange(); OnCbnRangeSelchange(); OnCbnDependSelchange(); // default value ... if (sop.type == L"bool") { GetDlgItem(IDC_EDIT_DEFAULT)->ShowWindow(SW_HIDE); def_val_.ShowWindow(SW_SHOW); def_val_.ResetContent(); def_val_.AddString(L"false"); def_val_.AddString(L"true"); def_val_.SetCurSel(def_val_.FindStringExact(-1, *(bool*)sop.def_val.c_str() ? L"true" : L"false")); } else if (sop.type == L"int") { if (sop.range_type == L"list") { GetDlgItem(IDC_EDIT_DEFAULT)->ShowWindow(SW_HIDE); def_val_.ShowWindow(SW_SHOW); def_val_.ResetContent(); for (auto& v : sop.range) { def_val_.AddString(std::to_wstring(*(int*)v.c_str()).c_str()); } def_val_.SetCurSel(def_val_.FindStringExact(-1, std::to_wstring(*(int*)sop.def_val.c_str()).c_str())); } else { GetDlgItem(IDC_EDIT_DEFAULT)->ShowWindow(SW_SHOW); SetDlgItemInt(IDC_EDIT_DEFAULT, *(int*)sop.def_val.c_str()); def_val_.ShowWindow(SW_HIDE); } } else if (sop.type == L"float") { if (sop.range_type == L"list") { GetDlgItem(IDC_EDIT_DEFAULT)->ShowWindow(SW_HIDE); def_val_.ShowWindow(SW_SHOW); def_val_.ResetContent(); for (auto& v : sop.range) { def_val_.AddString(std::to_wstring(*(double*)v.c_str()).c_str()); } def_val_.SetCurSel(def_val_.FindStringExact(-1, std::to_wstring(*(double*)sop.def_val.c_str()).c_str())); } else { GetDlgItem(IDC_EDIT_DEFAULT)->ShowWindow(SW_SHOW); SetDlgItemInt(IDC_EDIT_DEFAULT, *(double*)sop.def_val.c_str()); def_val_.ShowWindow(SW_HIDE); } } else if (sop.type == L"string") { if (sop.range_type == L"list") { GetDlgItem(IDC_EDIT_DEFAULT)->ShowWindow(SW_HIDE); def_val_.ShowWindow(SW_SHOW); def_val_.ResetContent(); for (auto& v : sop.range) { def_val_.AddString((const wchar_t*)v.c_str()); } def_val_.SetCurSel(def_val_.FindStringExact(-1, (const wchar_t*)sop.def_val.c_str())); } else { GetDlgItem(IDC_EDIT_DEFAULT)->ShowWindow(SW_SHOW); SetDlgItemText(IDC_EDIT_DEFAULT, (const wchar_t*)sop.def_val.c_str()); def_val_.ShowWindow(SW_HIDE); } } } HTREEITEM CDlgOptJson::insert_new_item(const SANEOPT& opt, bool sel) { HTREEITEM item = tree_.InsertItem(opt.title.c_str()); wchar_t* name = new wchar_t[opt.name.length() + 2]; wcscpy(name, opt.name.c_str()); if (!tree_.SetItemData(item, (DWORD_PTR)name)) delete[] name; opts_.push_back(opt); if (sel) { tree_.SelectItem(item); tree_.EnsureVisible(item); } return item; } void CDlgOptJson::delete_from_tree(const wchar_t* name) { if (name) { HTREEITEM item = tree_.GetRootItem(); while (item) { wchar_t* buf = (wchar_t*)tree_.GetItemData(item); if (buf && wcscmp(buf, name) == 0) { delete[] buf; tree_.DeleteItem(item); break; } item = tree_.GetNextSiblingItem(item); } } else { HTREEITEM item = tree_.GetRootItem(); while (item) { wchar_t* buf = (wchar_t*)tree_.GetItemData(item); if (buf) delete[] buf; item = tree_.GetNextSiblingItem(item); } tree_.DeleteAllItems(); } } HTREEITEM CDlgOptJson::modify_tree_title(const wchar_t* name, const wchar_t* title) { HTREEITEM item = tree_.GetRootItem(), found = NULL; while (item) { wchar_t* buf = (wchar_t*)tree_.GetItemData(item); if (buf && wcscmp(buf, name) == 0) { tree_.SetItemText(item, title); found = item; break; } item = tree_.GetNextSiblingItem(item); } return found; } bool CDlgOptJson::load_from_file(const wchar_t* path_file) { std::string cont(""); std::wstring unic(L""); bool ret = false; file_util::load_file(path_file, coding::get_string, &cont); coding_util::bom::to_unicode(cont.c_str(), cont.length(), coding::get_wstring, &unic); if (unic.length()) { if (!load_from_json_text(unic.c_str())) { unic = path_file; unic.insert(0, L"Parse json file '"); unic += L"' failed"; ::MessageBoxW(m_hWnd, unic.c_str(), L"Error", MB_OK); } else ret = true; } return ret; } bool CDlgOptJson::load_from_json_text(const wchar_t* txt, std::wstring* err_msg) { int pos = 0; known_file_util::IJsonW* jsn = known_file_util::create_jsonW(txt, &pos), * child = NULL; while (!jsn) { // try code-text ... { std::wstring code(txt); size_t splash = code.find(L"\\\\"); while (splash != std::wstring::npos) { code.erase(splash++, 1); splash = code.find(L"\\\\", splash); } splash = code.find(L"\\\""); while (splash != std::wstring::npos) { code.erase(splash++, 1); splash = code.find(L"\\\"", splash); } splash = 0; jsn = known_file_util::create_jsonW(&code[0], (int*)&splash); if (jsn) break; } int ep = 10, len = 10; if (lstrlenW(txt + pos) < 10) len = lstrlenW(txt + pos); if (pos < 10) { ep = pos; pos = 10; } pos -= 10; std::wstring info(txt + pos, len + ep + 1); wchar_t msg[80] = { 0 }; swprintf_s(msg, L"Error at position %d of char '%c'!\r\n\r\n", ep, info[ep]); if (err_msg) *err_msg = msg + info; else ::MessageBoxW(m_hWnd, (msg + info).c_str(), L"Load Error", MB_OK); return false; } delete_from_tree(); opts_.clear(); child = jsn->first_child(); while (child) { SANEOPT opt; if (opt.from_json(child)) { insert_new_item(opt, false); } child->release(); child = jsn->next_child(); } jsn->release(); return true; } void CDlgOptJson::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Control(pDX, IDC_COMBO_GROUP, group_); DDX_Control(pDX, IDC_COMBO_CATEGORY, cat_); DDX_Control(pDX, IDC_COMBO_AFFECT, affect_); DDX_Control(pDX, IDC_COMBO_UNIT, unit_); DDX_Control(pDX, IDC_COMBO_DATA_TYPE, type_); DDX_Control(pDX, IDC_COMBO_RANGE, range_); DDX_Control(pDX, IDC_COMBO_DEFAULT, def_val_); DDX_Control(pDX, IDC_COMBO_DEPEND, depend_); DDX_Control(pDX, IDC_COMBO_PARENT, parent_); DDX_Control(pDX, IDC_COMBO_LOGIC, logic_); DDX_Control(pDX, IDC_COMBO_LOW, lower_); DDX_Control(pDX, IDC_COMBO_BIG, upper_); DDX_Control(pDX, IDC_COMBO_EXPORT, export_type_); DDX_Control(pDX, IDC_LIST_DEPEND, depends_); DDX_Control(pDX, IDC_TREE2, tree_); } BOOL CDlgOptJson::OnInitDialog() { CDialogEx::OnInitDialog(); // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog group_.SetCurSel(0); cat_.SetCurSel(0); affect_.SetCurSel(0); unit_.SetCurSel(0); type_.SetCurSel(0); range_.SetCurSel(0); def_val_.SetCurSel(0); depend_.SetCurSel(0); set_button_check(IDC_CHECK_AUTO_RESTORE, true); parent_.EnableWindow(FALSE); logic_.EnableWindow(FALSE); GetDlgItem(IDC_EDIT_LOW)->EnableWindow(FALSE); depends_.EnableWindow(FALSE); GetDlgItem(IDC_BUTTON_ADD)->EnableWindow(FALSE); BITMAP bmi = { 0 }; GetObject(LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP1)), sizeof(bmi), &bmi); tree_img_.Create(IDB_BITMAP1, bmi.bmWidth / 2, bmi.bmWidth / 2, RGB(255, 255, 255)); tree_.SetImageList(&tree_img_, TVSIL_NORMAL); tree_menu_.LoadMenu(IDR_MENU1); fix_id_edit_.attach(GetDlgItem(IDC_EDIT_FIXED_ID)->m_hWnd); export_type_.SetCurSel(1); return TRUE; // return TRUE unless you set the focus to a control } BEGIN_MESSAGE_MAP(CDlgOptJson, CDialogEx) ON_WM_PASTE() ON_CBN_SELCHANGE(IDC_COMBO_DATA_TYPE, &CDlgOptJson::OnCbnDataTypeSelchange) ON_CBN_SELCHANGE(IDC_COMBO_RANGE, &CDlgOptJson::OnCbnRangeSelchange) ON_CBN_SELCHANGE(IDC_COMBO_DEPEND, &CDlgOptJson::OnCbnDependSelchange) ON_CBN_SELCHANGE(IDC_COMBO_PARENT, &CDlgOptJson::OnCbnParentSelchange) ON_CBN_SELCHANGE(IDC_COMBO_LOGIC, &CDlgOptJson::OnCbnLogicSelchange) ON_BN_CLICKED(IDC_BUTTON_MODIFY, &CDlgOptJson::OnBnClickedButtonModify) ON_BN_CLICKED(IDC_BUTTON_ADD, &CDlgOptJson::OnBnClickedButtonAdd) ON_NOTIFY(TVN_SELCHANGED, IDC_TREE2, &CDlgOptJson::OnTvnSelchangedTree2) ON_NOTIFY(NM_RCLICK, IDC_TREE2, &CDlgOptJson::OnNMRClickTree2) ON_NOTIFY(TVN_SELCHANGING, IDC_TREE2, &CDlgOptJson::OnTvnSelchangingTree2) ON_COMMAND(ID_TREE_LOADFILE, &CDlgOptJson::OnTreeLoadfile) ON_COMMAND(ID_TREE_LOADCLIPBOARD, &CDlgOptJson::OnTreeLoadclipboard) ON_LBN_DBLCLK(IDC_LIST_DEPEND, &CDlgOptJson::OnLbnDblclkListDepend) ON_BN_CLICKED(IDC_BUTTON_SET, &CDlgOptJson::OnBnClickedButtonSet) ON_COMMAND(ID_TREE_DELITEM, &CDlgOptJson::OnTreeDelitem) ON_BN_CLICKED(IDC_BUTTON_EXPORT, &CDlgOptJson::OnBnClickedButtonExport) ON_COMMAND(ID_TREE_MODIFYALLFIELD, &CDlgOptJson::OnTreeModifyallfield) ON_COMMAND(ID_SORT_NAME, &CDlgOptJson::OnSortName) ON_COMMAND(ID_SORT_TITLE, &CDlgOptJson::OnSortTitle) ON_COMMAND(ID_SORT_GROUP, &CDlgOptJson::OnSortGroup) ON_COMMAND(ID_SORT_POSITION, &CDlgOptJson::OnSortPosition) END_MESSAGE_MAP() // CDlgOptJson message handlers void CDlgOptJson::OnCbnSelchange() { } void CDlgOptJson::OnCbnDataTypeSelchange() { std::wstring val(get_item_text(IDC_COMBO_DATA_TYPE)); range_.EnableWindow(); if (val == L"bool") { range_.SetCurSel(range_.FindStringExact(-1, L"none")); OnCbnRangeSelchange(); range_.EnableWindow(FALSE); } } void CDlgOptJson::OnCbnRangeSelchange() { std::wstring val(get_item_text(IDC_COMBO_RANGE)), type(get_item_text(IDC_COMBO_DATA_TYPE)); GetDlgItem(IDC_BUTTON_SET)->EnableWindow(val != L"none"); if (val == L"list" || type == L"bool") { GetDlgItem(IDC_EDIT_DEFAULT)->ShowWindow(SW_HIDE); GetDlgItem(IDC_COMBO_DEFAULT)->ShowWindow(SW_SHOW); def_val_.ResetContent(); if (type == L"bool") { def_val_.AddString(L"false"); def_val_.AddString(L"true"); def_val_.SetCurSel(0); } } else { GetDlgItem(IDC_EDIT_DEFAULT)->ShowWindow(SW_SHOW); GetDlgItem(IDC_COMBO_DEFAULT)->ShowWindow(SW_HIDE); } } void CDlgOptJson::OnCbnDependSelchange() { std::wstring val(get_item_text(IDC_COMBO_DEPEND)); parent_.EnableWindow(val != L"none"); logic_.EnableWindow(val != L"none"); depends_.EnableWindow(val != L"none"); lower_.EnableWindow(val != L"none"); upper_.EnableWindow(val != L"none"); GetDlgItem(IDC_BUTTON_ADD)->EnableWindow(val != L"none"); GetDlgItem(IDC_EDIT_LOW)->EnableWindow(val != L"none"); GetDlgItem(IDC_EDIT_BIG)->EnableWindow(val != L"none"); if (val != L"none") { val = get_item_text(IDC_EDIT_NAME); parent_.ResetContent(); for (auto& v : opts_) { if (val == v.name) continue; parent_.AddString(v.title.c_str()); } } } void CDlgOptJson::OnCbnParentSelchange() { std::wstring val(get_item_text(IDC_COMBO_PARENT)); SANEOPT opt; for (auto& v : opts_) { if (val == v.title) { opt = v; break; } } if (opt.type == L"bool") { logic_.ResetContent(); logic_.AddString(L"=="); logic_.SetCurSel(0); OnCbnLogicSelchange(); GetDlgItem(IDC_EDIT_LOW)->ShowWindow(SW_HIDE); lower_.ShowWindow(SW_SHOW); lower_.ResetContent(); lower_.AddString(L"false"); lower_.AddString(L"true"); lower_.SetCurSel(0); } else if (opt.type == L"int" || opt.type == L"float") { logic_.ResetContent(); logic_.AddString(L"=="); logic_.AddString(L"!="); logic_.AddString(L"<"); logic_.AddString(L"<="); logic_.AddString(L">"); logic_.AddString(L">="); logic_.AddString(L"between"); logic_.AddString(L"out of"); logic_.SetCurSel(0); OnCbnLogicSelchange(); if (opt.range_type == L"list") { GetDlgItem(IDC_EDIT_LOW)->ShowWindow(SW_HIDE); lower_.ShowWindow(SW_SHOW); lower_.ResetContent(); upper_.ResetContent(); if (opt.type == L"int") { for (auto& v : opt.range) { std::wstring val(std::to_wstring(*(int*)v.c_str())); lower_.AddString(val.c_str()); upper_.AddString(val.c_str()); } } else { for (auto& v : opt.range) { std::wstring val(std::to_wstring(*(double*)v.c_str())); lower_.AddString(val.c_str()); upper_.AddString(val.c_str()); } } } else { GetDlgItem(IDC_EDIT_LOW)->ShowWindow(SW_SHOW); lower_.ShowWindow(SW_HIDE); } } else if (opt.type == L"string") { logic_.ResetContent(); logic_.AddString(L"=="); logic_.AddString(L"!="); logic_.SetCurSel(0); OnCbnLogicSelchange(); if (opt.range_type == L"list") { GetDlgItem(IDC_EDIT_LOW)->ShowWindow(SW_HIDE); lower_.ShowWindow(SW_SHOW); lower_.ResetContent(); for (auto& v : opt.range) { std::wstring val((const wchar_t*)v.c_str()); lower_.AddString(val.c_str()); } } else { GetDlgItem(IDC_EDIT_LOW)->ShowWindow(SW_SHOW); lower_.ShowWindow(SW_HIDE); } } } void CDlgOptJson::OnCbnLogicSelchange() { std::wstring val(get_item_text(IDC_COMBO_LOGIC)); if (val == L"between" || val == L"out of") { GetDlgItem(IDC_STATIC_AND)->ShowWindow(SW_SHOW); // upper_.ShowWindow(SW_SHOW); val = get_item_text(IDC_COMBO_PARENT); for (auto& v : opts_) { if (val == v.title) { val = v.range_type; break; } } if (val == L"list") { upper_.ShowWindow(SW_SHOW); GetDlgItem(IDC_EDIT_BIG)->ShowWindow(SW_HIDE); } else { upper_.ShowWindow(SW_HIDE); GetDlgItem(IDC_EDIT_BIG)->ShowWindow(SW_SHOW); } } else { GetDlgItem(IDC_STATIC_AND)->ShowWindow(SW_HIDE); GetDlgItem(IDC_EDIT_BIG)->ShowWindow(SW_HIDE); upper_.ShowWindow(SW_HIDE); } } void CDlgOptJson::OnPaste() { coding::CLPD clpb; file_util::get_clipboard(coding::get_clipboard_content, &clpb); if (clpb.cont.empty()) { MessageBox(TEXT("clipboard is empty.")); return; } if (clpb.file) { size_t pos = clpb.cont.find(L"\r\n"); bool loaded = false; while (!loaded && pos != std::wstring::npos) { loaded = load_from_file(clpb.cont.substr(0, pos).c_str()); clpb.cont.erase(0, pos + 2); pos = clpb.cont.find(L"\r\n"); } if (!loaded && file_util::is_file_existing(clpb.cont.c_str())) load_from_file(clpb.cont.c_str()); } else { std::wstring err(L""); if (load_from_json_text(clpb.cont.c_str(), &err)) return; // we assum the content from codes ... std::wstring jsn(L""); size_t pos = clpb.cont.find(L" std::string"); while (pos != std::wstring::npos) { clpb.cont.erase(0, pos); pos = clpb.cont.find(L"\""); if (pos == std::wstring::npos) break; clpb.cont.erase(0, pos + 1); pos = clpb.cont.find(L"\");"); if (pos == std::wstring::npos) { jsn += clpb.cont; break; } else jsn += clpb.cont.substr(0, pos); clpb.cont.erase(0, pos); pos = clpb.cont.find(L" std::string"); } if (jsn.length()) { pos = jsn.find(L"\\\\"); while (pos != std::wstring::npos) { jsn.erase(pos++, 1); pos = jsn.find(L"\\\\", pos); } pos = jsn.find(L"\\\""); while (pos != std::wstring::npos) { jsn.erase(pos++, 1); pos = jsn.find(L"\\\"", pos); } load_from_json_text(jsn.c_str()); } else ::MessageBoxW(m_hWnd, err.c_str(), L"Load Error", MB_OK); } } void CDlgOptJson::OnBnClickedButtonModify() { // TODO: 在此添加控件通知处理程序代码 SANEOPT sop; from_ui(sop); if (sop.name.empty() || sop.title.empty()) { MessageBox(TEXT("Name and Title must input!")); return; } for (auto& v : opts_) { if (v.title == sop.title && v.name != sop.name) { if (::MessageBoxW(m_hWnd, (L"\u5DF2\u7ECF\u5B58\u5728\u540D\u4E3A\u201C" + v.title + L"\u201D\u7684\u914D\u7F6E\u9879\uFF01\uFF0C\u60F3\u4FEE\u6539Name\u5B57\u6BB5\u5417\uFF1F").c_str(), L"Error", MB_ICONSTOP | MB_YESNO) == IDYES) { sop.range = std::move(v.range); v = std::move(sop); } return; } } for (auto& v : opts_) { if (v.name == sop.name) { sop.range = std::move(v.range); v = std::move(sop); modify_tree_title(v.name.c_str(), v.title.c_str()); return; } } insert_new_item(sop); } void CDlgOptJson::OnBnClickedButtonAdd() { // TODO: 在此添加控件通知处理程序代码 - add depend items std::wstring opt(get_item_text(IDC_COMBO_PARENT)), logic(get_item_text(IDC_COMBO_LOGIC)), l(L""), u(L""); int ind = 0; if (lower_.IsWindowVisible()) l = get_item_text(IDC_COMBO_LOW); else l = get_item_text(IDC_EDIT_LOW); if (upper_.IsWindowVisible()) u = get_item_text(IDC_COMBO_BIG); else if (GetDlgItem(IDC_EDIT_BIG)->IsWindowVisible()) u = get_item_text(IDC_EDIT_BIG); if (logic == L"between") { opt += L"==[" + l + L"," + u + L"]"; } else if (logic == L"out of") { opt += L"!=[" + l + L"," + u + L"]"; } else { opt += logic + l; } ind = depends_.FindStringExact(-1, opt.c_str()); if (ind == -1) { ind = depends_.AddString(opt.c_str()); } depends_.SetCurSel(ind); } void CDlgOptJson::OnTvnSelchangedTree2(NMHDR* pNMHDR, LRESULT* pResult) { LPNMTREEVIEW pNMTreeView = reinterpret_cast(pNMHDR); // TODO: 在此添加控件通知处理程序代码 HTREEITEM item = tree_.GetSelectedItem(); if (item) { TVITEM tvi; tvi.mask = TVIF_SELECTEDIMAGE; tvi.iSelectedImage = 1; tvi.hItem = item; tree_.SetItem(&tvi); wchar_t* name = (wchar_t*)tree_.GetItemData(item); for (auto& v : opts_) { if (v.name == name) { to_ui(v); break; } } } *pResult = 0; } void CDlgOptJson::OnNMRClickTree2(NMHDR* pNMHDR, LRESULT* pResult) { // TODO: 在此添加控件通知处理程序代码 *pResult = 0; POINT pt = { 0 }; HTREEITEM hsel = tree_.GetSelectedItem(); tree_menu_.EnableMenuItem(ID_TREE_ADDGROUP, MF_DISABLED); tree_menu_.EnableMenuItem(ID_TREE_ADDITEM, MF_DISABLED); tree_menu_.EnableMenuItem(ID_TREE_ADDPRODUCT, MF_DISABLED); tree_menu_.EnableMenuItem(ID_TREE_DELITEM, MF_DISABLED); tree_menu_.EnableMenuItem(ID_TREE_RENAME, MF_DISABLED); tree_menu_.EnableMenuItem(ID_TREE_TOOLTIPS, MF_DISABLED); tree_menu_.EnableMenuItem(ID_TREE_EXPORTCHAR, MF_DISABLED); tree_menu_.EnableMenuItem(ID_TREE_UNIFYSEQUENCE, MF_DISABLED); if (hsel) { tree_menu_.EnableMenuItem(ID_TREE_DELITEM, MF_ENABLED); } GetCursorPos(&pt); tree_menu_.GetSubMenu(0)->TrackPopupMenu(0, pt.x, pt.y, this); } void CDlgOptJson::OnTvnSelchangingTree2(NMHDR* pNMHDR, LRESULT* pResult) { LPNMTREEVIEW pNMTreeView = reinterpret_cast(pNMHDR); // TODO: 在此添加控件通知处理程序代码 HTREEITEM hsel = tree_.GetSelectedItem(); if (hsel) { } *pResult = 0; } void CDlgOptJson::OnTreeLoadfile() { // TODO: 在此添加命令处理程序代码 file_util::PATHFILE path = { 0 }; if (file_util::browser_file(m_hWnd, &path)) { load_from_file(path.path); } } void CDlgOptJson::OnTreeLoadclipboard() { // TODO: 在此添加命令处理程序代码 OnPaste(); } void CDlgOptJson::OnLbnDblclkListDepend() { // TODO: 在此添加控件通知处理程序代码 int sel = depends_.GetCurSel(); if (sel >= 0 && sel < depends_.GetCount()) depends_.DeleteString(sel); } void CDlgOptJson::OnBnClickedButtonSet() { // TODO: 在此添加控件通知处理程序代码 std::wstring val(get_item_text(IDC_COMBO_RANGE)); CDlgRange dlg(val == L"list", this); SANEOPT opt; val = get_item_text(IDC_EDIT_NAME); if (val.empty()) { MessageBox(TEXT("请先输入该配置项的唯一名称:Name字段值。")); GotoDlgCtrl(GetDlgItem(IDC_EDIT_NAME)); return; } opt.name = val; for (auto& v : opts_) { if (v.name == val) { opt = v; break; } } val = get_item_text(IDC_COMBO_DATA_TYPE); if (!opt.name.empty()) { if (val == L"int") { dlg.init_ = std::to_wstring(*(int*)opt.def_val.c_str()); for (auto& v : opt.range) dlg.vals_.push_back(std::to_wstring(*(int*)v.c_str())); } else if (val == L"float") { dlg.init_ = std::to_wstring(*(double*)opt.def_val.c_str()); for (auto& v : opt.range) dlg.vals_.push_back(std::to_wstring(*(double*)v.c_str())); } else { dlg.init_ = (const wchar_t*)opt.def_val.c_str(); for (auto& v : opt.range) dlg.vals_.push_back((const wchar_t*)v.c_str()); } } if (dlg.DoModal() == IDOK) { if (val == L"int") { int n = _wtoi(dlg.init_.c_str()); opt.def_val = std::string((char*)&n, sizeof(n)); opt.range.clear(); for (auto& v : dlg.vals_) { n = _wtoi(v.c_str()); opt.range.push_back(std::string((char*)&n, sizeof(n))); } } else if (val == L"float") { double n = _wtof(dlg.init_.c_str()); opt.def_val = std::string((char*)&n, sizeof(n)); opt.range.clear(); for (auto& v : dlg.vals_) { n = _wtof(v.c_str()); opt.range.push_back(std::string((char*)&n, sizeof(n))); } } else { opt.range.clear(); opt.def_val = std::string((const char*)dlg.init_.c_str(), dlg.init_.length() * 2 + 2); for (auto& v : dlg.vals_) opt.range.push_back(std::string((const char*)v.c_str(), v.length() * 2 + 2)); } // add or insert ... for (auto& v : opts_) { if (v.name == opt.name) { from_ui(v); v.range = opt.range; v.def_val = opt.def_val; to_ui(v); return; } } SANEOPT so; from_ui(so); so.range = opt.range; so.def_val = opt.def_val; insert_new_item(so); to_ui(so); } } void CDlgOptJson::OnTreeDelitem() { // TODO: 在此添加命令处理程序代码 HTREEITEM item = tree_.GetSelectedItem(); if (item) { CString text(tree_.GetItemText(item)); if (MessageBox(TEXT("确定要删除该项配置吗?"), text.GetBuffer(), MB_YESNO) == IDYES) { wchar_t* buf = (wchar_t*)tree_.GetItemData(item); tree_.DeleteItem(item); if (buf) { for (int i = 0; i < opts_.size(); ++i) { if (opts_[i].name == buf) { opts_.erase(opts_.begin() + i); break; } } delete[] buf; } } text.ReleaseBuffer(); } } void CDlgOptJson::OnBnClickedButtonExport() { // TODO: 在此添加控件通知处理程序代码 known_file_util::IJsonW* root = known_file_util::create_jsonW(), * child = NULL; for (auto& v : opts_) { child = v.to_json(); if (child) { root->set_value(v.name.c_str(), child); child->release(); } } std::wstring type(get_item_text(IDC_COMBO_EXPORT)), cont(L""); root->to_string(coding::get_wstring, &cont, type == L"\u683C\u5F0F\u6587\u672C" ? L"\t" : NULL); root->release(); if (cont.empty()) { MessageBox(TEXT("No content has been serialized! change exporting type and try again."), NULL, MB_OK | MB_ICONERROR); return; } if (type == L"\u4EE3\u7801\u6587\u672C") { size_t pos = cont.find(L"\\"); while (pos++ != std::wstring::npos) { cont.insert(pos++, L"\\"); pos = cont.find(L"\\", pos); } pos = cont.find(L"\""); while (pos != std::wstring::npos) { cont.insert(pos, L"\\"); pos = cont.find(L"\"", pos + 2); } } int n = file_util::set_clipboard(cont.c_str(), cont.length() * 2, CF_UNICODETEXT); MessageBox(TEXT("JSON text has set to clipboard already"), std::to_wstring(cont.length()).c_str()); } void CDlgOptJson::OnTreeModifyallfield() { // TODO: 在此添加命令处理程序代码 // Group;Category;Affect;Version;Position;Readonly;Public;Enabled;Depends; CDlgRange dlg(CDlgRange::TYPE_FIELDS, this); auto init_val = [&](const wchar_t* field, CComboBox* box) -> void { std::wstring n(field); wchar_t text[256] = { 0 }; int l = 0; box->ResetContent(); box->EnableWindow(); // 0x50010302 // ::SetWindowLong(box->m_hWnd, GWL_STYLE, (LONG)0x50010302); if (n == L"Group") { for (int i = 0; i < group_.GetCount(); ++i) { l = group_.GetLBText(i, text); text[l] = 0; box->AddString(text); } } else if (n == L"Category") { for (int i = 0; i < cat_.GetCount(); ++i) { l = cat_.GetLBText(i, text); text[l] = 0; box->AddString(text); } } else if (n == L"Depends") { box->AddString(L"none"); box->SetCurSel(0); box->EnableWindow(FALSE); } else if (n == L"Affect") { for (int i = 0; i < affect_.GetCount(); ++i) { l = affect_.GetLBText(i, text); text[l] = 0; box->AddString(text); } } else if (n == L"Version") { box->AddString(L"1"); box->SetCurSel(0); } else if (n == L"Position") { box->AddString(L"-1"); box->SetCurSel(0); } else if (n == L"Readonly") { box->AddString(L"false"); box->AddString(L"true"); //::SetWindowLong(box->m_hWnd, GWL_STYLE, (LONG)0x50010203); } else if (n == L"Public") { box->AddString(L"false"); box->AddString(L"true"); //::SetWindowLong(box->m_hWnd, GWL_STYLE, (LONG)0x50010203); } else if (n == L"Enabled") { box->AddString(L"false"); box->AddString(L"true"); //::SetWindowLong(box->m_hWnd, GWL_STYLE, (LONG)0x50010203); } }; dlg.set_init_val_api(init_val); if (dlg.DoModal() == IDOK) { std::wstring n(dlg.vals_[0]), val(dlg.init_); if (n == L"Group") { for (auto& v : opts_) v.group = val; } else if (n == L"Category") { for (auto& v : opts_) v.category = val; } else if (n == L"Depends") { for (auto& v : opts_) v.depend_oper = val; } else if (n == L"Affect") { for (auto& v : opts_) v.affect = val; } else if (n == L"Version") { for (auto& v : opts_) v.ver = _wtoi(val.c_str()); } else if (n == L"Position") { for (auto& v : opts_) v.pos = _wtoi(val.c_str()); } else if (n == L"Readonly") { for (auto& v : opts_) v.readonly = val == L"true"; } else if (n == L"Public") { for (auto& v : opts_) v.open = val == L"true"; } else if (n == L"Enabled") { for (auto& v : opts_) v.enable = val == L"true"; } HTREEITEM sel = tree_.GetSelectedItem(); if (sel) { wchar_t* n = (wchar_t*)tree_.GetItemData(sel); for (auto& v : opts_) { if (v.name == n) { to_ui(v); break; } } } } } void CDlgOptJson::OnSortName() { // TODO: 在此添加命令处理程序代码 HTREEITEM sel = tree_.GetSelectedItem(); std::wstring name(L""); std::vector all(std::move(opts_)); std::sort(all.begin(), all.end(), SANEOPT::compare_name); if (sel) { wchar_t* n = (wchar_t*)tree_.GetItemData(sel); if (n) name = n; } delete_from_tree(); for (auto& v : all) insert_new_item(v, v.name == name); } void CDlgOptJson::OnSortTitle() { // TODO: 在此添加命令处理程序代码 HTREEITEM sel = tree_.GetSelectedItem(); std::wstring name(L""); std::vector all(std::move(opts_)); std::sort(all.begin(), all.end(), SANEOPT::compare_title); if (sel) { wchar_t* n = (wchar_t*)tree_.GetItemData(sel); if (n) name = n; } delete_from_tree(); for (auto& v : all) insert_new_item(v, v.name == name); } void CDlgOptJson::OnSortGroup() { // TODO: 在此添加命令处理程序代码 HTREEITEM sel = tree_.GetSelectedItem(); std::wstring name(L""); std::vector all(std::move(opts_)); std::sort(all.begin(), all.end(), SANEOPT::compare_group); if (sel) { wchar_t* n = (wchar_t*)tree_.GetItemData(sel); if (n) name = n; } delete_from_tree(); for (auto& v : all) insert_new_item(v, v.name == name); } void CDlgOptJson::OnSortPosition() { // TODO: 在此添加命令处理程序代码 HTREEITEM sel = tree_.GetSelectedItem(); std::wstring name(L""); std::vector all(std::move(opts_)); std::sort(all.begin(), all.end(), SANEOPT::compare_position); if (sel) { wchar_t* n = (wchar_t*)tree_.GetItemData(sel); if (n) name = n; } delete_from_tree(); for (auto& v : all) insert_new_item(v, v.name == name); }