增加配置存取功能

This commit is contained in:
gb 2022-07-01 15:24:58 +08:00
parent 23cb82b7ce
commit fdd12a953c
15 changed files with 1580 additions and 47 deletions

View File

@ -6,9 +6,10 @@
#include "scanned_img.h" // for local_trans
// CDlgIndicator 对话框
#define WM_USB_PACKET_RECEIVED WM_USER + 1
#define WM_IMAGE_RECEIVED WM_USER + 2
#define WM_SCAN_FINISHED WM_USER + 3 // WPARAM: std::string* msg; LPARAM: boo err
#define WM_SCAN_WORKING WM_USER + 1 // WPARAM: unused; LPARAM: unsed
#define WM_USB_PACKET_RECEIVED WM_USER + 2 // WPARAM: unused; LPARAM: unsed
#define WM_IMAGE_RECEIVED WM_USER + 3 // WPARAM: unused; LPARAM: unsed
#define WM_SCAN_FINISHED WM_USER + 4 // WPARAM: std::string* msg; LPARAM: boo err
dlg_indicator::dlg_indicator(HWND parent) : dlg_base(parent, IDD_INDICATOR)
@ -62,6 +63,9 @@ 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);
break;
case WM_SCAN_FINISHED:
if (lp)
{
@ -158,4 +162,8 @@ void dlg_indicator::notify_scan_over(const char* msg, bool err)
notify_over(false);
}
}
void dlg_indicator::notify_working(void)
{
PostMessage(hwnd_, WM_SCAN_WORKING, 0, 0);
}
// CDlgIndicator 消息处理程序

View File

@ -28,4 +28,5 @@ public:
void hide(void);
void notify_data_arrived(bool image);
void notify_scan_over(const char* msg, bool err);
void notify_working(void);
};

View File

@ -6,6 +6,7 @@
#include "scanned_img.h" // for local_trans
#include "DlgArea.h"
#include "DlgGamma.h"
#include "gb_json.h"
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
@ -105,6 +106,14 @@ void dlg_base::notify_ui_event(ui_event ev)
if (ui_event_notify_)
ui_event_notify_(ev, this, ui_notify_param_);
}
gb::sane_config* dlg_base::get_config(void)
{
gb::sane_config* cfg = NULL;
SendMessage(parent_, WM_GET_CONFIG_OBJ, 0, (LPARAM)&cfg);
return cfg;
}
void dlg_base::set_ui_event_notify(void(__stdcall* notify)(ui_event, void*, void*), void* param)
{
@ -115,6 +124,51 @@ HWND dlg_base::hwnd(void)
{
return hwnd_;
}
void dlg_base::show(bool visible)
{
UINT cmd = SW_HIDE;
if (visible)
{
DWORD style = GetWindowLong(hwnd_, GWL_STYLE);
cmd = SW_SHOW;
if (!(style & WS_CHILD))
{
RECT r0 = { 0 }, rp = { 0 }, rme = { 0 };
POINT pt = { 0 };
if (IsWindow(parent_))
{
HMONITOR mon = MonitorFromWindow(parent_, MONITOR_DEFAULTTOPRIMARY);
MONITORINFO mi = { 0 };
mi.cbSize = sizeof(mi);
GetMonitorInfoW(mon, &mi);
r0 = mi.rcWork;
GetWindowRect(parent_, &rp);
}
else
{
GetWindowRect(GetDesktopWindow(), &r0);
rp = r0;
}
GetWindowRect(hwnd_, &rme);
pt.x = rp.left + (RECT_W(rp) - RECT_W(rme)) / 2;
pt.y = rp.top + (RECT_H(rp) - RECT_H(rme)) / 2;
if (pt.x + RECT_W(rme) > r0.right)
pt.x = r0.right - RECT_W(rme);
if (pt.x < r0.left)
pt.x = r0.left;
if (pt.y + RECT_H(rme) > r0.bottom)
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);
UpdateWindow(hwnd_);
}
}
ShowWindow(hwnd_, cmd);
}
void dlg_base::enable(bool enable)
{
EnableWindow(hwnd_, enable);
@ -536,16 +590,26 @@ void dlg_page::handle_command(WORD code, WORD id, HANDLE ctrl)
{
SANE_Fixed val = SANE_FIX(dlg.x_in_mm());
SANE_Int after = 0;
gb::sane_config* cfg = get_config();
sane_.sane_control_option_api(dev_, id_custom_left_, SANE_ACTION_SET_VALUE, &val, &after);
if (cfg)
cfg->config_changed(id_custom_left_, (char*)&val, sizeof(val));
val = SANE_FIX(dlg.y_in_mm());
sane_.sane_control_option_api(dev_, id_custom_top_, SANE_ACTION_SET_VALUE, &val, &after);
if (cfg)
cfg->config_changed(id_custom_top_, (char*)&val, sizeof(val));
val = SANE_FIX(dlg.x_in_mm() + dlg.w_in_mm());
sane_.sane_control_option_api(dev_, id_custom_right_, SANE_ACTION_SET_VALUE, &val, &after);
if (cfg)
cfg->config_changed(id_custom_right_, (char*)&val, sizeof(val));
val = SANE_FIX(dlg.y_in_mm() + dlg.h_in_mm());
sane_.sane_control_option_api(dev_, id_custom_bottom_, SANE_ACTION_SET_VALUE, &val, &after);
if (cfg)
cfg->config_changed(id_custom_bottom_, (char*)&val, sizeof(val));
}
return;
}
@ -586,6 +650,8 @@ BOOL dlg_page::on_notify(int ctrl_id, LPNMHDR pnmh)
if (IsWindow(host) && (int)GetPropW(host, dlg_page::property_type.c_str()) == SANE_TYPE_INT)
return FALSE;
}
else if (IS_BUTTON(cls))
return FALSE;
control_action(pnmh->hwndFrom);
@ -798,7 +864,31 @@ void dlg_page::control_action(HWND wnd)
{
SANE_Int after = 0;
SANE_Status statu = sane_.sane_control_option_api(dev_, id - dlg_page::dyn_id_base, SANE_ACTION_SET_VALUE, val, &after);
gb::sane_config* cfg = get_config();
done_ = false;
if (cfg)
{
size_t len = 0;
switch (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;
case SANE_TYPE_STRING:
len = lstrlenA((char*)val);
break;
default:
break;
}
if (len)
cfg->config_changed(id - dlg_page::dyn_id_base, (char*)val, len);
}
set_ctrl_value(wnd, type, val, false, !(after || statu));
done_ = true;
if (id == dlg_page::dyn_id_base + id_dpi_)
@ -1010,6 +1100,5 @@ const wchar_t* dlg_page::name(void)
return name_.c_str();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//

View File

@ -8,16 +8,24 @@
#include <sane/sane_option_definitions.h>
// CDlgIndicator 对话框
#define RECT_W(r) (r.right - r.left)
#define RECT_H(r) (r.bottom - r.top)
#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,
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
{
class sane_config;
}
class dlg_base
{
@ -34,6 +42,7 @@ protected:
virtual void on_font_changed(void);
void create(void);
void notify_ui_event(ui_event ev);
gb::sane_config* get_config(void);
public:
dlg_base(HWND parent, UINT idd);
@ -45,6 +54,7 @@ public:
public:
void set_ui_event_notify(void(__stdcall* notify)(ui_event, void*, void*), void* param);
HWND hwnd(void);
void show(bool visible);
void enable(bool enable);
void screen_2_client(LPRECT r);
void client_2_screen(LPRECT r);
@ -85,6 +95,7 @@ class dlg_page : public dlg_base
static int gap_y;
static int spin_w;
BOOL handle_message(UINT msg, WPARAM wp, LPARAM lp) override;
void on_font_changed(void) override;

View File

@ -5,6 +5,7 @@
#include "resource.h"
#include "scanned_img.h" // for local_trans
#include "DlgPage.h"
#include "gb_json.h"
// CDlgIndicator 对话框
#define WM_USB_PACKET_RECEIVED WM_USER + 1
@ -17,7 +18,7 @@ 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)
, papers_(0), images_(0), err_(false), tab_(NULL), cfg_(NULL), cfg_file_(L"")
{
create();
SetWindowTextW(hwnd(), (std::wstring(name) + L" \u8bbe\u7f6e").c_str());
@ -37,6 +38,7 @@ dlg_setting::~dlg_setting()
}
DestroyWindow(tab_);
}
cfg_->end_setting(false);
}
BOOL dlg_setting::handle_message(UINT msg, WPARAM wp, LPARAM lp)
@ -58,6 +60,9 @@ BOOL dlg_setting::handle_message(UINT msg, WPARAM wp, LPARAM lp)
case WM_REFRESH_OPTION:
refresh_controls((int)wp);
break;
case WM_GET_CONFIG_OBJ:
*((gb::sane_config**)lp) = cfg_;
break;
default:
ret = FALSE;
break;
@ -81,6 +86,12 @@ void dlg_setting::handle_command(WORD code, WORD id, HANDLE ctrl)
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_)
{
cfg_->begin_setting(true);
cfg_->end_setting(false);
cfg_->begin_setting();
}
}
else if (id == IDC_BUTTON_SCAN)
{
@ -328,6 +339,11 @@ void dlg_setting::refresh_controls(int src_sn)
}
}
void dlg_setting::set_config(gb::sane_config* cfg, const wchar_t* file)
{
cfg_ = cfg;
cfg_file_ = file;
}
HWND dlg_setting::window(void)
{
return hwnd_;
@ -336,21 +352,30 @@ HWND dlg_setting::parent(void)
{
return parent_;
}
void dlg_setting::show(void)
{
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_setting::show(void)
//{
// RECT rp, r, desk;
//
// if (IsWindow(parent_))
// GetWindowRect(parent_, &rp);
// else
// GetWindowRect(GetDesktopWindow(), &rp);
// GetWindowRect(hwnd_, &r);
// GetWindowRect(GetDesktopWindow(), &desk);
//
// rp.left += (rp.right - rp.left - (r.right - r.left)) / 2;
// rp.top += (rp.bottom - rp.top - (r.bottom - r.top)) / 2;
// if (rp.top > desk.bottom)
// rp.top = desk.bottom - (r.bottom - r.top);
// if (rp.top < desk.top)
// rp.top = desk.top;
// if (rp.left > desk.right)
// rp.left = desk.right - (rp.right - rp.left);
// if (rp.left < desk.left)
// rp.left = desk.left;
// SetWindowPos(hwnd_, HWND_TOPMOST, rp.left, rp.top, r.right - r.left, r.bottom - r.top, SWP_NOSIZE | SWP_SHOWWINDOW);
// UpdateWindow(hwnd_);
//}
void dlg_setting::hide(void)
{
ShowWindow(hwnd_, SW_HIDE);

View File

@ -15,6 +15,10 @@
#include <memory>
#endif
namespace gb
{
class sane_config;
}
class dlg_setting : public dlg_base
{
SANEAPI sane_api_;
@ -25,6 +29,8 @@ class dlg_setting : public dlg_base
bool err_;
int id_help_;
int id_restore_;
gb::sane_config* cfg_;
std::wstring cfg_file_;
HWND tab_;
@ -49,9 +55,10 @@ public:
~dlg_setting();
public:
void set_config(gb::sane_config* cfg, const wchar_t* file);
HWND window(void);
HWND parent(void);
void show(void);
//void show(void);
void hide(void);
void notify_data_arrived(bool image);
void notify_scan_over(const char* msg, bool err);

1073
sane/gb_json.cpp Normal file

File diff suppressed because it is too large Load Diff

116
sane/gb_json.h Normal file
View File

@ -0,0 +1,116 @@
#pragma once
#ifdef WIN32
#include <Windows.h>
#endif
// #include "cJSON.h"
#include "../../code_device/hgsane/cJSON.h"
#include <vector>
#include <string>
#include <map>
namespace gb
{
class json
{
cJSON *obj_;
cJSON* cur_child_;
bool is_array_;
cJSON* find_sibling(cJSON* first, const char* name, cJSON*** addr);
cJSON* find_child(cJSON *parent, std::vector<std::string>& path, bool create, cJSON*** addr = NULL);
cJSON* find(const char* path, bool create = false, cJSON*** addr = NULL);
public:
json(char* json_txt = 0);
~json();
static std::string to_string(cJSON* root, bool formatted);
static std::string get_value_as_string(cJSON* root, bool integer = false);
static void free_node_data(cJSON* node);
static cJSON* create_element_with_name(const char* name);
public:
bool attach_text(char* json_txt);
bool attach_cjson(cJSON* cjson);
bool create_empty(bool array = false);
void clear(void);
std::string to_string(bool formatted);
// can be path: child/value ...
bool get_value(const char* key, bool& val);
bool get_value(const char* key, int& val);
bool get_value(const char* key, double& val);
bool get_value(const char* key, std::string& val);
bool get_value(const char* key, json*& val); // caller shoud call "delete" to free the returned object !!!
bool get_value_as_string(const char* key, std::string& val, bool integer);
bool get_as_array(const char* key, std::vector<std::string>& val);
bool first_child(std::string& val, std::string* name = NULL);
bool next_child(std::string& val, std::string* name = NULL);
bool set_value(const char* key, bool val);
bool set_value(const char* key, int val);
bool set_value(const char* key, double val);
bool set_value(const char* key, std::string val);
bool set_value(const char* key, const char* val);
bool set_value(const char* key, json* obj);
bool remove(const char* key);
};
class base64
{
char base64_ind_[128];
char base64_char_[80];
char padding_char_;
bool is_valid_base64_table(const char* table);
bool initialize_base64_table(const char* table);
public:
base64();
~base64();
public:
bool set_base64_table(const char* table = NULL);
std::string encode(const char* data, size_t bytes, unsigned int line_bytes = -1, bool need_padding = true);
std::string decode(const char* data, size_t bytes);
};
class sane_config
{
json* jsn_;
json* bkp_;
json* def_val_;
bool in_setting_;
std::map<int, std::string> id_title_;
void clear();
std::string to_hex_letter(const char* data, size_t bytes);
std::string from_hex_letter(const char* data, size_t bytes);
std::string default_value(const char* hex_title);
public:
sane_config();
~sane_config();
static bool hex(unsigned char ch, unsigned char* val);
static bool hex_char(const char* data, unsigned char* val);
public:
bool load_from_file(const wchar_t* file);
bool load_from_mem(const char* mem);
bool save_to(const wchar_t* file);
void set_default_value(int sn, const char* title, const char* val, size_t bytes);
bool first_config(std::string& title, std::string& val);
bool next_config(std::string& title, std::string& val);
void begin_setting(bool restore = false);
void config_changed(const char* title, const char* val, size_t bytes);
void config_changed(int sn, const char* val, size_t bytes);
void end_setting(bool cancel);
int id_from_title(const char* title);
std::string to_text_stream(void);
};
}

View File

@ -266,6 +266,8 @@ __declspec(novtable) struct ISaneInvoker : public IRef
// twain
COM_API_DECLARE(void, twain_set_transfer(twain_xfer xfer));
COM_API_DECLARE(void, twain_set_compression(SANE_CompressionType compression, void* detail = NULL));
COM_API_DECLARE(int, twain_get_config(char* buf, size_t* len));
COM_API_DECLARE(int, twain_set_config(char* buf, size_t len));
};
struct delete_scanner

View File

@ -202,6 +202,7 @@ move /Y "$(OutDirFullPath)$(ProjectName).pdb" "$(SolutionDir)..\..\sdk\lib\win\$
<ClCompile Include="DlgIndicator.cpp" />
<ClCompile Include="DlgPage.cpp" />
<ClCompile Include="DlgSetting.cpp" />
<ClCompile Include="gb_json.cpp" />
<ClCompile Include="mem_dc.cpp" />
<ClCompile Include="sane_option_trans.cpp" />
<ClCompile Include="scanned_img.cpp" />
@ -225,6 +226,7 @@ move /Y "$(OutDirFullPath)$(ProjectName).pdb" "$(SolutionDir)..\..\sdk\lib\win\$
<ClInclude Include="DlgIndicator.h" />
<ClInclude Include="DlgPage.h" />
<ClInclude Include="DlgSetting.h" />
<ClInclude Include="gb_json.h" />
<ClInclude Include="mem_dc.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="s2t_api.h" />

View File

@ -63,6 +63,9 @@
<ClCompile Include="DlgGamma.cpp">
<Filter>sane2twain\UI</Filter>
</ClCompile>
<ClCompile Include="gb_json.cpp">
<Filter>sane2twain\UI</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\code_device\hgsane\cJSON.h">
@ -134,6 +137,9 @@
<ClInclude Include="DlgGamma.h">
<Filter>sane2twain\UI</Filter>
</ClInclude>
<ClInclude Include="gb_json.h">
<Filter>sane2twain\UI</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="sane.def">

View File

@ -9,6 +9,7 @@
#include <mutex>
#include "DlgIndicator.h"
#include "DlgSetting.h"
#include "gb_json.h"
static IMPLEMENT_OPTION_STRING_COMPARE(compare_sane_opt);
@ -109,9 +110,13 @@ 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"")
, ui_quit_(true), scanner_name_(L""), cfg_(NULL)
{
cfg_ = new gb::sane_config();
tmp_path_ = local_trans::a2u(hg_sane_middleware::sane_path().c_str());
cfg_path_ = tmp_path_ + L"config";
CreateDirectoryW(cfg_path_.c_str(), NULL);
cfg_path_ += L"\\";
tmp_path_ += L"imgs";
CreateDirectoryW(tmp_path_.c_str(), NULL);
tmp_path_ += L"\\";
@ -123,6 +128,8 @@ scanner::scanner(SCANNERID id) : handle_(NULL), id_(id), ex_id_(EXTENSION_ID_BAS
scanner::~scanner()
{
callback::unreg_callback(this);
if (cfg_)
delete cfg_;
}
std::string scanner::get_scanner_name(SCANNERID id)
@ -198,6 +205,45 @@ COM_API_IMPLEMENT(scanner, long, release(void))
return refer::release();
}
void scanner::load_config(const wchar_t* file)
{
cfg_->load_from_file(file);
}
void scanner::save_config(const wchar_t* file)
{
cfg_->save_to(file);
}
void scanner::apply_config(void)
{
std::string t(""), v("");
if (cfg_->first_config(t, v))
{
do
{
int id = cfg_->id_from_title(t.c_str());
if (id != -1)
{
void* data = &v[0];
const SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, id);
if (desc)
{
char* buf = NULL;
if (desc->type == SANE_TYPE_STRING)
{
buf = new char[desc->size + 4];
memset(buf, 0, desc->size + 4);
strcpy(buf, v.c_str());
data = buf;
}
SANE_Int after = 0;
hg_sane_middleware::instance()->set_option(handle_, id, SANE_ACTION_SET_VALUE, data, &after);
if (buf)
delete[] buf;
}
}
} while (cfg_->next_config(t, v));
}
}
void scanner::on_ui_quit(ui_event uev, void* sender)
{
switch (uev)
@ -205,12 +251,12 @@ void scanner::on_ui_quit(ui_event uev, void* sender)
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())
if (/*sender == indicator_.get() &&*/ setting_.get())
{
setting_->hide();
setting_.reset();
}
else if (sender == setting_.get() && indicator_.get())
/*else*/ if (/*sender == setting_.get() &&*/ indicator_.get())
{
indicator_->hide();
indicator_.reset();
@ -221,10 +267,17 @@ void scanner::on_ui_quit(ui_event uev, void* sender)
if (start() == SANE_STATUS_GOOD)
{
if (indicator_.get())
{
indicator_->show();
return;
}
}
else
{
setting_->enable(true);
return;
}
case UI_EVENT_SCAN_WORKING:
break;
default:
break;
@ -247,6 +300,8 @@ int scanner::open(void)
scanner_name_ = local_trans::a2u(name.c_str(), CP_UTF8);
callback::reg_callback(handle_, this);
ret = init_options_id();
load_config((cfg_path_ + scanner_name_).c_str());
// apply_config();
}
return ret;
@ -271,6 +326,32 @@ int scanner::init_options_id(void)
while ((desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, op_id)))
{
void* val = hg_sane_middleware::instance()->get_def_value(handle_, op_id);
if (val)
{
size_t len = 0;
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;
case SANE_TYPE_STRING:
len = lstrlenA((char*)val);
break;
default:
break;
}
if (len)
cfg_->set_default_value(op_id, desc->title, (char*)val, len);
local_utility::free_memory(val);
}
SET_OPT_ID(is_multiout, DLSC, extension_none)
else SET_OPT_ID(multiout_type, DLSCLX, extension_multiout_type)
else SET_OPT_ID(color_mode, YSMS, extension_color_mode)
@ -1879,6 +1960,31 @@ COM_API_IMPLEMENT(scanner, void, twain_set_compression(SANE_CompressionType comp
img_fmt_.compress.compression = compression;
img_fmt_.compress.detail = detail;
}
COM_API_IMPLEMENT(scanner, int, twain_get_config(char* buf, size_t* len))
{
std::string cont(cfg_->to_text_stream());
if (*len < cont.length())
{
*len = cont.length() + 4;
return SCANNER_ERR_INSUFFICIENT_MEMORY;
}
strcpy(buf, cont.c_str());
return SCANNER_ERR_OK;
}
COM_API_IMPLEMENT(scanner, int, twain_set_config(char* buf, size_t len))
{
if(cfg_->load_from_mem(buf))
{
apply_config();
return SCANNER_ERR_OK;
}
return SCANNER_ERR_DATA_DAMAGED;
}
// ui ...
@ -1906,6 +2012,8 @@ COM_API_IMPLEMENT(scanner, bool, ui_show_setting(HWND parent, bool with_scan))
setting_.reset(new dlg_setting(parent, &api, handle_, with_scan, scanner_name_.c_str()));
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(new dlg_indicator(parent));
@ -1913,7 +2021,7 @@ COM_API_IMPLEMENT(scanner, bool, ui_show_setting(HWND parent, bool with_scan))
}
else
indicator_.reset();
setting_->show();
setting_->show(true);
ui_quit_ = false;
return true;
@ -1941,10 +2049,15 @@ 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)
{
if (ev_code == SANE_EVENT_IMAGE_OK)
if (ev_code == SANE_EVENT_WORKING)
{
if (indicator_.get())
indicator_->notify_working();
}
else if (ev_code == SANE_EVENT_IMAGE_OK)
{
SANE_Image* simg = (SANE_Image*)data;
scanned_img* img = NULL;
@ -1955,6 +2068,8 @@ 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
{

View File

@ -24,6 +24,10 @@
#include "DlgPage.h"
class dlg_indicator;
class dlg_setting;
namespace gb
{
class sane_config;
}
class scanner : public ISaneInvoker, virtual public refer
{
@ -38,6 +42,7 @@ class scanner : public ISaneInvoker, virtual public refer
unsigned int img_ind_;
std::wstring scanner_name_;
std::wstring tmp_path_;
std::wstring cfg_path_;
std::string scan_msg_;
bool scan_err_;
twain_xfer xfer_;
@ -47,7 +52,11 @@ class scanner : public ISaneInvoker, virtual public refer
SANE_FinalImgFormat img_fmt_;
std::unique_ptr<dlg_indicator> indicator_;
std::unique_ptr<dlg_setting> setting_;
gb::sane_config* cfg_;
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);
int open(void);
int close(void);
@ -293,6 +302,8 @@ public:
// twain
COM_API_OVERRIDE(void, twain_set_transfer(twain_xfer xfer));
COM_API_OVERRIDE(void, twain_set_compression(SANE_CompressionType compression, void* detail = NULL));
COM_API_OVERRIDE(int, twain_get_config(char* buf, size_t* len));
COM_API_OVERRIDE(int, twain_set_config(char* buf, size_t len));
// methods:
public:

View File

@ -581,7 +581,7 @@ static const SCANNERID scanner_guid = MAKE_SCANNER_ID(PRODUCT_PID, PRODUCT_VID);
static std::once_flag oc;
huagao_ds::huagao_ds()
huagao_ds::huagao_ds() : cur_head_(NULL)
{
//std::call_once(oc, [&]() { log4cplus::Initializer(); });
}
@ -592,6 +592,8 @@ huagao_ds::~huagao_ds()
if (memoryinfo->joinable())
memoryinfo->join();
}
if (cur_head_)
delete cur_head_;
}
std::string huagao_ds::get_hidedlg_path(void)
@ -705,6 +707,9 @@ Result huagao_ds::capabilitySet(const Identity& origin, Capability& data)
}
Result huagao_ds::eventProcess(const Identity&, Event& event)
{
const MSG* msg = (const MSG*)event.event();
// event.setMessage(Msg::Null);
return { ReturnCode::NotDsEvent, ConditionCode::Success };
}
Twpp::Result huagao_ds::deviceEventGet(const Twpp::Identity& origin, Twpp::DeviceEvent& data)
@ -799,13 +804,24 @@ Result huagao_ds::pendingXfersReset(const Identity&, PendingXfers& data)
return success();
}
Result huagao_ds::setupMemXferGet(const Identity&, SetupMemXfer& data)
Result huagao_ds::setupMemXferGet(const Identity& id, SetupMemXfer& data)
{
SANE_Parameters head;
size_t total = 0;
DWORD to = cur_head_ ? -1 : 0;
if (!scanner_.get() || scanner_->get_scanned_images() == 0)
if (!scanner_.get() || scanner_->get_scanned_images(to) == 0)
{
if (cur_head_)
{
UserInterface ui(FALSE, FALSE, (Twpp::Handle)0);
data.setPreferredSize(1);
call(id, DataGroup::Control, Dat::UserInterface, Msg::DisableDs, &ui);
return success();
}
else
return seqError();
}
if (scanner_->get_first_image_header(&head, &total))
{
@ -838,12 +854,24 @@ 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();
scanner_->twain_set_transfer((twain_xfer)m_capXferMech);
return scanner_->start() == SCANNER_ERR_OK ? success() : seqError();
if (scanner_->start() == SCANNER_ERR_OK)
{
if (xfer_ready)
notifyXferReady();
return success();
}
else
{
return seqError();
}
}
return showTwainUI(ui);
@ -856,18 +884,35 @@ Result huagao_ds::userInterfaceEnableUiOnly(const Identity&, UserInterface& ui)
Result huagao_ds::imageInfoGet(const Identity&, ImageInfo& data)
{
SANE_Parameters head;
bool ok = false;
if (!scanner_.get())
return seqError();
if (cur_head_ && cur_head_->lines)
{
memcpy(&head, cur_head_, sizeof(head));
ok = true;
cur_head_->lines = 0;
}
else
{
if (!scanner_->wait_image())
return bummer();
ok = scanner_->get_first_image_header(&head);
}
if (scanner_->get_first_image_header(&head))
if (ok)
{
if (head.format == SANE_FRAME_RGB)
{
data.setBitsPerPixel(head.depth * 3);
data.bitsPerSample()[0] = data.bitsPerSample()[1] = data.bitsPerSample()[2] = 8;
}
else
{
data.setBitsPerPixel(head.depth);
data.bitsPerSample()[0] = 8;
}
data.setHeight(head.lines);
data.setPixelType(head.format == SANE_FRAME_RGB ? PixelType::Rgb : PixelType::Gray);
data.setPlanar(false);
@ -938,6 +983,10 @@ Result huagao_ds::imageMemXferGet(const Identity& origin, ImageMemXfer& data)
img->add_ref();
pending_xfer_.clear();
}
else if(cur_head_)
{
img->copy_header(cur_head_);
}
data.setBytesPerRow(line_l);
data.setColumns(img->width());
data.setRows(rows);
@ -949,8 +998,7 @@ Result huagao_ds::imageMemXferGet(const Identity& origin, ImageMemXfer& data)
want_read = img->bytes();
off = 0;
img->read(dst, &want_read, off);
data.setRows(1);
data.setColumns(want_read);
data.setRows(img->height());
data.setBytesWritten(want_read);
}
else if (img->read(dst, &want_read, off) == SCANNER_ERR_OK)
@ -1009,9 +1057,7 @@ Result huagao_ds::imageNativeXferGet(const Identity& id, ImageNativeXfer& data)
}
Twpp::Result huagao_ds::pendingXfersStopFeeder(const Identity& origin, PendingXfers& data)
{
if (!scanner_.get())
return seqError();
if (scanner_.get())
scanner_->stop();
return success();
@ -1085,7 +1131,7 @@ Twpp::Result huagao_ds::imageFileXferGet(const Twpp::Identity& origin)
conv.dst.data = target.c_str();
conv.dst.data_len = target.length();
MoveFileA(target.c_str(), file.c_str());
if(scanner_->convert_image(&conv) != SANE_STATUS_GOOD)
if(scanner_->convert_image(&conv) != SCANNER_ERR_OK)
ret = { ReturnCode::Failure, ConditionCode::FileWriteError };
DeleteFileA(file.c_str());
}
@ -1140,12 +1186,28 @@ Result huagao_ds::call(const Identity& origin, DataGroup dg, Dat dat, Msg msg, v
Result huagao_ds::customDataGet(const Twpp::Identity& origin, Twpp::CustomData& data)
{
// get user setting from local file ...
if (!scanner_.get())
return seqError();
char * buf = NULL;
size_t len = 0;
if (scanner_->twain_get_config(buf, &len) == SCANNER_ERR_INSUFFICIENT_MEMORY)
{
data = CustomData(len);
buf = data.lock<char>();
scanner_->twain_get_config(buf, &len);
}
return success();
}
Result huagao_ds::customDataSet(const Twpp::Identity& origin, Twpp::CustomData& data)
{
// write user setting to local file ...
if (!scanner_.get())
return seqError();
char* buf = data.lock<char>();
scanner_->twain_set_config(buf, data.size());
return success();
}
@ -2529,7 +2591,11 @@ void huagao_ds::on_scan_event(int sane_event, void* data, unsigned int* len)
{
if (scanner_.get())
{
if (sane_event == SANE_EVENT_SCAN_FINISHED)
/*if (sane_event == SANE_EVENT_IMAGE_OK)
{
notifyDeviceEvent();
}
else*/ if (sane_event == SANE_EVENT_SCAN_FINISHED)
{
notifyCloseCancel();
}

View File

@ -40,6 +40,7 @@ class huagao_ds : public Twpp::SourceFromThis<huagao_ds> {
bool m_bIndicator = true;
int m_jpegQuality = 80;
Twpp::Compression m_compression = Twpp::Compression::None;
SANE_Parameters* cur_head_;
static std::string get_hidedlg_path(void);
static void showmsg(const char* msg, int err);