This commit is contained in:
13038267101 2023-03-28 15:54:08 +08:00
commit 5fa741d27d
6 changed files with 444 additions and 69 deletions

View File

@ -545,9 +545,12 @@ void dlg_setting::save_changes_to_cur_scheme(int reason)
if (changed)
{
dlg_save_scheme dlg(hwnd());
std::wstring sug(L"");
sug = local_trans::a2u(twain_schm_->auto_gen_scheme_name(local_trans::lang_trans_between_hz936, nullptr, false).c_str(), CP_UTF8);
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));
, SAVE_METHOD_MASK(SAVE_DISCARD) | SAVE_METHOD_MASK(SAVE_NEW),
sug.c_str());
dlg.do_modal(hwnd());
if(dlg.get_dispose() == SAVE_NEW)
{

View File

@ -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), twain_set_(false)
, max_img_mem_(1 * 1024), twain_set_(false), ev_cnt_(0)
{
cfg_ = new gb::scanner_cfg();
cfg_->set_language_transform(&callback::language_trans, NULL);
@ -624,41 +624,41 @@ void scanner::on_ui_event(int uev, void* sender)
if (indicator)
indicator_.reset();
is_scanning_ = false;
if (err_ && setting_.get())
{
return;
}
is_scanning_ = false;
}
int(__stdcall * h)(int, void*) = scanner_ev_handler_;
if (h)
{
if (SANE_EVENT_UI_CLOSE_SETTING == uev)
{
is_scanning_ = false;
setting_.reset();
}
//int(__stdcall * h)(int, void*) = scanner_ev_handler_;
//if (h)
//{
// if (SANE_EVENT_UI_CLOSE_SETTING == uev)
// {
// is_scanning_ = false;
// setting_.reset();
// }
h(uev, evh_param_);
return;
}
// h(uev, evh_param_);
// return;
//}
if (prev_start_result_ != SANE_STATUS_GOOD && indicator)
indicator_.reset();
else
//if (prev_start_result_ != SANE_STATUS_GOOD && indicator)
// indicator_.reset();
//else
{
if (uev == SANE_EVENT_UI_SCAN_COMMAND)
{
ui_show_progress(NULL);
start();
return;
}
//if (uev == SANE_EVENT_UI_SCAN_COMMAND)
//{
// ui_show_progress(NULL);
// start();
// return;
//}
if (/*events_.count() > 5 && !is_ui_wait_img_ &&*/
(uev == SANE_EVENT_UI_CLOSE_CANCEL || uev == SANE_EVENT_UI_CLOSE_NORMAL || uev == SANE_EVENT_UI_CLOSE_SETTING))
{
events_.clear();
// events_.clear();
ui_hide();
if(indicator || !indicator_.get())
uev = SANE_EVENT_SCAN_FINISHED;
@ -667,6 +667,21 @@ void scanner::on_ui_event(int uev, void* sender)
}
events_.save(uev, sizeof(uev));
ev_cnt_++;
}
if (ev_cnt_ == events_.count() &&
(ev_cnt_ >= 5 || (ev_cnt_ > 1 && !is_scanning_)))
{
// maybe no event has been handled by APP, triggered by callback
int(__stdcall * h)(int, void*) = scanner_ev_handler_;
if (h)
{
wchar_t info[128] = { 0 };
swprintf_s(info, _countof(info) - 1, L"[CRAZY]%d scanner events stored but APP has no action, we try to trigger it ONCE ...\r\n", ev_cnt_);
ev_cnt_--;
h(events_.take(), evh_param_);
}
}
}
std::string scanner::choose_scanner(const std::vector<std::string>& scanners)
@ -2261,6 +2276,7 @@ COM_API_IMPLEMENT(scanner, int, start(void))
{
int ret = SANE_STATUS_GOOD;
ev_cnt_ = 0;
events_.clear();
images_.clear();
scan_msg_ = "OK";

View File

@ -50,6 +50,7 @@ class scanner : public ISaneInvoker, virtual public refer
safe_img_queue images_;
size_t max_img_mem_;
safe_queue<int> events_; //如果有界面,则全部保存从界面传回的消息;否则只保存开始扫描和结束扫描的事件
int ev_cnt_;
SANE_FinalImgFormat img_fmt_;
std::unique_ptr<dlg_indicator> indicator_;
std::unique_ptr<dlg_setting> setting_;

View File

@ -181,8 +181,14 @@ namespace load_sane_util
}
void uninitialize(void)
{
sane_inst = NULL;
is_on = NULL;
init = NULL;
log = NULL;
if (uninit)
uninit(NULL);
uninit = NULL;
if (sane_module)
{

View File

@ -161,6 +161,191 @@ TWPP_ENTRY(huagao_ds)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// utilites ...
// some helper functions to handle capability stuff
#define RETURN_ENUM_DESC(en, v, space) \
if(v == space::en) \
return L###en;
const wchar_t* desc_state(DsState s, wchar_t unk[20])
{
RETURN_ENUM_DESC(Closed, s, DsState);
RETURN_ENUM_DESC(Open, s, DsState);
RETURN_ENUM_DESC(Enabled, s, DsState);
RETURN_ENUM_DESC(XferReady, s, DsState);
RETURN_ENUM_DESC(Xferring, s, DsState);
swprintf(unk, L"%d", s);
return unk;
}
const wchar_t* desc_data_group(DataGroup d, wchar_t unk[20])
{
RETURN_ENUM_DESC(Control, d, DataGroup);
RETURN_ENUM_DESC(Image, d, DataGroup);
RETURN_ENUM_DESC(Audio, d, DataGroup);
{
swprintf(unk, L"%d", d);
return unk;
}
}
const wchar_t* desc_data(Dat d, wchar_t unk[20])
{
RETURN_ENUM_DESC(Null, d, Dat);
RETURN_ENUM_DESC(Capability, d, Dat);
RETURN_ENUM_DESC(Event, d, Dat);
RETURN_ENUM_DESC(Identity, d, Dat);
RETURN_ENUM_DESC(Parent, d, Dat);
RETURN_ENUM_DESC(PendingXfers, d, Dat);
RETURN_ENUM_DESC(SetupMemXfer, d, Dat);
RETURN_ENUM_DESC(SetupFileXfer, d, Dat);
RETURN_ENUM_DESC(Status, d, Dat);
RETURN_ENUM_DESC(UserInterface, d, Dat);
RETURN_ENUM_DESC(XferGroup, d, Dat);
RETURN_ENUM_DESC(CustomData, d, Dat);
RETURN_ENUM_DESC(DeviceEvent, d, Dat);
RETURN_ENUM_DESC(FileSystem, d, Dat);
RETURN_ENUM_DESC(PassThrough, d, Dat);
RETURN_ENUM_DESC(Callback, d, Dat);
RETURN_ENUM_DESC(StatusUtf8, d, Dat);
RETURN_ENUM_DESC(Callback2, d, Dat);
RETURN_ENUM_DESC(ImageInfo, d, Dat);
RETURN_ENUM_DESC(ImageLayout, d, Dat);
RETURN_ENUM_DESC(ImageMemXfer, d, Dat);
RETURN_ENUM_DESC(ImageNativeXfer, d, Dat);
RETURN_ENUM_DESC(ImageFileXfer, d, Dat);
RETURN_ENUM_DESC(CieColor, d, Dat);
RETURN_ENUM_DESC(GrayResponse, d, Dat);
RETURN_ENUM_DESC(RgbResponse, d, Dat);
RETURN_ENUM_DESC(JpegCompression, d, Dat);
RETURN_ENUM_DESC(Palette8, d, Dat);
RETURN_ENUM_DESC(ExtImageInfo, d, Dat);
RETURN_ENUM_DESC(Filter, d, Dat);
RETURN_ENUM_DESC(AudioFileXfer, d, Dat);
RETURN_ENUM_DESC(AudioInfo, d, Dat);
RETURN_ENUM_DESC(AudioNativeXfer, d, Dat);
RETURN_ENUM_DESC(IccProfile, d, Dat);
RETURN_ENUM_DESC(ImageMemFileXfer, d, Dat);
RETURN_ENUM_DESC(EntryPoint, d, Dat);
{
swprintf(unk, L"%d", d);
return unk;
}
}
const wchar_t* desc_msg(Msg m, wchar_t unk[20])
{
RETURN_ENUM_DESC(Null, m, Msg);
RETURN_ENUM_DESC(Get, m, Msg);
RETURN_ENUM_DESC(GetCurrent, m, Msg);
RETURN_ENUM_DESC(GetDefault, m, Msg);
RETURN_ENUM_DESC(GetFirst, m, Msg);
RETURN_ENUM_DESC(GetNext, m, Msg);
RETURN_ENUM_DESC(Set, m, Msg);
RETURN_ENUM_DESC(Reset, m, Msg);
RETURN_ENUM_DESC(QuerySupport, m, Msg);
RETURN_ENUM_DESC(GetHelp, m, Msg);
RETURN_ENUM_DESC(GetLabel, m, Msg);
RETURN_ENUM_DESC(GetLabelEnum, m, Msg);
RETURN_ENUM_DESC(SetConstraint, m, Msg);
RETURN_ENUM_DESC(XferReady, m, Msg);
RETURN_ENUM_DESC(CloseDsReq, m, Msg);
RETURN_ENUM_DESC(CloseDsOk, m, Msg);
RETURN_ENUM_DESC(DeviceEvent, m, Msg);
RETURN_ENUM_DESC(OpenDsm, m, Msg);
RETURN_ENUM_DESC(CloseDsm, m, Msg);
RETURN_ENUM_DESC(OpenDs, m, Msg);
RETURN_ENUM_DESC(CloseDs, m, Msg);
RETURN_ENUM_DESC(UserSelect, m, Msg);
RETURN_ENUM_DESC(DisableDs, m, Msg);
RETURN_ENUM_DESC(EnableDs, m, Msg);
RETURN_ENUM_DESC(EnableDsUiOnly, m, Msg);
RETURN_ENUM_DESC(ProcessEvent, m, Msg);
RETURN_ENUM_DESC(EndXfer, m, Msg);
RETURN_ENUM_DESC(StopFeeder, m, Msg);
RETURN_ENUM_DESC(ChangeDir, m, Msg);
RETURN_ENUM_DESC(CreateDir, m, Msg);
RETURN_ENUM_DESC(Delete, m, Msg);
RETURN_ENUM_DESC(FormatMedia, m, Msg);
RETURN_ENUM_DESC(GetClose, m, Msg);
RETURN_ENUM_DESC(GetFirstFile, m, Msg);
RETURN_ENUM_DESC(GetInfo, m, Msg);
RETURN_ENUM_DESC(GetNextFile, m, Msg);
RETURN_ENUM_DESC(Rename, m, Msg);
RETURN_ENUM_DESC(Copy, m, Msg);
RETURN_ENUM_DESC(AutomaticCaptureDir, m, Msg);
RETURN_ENUM_DESC(PassThrough, m, Msg);
RETURN_ENUM_DESC(RegisterCallback, m, Msg);
RETURN_ENUM_DESC(ResetAll, m, Msg);
RETURN_ENUM_DESC(CustomBase, m, Msg);
{
swprintf(unk, L"%d", m);
return unk;
}
}
const wchar_t* desc_return_code(ReturnCode rc, wchar_t unk[20])
{
RETURN_ENUM_DESC(Success, rc, ReturnCode);
RETURN_ENUM_DESC(Failure, rc, ReturnCode);
RETURN_ENUM_DESC(CheckStatus, rc, ReturnCode);
RETURN_ENUM_DESC(Cancel, rc, ReturnCode);
RETURN_ENUM_DESC(DsEvent, rc, ReturnCode);
RETURN_ENUM_DESC(NotDsEvent, rc, ReturnCode);
RETURN_ENUM_DESC(XferDone, rc, ReturnCode);
RETURN_ENUM_DESC(EndOfList, rc, ReturnCode);
RETURN_ENUM_DESC(InfoNotSupported, rc, ReturnCode);
RETURN_ENUM_DESC(DataNotAvailable, rc, ReturnCode);
RETURN_ENUM_DESC(Busy, rc, ReturnCode);
RETURN_ENUM_DESC(ScannerLocked, rc, ReturnCode);
{
swprintf(unk, L"%d", rc);
return unk;
}
}
const wchar_t* desc_condition_code(ConditionCode c, wchar_t unk[20])
{
RETURN_ENUM_DESC(Success, c, ConditionCode);
RETURN_ENUM_DESC(Bummer, c, ConditionCode);
RETURN_ENUM_DESC(LowMemory, c, ConditionCode);
RETURN_ENUM_DESC(NoDs, c, ConditionCode);
RETURN_ENUM_DESC(MaxConnections, c, ConditionCode);
RETURN_ENUM_DESC(OperationError, c, ConditionCode);
RETURN_ENUM_DESC(BadCap, c, ConditionCode);
RETURN_ENUM_DESC(BadProtocol, c, ConditionCode);
RETURN_ENUM_DESC(BadValue, c, ConditionCode);
RETURN_ENUM_DESC(SeqError, c, ConditionCode);
RETURN_ENUM_DESC(BadDest, c, ConditionCode);
RETURN_ENUM_DESC(CapUnsupported, c, ConditionCode);
RETURN_ENUM_DESC(CapBadOperation, c, ConditionCode);
RETURN_ENUM_DESC(CapSeqError, c, ConditionCode);
RETURN_ENUM_DESC(Denied, c, ConditionCode);
RETURN_ENUM_DESC(FileExists, c, ConditionCode);
RETURN_ENUM_DESC(FileNotFound, c, ConditionCode);
RETURN_ENUM_DESC(NotEmpty, c, ConditionCode);
RETURN_ENUM_DESC(PaperJam, c, ConditionCode);
RETURN_ENUM_DESC(PaperDoubleFeed, c, ConditionCode);
RETURN_ENUM_DESC(FileWriteError, c, ConditionCode);
RETURN_ENUM_DESC(CheckDeviceOnline, c, ConditionCode);
RETURN_ENUM_DESC(InterLock, c, ConditionCode);
RETURN_ENUM_DESC(DamagedCorner, c, ConditionCode);
RETURN_ENUM_DESC(FocusError, c, ConditionCode);
RETURN_ENUM_DESC(DocTooLight, c, ConditionCode);
RETURN_ENUM_DESC(DocTooDark, c, ConditionCode);
RETURN_ENUM_DESC(NoMedia, c, ConditionCode);
{
swprintf(unk, L"%d", c);
return unk;
}
}
template<typename T>
static Result oneValGet(Msg msg, Capability& data, const T& value) {
switch (msg) {
@ -668,7 +853,7 @@ static const SCANNERID scanner_guid = MAKE_SCANNER_ID(PRODUCT_PID, PRODUCT_VID);
static std::once_flag oc;
huagao_ds::huagao_ds() : cur_head_(NULL), dpi_(200)
huagao_ds::huagao_ds() : cur_head_(NULL), dpi_(200), xfer_ready_failed_(false), log_all_triple_(false), scanner_status_(SCANNER_STATUS_NOT_INIT)
{
//std::call_once(oc, [&]() { log4cplus::Initializer(); });
}
@ -707,7 +892,7 @@ void huagao_ds::showmsg(const char* msg, int err)
}
int __stdcall huagao_ds::on_scanner_event(int ev, void* param)
{
return ((huagao_ds*)param)->handle_scanner_event(ev);
return ((huagao_ds*)param)->handle_scanner_event(ev, false);
}
const Identity& huagao_ds::defaultIdentity() noexcept {
@ -866,10 +1051,12 @@ Result huagao_ds::identityOpenDs(const Identity& id)
cur_head_ = new SANE_Parameters;
memset(cur_head_, 0, sizeof(SANE_Parameters));
}
log_all_triple_ = get_config_number(L"twain-app", L"log-all-triple") == 1;
m_compression = Compression::None;
init_support_caps();
m_fileXfer.setFormat(ImageFileFormat::Bmp);
scanner_status_ = SCANNER_STATUS_READY;
return success();
}
@ -887,6 +1074,7 @@ Result huagao_ds::identityCloseDs(const Identity&)
singleton_ = NULL;
}
load_sane_util::uninitialize();
scanner_status_ = SCANNER_STATUS_NOT_INIT;
return success();
}
@ -895,7 +1083,7 @@ Result huagao_ds::pendingXfersGet(const Identity&, PendingXfers& data)
if (!scanner_.get())
return seqError();
data.setCount(scanner_->get_scanned_images(-1));
data.setCount(get_scanned_image_count(-1));
return success();
}
Result huagao_ds::pendingXfersEnd(const Identity& id, PendingXfers& data)
@ -905,7 +1093,7 @@ Result huagao_ds::pendingXfersEnd(const Identity& id, PendingXfers& data)
Result huagao_ds::pendingXfersReset(const Identity&, PendingXfers& data)
{
pending_xfer_.clear();
data.setCount(scanner_->get_scanned_images(-1));
data.setCount(get_scanned_image_count(-1));
return success();
}
@ -915,7 +1103,7 @@ Result huagao_ds::setupMemXferGet(const Identity& id, SetupMemXfer& data)
size_t total = 0;
DWORD to = cur_head_ ? -1 : 0;
if (!scanner_.get() || scanner_->get_scanned_images(to) == 0)
if (!scanner_.get() || get_scanned_image_count(to) == 0)
{
if (cur_head_)
{
@ -969,7 +1157,10 @@ Result huagao_ds::userInterfaceEnable(const Identity&, UserInterface& ui)
if (m_bIndicator && !scanner_->ui_show_progress((HWND)ui.parent().raw()))
return seqError();
xfer_ready_failed_ = false;
scanner_->twain_set_transfer((twain_xfer)m_capXferMech);
scanner_status_ = SCANNER_STATUS_SCAN_1;
app_trigger_event_ = false;
int err = scanner_->start();
if (err == SCANNER_ERR_OK)
{
@ -977,6 +1168,7 @@ Result huagao_ds::userInterfaceEnable(const Identity&, UserInterface& ui)
}
else
{
scanner_status_ = SCANNER_STATUS_READY;
// if (err == SCANNER_ERR_DEVICE_NO_PAPER)
return { ReturnCode::Failure, huagao_ds::condition_code_from_hg_error(err) };
@ -1045,7 +1237,7 @@ Result huagao_ds::imageInfoGet(const Identity&, ImageInfo& data)
{
if (!scanner_->wait_image())
{
notifyCloseOk();
// notifyCloseOk();
return success(); // ºÃ·ÖÊýÐèÒª·µ»Ø³É¹¦
}
ok = scanner_->get_first_image_header(&head, NULL, &res);
@ -1091,8 +1283,10 @@ Result huagao_ds::imageLayoutGet(const Identity&, ImageLayout& data)
{
SANE_Parameters head = { 0 };
if (!scanner_.get() || scanner_->get_scanned_images(-1) == 0)
if (!scanner_.get())
return seqError();
else if(get_scanned_image_count(-1) == 0)
return { ReturnCode::XferDone, ConditionCode::Success };
int res = 200;
@ -1126,13 +1320,15 @@ Result huagao_ds::imageMemXferGet(const Identity& origin, ImageMemXfer& data)
if (!scanner_.get())
return seqError();
if (scanner_->get_scanned_images(-1) == 0 && !pending_xfer_.img)
if (get_scanned_image_count(-1) == 0 && !pending_xfer_.img)
{
if (!cur_head_ || !scanner_->wait_image())
{
notifyCloseOk();
return seqError();
}
//if (!cur_head_ || !scanner_->wait_image())
//{
// notifyCloseOk();
// return seqError();
//}
return { ReturnCode::XferDone, ConditionCode::Success };
}
IScanImg *img = pending_xfer_.img ? pending_xfer_.img : scanner_->take_first_image(TWAIN_XFER_Memory);
@ -1205,8 +1401,10 @@ Result huagao_ds::imageMemXferGet(const Identity& origin, ImageMemXfer& data)
}
Result huagao_ds::imageNativeXferGet(const Identity& id, ImageNativeXfer& data)
{
if (!scanner_.get() || scanner_->get_scanned_images(-1) == 0)
if (!scanner_.get())
return seqError();
else if(get_scanned_image_count(-1) == 0)
return { ReturnCode::XferDone, ConditionCode::Success };
IScanImg* img = scanner_->take_first_image(TWAIN_XFER_Native);
@ -1244,8 +1442,10 @@ Twpp::Result huagao_ds::pendingXfersStopFeeder(const Identity& origin, PendingXf
Twpp::Result huagao_ds::imageFileXferGet(const Twpp::Identity& origin)
{
// assume that the file format has set before start-scanning, so we write-down the image content to file directly here ...
if (!scanner_.get() || scanner_->get_scanned_images(-1) == 0)
if (!scanner_.get())
return seqError();
else if(get_scanned_image_count(-1) == 0)
return { ReturnCode::XferDone, ConditionCode::Success };
IScanImg* img = scanner_->take_first_image(TWAIN_XFER_File);
Twpp::Result ret = seqError();
@ -1410,14 +1610,19 @@ Result huagao_ds::call(const Identity& origin, DataGroup dg, Dat dat, Msg msg, v
try {
// we can override almost anything from SourceFromThis, even the top-most source instance call
//FileTools::write_log("D:\\1.txt", "call:datagroup-"+to_string((int)dg)+"dat-"+to_string(int(dat))+"msg-"+to_string(int(msg)));
if (dat == Dat::ImageNativeXfer && state() == DsState::Enabled) // 云阅卷扫描端不等状态改变,直接取图,此处设置一次状态 2022-11-07
Result rt;
trigger_ProcessEvent(dg, dat, msg); // some APPs may be not trigger (Control, Event, ProcessEvent), we help them :( ... // 云阅卷扫描端不等状态改变,直接取图,此处设置一次状态 2022-11-07
rt = Base::call(origin, dg, dat, msg, data);
if(log_all_triple_ || (int)rt.returnCode())
{
load_sane_util::log_info(L"APP SEQ ERROR: fetch image while status in 'Enabled' yet! we change it to 'XferReady' manually.\r\n", 0);
notifyXferReady();
wchar_t buf[128] = { 0 }, dgs[20] = { 0 }, dts[20] = { 0 }, ms[20] = { 0 }, ss[20] = { 0 }, rcs[20] = { 0 }, cs[20] = { 0 };
swprintf_s(buf, _countof(buf) - 1, L"[%x - %s]DSEntry(%s, %s, %s) = {%s, %s}\r\n", GetCurrentThreadId(), desc_state(state(), ss),
desc_data_group(dg, dgs), desc_data(dat, dts), desc_msg(msg, ms), desc_return_code(rt, rcs), desc_condition_code((ConditionCode)(Status)rt, cs));
load_sane_util::log_info(buf, 0);
}
return Base::call(origin, dg, dat, msg, data);
return rt;
}
catch (const CapabilityException& e) {
//FileTools::writelog(log_ERROR, e.what());
@ -3084,6 +3289,18 @@ void huagao_ds::init_support_caps_ex(void)
ADD_SANE_CAP(color_correction);
}
std::wstring huagao_ds::get_config_file(void)
{
char* tmp = getenv("LOCALAPPDATA");
if (tmp)
{
std::wstring str(L"");
std::string path(tmp);
path += std::string("\\") + PRODUCT_VENDOR + "Scan\\config\\debug.cfg";
return std::move(load_sane_util::ansi2unic(path.c_str()));
}
else
{
wchar_t path[MAX_PATH] = { 0 }, * name = NULL;
@ -3091,25 +3308,35 @@ std::wstring huagao_ds::get_config_file(void)
name = wcsrchr(path, L'\\');
if (name++ == NULL)
name = path;
wcscpy_s(name, _countof(path) - 1 - (name - path), L"first.cfg");
wcscpy_s(name, _countof(path) - 1 - (name - path), L"debug.cfg");
return path;
}
}
std::wstring huagao_ds::get_config_value(const wchar_t* sec, const wchar_t* key)
{
wchar_t v[256] = { 0 };
std::wstring cfg_f(get_config_file());
if(!cfg_f.empty())
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)
{
std::wstring cfg_f(get_config_file());
if (cfg_f.empty())
return 0;
else
return GetPrivateProfileIntW(sec, key, 0, get_config_file().c_str());
}
int huagao_ds::handle_scanner_event(int ev)
int huagao_ds::handle_scanner_event(int ev, bool from_event_proc)
{
static int count_0 = 0;
ReturnCode rc = ReturnCode::Success;
int ret = 0;
if (ev == 0)
count_0++;
@ -3117,41 +3344,149 @@ int huagao_ds::handle_scanner_event(int ev)
{
wchar_t msg[128] = { 0 };
if (count_0)
swprintf_s(msg, _countof(msg) - 1, L"ds::eventProcess(0x0 +%d)\r\nds::eventProcess(0x%x)\r\n", count_0, ev);
swprintf_s(msg, _countof(msg) - 1, L"[%x]handle_scanner_event(0x0 +%d)\r\nds::eventProcess(0x%x)\r\n", GetCurrentThreadId(), count_0, ev);
else
swprintf_s(msg, _countof(msg) - 1, L"ds::eventProcess(0x%x)\r\n", ev);
swprintf_s(msg, _countof(msg) - 1, L"[%x]handle_scanner_event(0x%x)\r\n", GetCurrentThreadId(), ev);
load_sane_util::log_info(msg, 0);
count_0 = 0;
}
switch (ev)
{
case SANE_EVENT_WORKING:
notifyXferReady();
scanner_status_ = SCANNER_STATUS_SCANNING;
rc = notifyXferReady();
if (!Twpp::success(rc))
{
wchar_t msg[128] = { 0 };
swprintf_s(msg, _countof(msg) - 1, L"[%x]Warning: change state to XferReady failed with error %d while in state(%d), STOP scanning ...\r\n", GetCurrentThreadId(), rc, state());
load_sane_util::log_info(msg, 0);
// we stop scanning here ...
scanner_->stop();
}
break;
case SANE_EVENT_UI_CLOSE_CANCEL:
scanner_->stop();
// notifyEndWithoutImages();
notifyCloseCancel(); // 修复点击进度框"取消"按钮UI不能正常结束的BUG - added on 2023-02-14
break;
//notifyCloseCancel(); // 修复点击进度框"取消"按钮UI不能正常结束的BUG - added on 2023-02-14
//break;
case SANE_EVENT_UI_CLOSE_NORMAL:
scanner_->ui_hide();
case SANE_EVENT_SCAN_FINISHED:
scanner_status_ = SCANNER_STATUS_STOPPED;
//notifyCloseOk();
//break;
case SANE_EVENT_UI_CLOSE_SETTING:
if(m_bIndicator)
notifyCloseCancel();
else
notifyXferReady(); // 好分数需要再通知 FAINT :( - modified on 2022-10-20
if (ev == SANE_EVENT_UI_CLOSE_SETTING)
{
rc = notifyXferReady(); // 好分数需要再通知 FAINT :( - modified on 2022-10-20
if (!Twpp::success(rc))
{
wchar_t msg[128] = { 0 }, unk[20] = { 0 };
swprintf_s(msg, _countof(msg) - 1, L"[%x]yscan: notifyXferReady failed after setting UI closed with error %d\r\n", GetCurrentThreadId(), rc);
load_sane_util::log_info(msg, 0);
}
}
break;
case SANE_EVENT_UI_SCAN_COMMAND:
if (m_bIndicator)
scanner_->ui_show_progress(NULL);
scanner_->start();
else
scanner_->ui_hide();
scanner_status_ = SCANNER_STATUS_SCAN_1;
app_trigger_event_ = false;
if ((ret = scanner_->start()))
{
wchar_t msg[128] = { 0 }, unk[20] = { 0 };
swprintf_s(msg, _countof(msg) - 1, L"[%x - %s]Fatal: start scanning from setting UI failed with error %d\r\n", GetCurrentThreadId(), desc_state(state(), unk), ret);
load_sane_util::log_info(msg, 0);
scanner_status_ = SCANNER_STATUS_STOPPED;
rc = notifyCloseCancel();
if (Twpp::success(rc))
{
scanner_status_ = SCANNER_STATUS_READY;
}
else
{
swprintf_s(msg, _countof(msg) - 1, L"[%x]Warning: notifyCloseCancel failed with error %d after start scanning failed\r\n", GetCurrentThreadId(), rc, state());
load_sane_util::log_info(msg, 0);
}
}
break;
}
return 0;
}
int huagao_ds::get_scanned_image_count(DWORD timeout)
{
int cnt = scanner_->get_scanned_images(timeout);
//if (cnt == -1)
//{
// // This is a special value indicates the scanning is over
// cnt = 0;
// scanner_->ui_hide();
// notifyCloseCancel();
//}
return cnt;
}
void huagao_ds::trigger_ProcessEvent(Twpp::DataGroup dg, Twpp::Dat dat, Twpp::Msg msg)
{
ReturnCode rc;
if (state() == DsState::Enabled && scanner_status_ >= SCANNER_STATUS_SCAN_1) // in scanning events ...
{
// here ensure APP enter into XferImage process ...
if (!app_trigger_event_ && scanner_status_ == SCANNER_STATUS_STOPPED)
{
// scanning stopped, reset APP state to ready ...
scanner_status_ = SCANNER_STATUS_READY;
rc = notifyCloseCancel();
if (!Twpp::success(rc))
{
wchar_t info[128] = { 0 }, unk[20] = { 0 };
swprintf_s(info, _countof(info) - 1, L"[%x]Warning: notifyCloseCancel failed with error %s!\r\n", GetCurrentThreadId(), desc_return_code(rc, unk));
load_sane_util::log_info(info, 0);
}
}
else
{
// start scanning, expect frist TRIPLE is ProcessEvent ...
if (dg == DataGroup::Control && dat == Dat::Event && msg == Msg::ProcessEvent && scanner_status_ == SCANNER_STATUS_SCAN_1)
{
app_trigger_event_ = true; // nothing else to do
load_sane_util::log_info(L"Good! first event is (Control, Event, ProcessEvent) after start scanning ^_^.\r\n", 0);
}
else if(!app_trigger_event_)
{
int ev = 0;
if (scanner_status_ == SCANNER_STATUS_SCAN_1)
load_sane_util::log_info(L"Sorry, first event is not (Control, Event, ProcessEvent) after start scanning, we takeover it!\r\n", 0);
if (scanner_.get())
{
ev = scanner_->get_event();
if (ev)
handle_scanner_event(ev, true);
}
}
}
}
else if (state() >= DsState::XferReady && scanner_status_ == SCANNER_STATUS_STOPPED)
{
// here ensure APP return to ready state ...
if (scanner_.get() && scanner_->get_scanned_images(0) == 0)
{
rc = notifyCloseCancel();
if (!Twpp::success(rc))
{
wchar_t info[128] = { 0 }, unk[20] = { 0 };
swprintf_s(info, _countof(info) - 1, L"[%x]Warning: notifyCloseCancel failed with error %s when scanner is stopped!\r\n", GetCurrentThreadId(), desc_return_code(rc, unk));
load_sane_util::log_info(info, 0);
}
}
}
}

View File

@ -23,6 +23,14 @@ namespace std {
class twain_ui;
enum scanner_status
{
SCANNER_STATUS_NOT_INIT = 0, // has not call identityOpenDs or called identityCloseDs
SCANNER_STATUS_READY, // called identityOpenDs
SCANNER_STATUS_SCAN_1, // scanner_->start() should be called
SCANNER_STATUS_SCANNING, // received SANE_EVENT_WORKING
SCANNER_STATUS_STOPPED, // received SANE_EVENT_SCAN_FINISHED
};
class huagao_ds : public Twpp::SourceFromThis<huagao_ds> {
std::unordered_map<Twpp::CapType, std::function<Twpp::Result(Twpp::Msg msg, Twpp::Capability& data)>> m_caps;
std::unordered_map<Twpp::CapType, Twpp::MsgSupport> m_query;
@ -42,6 +50,10 @@ class huagao_ds : public Twpp::SourceFromThis<huagao_ds> {
Twpp::Compression m_compression = Twpp::Compression::None;
SANE_Parameters* cur_head_;
int dpi_;
int scanner_status_;
bool xfer_ready_failed_;
bool log_all_triple_;
bool app_trigger_event_;
static std::string get_hidedlg_path(void);
static void showmsg(const char* msg, int err);
@ -55,7 +67,9 @@ class huagao_ds : public Twpp::SourceFromThis<huagao_ds> {
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);
int handle_scanner_event(int ev);
int handle_scanner_event(int ev, bool from_event_proc = true);
int get_scanned_image_count(DWORD timeout);
void trigger_ProcessEvent(Twpp::DataGroup dg, Twpp::Dat dat, Twpp::Msg msg);
typedef struct _pending_xfer
{