From 3467a987ea15f0fad2cb11487e67a114b96f5209 Mon Sep 17 00:00:00 2001 From: gb <741021719@qq.com> Date: Wed, 8 Mar 2023 14:45:50 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=85=8D=E7=BD=AE=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E2=80=94=E5=9C=A8=E7=8E=B0=E6=9C=89=E6=96=B9=E6=A1=88?= =?UTF-8?q?=E4=B8=8A=E7=9A=84=E4=BF=AE=E6=94=B9=EF=BC=8C=E9=9C=80=E8=A6=81?= =?UTF-8?q?=E6=8F=90=E7=A4=BA=E7=94=A8=E6=88=B7=E8=BF=9B=E8=A1=8C=E4=BF=9D?= =?UTF-8?q?=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sane/DlgPage.cpp | 15 ++ sane/DlgPage.h | 3 +- sane/DlgSaveScheme.cpp | 246 ++++++++++++++++++++++++++++++++ sane/DlgSaveScheme.h | 47 ++++++ sane/DlgSetting.cpp | 292 ++++++++++++++++++++++++++++++++------ sane/DlgSetting.h | 7 +- sane/const_str.h | 9 ++ sane/gb_json.cpp | 7 +- sane/resource.h | 7 +- sane/sane.rc | 25 ++++ sane/sane.vcxproj | 2 + sane/sane.vcxproj.filters | 6 + sane/scanner.cpp | 5 +- sane/scanner.h | 1 + 14 files changed, 624 insertions(+), 48 deletions(-) create mode 100644 sane/DlgSaveScheme.cpp create mode 100644 sane/DlgSaveScheme.h diff --git a/sane/DlgPage.cpp b/sane/DlgPage.cpp index 9fb1780..c48c72e 100644 --- a/sane/DlgPage.cpp +++ b/sane/DlgPage.cpp @@ -163,6 +163,20 @@ std::wstring dlg_base::get_menu_text(HMENU menu, int ind) return text; } +void dlg_base::center_window(HWND wnd, HWND parent) +{ + RECT rme = { 0 }, rp = { 0 }; + int x = 0, y = 0; + + GetWindowRect(wnd, &rme); + if (!IsWindow(parent)) + parent = GetDesktopWindow(); + GetWindowRect(parent, &rp); + x = rp.left + (RECT_W(rp) - RECT_W(rme)) / 2; + y = rp.top + (RECT_H(rp) - RECT_H(rme)) / 2; + OffsetRect(&rme, x - rme.left, y - rme.top); + MoveWindow(wnd, rme.left, rme.top, RECT_W(rme), RECT_H(rme), FALSE); +} int dlg_base::list_insert_column(HWND list_wnd, const wchar_t* text, int cx, int ind) { LVCOLUMNW col = { 0 }; @@ -348,6 +362,7 @@ int dlg_base::do_modal(HWND parent) enable_parent = TRUE; } + dlg_base::center_window(hwnd(), parent); ShowWindow(hwnd(), SW_SHOW); while ((got = GetMessage(&msg, NULL, 0, 0))) { diff --git a/sane/DlgPage.h b/sane/DlgPage.h index 6e87f0e..0a2952f 100644 --- a/sane/DlgPage.h +++ b/sane/DlgPage.h @@ -25,7 +25,7 @@ #define WM_IMAGE_RECEIVED WM_USER + 303 #define WM_SCAN_FINISHED WM_USER + 304 // WPARAM: std::string* msg; LPARAM: boo err #define WM_REFRESH_OPTION WM_USER + 311 // WPARAM: source option SN, LPARAM: unused now -#define WM_GET_CONFIG_OBJ WM_USER + 312 // WPARAM: bool*, [in]create new if NULL; [out]created, LPARAM: to receive the gb::sane_config* object +#define WM_GET_CONFIG_OBJ WM_USER + 312 // WPARAM: bool*, [in]create new if NULL; [out]created, LPARAM: to receive the gb::sane_config_schm* object extern HMODULE g_my_inst; @@ -66,6 +66,7 @@ public: static std::wstring get_wnd_text(HWND h); static bool is_language_pack_default_code_page(void); static std::wstring get_menu_text(HMENU menu, int ind); + static void center_window(HWND wnd, HWND parent); static int list_insert_column(HWND list_wnd, const wchar_t* text, int cx = 20, int ind = -1); static int list_insert_item(HWND list_wnd, const wchar_t* text, int ind = -1); diff --git a/sane/DlgSaveScheme.cpp b/sane/DlgSaveScheme.cpp new file mode 100644 index 0000000..4465116 --- /dev/null +++ b/sane/DlgSaveScheme.cpp @@ -0,0 +1,246 @@ +// DlgSaveScheme.cpp: 实现文件 +// + +#include "DlgSaveScheme.h" +#include "resource.h" +#include "scanned_img.h" // for local_trans +#include "gb_json.h" +#include "mem_dc.h" + +#include "../../sdk/include/lang/app_language.h" + +#define WIDTH_MARGINS 10 + + + +dlg_save_scheme::dlg_save_scheme(HWND parent) : dlg_base(parent, IDD_SAVE_SCHEME) +{ + create(); + + std::wstring title(local_trans::lang_trans_between_hz936(CONST_STRING_SAVE_TITLE)); + int dif = 0; + + SetWindowTextW(hwnd(), title.c_str()); + + title = local_trans::lang_trans_between_hz936(CONST_STRING_SAVE_DISCARD); + set_item_text(IDC_RADIO_DISCARD, title.c_str()); + set_item_fit_to_text(IDC_RADIO_DISCARD); + + title = local_trans::lang_trans_between_hz936(CONST_STRING_SAVE_OVERWRITE); + set_item_text(IDC_RADIO_OVERWRITE, title.c_str()); + dif = set_item_fit_to_text(IDC_RADIO_OVERWRITE); + + title = local_trans::lang_trans_between_hz936(CONST_STRING_SAVE_NEW); + set_item_text(IDC_RADIO_NEW, title.c_str()); + dif = set_item_fit_to_text(IDC_RADIO_NEW); + offset_item(IDC_NAME, dif, 0); + // expand_item(IDC_NAME, dif, 0); + + { + RECT r = { 0 }, rc = { 0 }; + + GetWindowRect(hwnd(), &r); + GetWindowRect(get_item(IDC_NAME), &rc); + if (rc.right + WIDTH_MARGINS > r.right) + { + r.right = rc.right + WIDTH_MARGINS; + MoveWindow(hwnd(), r.left, r.top, RECT_W(r), RECT_H(r), FALSE); + } + } + + title = local_trans::lang_trans_between_hz936(CONST_STRING_OK); + set_item_text(IDOK, title.c_str()); +} +dlg_save_scheme::~dlg_save_scheme() +{ +} + + +BOOL dlg_save_scheme::handle_message(UINT msg, WPARAM wp, LPARAM lp) +{ + wchar_t text[40] = { 0 }; + BOOL ret = TRUE; + + switch (msg) + { + case WM_INITDIALOG: + on_init_dlg(); + UpdateWindow(hwnd()); + break; + case WM_COMMAND: + handle_command(HIWORD(wp), LOWORD(wp), (HWND)lp); + break; + case WM_NOTIFY: + handle_notify(wp, (LPNMHDR)lp); + break; + case WM_PAINT: + { + PAINTSTRUCT ps = { 0 }; + HDC hdc = BeginPaint(hwnd(), &ps); + { + compatible_dc dc(hdc); + on_paint(dc.get_dc()); + } + EndPaint(hwnd(), &ps); + } + break; + default: + ret = FALSE; + } + return ret; +} +void dlg_save_scheme::handle_command(WORD code, WORD id, HANDLE ctrl) +{ + wchar_t cls[128] = { 0 }; + + GetClassNameW((HWND)ctrl, cls, _countof(cls) - 1); + if (IS_BUTTON(cls)) + { + if (code == BN_CLICKED) + { + EnableWindow(get_item(IDC_NAME), FALSE); + if (id == IDOK) + { + if (method_ == SAVE_NEW) + { + std::wstring text(get_wnd_text(get_item(IDC_NAME))); + + if (text.empty() || std::find(existing_.begin(), existing_.end(), text) != existing_.end()) + { + std::wstring info(L""), title(local_trans::lang_trans_between_hz936(CONST_STRING_ERROR)); + + if (text.empty()) + { + info = local_trans::lang_trans_between_hz936(CONST_STRING_REINPUT_SCHEME_NAME); + } + else + { + info = local_trans::lang_trans_between_hz936(CONST_STRING_LEFT_QUOTE) + text + + local_trans::lang_trans_between_hz936(CONST_STRING_RIGHT_QUOTE) + + local_trans::lang_trans_between_hz936(CONST_STRING_REINPUT_WHEN_EXISTING); + } + EnableWindow(get_item(IDC_NAME), TRUE); + MessageBoxW(hwnd(), info.c_str(), title.c_str(), MB_OK); + goto_name(); + return; + } + + name_ = std::move(text); + } + if (method_ == SAVE_DISCARD) + log_info((L"Discard changes on scheme '" + name_ + L"'.\r\n").c_str(), 0); + else + log_info((L"Save changes to scheme '" + name_ + L"'.\r\n").c_str(), 0); + quit_modal(id); + } + else if (id == IDC_RADIO_DISCARD) + method_ = SAVE_DISCARD; + else if (id == IDC_RADIO_OVERWRITE) + method_ = SAVE_OVERWRITE; + else if (id == IDC_RADIO_NEW) + { + method_ = SAVE_NEW; + EnableWindow(get_item(IDC_NAME), TRUE); + goto_name(); + } + } + } +} +void dlg_save_scheme::handle_notify(UINT id, LPNMHDR pnhdr) +{ +} +void dlg_save_scheme::layout(void) +{ +} + + +void dlg_save_scheme::on_init_dlg(void) +{ + check_radio(IDC_RADIO_DISCARD); +} +void dlg_save_scheme::on_paint(HDC hdc) +{ +} +void dlg_save_scheme::goto_name(void) +{ + SendMessageW(get_item(IDC_NAME), EM_SETSEL, 0, -1); + SetFocus(get_item(IDC_NAME)); +} +void dlg_save_scheme::check_radio(UINT id, bool check) +{ + SendMessage(get_item(id), BM_SETCHECK, check ? (WPARAM)BST_CHECKED : (WPARAM)BST_UNCHECKED, 0); +} + + +void dlg_save_scheme::set_info(const wchar_t* name, std::vector& existing, int mask) +{ + bool set_method = false; + + name_ = name; + existing_ = existing; + set_item_text(IDC_NAME, name); + + { + std::wstring schem(local_trans::lang_trans_between_hz936(CONST_STRING_SAVE_OVERWRITE)); + schem += L" - '"; + schem += name; + schem += L"'"; + set_item_text(IDC_RADIO_OVERWRITE, schem.c_str()); + set_item_fit_to_text(IDC_RADIO_OVERWRITE); + + RECT r = { 0 }, rc = { 0 }; + + GetWindowRect(get_item(IDC_RADIO_OVERWRITE), &rc); + GetWindowRect(hwnd(), &r); + if (RECT_W(r) < RECT_W(rc) + WIDTH_MARGINS) + { + r.right = r.left + RECT_W(rc) + WIDTH_MARGINS; + MoveWindow(hwnd(), r.left, r.top, RECT_W(r), RECT_H(r), FALSE); + } + } + + if (mask & SAVE_METHOD_MASK(SAVE_DISCARD)) + { + set_method = true; + method_ = SAVE_DISCARD; + EnableWindow(get_item(IDC_RADIO_DISCARD), TRUE); + check_radio(IDC_RADIO_DISCARD); + } + else + EnableWindow(get_item(IDC_RADIO_DISCARD), FALSE); + + if (mask & SAVE_METHOD_MASK(SAVE_OVERWRITE)) + { + if (!set_method) + { + set_method = true; + method_ = SAVE_OVERWRITE; + check_radio(IDC_RADIO_OVERWRITE); + } + EnableWindow(get_item(IDC_RADIO_OVERWRITE), TRUE); + } + else + EnableWindow(get_item(IDC_RADIO_OVERWRITE), FALSE); + + if (mask & SAVE_METHOD_MASK(SAVE_NEW)) + { + if (!set_method) + { + set_method = true; + method_ = SAVE_NEW; + check_radio(IDC_RADIO_NEW); + EnableWindow(get_item(IDC_NAME), TRUE); + } + EnableWindow(get_item(IDC_RADIO_NEW), TRUE); + } + else + EnableWindow(get_item(IDC_RADIO_NEW), FALSE); +} +save_method dlg_save_scheme::get_dispose(void) +{ + return method_; +} +std::wstring dlg_save_scheme::get_name(void) +{ + return name_; +} diff --git a/sane/DlgSaveScheme.h b/sane/DlgSaveScheme.h new file mode 100644 index 0000000..320c325 --- /dev/null +++ b/sane/DlgSaveScheme.h @@ -0,0 +1,47 @@ +#pragma once +#include +#include + +#include "DlgPage.h" + + +// CDlgSaveScheme 对话框 +enum save_method +{ + SAVE_DISCARD = 0, + SAVE_OVERWRITE, + SAVE_NEW, +}; +enum +{ + SAVE_REASON_QUIT_UI = 0, + SAVE_REASON_SWITCH_SCHEME, + SAVE_REASON_RESTORE, +}; +#define SAVE_METHOD_MASK(m) (1 << m) + +class dlg_save_scheme : public dlg_base +{ + std::vector existing_; + std::wstring name_ = L""; + save_method method_ = SAVE_DISCARD; + + BOOL handle_message(UINT msg, WPARAM wp, LPARAM lp) override; + void handle_command(WORD code, WORD id, HANDLE ctrl); + void handle_notify(UINT id, LPNMHDR pnhdr); + void layout(void); + + void on_init_dlg(void); + void on_paint(HDC hdc); + void goto_name(void); + void check_radio(UINT id, bool check = true); + +public: + dlg_save_scheme(HWND parent); + ~dlg_save_scheme(); + +public: + void set_info(const wchar_t* name, std::vector& existing, int mask); + save_method get_dispose(void); + std::wstring get_name(void); +}; diff --git a/sane/DlgSetting.cpp b/sane/DlgSetting.cpp index ebbae8c..1a8039f 100644 --- a/sane/DlgSetting.cpp +++ b/sane/DlgSetting.cpp @@ -12,6 +12,7 @@ // CDlgIndicator 对话框 #include "DlgCfgMgr.h" #include "DlgInput.h" +#include "DlgSaveScheme.h" #define MENU_CMD_0 ((unsigned short)0x8888) @@ -20,7 +21,8 @@ static IMPLEMENT_OPTION_STRING_COMPARE(cmp_sane_opt); dlg_setting::dlg_setting(HWND parent, LPSANEAPI api, SANE_Handle dev, bool with_scan, const wchar_t* name) : dlg_base(parent, IDD_SETTING) , sane_api_(*api), sane_dev_(dev), with_scan_(with_scan) - , papers_(0), images_(0), err_(false), tab_(NULL), cfg_(NULL), cfg_file_(L"") + , papers_(0), images_(0), err_(false), tab_(NULL), cfg_(NULL), cfg_file_(L""), twain_set_(nullptr), twain_schm_(nullptr) + , schm_from_empty_(false) { std::wstring setting(local_trans::lang_trans_between_hz936(CONST_STRING_SETTING)); @@ -45,13 +47,9 @@ dlg_setting::~dlg_setting() } DestroyWindow(tab_); } + if (twain_schm_) + twain_schm_->release(); - gb::sane_config_schm* schm = cfg_->get_scheme(); - if (schm) - { - schm->end_setting(false); - schm->release(); - } cfg_->save(local_trans::u2a(cfg_file_.c_str()).c_str()); DestroyMenu(cfg_menu_); } @@ -77,17 +75,29 @@ BOOL dlg_setting::handle_message(UINT msg, WPARAM wp, LPARAM lp) break; case WM_GET_CONFIG_OBJ: { - gb::sane_config_schm* schm = cfg_->get_scheme(); + gb::sane_config_schm* schm = twain_schm_ ? twain_schm_ : cfg_->get_scheme(); + if (twain_schm_) + twain_schm_->add_ref(); if (wp) { if (!schm && *(bool*)wp) { schm = cfg_->create_empty_scheme(true); + if (schm) + schm->begin_setting(); + schm_from_empty_ = true; + log_info(L"Create a new config scheme for recording user settings.\r\n", 0); } else *(bool*)wp = false; } *((gb::sane_config_schm**)lp) = schm; + { + std::wstring name(schm ? local_trans::a2u(schm->get_scheme_name().c_str(), CP_UTF8) : L"default"); + name.insert(0, L"Return scheme '"); + name += L"' to user.\r\n"; + log_info(name.c_str(), 0); + } } break; default: @@ -105,32 +115,52 @@ void dlg_setting::handle_command(WORD code, WORD id, HANDLE ctrl) if (id == MENU_CMD_0) { // save current scheme as ... - gb::sane_config_schm* s = cfg_->get_scheme(); + bool new_scheme = false; + gb::sane_config_schm* s = twain_schm_ ? twain_schm_ : cfg_->get_scheme(); if (!s) + { s = cfg_->copy_scheme(nullptr); + new_scheme = true; + } + + if (twain_schm_) + { + s->add_ref(); + twain_schm_->release(); + twain_schm_ = nullptr; + new_scheme = true; + } if (s) { - std::vector all; - std::vector allw; + std::vector all(get_stored_scheme_names()); std::wstring cur(local_trans::a2u(s->get_scheme_name().c_str(), CP_UTF8)); dlg_input dlg(hwnd(), cur.c_str()); - cfg_->get_all_schemes(all); - for (auto& v : all) - allw.push_back(local_trans::a2u(v.c_str(), CP_UTF8)); - dlg.set_no_repeats(allw); + dlg.set_no_repeats(all); if (dlg.do_modal(hwnd()) == IDOK) { std::string name(local_trans::u2a(dlg.get_value().c_str(), CP_UTF8)); - gb::sane_config_schm* n = s->copy(); + gb::sane_config_schm* n = s; + if (new_scheme) + { + n->add_ref(); + n->end_setting(false); + } + else + { + n = s->copy(); + s->end_setting(true); + n->end_setting(false); + } + if (cfg_->add_scheme(n, name.c_str())) { cfg_->select_scheme(name.c_str()); + n->begin_setting(); } n->release(); } - s->end_setting(true); // discard changes in prev-scheme s->release(); } } @@ -139,14 +169,12 @@ void dlg_setting::handle_command(WORD code, WORD id, HANDLE ctrl) // config scheme changed ... std::string schm(local_trans::u2a(dlg_base::get_menu_text(cfg_menu_, id - MENU_CMD_0).c_str(), CP_UTF8)); - if (cfg_->get_current_scheme_name() != schm) + log_info((L"Select scheme '" + local_trans::a2u(schm.c_str(), CP_UTF8) + L"' on scheme menu.\r\n").c_str(), 0); + + save_changes_to_cur_scheme(SAVE_REASON_SWITCH_SCHEME); + // if (cfg_->get_current_scheme_name() != schm) { - gb::sane_config_schm* s = cfg_->get_scheme(); - if (s) - { - s->end_setting(false); // save changes - s->release(); - } + gb::sane_config_schm* s = nullptr; if (cfg_->select_scheme(schm.c_str())) { @@ -154,6 +182,7 @@ void dlg_setting::handle_command(WORD code, WORD id, HANDLE ctrl) apply_scheme_(s, apply_param_); if (s) { + s->begin_setting(); s->release(); } refresh_controls(-1); @@ -164,6 +193,7 @@ void dlg_setting::handle_command(WORD code, WORD id, HANDLE ctrl) } else if (id == IDOK) { + save_changes_to_cur_scheme(SAVE_REASON_QUIT_UI); notify_over(); } else if (id == IDC_BUTTON_HELP) @@ -173,42 +203,54 @@ void dlg_setting::handle_command(WORD code, WORD id, HANDLE ctrl) } else if (id == IDC_BUTTON_RESTORE) { + log_info(L"Press 'Restore' button to restore settings\r\n", 0); + + save_changes_to_cur_scheme(SAVE_REASON_RESTORE); + SANE_Int after = 0; SANE_Status statu = sane_api_.sane_control_option_api(sane_dev_, id_restore_, SANE_ACTION_SET_VALUE, &after, &after); refresh_controls(id_restore_); - if (cfg_) - { - gb::sane_config_schm* schm = cfg_->get_scheme(); - if (schm) - { - schm->end_setting(false); - schm->release(); - } - cfg_->select_scheme(nullptr); - } + cfg_->select_scheme(nullptr); } else if (id == IDC_BUTTON_SCAN) { // enable(false); + save_changes_to_cur_scheme(SAVE_REASON_QUIT_UI); notify_ui_event(SANE_EVENT_UI_SCAN_COMMAND); } else if (id == IDC_BUTTON_CONFIG_MGR) { dlg_cfg_mgr dlg(cfg_, hwnd()); + gb::sane_config_schm* prev = cfg_->get_scheme(), * after = nullptr; + dlg.do_modal(hwnd()); - if (dlg.is_scheme_changed()) // refresh settings and UI + after = cfg_->get_scheme(); + if (prev != after) // refresh settings and UI { - gb::sane_config_schm* schm = cfg_->get_scheme(); - apply_scheme_(schm, apply_param_); - if (schm) - schm->release(); + { + std::wstring info(L"Current scheme has changed from '"); + if (prev) + info += local_trans::a2u(prev->get_scheme_name().c_str(), CP_UTF8) + L"' to '"; + else + info += L"default' to '"; + if (after) + info += local_trans::a2u(after->get_scheme_name().c_str(), CP_UTF8) + L"' in management UI\r\n"; + else + info += L"default' in management UI\r\n"; + log_info(info.c_str(), 0); + } + apply_scheme_(after, apply_param_); refresh_controls(-1); } + if (prev) + prev->release(); + if (after) + after->release(); } else if (id == IDC_BUTTON_CONFIG_MENU) { HMENU sub = cfg_menu_; // GetSubMenu(cfg_menu_, 0); - int ind = 2; + int ind = 2; // 0 - save as ...; 1 - separator std::vector schemes; while (DeleteMenu(sub, 2, MF_BYPOSITION)); @@ -217,7 +259,7 @@ void dlg_setting::handle_command(WORD code, WORD id, HANDLE ctrl) { UINT flag = MF_BYPOSITION; - if (v == cfg_->get_current_scheme_name()) + if (twain_set_ && *twain_set_ == false && v == cfg_->get_current_scheme_name()) flag |= MF_CHECKED; InsertMenuW(sub, ind, flag, MENU_CMD_0 + ind, local_trans::a2u(v.c_str(), CP_UTF8).c_str()); ind++; @@ -484,13 +526,165 @@ void dlg_setting::refresh_controls(int src_sn) desc = sane_api_.sane_get_option_descriptor_api(sane_dev_, sn++); } } +void dlg_setting::save_changes_to_cur_scheme(int reason) +{ + // discard, overwrite, new + int items = 0; + bool changed = false; + std::vector now(get_stored_scheme_names()); -void dlg_setting::set_config(gb::scanner_cfg* cfg, const wchar_t* file, void(__stdcall* apply)(gb::sane_config_schm*, void*), void* param) + if (!cfg_) + return; + + if (twain_set_ && reason != SAVE_REASON_QUIT_UI) + *twain_set_ = false; + + if (twain_schm_) + { + changed = twain_schm_->has_changed(&items); + if (changed) + { + dlg_save_scheme dlg(hwnd()); + + dlg.set_info(local_trans::a2u(twain_schm_->get_scheme_name().c_str(), CP_UTF8).c_str(), now + , SAVE_METHOD_MASK(SAVE_DISCARD) | SAVE_METHOD_MASK(SAVE_NEW)); + dlg.do_modal(hwnd()); + if(dlg.get_dispose() == SAVE_NEW) + { + std::string name(local_trans::u2a(dlg.get_name().c_str(), CP_UTF8)); + if (cfg_->add_scheme(twain_schm_, name.c_str()) && + reason == SAVE_REASON_QUIT_UI) + cfg_->select_scheme(name.c_str()); + } + } + twain_schm_->release(); + twain_schm_ = nullptr; + } + else + { + gb::sane_config_schm* schm = cfg_->get_scheme(); + if (schm) + { + changed = schm->has_changed(&items); + if (changed) + { + if (schm_from_empty_) + schm->end_setting(false); + else + { + dlg_save_scheme dlg(hwnd()); + std::wstring name(local_trans::a2u(schm->get_scheme_name().c_str(), CP_UTF8)); + + dlg.set_info(name.c_str(), now, SAVE_METHOD_MASK(SAVE_DISCARD) | SAVE_METHOD_MASK(SAVE_OVERWRITE) | SAVE_METHOD_MASK(SAVE_NEW)); + dlg.do_modal(hwnd()); + + int dispose = dlg.get_dispose(); + if (dispose == SAVE_NEW) + { + std::string uname(local_trans::u2a(dlg.get_name().c_str(), CP_UTF8)); + gb::sane_config_schm* s = schm->copy(); + + schm->end_setting(true); + s->end_setting(false); + cfg_->add_scheme(s, uname.c_str()); + s->release(); + if (reason == SAVE_REASON_QUIT_UI) + cfg_->select_scheme(uname.c_str()); + } + else + { + schm->end_setting(dispose == SAVE_DISCARD); + if (dispose == SAVE_DISCARD && reason == SAVE_REASON_QUIT_UI && twain_set_) + { + std::wstring info(local_trans::a2u(schm->get_scheme_name().c_str(), CP_UTF8)); + + info.insert(0, L"User discard the changes on scheme '"); + info += L"' and will quit UI, set temporary scheme flag!\r\n"; + log_info(info.c_str(), 0); + + *twain_set_ = true; + } + } + } + } + schm->release(); + } + } + schm_from_empty_ = false; +} + +void dlg_setting::set_config(gb::scanner_cfg* cfg, const wchar_t* file, void(__stdcall* apply)(gb::sane_config_schm*, void*), void* param, bool* twain_set) { cfg_ = cfg; cfg_file_ = file; apply_scheme_ = apply; apply_param_ = param; + twain_set_ = twain_set; + + if (twain_set && *twain_set && cfg_) + { + // create a temporary scheme because of APP has changed the setting after we applied the store scheme ... + twain_schm_ = new gb::sane_config_schm(cfg_); + + int sn = 1; + const SANE_Option_Descriptor* desc = sane_api_.sane_get_option_descriptor_api(sane_dev_, sn++); + + while (desc) + { + if (desc->type != SANE_TYPE_BUTTON && desc->type != SANE_TYPE_GROUP) + { + char* buf = new char[desc->size + 8]; + SANE_Int info = 0; + dlg_page* page = NULL; + memset(buf, 0, desc->size + 8); + sane_api_.sane_control_option_api(sane_dev_, sn - 1, SANE_ACTION_GET_VALUE, buf, &info); + if (desc->type == SANE_TYPE_STRING) + { + std::string defl(to_default_language(buf, nullptr)); + twain_schm_->config_changed(sn - 1, defl.c_str(), defl.length()); + } + else + { + int len = desc->size; + switch (desc->type) + { + case SANE_TYPE_BOOL: + len = sizeof(SANE_Bool); + break; + case SANE_TYPE_INT: + len = sizeof(SANE_Int); + break; + case SANE_TYPE_FIXED: + len = sizeof(SANE_Fixed); + break; + } + twain_schm_->config_changed(sn - 1, buf, len); + } + + delete[] buf; + } + desc = sane_api_.sane_get_option_descriptor_api(sane_dev_, sn++); + } + twain_schm_->has_changed(&sn); + twain_schm_->auto_gen_scheme_name(local_trans::lang_trans_between_hz936, nullptr); + twain_schm_->begin_setting(); + if(sn) + { + std::wstring name(local_trans::a2u(cfg_->get_current_scheme_name().c_str(), CP_UTF8)); + name.insert(0, L"TWAIN-app has changed " + std::to_wstring(sn) + L" setting(s) after we applied stored scheme '"); + name += L"'\r\n"; + log_info(name.c_str(), 0); + } + } + else if(cfg_) + { + gb::sane_config_schm* schm = cfg_->get_scheme(); + if (schm) + { + schm->begin_setting(); + schm->release(); + } + } } HWND dlg_setting::window(void) { @@ -532,4 +726,18 @@ void dlg_setting::notify_scan_over(void) { enable(true); } +std::vector dlg_setting::get_stored_scheme_names(void) +{ + std::vector now; + std::vector wnow; + + if (cfg_) + { + cfg_->get_all_schemes(now); + for (auto& v : now) + wnow.push_back(local_trans::a2u(v.c_str(), CP_UTF8)); + } + + return std::move(wnow); +} // CDlgIndicator 消息处理程序 diff --git a/sane/DlgSetting.h b/sane/DlgSetting.h index f37d944..612e459 100644 --- a/sane/DlgSetting.h +++ b/sane/DlgSetting.h @@ -31,6 +31,9 @@ class dlg_setting : public dlg_base int id_restore_; gb::scanner_cfg *cfg_; std::wstring cfg_file_; + bool *twain_set_; + gb::sane_config_schm* twain_schm_; + bool schm_from_empty_; HMENU cfg_menu_; void(__stdcall* apply_scheme_)(gb::sane_config_schm*, void*); @@ -53,16 +56,18 @@ class dlg_setting : public dlg_base dlg_page* get_page(const char* utf8_title); dlg_page* select_page(int index); void refresh_controls(int src_sn); + void save_changes_to_cur_scheme(int reason); public: dlg_setting(HWND parent, LPSANEAPI api, SANE_Handle dev, bool with_scan, const wchar_t* name); ~dlg_setting(); public: - void set_config(gb::scanner_cfg* cfg, const wchar_t* file, void(__stdcall* apply)(gb::sane_config_schm*, void*), void* param); + void set_config(gb::scanner_cfg* cfg, const wchar_t* file, void(__stdcall* apply)(gb::sane_config_schm*, void*), void* param, bool* twain_set = nullptr); HWND window(void); HWND parent(void); //void show(void); void hide(void); void notify_scan_over(void); + std::vector get_stored_scheme_names(void); }; diff --git a/sane/const_str.h b/sane/const_str.h index 21f9f2e..c52c879 100644 --- a/sane/const_str.h +++ b/sane/const_str.h @@ -83,3 +83,12 @@ #define CONST_STRING_START_FAILED L"\u542F\u52A8\u5931\u8D25" #define CONST_STRING_ERROR L"\u9519\u8BEF" + +#define CONST_STRING_SAVE_TITLE L"\u5F53\u524D\u914D\u7F6E\u5DF2\u7ECF\u66F4\u6539\uFF0C\u8BF7\u9009\u62E9\u4FDD\u5B58\u65B9\u5F0F" +#define CONST_STRING_SAVE_DISCARD L"\u4E0D\u4FDD\u5B58\uFF0C\u4EC5\u7528\u4E8E\u8BE5\u6B21\u626B\u63CF\u6216\u653E\u5F03\u66F4\u6539" +#define CONST_STRING_SAVE_OVERWRITE L"\u8986\u76D6\u73B0\u6709\u65B9\u6848" +#define CONST_STRING_SAVE_NEW L"\u4FDD\u5B58\u4E3A\u65B0\u65B9\u6848" +#define CONST_STRING_REINPUT_SCHEME_NAME L"\u8BF7\u8F93\u5165\u65B0\u914D\u7F6E\u65B9\u6848\u540D\u79F0\u3002" +#define CONST_STRING_LEFT_QUOTE L"\u201C" +#define CONST_STRING_RIGHT_QUOTE L"\u201D" +#define CONST_STRING_REINPUT_WHEN_EXISTING L"\u5DF2\u7ECF\u5B58\u5728\uFF0C\u8BF7\u91CD\u65B0\u8F93\u5165\u3002" \ No newline at end of file diff --git a/sane/gb_json.cpp b/sane/gb_json.cpp index a9aa402..3aebefa 100644 --- a/sane/gb_json.cpp +++ b/sane/gb_json.cpp @@ -1360,6 +1360,11 @@ namespace gb cp->file_ = file_; if(jsn_) cp->jsn_->copy_from(*jsn_); + if (bkp_) + { + cp->bkp_ = new gb::json(); + cp->bkp_->copy_from(*bkp_); + } cp->def_val_->release(); cp->def_val_ = def_val_; def_val_->add_ref(); @@ -2013,7 +2018,7 @@ namespace gb } bool scanner_cfg::rename_scheme(const char* from, const char* to) { - if (to && std::find(schemes_.begin(), schemes_.end(), to) != schemes_.end()) + if (to && (strcmp(to, trans_language(scanner_cfg::default_setting_name_.c_str(), true)) == 0 || std::find(schemes_.begin(), schemes_.end(), to) != schemes_.end())) return false; for(auto& v: schemes_) diff --git a/sane/resource.h b/sane/resource.h index 3b6ebee..f67dbaa 100644 --- a/sane/resource.h +++ b/sane/resource.h @@ -11,6 +11,7 @@ #define IDD_CHOOSE_DEV 108 #define IDD_CFG_MGR 109 #define IDD_INPUT 110 +#define IDD_SAVE_SCHEME 111 #define IDC_EDIT_PAPER 1001 #define IDC_EDIT_IMAGE 1002 #define IDC_STATIC_PAPER 1003 @@ -50,6 +51,10 @@ #define IDC_BUTTON_DEL_ALL 1032 #define IDC_EDIT1 1033 #define IDC_STATIC_SKETCH 1034 +#define IDC_RADIO_DISCARD 1035 +#define IDC_RADIO_OVERWRITE 1036 +#define IDC_RADIO_NEW 1037 +#define IDC_NAME 1038 // Next default values for new objects // @@ -57,7 +62,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 109 #define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1035 +#define _APS_NEXT_CONTROL_VALUE 1039 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/sane/sane.rc b/sane/sane.rc index decac46..47ade48 100644 --- a/sane/sane.rc +++ b/sane/sane.rc @@ -161,6 +161,18 @@ BEGIN PUSHBUTTON "ȡ",IDCANCEL,7,22,42,12 END +IDD_SAVE_SCHEME DIALOGEX 0, 0, 193, 75 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_CAPTION +CAPTION "ǰѾģѡ񱣴淽ʽ" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "棬ڸôɨ",IDC_RADIO_DISCARD,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,7,7,104,10 + CONTROL "з",IDC_RADIO_OVERWRITE,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,7,22,64,10 + CONTROL "Ϊ·",IDC_RADIO_NEW,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,7,37,64,10 + EDITTEXT IDC_NAME,71,36,115,12,ES_AUTOHSCROLL | WS_DISABLED + PUSHBUTTON "ȷ",IDOK,79,56,42,12 +END + ///////////////////////////////////////////////////////////////////////////// // @@ -233,6 +245,14 @@ BEGIN TOPMARGIN, 7 BOTTOMMARGIN, 34 END + + IDD_SAVE_SCHEME, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 186 + TOPMARGIN, 7 + BOTTOMMARGIN, 68 + END END #endif // APSTUDIO_INVOKED @@ -282,6 +302,11 @@ BEGIN 0 END +IDD_SAVE_SCHEME AFX_DIALOG_LAYOUT +BEGIN + 0 +END + ///////////////////////////////////////////////////////////////////////////// // diff --git a/sane/sane.vcxproj b/sane/sane.vcxproj index 71e84fa..8834c97 100644 --- a/sane/sane.vcxproj +++ b/sane/sane.vcxproj @@ -205,6 +205,7 @@ + @@ -232,6 +233,7 @@ + diff --git a/sane/sane.vcxproj.filters b/sane/sane.vcxproj.filters index 9eba608..73d0df0 100644 --- a/sane/sane.vcxproj.filters +++ b/sane/sane.vcxproj.filters @@ -72,6 +72,9 @@ sane2twain\UI + + sane2twain\UI + @@ -155,6 +158,9 @@ sane2twain\UI + + sane2twain\UI + diff --git a/sane/scanner.cpp b/sane/scanner.cpp index 8361cab..208ae8c 100644 --- a/sane/scanner.cpp +++ b/sane/scanner.cpp @@ -333,7 +333,7 @@ scanner::scanner(SCANNERID id) : handle_(NULL), id_(id), ex_id_(EXTENSION_ID_BAS , dpi_(200), tmp_path_(L""), img_ind_(0) , scanner_name_(L""), cfg_(NULL), is_ui_wait_img_(false), is_scanning_(false) , scanner_ev_handler_(NULL), evh_param_(NULL), app_wnd_(NULL), user_cancel_(false) - , max_img_mem_(1 * 1024) + , max_img_mem_(1 * 1024), twain_set_(false) { cfg_ = new gb::scanner_cfg(); cfg_->set_language_transform(&callback::language_trans, NULL); @@ -2593,6 +2593,7 @@ COM_API_IMPLEMENT(scanner, int, set_value(int sn, void* val)) log_info(msg, 0); } + twain_set_ = true; if (ex == ex_opts_.end()) { if (!set_option_value_with_parent(sn, val, &ret)) @@ -2798,7 +2799,7 @@ COM_API_IMPLEMENT(scanner, bool, ui_show_setting(HWND parent, bool with_scan, bo pid = scanner_name_.length(); setting_.reset(new dlg_setting(parent, &api, handle_, with_scan, scanner_name_.substr(0, pid).c_str())); setting_->set_ui_event_notify(&scanner::ui_callback, this); - setting_->set_config(cfg_, (cfg_path_ + scanner_name_.substr(0, pid) + L".cfg").c_str(), &scanner::apply_scheme, this); + setting_->set_config(cfg_, (cfg_path_ + scanner_name_.substr(0, pid) + L".cfg").c_str(), &scanner::apply_scheme, this, &twain_set_); indicator_.reset(); if (indicator) { diff --git a/sane/scanner.h b/sane/scanner.h index d38e60b..4c83890 100644 --- a/sane/scanner.h +++ b/sane/scanner.h @@ -54,6 +54,7 @@ class scanner : public ISaneInvoker, virtual public refer std::unique_ptr indicator_; std::unique_ptr setting_; gb::scanner_cfg* cfg_; + bool twain_set_; int(__stdcall* scanner_ev_handler_)(int, void*); void* evh_param_;