From 6cbe8f125c5f5f423c25cc11f118ee4692464fcb Mon Sep 17 00:00:00 2001 From: gb <741021719@qq.com> Date: Sat, 2 Jul 2022 17:27:21 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4UI=E4=B8=8EAPP=E4=BA=A4?= =?UTF-8?q?=E4=BA=92=E6=96=B9=E5=BC=8F=EF=BC=8C=E8=AE=BE=E5=A4=87=E5=B1=82?= =?UTF-8?q?=E5=9B=9E=E8=B0=83=E4=B8=8D=E7=9B=B4=E6=8E=A5=E8=B0=83=E7=94=A8?= =?UTF-8?q?UI=EF=BC=9B=E5=B1=8F=E8=94=BDTwpp=E6=A1=86=E6=9E=B6=E4=B8=AD?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E8=B0=83=E7=94=A8=E2=80=9CnotifyXferReady?= =?UTF-8?q?=EF=BC=88=EF=BC=89=E2=80=9D=EF=BC=8C=E7=BB=9F=E4=B8=80=E4=B8=BA?= =?UTF-8?q?=E5=9C=A8=E4=BA=8B=E4=BB=B6=E9=98=9F=E5=88=97eventProcess?= =?UTF-8?q?=E4=B8=AD=E9=80=9A=E7=9F=A5=EF=BC=9B=E6=89=80=E6=9C=89=E5=BC=B9?= =?UTF-8?q?=E5=87=BA=E7=AA=97=E5=8F=A3=E8=87=AA=E5=8A=A8=E7=A6=81=E7=94=A8?= =?UTF-8?q?=E5=85=B6=E7=88=B6=E7=AA=97=E5=8F=A3=EF=BC=8C=E9=80=80=E5=87=BA?= =?UTF-8?q?=E6=97=B6=E5=86=8D=E5=90=AF=E7=94=A8=E7=88=B6=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E5=B9=B6=E5=9C=A8=E5=89=8D=E6=96=B9=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sane/DlgIndicator.cpp | 23 +----- sane/DlgIndicator.h | 2 - sane/DlgPage.cpp | 25 ++++-- sane/DlgPage.h | 13 +--- sane/DlgSetting.cpp | 21 ++--- sane/DlgSetting.h | 3 +- sane/s2t_api.h | 4 +- sane/scanned_img.cpp | 45 +++-------- sane/scanned_img.h | 65 ++++++++++++++-- sane/scanner.cpp | 131 ++++++++++++-------------------- sane/scanner.h | 15 ++-- twain/twain/huagaods.cpp | 107 ++++++++++++++++++-------- twain/twain/huagaods.hpp | 5 +- twain/twain/twpp/datasource.hpp | 9 ++- 14 files changed, 244 insertions(+), 224 deletions(-) diff --git a/sane/DlgIndicator.cpp b/sane/DlgIndicator.cpp index c03d371..58bf365 100644 --- a/sane/DlgIndicator.cpp +++ b/sane/DlgIndicator.cpp @@ -64,7 +64,7 @@ BOOL dlg_indicator::handle_message(UINT msg, WPARAM wp, LPARAM lp) ret = FALSE; break; case WM_SCAN_WORKING: - notify_ui_event(UI_EVENT_SCAN_WORKING); + notify_ui_event(SANE_EVENT_WORKING); break; case WM_SCAN_FINISHED: if (lp) @@ -117,7 +117,7 @@ void dlg_indicator::handle_command(WORD code, WORD id, HANDLE ctrl) } void dlg_indicator::notify_over(bool cancel) { - notify_ui_event(cancel ? UI_EVENT_CLOSE_CANCEL : UI_EVENT_CLOSE_NORMAL); + notify_ui_event(cancel ? SANE_EVENT_UI_CLOSE_CANCEL : SANE_EVENT_SCAN_FINISHED); } HWND dlg_indicator::window(void) @@ -128,25 +128,6 @@ HWND dlg_indicator::parent(void) { return parent_; } -void dlg_indicator::show() -{ - RECT rp, r; - - if (IsWindow(parent_)) - GetWindowRect(parent_, &rp); - else - GetWindowRect(GetDesktopWindow(), &rp); - GetWindowRect(hwnd_, &r); - - rp.left += (rp.right - rp.left - (r.right - r.left)) / 2; - rp.top += (rp.bottom - rp.top - (r.bottom - r.top)) / 2; - SetWindowPos(hwnd_, HWND_TOPMOST, rp.left, rp.top, r.right - r.left, r.bottom - r.top, SWP_NOSIZE | SWP_SHOWWINDOW); - UpdateWindow(hwnd_); -} -void dlg_indicator::hide(void) -{ - ShowWindow(hwnd_, SW_HIDE); -} void dlg_indicator::notify_data_arrived(bool image) { PostMessage(hwnd_, image ? WM_IMAGE_RECEIVED : WM_USB_PACKET_RECEIVED, 0, 0); diff --git a/sane/DlgIndicator.h b/sane/DlgIndicator.h index 789d232..8e51841 100644 --- a/sane/DlgIndicator.h +++ b/sane/DlgIndicator.h @@ -24,8 +24,6 @@ public: public: HWND window(void); HWND parent(void); - void show(void); - void hide(void); void notify_data_arrived(bool image); void notify_scan_over(const char* msg, bool err); void notify_working(void); diff --git a/sane/DlgPage.cpp b/sane/DlgPage.cpp index 69caa78..7d2376e 100644 --- a/sane/DlgPage.cpp +++ b/sane/DlgPage.cpp @@ -31,8 +31,13 @@ dlg_base::dlg_base(HWND parent, UINT idd) : parent_(parent), hwnd_(NULL), idd_(i } dlg_base::~dlg_base() { - if(IsWindow(hwnd_)) - DestroyWindow(hwnd_); + if (IsWindow(hwnd_)) + { + //if (GetCurrentThreadId() == GetWindowThreadProcessId(hwnd_, NULL)) + DestroyWindow(hwnd_); + } + EnableWindow(parent_, TRUE); + BringWindowToTop(parent_); } BOOL CALLBACK dlg_base::dlg_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) @@ -44,12 +49,21 @@ BOOL CALLBACK dlg_base::dlg_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) SetPropW(hwnd, dlg_base::prop_name.c_str(), (HANDLE)obj); obj->hwnd_ = hwnd; } + else if (msg == WM_DESTROY) + { + dlg_base* obj = (dlg_base*)GetPropW(hwnd, dlg_base::prop_name.c_str()); + SetPropW(hwnd, dlg_base::prop_name.c_str(), NULL); + + return FALSE; + } dlg_base *obj = (dlg_base*)GetPropW(hwnd, dlg_base::prop_name.c_str()); BOOL ret = FALSE; if (obj) + { ret = obj->handle_message(msg, wp, lp); + } return ret; } @@ -101,7 +115,7 @@ void dlg_base::create(void) { hwnd_ = CreateDialogParamW(g_my_inst, MAKEINTRESOURCE(idd_), parent_, &dlg_base::dlg_proc, (LPARAM)this); } -void dlg_base::notify_ui_event(ui_event ev) +void dlg_base::notify_ui_event(int ev) { if (ui_event_notify_) ui_event_notify_(ev, this, ui_notify_param_); @@ -115,7 +129,7 @@ gb::sane_config* dlg_base::get_config(void) return cfg; } -void dlg_base::set_ui_event_notify(void(__stdcall* notify)(ui_event, void*, void*), void* param) +void dlg_base::set_ui_event_notify(void(__stdcall* notify)(int, void*, void*), void* param) { ui_event_notify_ = notify; ui_notify_param_ = param; @@ -163,11 +177,12 @@ void dlg_base::show(bool visible) pt.y = r0.bottom - RECT_H(rme); if (pt.y < r0.top) pt.y = r0.top; - SetWindowPos(hwnd_, HWND_TOPMOST, pt.x, pt.y, RECT_W(rme), RECT_H(rme), SWP_NOSIZE); + SetWindowPos(hwnd_, HWND_TOP, pt.x, pt.y, RECT_W(rme), RECT_H(rme), SWP_NOSIZE); UpdateWindow(hwnd_); } } ShowWindow(hwnd_, cmd); + EnableWindow(parent_, !visible); } void dlg_base::enable(bool enable) { diff --git a/sane/DlgPage.h b/sane/DlgPage.h index cd6c283..d7a769b 100644 --- a/sane/DlgPage.h +++ b/sane/DlgPage.h @@ -13,13 +13,6 @@ #define WM_REFRESH_OPTION WM_USER + 111 // WPARAM: source option SN, LPARAM: unused now #define WM_GET_CONFIG_OBJ WM_USER + 112 // WPARAM: not use, LPARAM: to receive the gb::sane_config* object -enum ui_event -{ - UI_EVENT_CLOSE_NORMAL = 0, - UI_EVENT_CLOSE_CANCEL, - UI_EVENT_BEGIN_SCANNING, // setting ui notify button 'scan' clicked - UI_EVENT_SCAN_WORKING, // scanner thread notify working -}; extern HMODULE g_my_inst; namespace gb @@ -33,7 +26,7 @@ protected: HWND hwnd_; HWND parent_; UINT idd_; - void(__stdcall* ui_event_notify_)(ui_event uev, void* sender, void* param); + void(__stdcall* ui_event_notify_)(int uev, void* sender, void* param); void* ui_notify_param_; static std::wstring prop_name; static BOOL CALLBACK dlg_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp); @@ -41,7 +34,7 @@ protected: virtual BOOL handle_message(UINT msg, WPARAM wp, LPARAM lp); virtual void on_font_changed(void); void create(void); - void notify_ui_event(ui_event ev); + void notify_ui_event(int ev); gb::sane_config* get_config(void); public: @@ -52,7 +45,7 @@ public: static bool get_max_size(SIZE& dst, int cx, int cy); // return whether changed dst public: - void set_ui_event_notify(void(__stdcall* notify)(ui_event, void*, void*), void* param); + void set_ui_event_notify(void(__stdcall* notify)(int, void*, void*), void* param); HWND hwnd(void); void show(bool visible); void enable(bool enable); diff --git a/sane/DlgSetting.cpp b/sane/DlgSetting.cpp index 5dc8e53..cf8876f 100644 --- a/sane/DlgSetting.cpp +++ b/sane/DlgSetting.cpp @@ -95,13 +95,13 @@ void dlg_setting::handle_command(WORD code, WORD id, HANDLE ctrl) } else if (id == IDC_BUTTON_SCAN) { - enable(false); - notify_ui_event(UI_EVENT_BEGIN_SCANNING); + // enable(false); + notify_ui_event(SANE_EVENT_UI_SCAN_COMMAND); } } void dlg_setting::notify_over(void) { - notify_ui_event(UI_EVENT_CLOSE_NORMAL); + notify_ui_event(SANE_EVENT_UI_CLOSE_NORMAL); } void dlg_setting::on_init_dialog(void) { @@ -380,19 +380,8 @@ void dlg_setting::hide(void) { ShowWindow(hwnd_, SW_HIDE); } -void dlg_setting::notify_data_arrived(bool image) +void dlg_setting::notify_scan_over(void) { - PostMessage(hwnd_, image ? WM_IMAGE_RECEIVED : WM_USB_PACKET_RECEIVED, 0, 0); -} -void dlg_setting::notify_scan_over(const char* msg, bool err) -{ - std::string* mstr(new std::string(msg ? msg : "")); - - err_ = err; - if (!PostMessage(hwnd_, WM_SCAN_FINISHED, (WPARAM)mstr, (LPARAM)err)) - { - delete mstr; - notify_over(); - } + enable(true); } // CDlgIndicator 消息处理程序 diff --git a/sane/DlgSetting.h b/sane/DlgSetting.h index da7221c..d81fc79 100644 --- a/sane/DlgSetting.h +++ b/sane/DlgSetting.h @@ -60,6 +60,5 @@ public: HWND parent(void); //void show(void); void hide(void); - void notify_data_arrived(bool image); - void notify_scan_over(const char* msg, bool err); + void notify_scan_over(void); }; diff --git a/sane/s2t_api.h b/sane/s2t_api.h index 19a2f33..710c9e9 100644 --- a/sane/s2t_api.h +++ b/sane/s2t_api.h @@ -148,7 +148,7 @@ __declspec(novtable) struct ISaneInvoker : public IRef { COM_API_DECLARE(int, start(void)); COM_API_DECLARE(int, stop(void)); - COM_API_DECLARE(void, set_event_callback(void(*cb)(int ev_type, void* data, unsigned int* len, void* param), void* param)); + COM_API_DECLARE(int, get_event(void)); COM_API_DECLARE(bool, wait_image(DWORD milliseconds = -1)); COM_API_DECLARE(int, get_scanned_images(DWORD milliseconds = 0)); COM_API_DECLARE(IScanImg*, take_first_image(twain_xfer xfer = TWAIN_XFER_Native)); // call 'release' on returned value, plz @@ -258,7 +258,7 @@ __declspec(novtable) struct ISaneInvoker : public IRef // ui ... COM_API_DECLARE(bool, ui_show_main(HWND parent)); - COM_API_DECLARE(bool, ui_show_setting(HWND parent, bool with_scan)); + COM_API_DECLARE(bool, ui_show_setting(HWND parent, bool with_scan, bool indicator = true)); COM_API_DECLARE(bool, ui_show_progress(HWND parent)); COM_API_DECLARE(void, ui_hide(void)); COM_API_DECLARE(bool, ui_is_ok(void)); diff --git a/sane/scanned_img.cpp b/sane/scanned_img.cpp index 2e2240e..11706fa 100644 --- a/sane/scanned_img.cpp +++ b/sane/scanned_img.cpp @@ -719,57 +719,36 @@ safe_img_queue::~safe_img_queue() clear(); } -size_t safe_img_queue::count(void) +void __stdcall safe_img_queue::access_image(scanned_img* img) { - std::lock_guard lock(que_lock_); - - return queue_.size(); + img->add_ref(); } -bool safe_img_queue::save(scanned_img* img) +void __stdcall safe_img_queue::free_image(scanned_img* img) { - std::lock_guard lock(que_lock_); - - queue_.push_back(img); - - return true; + img->release(); } + bool safe_img_queue::get_header(SANE_Parameters* header, size_t* bytes) { - std::lock_guard lock(que_lock_); - bool ok = false; + scanned_img *img = take(false, &safe_img_queue::access_image); + bool ok = false; if (bytes) *bytes = 0; - if (queue_.size()) + if (img) { if(header) - queue_[0]->copy_header(header); + img->copy_header(header); if(bytes) - *bytes = queue_[0]->bytes(); + *bytes = img->bytes(); ok = true; + img->release(); } return ok; } -scanned_img* safe_img_queue::take(void) -{ - std::lock_guard lock(que_lock_); - scanned_img* img = NULL; - - if (queue_.size()) - { - img = queue_[0]; - queue_.erase(queue_.begin()); - } - - return img; -} void safe_img_queue::clear() { - std::lock_guard lock(que_lock_); - - for (size_t i = 0; i < queue_.size(); ++i) - queue_[i]->release(); - queue_.clear(); + safe_queue::clear(&safe_img_queue::free_image); } diff --git a/sane/scanned_img.h b/sane/scanned_img.h index f9abe7f..4e87131 100644 --- a/sane/scanned_img.h +++ b/sane/scanned_img.h @@ -98,20 +98,73 @@ public: COM_API_OVERRIDE(void, copy_header(SANE_Parameters* head)); }; -class safe_img_queue +template +class safe_queue { - std::mutex que_lock_; - std::vector queue_; + std::mutex lock_; + std::vector queue_; + +public: + safe_queue() + {} + virtual ~safe_queue() + {} + +public: + size_t count(void) + { + std::lock_guard lock(lock_); + + return queue_.size(); + } + bool save(T v) + { + std::lock_guard lock(lock_); + + queue_.push_back(v); + + return true; + } + T take(bool remove = true, void(__stdcall* first)(T) = NULL) + { + std::lock_guard lock(lock_); + T t = 0; + + if (queue_.size()) + { + t = queue_[0]; + if(remove) + queue_.erase(queue_.begin()); + if (first) + first(t); + } + + return t; + } + void clear(void(__stdcall* tfree)(T) = NULL) + { + std::lock_guard lock(lock_); + + if (tfree) + { + for (auto& v : queue_) + tfree(v); + } + queue_.clear(); + } +}; + +class safe_img_queue : public safe_queue +{ + static void __stdcall access_image(scanned_img* img); + static void __stdcall free_image(scanned_img* img); public: safe_img_queue(); ~safe_img_queue(); public: - size_t count(void); - bool save(scanned_img* img); bool get_header(SANE_Parameters* header, size_t* bytes = NULL); - scanned_img* take(void); void clear(); }; diff --git a/sane/scanner.cpp b/sane/scanner.cpp index 5736d09..84f6fa5 100644 --- a/sane/scanner.cpp +++ b/sane/scanner.cpp @@ -78,7 +78,7 @@ namespace callback std::vector::iterator it = std::find(g_scanner_instances.begin(), g_scanner_instances.end(), hdev); if (it != g_scanner_instances.end()) - return it->invoker->handle_event(code, data, len); + return it->invoker->handle_device_event(code, data, len); else return 0; } @@ -109,8 +109,8 @@ namespace callback ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // class scanner scanner::scanner(SCANNERID id) : handle_(NULL), id_(id), ex_id_(EXTENSION_ID_BASE), prev_start_result_(SCANNER_ERR_NOT_START) - , dpi_(200), tmp_path_(L""), img_ind_(0), cb_invoker_(NULL), cb_param_(NULL), working_(false) - , ui_quit_(true), scanner_name_(L""), cfg_(NULL) + , dpi_(200), tmp_path_(L""), img_ind_(0) + , scanner_name_(L""), cfg_(NULL) { cfg_ = new gb::sane_config(); tmp_path_ = local_trans::a2u(hg_sane_middleware::sane_path().c_str()); @@ -190,9 +190,9 @@ float __stdcall scanner::to_float(SANE_Fixed v) { return SANE_UNFIX(v); } -void __stdcall scanner::ui_callback(ui_event uev, void* sender, void* param) +void __stdcall scanner::ui_callback(int uev, void* sender, void* param) { - ((scanner*)param)->on_ui_quit(uev, sender); + ((scanner*)param)->on_ui_event(uev, sender); } // IRef @@ -244,46 +244,9 @@ void scanner::apply_config(void) } while (cfg_->next_config(t, v)); } } -void scanner::on_ui_quit(ui_event uev, void* sender) +void scanner::on_ui_event(int uev, void* sender) { - switch (uev) - { - case UI_EVENT_CLOSE_CANCEL: // post from indicator - stop(); - case UI_EVENT_CLOSE_NORMAL: // post from indicator & dlg_setting - if (/*sender == indicator_.get() &&*/ setting_.get()) - { - setting_->hide(); - setting_.reset(); - } - /*else*/ if (/*sender == setting_.get() &&*/ indicator_.get()) - { - indicator_->hide(); - indicator_.reset(); - } - ui_quit_ = true; - break; - case UI_EVENT_BEGIN_SCANNING: // post from dlg_setting, so we show indicator ... - if (start() == SANE_STATUS_GOOD) - { - if (indicator_.get()) - { - indicator_->show(); - return; - } - } - else - { - setting_->enable(true); - return; - } - case UI_EVENT_SCAN_WORKING: - break; - default: - break; - } - if (cb_invoker_) - cb_invoker_(ui_quit_ ? SANE_EVENT_SCAN_FINISHED : SANE_EVENT_WORKING, NULL, NULL, cb_param_); + events_.save(uev); } int scanner::open(void) { @@ -1583,7 +1546,10 @@ COM_API_IMPLEMENT(scanner, int, start(void)) scan_msg_ = "OK"; scan_err_ = false; - hg_sane_middleware::instance()->start(handle_, NULL); + ret = hg_sane_middleware::instance()->start(handle_, NULL); + + if (indicator_.get() && !IsWindowVisible(indicator_->hwnd())) + indicator_->show(true); // the third-APPs in linux will call 'stop' after every start, but it not happens in windows-apps, so we handle this as following ... if(ret == SANE_STATUS_NO_DOCS && prev_start_result_ == SANE_STATUS_GOOD) @@ -1596,7 +1562,6 @@ COM_API_IMPLEMENT(scanner, int, start(void)) if (hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_FINAL_IMAGE_FORMAT, &img_fmt_, &l)) img_fmt_.img_format = SANE_IMAGE_TYPE_BMP; img_fmt_.compress.compression = cmprsn; - working_ = true; } prev_start_result_ = ret; @@ -1604,13 +1569,11 @@ COM_API_IMPLEMENT(scanner, int, start(void)) } COM_API_IMPLEMENT(scanner, int, stop(void)) { - working_ = false; return hg_sane_middleware::instance()->stop(handle_); } -COM_API_IMPLEMENT(scanner, void, set_event_callback(void(*cb)(int ev_type, void* data, unsigned int* len, void* param), void* param)) +COM_API_IMPLEMENT(scanner, int, get_event(void)) { - cb_invoker_ = cb; - cb_param_ = param; + return events_.take(); } COM_API_IMPLEMENT(scanner, bool, wait_image(DWORD milliseconds)) { @@ -1621,7 +1584,7 @@ COM_API_IMPLEMENT(scanner, bool, wait_image(DWORD milliseconds)) COM_API_IMPLEMENT(scanner, int, get_scanned_images(DWORD milliseconds)) { size_t count = images_.count(); - bool notify = true; + DWORD elapse = 10; while (count == 0 && milliseconds) { @@ -1631,24 +1594,33 @@ COM_API_IMPLEMENT(scanner, int, get_scanned_images(DWORD milliseconds)) TranslateMessage(&msg); DispatchMessageW(&msg); } - Sleep(10); - if (!working_) - { - if (notify && indicator_.get()) - { - notify = false; - indicator_->notify_scan_over(scan_msg_.c_str(), scan_err_); // Ending by UI - } - else if(ui_quit_) - break; - } + Sleep(elapse); + + int ev = get_event(); + count = images_.count(); + if (ev == SANE_EVENT_SCAN_FINISHED) + { + ui_hide(); + break; + } + else if (ev == SANE_EVENT_UI_CLOSE_CANCEL) + { + stop(); + ui_hide(); + break; + } + else if (ev == SANE_EVENT_UI_CLOSE_NORMAL) + { + ui_hide(); + break; + } if (milliseconds != -1) { - if (milliseconds <= 10) + if (milliseconds <= elapse) break; - milliseconds -= 10; + milliseconds -= elapse; } } @@ -1992,7 +1964,7 @@ COM_API_IMPLEMENT(scanner, bool, ui_show_main(HWND parent)) { return false; } -COM_API_IMPLEMENT(scanner, bool, ui_show_setting(HWND parent, bool with_scan)) +COM_API_IMPLEMENT(scanner, bool, ui_show_setting(HWND parent, bool with_scan, bool indicator)) { SANEAPI api = { NULL }; @@ -2014,15 +1986,13 @@ COM_API_IMPLEMENT(scanner, bool, ui_show_setting(HWND parent, bool with_scan)) setting_->set_ui_event_notify(&scanner::ui_callback, this); setting_->set_config(cfg_, (cfg_path_ + scanner_name_).c_str()); cfg_->begin_setting(); - if (with_scan) + indicator_.reset(); + if (indicator) { - indicator_.reset(new dlg_indicator(parent)); + indicator_.reset(new dlg_indicator(setting_->hwnd())); indicator_->set_ui_event_notify(&scanner::ui_callback, this); } - else - indicator_.reset(); setting_->show(true); - ui_quit_ = false; return true; } @@ -2030,8 +2000,7 @@ COM_API_IMPLEMENT(scanner, bool, ui_show_progress(HWND parent)) { indicator_.reset(new dlg_indicator(parent)); indicator_->set_ui_event_notify(&scanner::ui_callback, this); - indicator_->show(); - ui_quit_ = false; + indicator_->show(true); return true; } @@ -2050,12 +2019,14 @@ COM_API_IMPLEMENT(scanner, bool, ui_is_ok(void)) // called from device-layer ... -int scanner::handle_event(int ev_code, void* data, unsigned int* len) +int scanner::handle_device_event(int ev_code, void* data, unsigned int* len) { if (ev_code == SANE_EVENT_WORKING) { if (indicator_.get()) indicator_->notify_working(); + else + events_.save(ev_code); } else if (ev_code == SANE_EVENT_IMAGE_OK) { @@ -2068,29 +2039,25 @@ int scanner::handle_event(int ev_code, void* data, unsigned int* len) if (img->bytes() /*>= simg->bytes*/) { images_.save(img); - if (cb_invoker_) // added for notify twain-app XferReady ... - cb_invoker_(ev_code, NULL, NULL, cb_param_); } else { img->release(); } - if (indicator_) + if (indicator_.get()) indicator_->notify_data_arrived(true); } else if (ev_code == SANE_EVENT_USB_DATA_RECEIVED) { - if (indicator_) + if (indicator_.get()) indicator_->notify_data_arrived(false); } else if (ev_code == SANE_EVENT_SCAN_FINISHED) { if (indicator_.get()) - { - scan_msg_ = (char*)data; - scan_err_ = *len != SCANNER_ERR_OK; - } - working_ = false; + indicator_->notify_scan_over((char*)data, *len != SCANNER_ERR_OK); + else + events_.save(ev_code); } return 0; diff --git a/sane/scanner.h b/sane/scanner.h index f2490a1..fef8e14 100644 --- a/sane/scanner.h +++ b/sane/scanner.h @@ -34,8 +34,6 @@ class scanner : public ISaneInvoker, virtual public refer SANE_Handle handle_; SCANNERID id_; int err_; - void(*cb_invoker_)(int ev_type, void* data, unsigned int* len, void* param); - void* cb_param_; int ex_id_; int prev_start_result_; int dpi_; @@ -47,8 +45,7 @@ class scanner : public ISaneInvoker, virtual public refer bool scan_err_; twain_xfer xfer_; safe_img_queue images_; - volatile bool working_; - bool ui_quit_; + safe_queue events_; //如果有界面,则全部保存从界面传回的消息;否则只保存开始扫描和结束扫描的事件 SANE_FinalImgFormat img_fmt_; std::unique_ptr indicator_; std::unique_ptr setting_; @@ -57,7 +54,7 @@ class scanner : public ISaneInvoker, virtual public refer void load_config(const wchar_t* file); void save_config(const wchar_t* file); void apply_config(void); - void on_ui_quit(ui_event uev, void* sender); + void on_ui_event(int uev, void* sender); int open(void); int close(void); int init_options_id(void); @@ -175,7 +172,7 @@ class scanner : public ISaneInvoker, virtual public refer static int __stdcall to_int(SANE_Int v); static float __stdcall to_float(SANE_Fixed v); - static void __stdcall ui_callback(ui_event uev, void* sender, void* param); + static void __stdcall ui_callback(int uev, void* sender, void* param); public: scanner(SCANNERID id); @@ -196,7 +193,7 @@ public: public: COM_API_OVERRIDE(int, start(void)); COM_API_OVERRIDE(int, stop(void)); - COM_API_OVERRIDE(void, set_event_callback(void(*cb)(int ev_type, void* data, unsigned int* len, void* param), void* param)); + COM_API_OVERRIDE(int, get_event(void)); COM_API_OVERRIDE(bool, wait_image(DWORD milliseconds = -1)); COM_API_OVERRIDE(int, get_scanned_images(DWORD milliseconds = 0)); COM_API_OVERRIDE(IScanImg*, take_first_image(twain_xfer xfer = TWAIN_XFER_Native)); // call 'release' on returned value, plz @@ -294,7 +291,7 @@ public: // ui ... COM_API_OVERRIDE(bool, ui_show_main(HWND parent)); - COM_API_OVERRIDE(bool, ui_show_setting(HWND parent, bool with_scan)); + COM_API_OVERRIDE(bool, ui_show_setting(HWND parent, bool with_scan, bool indicator = true)); COM_API_OVERRIDE(bool, ui_show_progress(HWND parent)); COM_API_OVERRIDE(void, ui_hide(void)); COM_API_OVERRIDE(bool, ui_is_ok(void)); @@ -307,5 +304,5 @@ public: // methods: public: - int handle_event(int ev_code, void* data, unsigned int* len); + int handle_device_event(int ev_code, void* data, unsigned int* len); }; \ No newline at end of file diff --git a/twain/twain/huagaods.cpp b/twain/twain/huagaods.cpp index 6b50c48..00b03b2 100644 --- a/twain/twain/huagaods.cpp +++ b/twain/twain/huagaods.cpp @@ -126,6 +126,11 @@ enum CapTypeEx : unsigned short { // END for SANE豸ԭʼ͸ ///////////////////////////////////////////////////////////////////////// }; +enum // .twain/first.cfg: [twain-app] flow=0 +{ + TWAIN_APP_TRANSFER_NORMAL = 0, // first get head and then bits + TWAIN_APP_TRANSFER_REVERSE, // first get bits and then head +}; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -618,10 +623,6 @@ void huagao_ds::showmsg(const char* msg, int err) { ShellExecuteA(NULL, "open", huagao_ds::get_hidedlg_path().c_str(), msg, NULL, SW_HIDE); } -void huagao_ds::scan_event(int sane_event, void* data, unsigned int* len, void* param) -{ - ((huagao_ds*)param)->on_scan_event(sane_event, data, len); -} const Identity& huagao_ds::defaultIdentity() noexcept { // remember, we return a reference, therefore the identity must not be placed on the stack of this method @@ -709,6 +710,25 @@ Result huagao_ds::eventProcess(const Identity&, Event& event) { const MSG* msg = (const MSG*)event.event(); // event.setMessage(Msg::Null); + if (scanner_.get()) + { + switch (scanner_->get_event()) + { + case SANE_EVENT_WORKING: + notifyXferReady(); + break; + case SANE_EVENT_UI_CLOSE_CANCEL: + scanner_->stop(); + notifyEndWithoutImages(); + case SANE_EVENT_UI_CLOSE_NORMAL: + scanner_->ui_hide(); + notifyCloseOk(); + break; + case SANE_EVENT_UI_SCAN_COMMAND: + scanner_->start(); + break; + } + } return { ReturnCode::NotDsEvent, ConditionCode::Success }; } @@ -763,7 +783,13 @@ Result huagao_ds::identityOpenDs(const Identity& id) return { ReturnCode::Failure, huagao_ds::condition_code_from_hg_error(err) }; } // ui_.reset(new twain_ui(local_utility::reg_get_app_installing_path().c_str())); - scanner_->set_event_callback(&huagao_ds::scan_event, this); + if (get_config_number(L"twain-app", L"flow") == TWAIN_APP_TRANSFER_REVERSE) + { + cur_head_ = new SANE_Parameters; + memset(cur_head_, 0, sizeof(SANE_Parameters)); + } + + m_compression = Compression::None; init_support_caps(); m_fileXfer.setFormat(ImageFileFormat::Bmp); @@ -846,7 +872,8 @@ Result huagao_ds::setupMemXferGet(const Identity& id, SetupMemXfer& data) } Result huagao_ds::userInterfaceDisable(const Identity&, UserInterface& ui) { - scanner_->ui_hide(); + if (scanner_.get()) + scanner_->stop(); return success(); } @@ -854,8 +881,6 @@ Result huagao_ds::userInterfaceEnable(const Identity&, UserInterface& ui) { if (!ui.showUi()) { - bool xfer_ready = !m_bIndicator; - if (m_bIndicator && !scanner_->ui_show_progress((HWND)ui.parent().raw())) return seqError(); @@ -863,14 +888,11 @@ Result huagao_ds::userInterfaceEnable(const Identity&, UserInterface& ui) if (scanner_->start() == SCANNER_ERR_OK) { - if (xfer_ready) - notifyXferReady(); - return success(); } else { - return seqError(); + return bummer(); } } @@ -897,7 +919,10 @@ Result huagao_ds::imageInfoGet(const Identity&, ImageInfo& data) else { if (!scanner_->wait_image()) + { + notifyCloseOk(); return bummer(); + } ok = scanner_->get_first_image_header(&head); } @@ -914,7 +939,10 @@ Result huagao_ds::imageInfoGet(const Identity&, ImageInfo& data) data.bitsPerSample()[0] = 8; } data.setHeight(head.lines); - data.setPixelType(head.format == SANE_FRAME_RGB ? PixelType::Rgb : PixelType::Gray); + if (m_compression == Compression::Group4) + data.setPixelType(PixelType::BlackWhite); + else + data.setPixelType(head.format == SANE_FRAME_RGB ? PixelType::Rgb : PixelType::Gray); data.setPlanar(false); data.setWidth(head.pixels_per_line); @@ -924,7 +952,7 @@ Result huagao_ds::imageInfoGet(const Identity&, ImageInfo& data) data.setYResolution(res); data.compression(m_compression); } - + return success(); } Result huagao_ds::imageLayoutGet(const Identity&, ImageLayout& data) @@ -964,9 +992,18 @@ Result huagao_ds::imageLayoutReset(const Identity& origin, ImageLayout& data) } Result huagao_ds::imageMemXferGet(const Identity& origin, ImageMemXfer& data) { - if (!scanner_.get() || (scanner_->get_scanned_images() == 0 && !pending_xfer_.img)) + if (!scanner_.get()) return seqError(); + if (scanner_->get_scanned_images() == 0 && !pending_xfer_.img) + { + if (!cur_head_ || !scanner_->wait_image()) + { + notifyCloseOk(); + return seqError(); + } + } + IScanImg *img = pending_xfer_.img ? pending_xfer_.img : scanner_->take_first_image(TWAIN_XFER_Memory); unsigned long long off = pending_xfer_.img ? pending_xfer_.off : 0; unsigned char *dst = (unsigned char*)data.memory().data().data(); @@ -1227,7 +1264,7 @@ Result huagao_ds::capCommon(const Identity&, Msg msg, Capability& data) { Twpp::Result huagao_ds::showTwainUI(Twpp::UserInterface& data, bool bUiOnly) { // display user UI ... (setting UI, can we show my own main window here ?) - return scanner_->ui_show_setting((HWND)data.parent().raw(), !bUiOnly) ? success() : seqError(); + return scanner_->ui_show_setting((HWND)data.parent().raw(), !bUiOnly, m_bIndicator) ? success() : seqError(); } void huagao_ds::init_support_caps(void) { @@ -2587,23 +2624,29 @@ void huagao_ds::init_support_caps_ex(void) ADD_SANE_CAP(skew_range); ADD_SANE_CAP(black_white_threshold); } -void huagao_ds::on_scan_event(int sane_event, void* data, unsigned int* len) +std::wstring huagao_ds::get_config_file(void) { - if (scanner_.get()) - { - /*if (sane_event == SANE_EVENT_IMAGE_OK) - { - notifyDeviceEvent(); - } - else*/ if (sane_event == SANE_EVENT_SCAN_FINISHED) - { - notifyCloseCancel(); - } - else if (sane_event == SANE_EVENT_WORKING) - { - notifyXferReady(); - } - } + wchar_t path[MAX_PATH] = { 0 }, * name = NULL; + + GetModuleFileNameW(me_, path, _countof(path) - 1); + name = wcsrchr(path, L'\\'); + if (name++ == NULL) + name = path; + wcscpy_s(name, _countof(path) - 1 - (name - path), L"first.cfg"); + + return path; +} +std::wstring huagao_ds::get_config_value(const wchar_t* sec, const wchar_t* key) +{ + wchar_t v[256] = { 0 }; + + GetPrivateProfileStringW(sec, key, L"", v, _countof(v) - 1, get_config_file().c_str()); + + return v; +} +DWORD huagao_ds::get_config_number(const wchar_t* sec, const wchar_t* key) +{ + return GetPrivateProfileIntW(sec, key, 0, get_config_file().c_str()); } diff --git a/twain/twain/huagaods.hpp b/twain/twain/huagaods.hpp index eff091a..18a5d2a 100644 --- a/twain/twain/huagaods.hpp +++ b/twain/twain/huagaods.hpp @@ -44,14 +44,15 @@ class huagao_ds : public Twpp::SourceFromThis { static std::string get_hidedlg_path(void); static void showmsg(const char* msg, int err); - static void scan_event(int sane_event, void* data, unsigned int* len, void* param); void CapabilityPrintf(Twpp::Msg msg, std::string capability, std::string value = ""); Twpp::Result capCommon(const Twpp::Identity& origin, Twpp::Msg msg, Twpp::Capability& data); Twpp::Result showTwainUI(Twpp::UserInterface& data, bool bUiOnly = false); void init_support_caps(void); void init_support_caps_ex(void); - void on_scan_event(int sane_event, void* data, unsigned int* len); + std::wstring get_config_file(void); + std::wstring get_config_value(const wchar_t* sec, const wchar_t* key); + DWORD get_config_number(const wchar_t* sec, const wchar_t* key); typedef struct _pending_xfer { diff --git a/twain/twain/twpp/datasource.hpp b/twain/twain/twpp/datasource.hpp index cfbf81b..85d82bb 100644 --- a/twain/twain/twpp/datasource.hpp +++ b/twain/twain/twpp/datasource.hpp @@ -302,6 +302,11 @@ namespace Twpp { return notifyApp(Msg::XferReady); } + /// Notifies application scanning complete with no image got - added on 2022-07-02 + ReturnCode notifyEndWithoutImages() noexcept { + return notifyApp(Msg::Null); + } + /// Root of source TWAIN calls. @@ -1185,8 +1190,8 @@ namespace Twpp { if (Twpp::success(rc) || rc == ReturnCode::CheckStatus) { if (inState(DsState::Open)) { // allow userInterfaceEnable to transfer to higher states setState(DsState::Enabled); - if(!data.showUi()) - notifyXferReady(); + //if(!data.showUi()) + // notifyXferReady(); } }