diff --git a/sane/scanner.cpp b/sane/scanner.cpp index bfa10a5..2cfeaeb 100644 --- a/sane/scanner.cpp +++ b/sane/scanner.cpp @@ -21,6 +21,8 @@ #pragma comment(lib, "Shlwapi.lib") +#define START_SCAN_IN_THREAD + static IMPLEMENT_OPTION_STRING_COMPARE(compare_sane_opt); #define SET_SANE_OPT_ID(id, id_name, name, val, extension) \ @@ -490,6 +492,10 @@ scanner::scanner(SCANNERID id) : handle_(NULL), id_(id), ex_id_(EXTENSION_ID_BAS scanner::~scanner() { close(); + if (thread_starting_.get() && thread_starting_->joinable()) + thread_starting_->join(); + thread_starting_.reset(); + if (cfg_) { cfg_->release(); @@ -1388,6 +1394,67 @@ int scanner::set_is_multiout(bool enable) return ret; } +int scanner::thread_start(void) +{ + int ret = hg_sane_middleware::instance()->start(handle_, NULL); + + // 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) + ret = hg_sane_middleware::instance()->start(handle_, NULL); + + if (ret == SANE_STATUS_GOOD) + { + /*if (indicator_.get() && !IsWindowVisible(indicator_->hwnd())) + indicator_->show(true);*/ + + unsigned int l = sizeof(img_fmt_); + SANE_CompressionType cmprsn = img_fmt_.compress.compression; + 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; + } + //else if (indicator_.get()) + //{ + // indicator_->notify_scan_over(hg_scanner_err_description(ret), true); + //} + else + { + // display error message on progress UI, may be closed immediately by APP, so we hide progress UI and call message_box ... + // + //if (callback::show_progress_ui && is_bIndicator) + //{ + // int ev = SANE_EVENT_WORKING; + // + //// on_ui_event(ev, (void*)ev); + // ui_notify(SANE_EVENT_SCAN_FINISHED, (void *)hg_scanner_err_description(ret), ret); + //} + //else + { + if (callback::close_ui) + callback::close_ui(UI_INDICATOR); + + if (callback::show_messagebox_ui) + { + callback::show_messagebox_ui(app_wnd_, ret, (void*)hg_scanner_err_description(ret), 0); + } + else + { + std::wstring msg(local_trans::a2u(hg_scanner_err_description(ret), CP_UTF8)); + + //if (indicator_.get()) + // indicator_->show(false); + if (!IsWindow(app_wnd_)) + callback::bring_message_box_topmost(local_trans::lang_trans_between_hz936(CONST_STRING_START_FAILED).c_str()); + MessageBoxW(app_wnd_, msg.c_str(), local_trans::lang_trans_between_hz936(CONST_STRING_START_FAILED).c_str(), MB_OK | MB_ICONERROR); + } + } + is_scanning_ = false; + } + prev_start_result_ = ret; + + return ret; +} + scanner::EXAPIPOS scanner::find_ex_api(int op_id) { return std::find(ex_opts_.begin(), ex_opts_.end(), op_id); @@ -2452,64 +2519,18 @@ COM_API_IMPLEMENT(scanner, int, start(void)) scan_err_ = false; user_cancel_ = false; fetch_imgs_ = 0; + is_scanning_ = true; app_wnd_ = setting_.get() ? setting_->hwnd() : callback::find_main_wnd(); - ret = hg_sane_middleware::instance()->start(handle_, NULL); - // 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) - ret = hg_sane_middleware::instance()->start(handle_, NULL); + if (thread_starting_.get() && thread_starting_->joinable()) + thread_starting_->join(); +#ifdef START_SCAN_IN_THREAD + thread_starting_.reset(new std::thread(&scanner::thread_start, this)); +#else + ret = thread_start(); +#endif - if (ret == SANE_STATUS_GOOD) - { - /*if (indicator_.get() && !IsWindowVisible(indicator_->hwnd())) - indicator_->show(true);*/ - - unsigned int l = sizeof(img_fmt_); - SANE_CompressionType cmprsn = img_fmt_.compress.compression; - 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; - } - //else if (indicator_.get()) - //{ - // indicator_->notify_scan_over(hg_scanner_err_description(ret), true); - //} - else - { - // display error message on progress UI, may be closed immediately by APP, so we hide progress UI and call message_box ... - // - //if (callback::show_progress_ui && is_bIndicator) - //{ - // int ev = SANE_EVENT_WORKING; - // - //// on_ui_event(ev, (void*)ev); - // ui_notify(SANE_EVENT_SCAN_FINISHED, (void *)hg_scanner_err_description(ret), ret); - //} - //else - { - if (callback::close_ui) - callback::close_ui(UI_INDICATOR); - - if (callback::show_messagebox_ui) - { - callback::show_messagebox_ui(app_wnd_, ret, (void*)hg_scanner_err_description(ret), 0); - } - else - { - std::wstring msg(local_trans::a2u(hg_scanner_err_description(ret), CP_UTF8)); - - //if (indicator_.get()) - // indicator_->show(false); - if (!IsWindow(app_wnd_)) - callback::bring_message_box_topmost(local_trans::lang_trans_between_hz936(CONST_STRING_START_FAILED).c_str()); - MessageBoxW(app_wnd_, msg.c_str(), local_trans::lang_trans_between_hz936(CONST_STRING_START_FAILED).c_str(), MB_OK | MB_ICONERROR); - } - } - } - prev_start_result_ = ret; - is_scanning_ = ret == SANE_STATUS_GOOD; - - return local_utility::sane_statu_2_scanner_err(ret); + return ret; } COM_API_IMPLEMENT(scanner, int, stop(void)) { diff --git a/sane/scanner.h b/sane/scanner.h index 79a3699..4eb4f1f 100644 --- a/sane/scanner.h +++ b/sane/scanner.h @@ -104,6 +104,9 @@ class scanner : public ISaneInvoker, virtual public refer int set_option_value(int sn, SANE_Value_Type type, int size, void* data); int set_is_multiout(bool enable); + int thread_start(void); + std::unique_ptr thread_starting_; + typedef struct _ex_api { unsigned int ind;