1053 lines
29 KiB
C++
1053 lines
29 KiB
C++
|
// DlgScanner.cpp: 实现文件
|
|||
|
//
|
|||
|
|
|||
|
#include "pch.h"
|
|||
|
#include "usb_tools.h"
|
|||
|
#include "DlgScanner.h"
|
|||
|
#include "afxdialogex.h"
|
|||
|
|
|||
|
#include <direct.h>
|
|||
|
#include <file/file_util.h>
|
|||
|
|
|||
|
#define TIMER_ID_REFRESH_BULK 1001
|
|||
|
#include <log_util.h>
|
|||
|
#include <json/json.h>
|
|||
|
|
|||
|
HMODULE g_my_inst;
|
|||
|
|
|||
|
namespace sane
|
|||
|
{
|
|||
|
#define ALIGN_INTEGER(v) ALIGN_INT(v, sizeof(int))
|
|||
|
|
|||
|
static std::vector<SANE_Option_Descriptor*> g_opts;
|
|||
|
SANE_Option_Descriptor g_opt0;
|
|||
|
|
|||
|
namespace local_utility
|
|||
|
{
|
|||
|
void* acquire_memory(size_t bytes, const char* msg)
|
|||
|
{
|
|||
|
char* buf = new char[bytes];
|
|||
|
|
|||
|
memset(buf, 0, bytes);
|
|||
|
|
|||
|
return buf;
|
|||
|
}
|
|||
|
}
|
|||
|
static void bzero(void* buf, size_t len)
|
|||
|
{
|
|||
|
memset(buf, 0, len);
|
|||
|
}
|
|||
|
|
|||
|
SANE_Option_Descriptor* string_option_to_SANE_descriptor(const char* name, const char* title, const char* desc
|
|||
|
, const std::vector<std::string>& values)
|
|||
|
{
|
|||
|
int bytes = sizeof(SANE_Option_Descriptor) + sizeof(char*);
|
|||
|
SANE_Option_Descriptor* sod = NULL;
|
|||
|
char* str = NULL, ** str_arr = NULL;
|
|||
|
|
|||
|
bytes += ALIGN_INTEGER(strlen(name) + 1);
|
|||
|
bytes += ALIGN_INTEGER(strlen(title) + 1);
|
|||
|
bytes += ALIGN_INTEGER(strlen(desc) + 1);
|
|||
|
bytes += sizeof(SANE_Option_Descriptor);
|
|||
|
bytes += sizeof(char*);
|
|||
|
for (size_t i = 0; i < values.size(); ++i)
|
|||
|
bytes += ALIGN_INTEGER(values[i].length() + 1);
|
|||
|
bytes += sizeof(char*) * (values.size() + 1);
|
|||
|
sod = (SANE_Option_Descriptor*)local_utility::acquire_memory(bytes, "string_option_to_SANE_descriptor");
|
|||
|
bzero(sod, bytes);
|
|||
|
str = (char*)sod;
|
|||
|
str += sizeof(SANE_Option_Descriptor);
|
|||
|
|
|||
|
sod->name = str;
|
|||
|
strcpy(str, name);
|
|||
|
str += ALIGN_INTEGER(strlen(str) + 1);
|
|||
|
|
|||
|
sod->title = str;
|
|||
|
strcpy(str, title);
|
|||
|
str += ALIGN_INTEGER(strlen(str) + 1);
|
|||
|
|
|||
|
sod->desc = str;
|
|||
|
strcpy(str, desc);
|
|||
|
str += ALIGN_INTEGER(strlen(str) + 1);
|
|||
|
|
|||
|
sod->type = SANE_TYPE_STRING;
|
|||
|
sod->unit = SANE_UNIT_NONE;
|
|||
|
sod->size = values.size();
|
|||
|
sod->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT // 软件可设置选项
|
|||
|
| SANE_CAP_AUTOMATIC; // 硬件可设置默认<E9BB98>?
|
|||
|
if (values.size())
|
|||
|
{
|
|||
|
sod->constraint_type = SANE_CONSTRAINT_STRING_LIST;
|
|||
|
sod->constraint.string_list = (char**)str;
|
|||
|
str_arr = (char**)str;
|
|||
|
str += (values.size() + 1) * sizeof(char*);
|
|||
|
for (size_t i = 0; i < values.size(); ++i)
|
|||
|
{
|
|||
|
str_arr[i] = str;
|
|||
|
strcpy(str, values[i].c_str());
|
|||
|
|
|||
|
str += ALIGN_INTEGER(values[i].length() + 1);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//VLOG_MINI_2(LOG_LEVEL_ALL, "Memory usage: %u/%u\n", str - (char*)sod, bytes);
|
|||
|
|
|||
|
return sod;
|
|||
|
}
|
|||
|
SANE_Option_Descriptor* number_option_to_SANE_descriptor(const char* name, const char* title, const char* desc
|
|||
|
, bool double_val, double* lower, double* upper, double* step)
|
|||
|
{
|
|||
|
int bytes = sizeof(SANE_Option_Descriptor) + sizeof(SANE_Range);
|
|||
|
SANE_Option_Descriptor* sod = NULL;
|
|||
|
char* str = NULL;
|
|||
|
|
|||
|
bytes += ALIGN_INTEGER(strlen(name) + 1);
|
|||
|
bytes += ALIGN_INTEGER(strlen(title) + 1);
|
|||
|
bytes += ALIGN_INTEGER(strlen(desc) + 1);
|
|||
|
bytes += sizeof(SANE_Option_Descriptor);
|
|||
|
bytes += sizeof(SANE_Range*) + sizeof(SANE_Range);
|
|||
|
sod = (SANE_Option_Descriptor*)local_utility::acquire_memory(bytes, "number_option_to_SANE_descriptor");
|
|||
|
bzero(sod, bytes);
|
|||
|
str = (char*)sod;
|
|||
|
str += sizeof(SANE_Option_Descriptor);
|
|||
|
|
|||
|
sod->name = str;
|
|||
|
strcpy(str, name);
|
|||
|
str += ALIGN_INTEGER(strlen(str) + 1);
|
|||
|
|
|||
|
sod->title = str;
|
|||
|
strcpy(str, title);
|
|||
|
str += ALIGN_INTEGER(strlen(str) + 1);
|
|||
|
|
|||
|
sod->desc = str;
|
|||
|
strcpy(str, desc);
|
|||
|
str += ALIGN_INTEGER(strlen(str) + 1);
|
|||
|
|
|||
|
sod->type = double_val ? SANE_TYPE_FIXED : SANE_TYPE_INT;
|
|||
|
sod->unit = SANE_UNIT_NONE;
|
|||
|
sod->size = sizeof(SANE_Word);
|
|||
|
sod->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT
|
|||
|
| SANE_CAP_AUTOMATIC;
|
|||
|
if (lower || upper)
|
|||
|
{
|
|||
|
sod->size = sizeof(SANE_Range);
|
|||
|
sod->constraint_type = SANE_CONSTRAINT_RANGE;
|
|||
|
sod->constraint.range = (SANE_Range*)str;
|
|||
|
if (lower)
|
|||
|
{
|
|||
|
if (double_val)
|
|||
|
(*(SANE_Range*)str).min = SANE_FIX(*lower);
|
|||
|
else
|
|||
|
(*(SANE_Range*)str).min = (SANE_Word)*lower;
|
|||
|
}
|
|||
|
if (upper)
|
|||
|
{
|
|||
|
if (double_val)
|
|||
|
(*(SANE_Range*)str).max = SANE_FIX(*upper);
|
|||
|
else
|
|||
|
(*(SANE_Range*)str).max = (SANE_Word)*upper;
|
|||
|
}
|
|||
|
(*(SANE_Range*)str).quant = 0;
|
|||
|
if (step)
|
|||
|
{
|
|||
|
if (double_val)
|
|||
|
(*(SANE_Range*)str).quant = SANE_FIX(*step);
|
|||
|
else
|
|||
|
(*(SANE_Range*)str).quant = (SANE_Word)(*step);
|
|||
|
}
|
|||
|
|
|||
|
str = (char*)((SANE_Range*)str + 1);
|
|||
|
}
|
|||
|
//VLOG_MINI_2(LOG_LEVEL_ALL, "Memory usage: %u/%u\n", str - (char*)sod, bytes);
|
|||
|
|
|||
|
return sod;
|
|||
|
}
|
|||
|
SANE_Option_Descriptor* number_option_to_SANE_descriptor(const char* name, const char* title, const char* desc
|
|||
|
, const std::vector<int>& values)
|
|||
|
{
|
|||
|
int bytes = sizeof(SANE_Option_Descriptor) + sizeof(SANE_Range);
|
|||
|
SANE_Option_Descriptor* sod = NULL;
|
|||
|
char* str = NULL;
|
|||
|
|
|||
|
bytes += ALIGN_INTEGER(strlen(name) + 1);
|
|||
|
bytes += ALIGN_INTEGER(strlen(title) + 1);
|
|||
|
bytes += ALIGN_INTEGER(strlen(desc) + 1);
|
|||
|
bytes += sizeof(SANE_Option_Descriptor);
|
|||
|
bytes += sizeof(SANE_Word*) + sizeof(SANE_Word) * (values.size() + 1);
|
|||
|
sod = (SANE_Option_Descriptor*)local_utility::acquire_memory(bytes, "number_option_to_SANE_descriptor");
|
|||
|
bzero(sod, bytes);
|
|||
|
str = (char*)sod;
|
|||
|
str += sizeof(SANE_Option_Descriptor);
|
|||
|
|
|||
|
sod->name = str;
|
|||
|
strcpy(str, name);
|
|||
|
str += ALIGN_INTEGER(strlen(str) + 1);
|
|||
|
|
|||
|
sod->title = str;
|
|||
|
strcpy(str, title);
|
|||
|
str += ALIGN_INTEGER(strlen(str) + 1);
|
|||
|
|
|||
|
sod->desc = str;
|
|||
|
strcpy(str, desc);
|
|||
|
str += ALIGN_INTEGER(strlen(str) + 1);
|
|||
|
|
|||
|
sod->type = SANE_TYPE_INT;
|
|||
|
sod->unit = SANE_UNIT_NONE;
|
|||
|
sod->size = sizeof(SANE_Word);
|
|||
|
sod->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT // 软件可设置选项
|
|||
|
| SANE_CAP_AUTOMATIC; // 硬件可设置默认<E9BB98>?
|
|||
|
|
|||
|
if (values.size())
|
|||
|
{
|
|||
|
SANE_Word* val = (SANE_Word*)str;
|
|||
|
sod->constraint.word_list = val;
|
|||
|
sod->constraint_type = SANE_CONSTRAINT_WORD_LIST;
|
|||
|
*val++ = values.size();
|
|||
|
for (size_t i = 0; i < values.size(); ++i)
|
|||
|
val[i] = values[i];
|
|||
|
|
|||
|
str = (char*)(val + values.size());
|
|||
|
}
|
|||
|
//VLOG_MINI_2(LOG_LEVEL_ALL, "Memory usage: %u/%u\n", str - (char*)sod, bytes);
|
|||
|
|
|||
|
return sod;
|
|||
|
}
|
|||
|
SANE_Option_Descriptor* number_option_to_SANE_descriptor(const char* name, const char* title, const char* desc
|
|||
|
, const std::vector<double>& values)
|
|||
|
{
|
|||
|
int bytes = sizeof(SANE_Option_Descriptor) + sizeof(SANE_Range);
|
|||
|
SANE_Option_Descriptor* sod = NULL;
|
|||
|
char* str = NULL;
|
|||
|
|
|||
|
bytes += ALIGN_INTEGER(strlen(name) + 1);
|
|||
|
bytes += ALIGN_INTEGER(strlen(title) + 1);
|
|||
|
bytes += ALIGN_INTEGER(strlen(desc) + 1);
|
|||
|
bytes += sizeof(SANE_Option_Descriptor);
|
|||
|
bytes += sizeof(SANE_Word*) + sizeof(SANE_Word) * (values.size() + 1);
|
|||
|
sod = (SANE_Option_Descriptor*)local_utility::acquire_memory(bytes, "number_option_to_SANE_descriptor");
|
|||
|
bzero(sod, bytes);
|
|||
|
str = (char*)sod;
|
|||
|
str += sizeof(SANE_Option_Descriptor);
|
|||
|
|
|||
|
sod->name = str;
|
|||
|
strcpy(str, name);
|
|||
|
str += ALIGN_INTEGER(strlen(str) + 1);
|
|||
|
|
|||
|
sod->title = str;
|
|||
|
strcpy(str, title);
|
|||
|
str += ALIGN_INTEGER(strlen(str) + 1);
|
|||
|
|
|||
|
sod->desc = str;
|
|||
|
strcpy(str, desc);
|
|||
|
str += ALIGN_INTEGER(strlen(str) + 1);
|
|||
|
|
|||
|
sod->type = SANE_TYPE_FIXED;
|
|||
|
sod->unit = SANE_UNIT_NONE;
|
|||
|
sod->size = sizeof(SANE_Word);
|
|||
|
sod->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT // 软件可设置选项
|
|||
|
| SANE_CAP_AUTOMATIC; // 硬件可设置默认<E9BB98>?
|
|||
|
|
|||
|
if (values.size())
|
|||
|
{
|
|||
|
SANE_Word* val = (SANE_Word*)str;
|
|||
|
sod->constraint.word_list = val;
|
|||
|
sod->constraint_type = SANE_CONSTRAINT_WORD_LIST;
|
|||
|
*val++ = values.size();
|
|||
|
for (size_t i = 0; i < values.size(); ++i)
|
|||
|
val[i] = SANE_FIX(values[i]);
|
|||
|
|
|||
|
str = (char*)(val + values.size());
|
|||
|
}
|
|||
|
//VLOG_MINI_2(LOG_LEVEL_ALL, "Memory usage: %u/%u\n", str - (char*)sod, bytes);
|
|||
|
|
|||
|
return sod;
|
|||
|
}
|
|||
|
SANE_Option_Descriptor* trans_json_to_opt_desc(json* jsn)
|
|||
|
{
|
|||
|
std::string title(""),
|
|||
|
desc(""),
|
|||
|
name(""),
|
|||
|
val("");
|
|||
|
std::vector<std::string> constraints;
|
|||
|
double lower = .0f, upper = .0f, step = .0f;
|
|||
|
bool db_val = false;
|
|||
|
SANE_Option_Descriptor *ret = NULL;
|
|||
|
|
|||
|
jsn->get_value("title", title);
|
|||
|
jsn->get_value("desc", desc);
|
|||
|
name = jsn->key();
|
|||
|
if (!jsn->get_value("type", val))
|
|||
|
return NULL;
|
|||
|
|
|||
|
if (val == "string")
|
|||
|
{
|
|||
|
json* range = NULL, * child = NULL;
|
|||
|
|
|||
|
jsn->get_value("range", range);
|
|||
|
if (range)
|
|||
|
{
|
|||
|
child = range->first_child();
|
|||
|
while (child)
|
|||
|
{
|
|||
|
if (child->value(val))
|
|||
|
constraints.push_back(val);
|
|||
|
child->release();
|
|||
|
child = range->next_child();
|
|||
|
}
|
|||
|
range->release();
|
|||
|
}
|
|||
|
|
|||
|
ret = string_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str()
|
|||
|
, constraints);
|
|||
|
}
|
|||
|
else if (val == "int" || val == "float")
|
|||
|
{
|
|||
|
json* range = NULL;
|
|||
|
|
|||
|
jsn->get_value("range", range);
|
|||
|
if (range)
|
|||
|
{
|
|||
|
if (val == "int")
|
|||
|
{
|
|||
|
int l = 0;
|
|||
|
if (range->get_value("min", l))
|
|||
|
{
|
|||
|
int u = 0, s = 1;
|
|||
|
range->get_value("max", u);
|
|||
|
range->get_value("step", s);
|
|||
|
lower = l;
|
|||
|
upper = u;
|
|||
|
step = s;
|
|||
|
ret = number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str()
|
|||
|
, false, &lower, &upper, &step);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
std::vector<int> constraints;
|
|||
|
json* child = range->first_child();
|
|||
|
|
|||
|
while(child)
|
|||
|
{
|
|||
|
int val = 0;
|
|||
|
if(child->value(val))
|
|||
|
constraints.push_back(val);
|
|||
|
child->release();
|
|||
|
child = range->next_child();
|
|||
|
}
|
|||
|
ret = number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str()
|
|||
|
, constraints);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (range->get_value("min", lower))
|
|||
|
{
|
|||
|
range->get_value("max", upper);
|
|||
|
step = (upper - lower) / 10.0f;
|
|||
|
range->get_value("step", step);
|
|||
|
ret = number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str()
|
|||
|
, true, &lower, &upper, &step);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
std::vector<double> constraints;
|
|||
|
json* child = range->first_child();
|
|||
|
|
|||
|
while(child)
|
|||
|
{
|
|||
|
double val = .0f;
|
|||
|
if(child->value(val))
|
|||
|
constraints.push_back(val);
|
|||
|
child->release();
|
|||
|
child = range->next_child();
|
|||
|
}
|
|||
|
ret = number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str()
|
|||
|
, constraints);
|
|||
|
}
|
|||
|
}
|
|||
|
range->release();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
ret = number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str()
|
|||
|
, false, NULL, NULL, NULL);
|
|||
|
}
|
|||
|
}
|
|||
|
else if (val == "bool")
|
|||
|
{
|
|||
|
ret = number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str()
|
|||
|
, false, NULL, NULL, NULL);
|
|||
|
ret->type = SANE_TYPE_BOOL;
|
|||
|
}
|
|||
|
else if (val == "button")
|
|||
|
{
|
|||
|
ret = number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str()
|
|||
|
, false, NULL, NULL, NULL);
|
|||
|
ret->type = SANE_TYPE_BUTTON;
|
|||
|
}
|
|||
|
else if (val == "group")
|
|||
|
{
|
|||
|
ret = number_option_to_SANE_descriptor(name.c_str(), title.c_str(), desc.c_str()
|
|||
|
, false, NULL, NULL, NULL);
|
|||
|
ret->type = SANE_TYPE_GROUP;
|
|||
|
}
|
|||
|
|
|||
|
// fill the 'size' field, for SANE_ACTION_GET action ...
|
|||
|
if (ret)
|
|||
|
{
|
|||
|
int bytes = 0;
|
|||
|
bool bv = false;
|
|||
|
|
|||
|
jsn->get_value("size", bytes);
|
|||
|
ret->size = bytes;
|
|||
|
|
|||
|
if (jsn->get_value("readonly", bv) && bv)
|
|||
|
SET_CAP_READONLY(ret->cap)
|
|||
|
else if (jsn->get_value("hwonly", bv) && bv)
|
|||
|
SET_CAP_DEVICE_SETTABLE(ret->cap, true)
|
|||
|
|
|||
|
val = "";
|
|||
|
jsn->get_value("category", val);
|
|||
|
if (val == "advanced")
|
|||
|
{
|
|||
|
ret->cap |= SANE_CAP_ADVANCED;
|
|||
|
}
|
|||
|
|
|||
|
if (strcmp(ret->name, SANE_STD_OPT_NAME_RESOLUTION) == 0)
|
|||
|
{
|
|||
|
ret->unit = SANE_UNIT_DPI;
|
|||
|
}
|
|||
|
else if (strcmp(ret->name, SANE_STD_OPT_NAME_CUSTOM_AREA_LEFT) == 0 ||
|
|||
|
strcmp(ret->name, SANE_STD_OPT_NAME_CUSTOM_AREA_RIGHT) == 0 ||
|
|||
|
strcmp(ret->name, SANE_STD_OPT_NAME_CUSTOM_AREA_TOP) == 0 ||
|
|||
|
strcmp(ret->name, SANE_STD_OPT_NAME_CUSTOM_AREA_BOTTOM) == 0)
|
|||
|
ret->unit = SANE_UNIT_MM;
|
|||
|
|
|||
|
//bool enabled = true;
|
|||
|
//if (jsn->get_value("enable", enabled) && !enabled)
|
|||
|
// ret->cap |= SANE_CAP_INACTIVE;
|
|||
|
|
|||
|
// 关联<E585B3>?
|
|||
|
json* depend = NULL;
|
|||
|
}
|
|||
|
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
void reset_opts(const char* json_txt)
|
|||
|
{
|
|||
|
for (auto& v : g_opts)
|
|||
|
delete[] v;
|
|||
|
g_opts.clear();
|
|||
|
|
|||
|
g_opt0.cap = CAPABILITY_READONLY;
|
|||
|
g_opt0.name = "option-count";
|
|||
|
g_opt0.title = "";
|
|||
|
g_opt0.desc = "Number of options";
|
|||
|
g_opt0.type = SANE_TYPE_INT;
|
|||
|
g_opt0.size = sizeof(SANE_TYPE_INT);
|
|||
|
|
|||
|
if (json_txt)
|
|||
|
{
|
|||
|
json* jsn = new json(), * child = NULL;
|
|||
|
if (jsn->attach_text((char*)json_txt))
|
|||
|
{
|
|||
|
child = jsn->first_child();
|
|||
|
if (child)
|
|||
|
{
|
|||
|
child->release();
|
|||
|
while ((child = jsn->next_child()))
|
|||
|
{
|
|||
|
SANE_Option_Descriptor* desc = trans_json_to_opt_desc(child);
|
|||
|
if (desc)
|
|||
|
g_opts.push_back(desc);
|
|||
|
child->release();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
jsn->release();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
SANE_Status sane_get_devices_api(const SANE_Device*** device_list, SANE_Bool local_only)
|
|||
|
{
|
|||
|
return SANE_STATUS_INVAL;
|
|||
|
}
|
|||
|
SANE_Status sane_open_api(SANE_String_Const devicename, SANE_Handle* handle)
|
|||
|
{
|
|||
|
return SANE_STATUS_INVAL;
|
|||
|
}
|
|||
|
void sane_close_api(SANE_Handle handle)
|
|||
|
{}
|
|||
|
const SANE_Option_Descriptor* sane_get_option_descriptor_api(SANE_Handle handle, SANE_Int option)
|
|||
|
{
|
|||
|
if (option == 0)
|
|||
|
return &g_opt0;
|
|||
|
else if (option <= g_opts.size())
|
|||
|
return g_opts[option - 1];
|
|||
|
else
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
SANE_Status sane_control_option_api(SANE_Handle handle, SANE_Int option, SANE_Action action, void* value, SANE_Int* info)
|
|||
|
{
|
|||
|
CDlgScanner* dlg = (CDlgScanner*)handle;
|
|||
|
|
|||
|
if (action == SANE_ACTION_GET_VALUE && option > 0 && option <= g_opts.size())
|
|||
|
{
|
|||
|
dlg->get_option(g_opts[option - 1]->name, value, g_opts[option - 1]->size);
|
|||
|
|
|||
|
return SANE_STATUS_GOOD;
|
|||
|
}
|
|||
|
|
|||
|
return SANE_STATUS_INVAL;
|
|||
|
}
|
|||
|
SANE_Status sane_get_parameters_api(SANE_Handle handle, SANE_Parameters* params)
|
|||
|
{
|
|||
|
return SANE_STATUS_INVAL;
|
|||
|
}
|
|||
|
SANE_Status sane_start_api(SANE_Handle handle)
|
|||
|
{
|
|||
|
return SANE_STATUS_INVAL;
|
|||
|
}
|
|||
|
SANE_Status sane_read_api(SANE_Handle handle, SANE_Byte* data, SANE_Int max_length, SANE_Int* length)
|
|||
|
{
|
|||
|
return SANE_STATUS_INVAL;
|
|||
|
}
|
|||
|
void sane_cancel_api(SANE_Handle handle)
|
|||
|
{}
|
|||
|
SANE_Status sane_set_io_mode_api(SANE_Handle handle, SANE_Bool non_blocking)
|
|||
|
{
|
|||
|
return SANE_STATUS_INVAL;
|
|||
|
}
|
|||
|
SANE_Status sane_get_select_fd_api(SANE_Handle handle, SANE_Int* fd)
|
|||
|
{
|
|||
|
return SANE_STATUS_INVAL;
|
|||
|
}
|
|||
|
SANE_String_Const sane_strstatus_api(SANE_Status status)
|
|||
|
{
|
|||
|
return "";
|
|||
|
}
|
|||
|
SANE_Status sane_io_control_api(SANE_Handle h, unsigned long code, void* data, unsigned* len)
|
|||
|
{
|
|||
|
return SANE_STATUS_INVAL;
|
|||
|
}
|
|||
|
SANE_Status sane_init_api(SANE_Int* version_code, SANE_Auth_Callback authorize)
|
|||
|
{
|
|||
|
return SANE_STATUS_INVAL;
|
|||
|
}
|
|||
|
void sane_exit_api(void)
|
|||
|
{}
|
|||
|
};
|
|||
|
|
|||
|
template<typename ... Args>
|
|||
|
static int msg_box(HWND owner, UINT type, const wchar_t* title, const wchar_t* fmt, Args ... args)
|
|||
|
{
|
|||
|
size_t size = _snwprintf(nullptr, 0, fmt, args ...) + 1;
|
|||
|
std::unique_ptr<wchar_t[]> buf(new wchar_t[size]);
|
|||
|
|
|||
|
_snwprintf(buf.get(), size, fmt, args ...);
|
|||
|
|
|||
|
return ::MessageBoxW(owner, buf.get(), title, type);
|
|||
|
}
|
|||
|
const wchar_t* peer_bulk_status(int s, wchar_t unk[20])
|
|||
|
{
|
|||
|
#define RETURN_EQUAL(v, e) \
|
|||
|
if(v == e) \
|
|||
|
return L###e;
|
|||
|
|
|||
|
RETURN_EQUAL(s, BULK_STATUS_NOT_START);
|
|||
|
RETURN_EQUAL(s, BULK_STATUS_IDLE);
|
|||
|
RETURN_EQUAL(s, BULK_STATUS_IO);
|
|||
|
RETURN_EQUAL(s, BULK_STATUS_ERROR);
|
|||
|
RETURN_EQUAL(s, BULK_STATUS_RESET);
|
|||
|
|
|||
|
swprintf_s(unk, 18, L"%x", s);
|
|||
|
|
|||
|
return unk;
|
|||
|
}
|
|||
|
|
|||
|
// CDlgScanner 对话框
|
|||
|
|
|||
|
IMPLEMENT_DYNAMIC(CDlgScanner, CDialogEx)
|
|||
|
|
|||
|
CDlgScanner::CDlgScanner(CWnd* pParent /*=nullptr*/)
|
|||
|
: CDialogEx(IDD_SCANNER, pParent)
|
|||
|
, scanner_(NULL), auto_tx_file_(-1), auto_tx_(false)
|
|||
|
, setting_ui_(NULL)
|
|||
|
{
|
|||
|
g_my_inst = GetModuleHandle(NULL);
|
|||
|
|
|||
|
threads_ = new thread_pool<CDlgScanner>(this);
|
|||
|
parent_ = pParent ? pParent->m_hWnd : NULL;
|
|||
|
auto_wait_ = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|||
|
|
|||
|
char buf[40] = { 0 };
|
|||
|
sscanf(" ether fe:26:f4:f3:29:07 txqueuelen 1000 (Ethernet)", " ether %s", buf);
|
|||
|
}
|
|||
|
|
|||
|
CDlgScanner::~CDlgScanner()
|
|||
|
{
|
|||
|
if (scanner_)
|
|||
|
{
|
|||
|
scanner_->close();
|
|||
|
scanner_->release();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void CDlgScanner::DoDataExchange(CDataExchange* pDX)
|
|||
|
{
|
|||
|
CDialogEx::DoDataExchange(pDX);
|
|||
|
// DDX_Control(pDX, IDC_TAB_OPT, tab_opt_);
|
|||
|
DDX_Control(pDX, IDC_TAB_OPER, tab_oper_);
|
|||
|
}
|
|||
|
|
|||
|
void CDlgScanner::set_device(usb::LPUSBPNP pnp)
|
|||
|
{
|
|||
|
if (!pnp)
|
|||
|
{
|
|||
|
auto_tx_ = false;
|
|||
|
SetEvent(auto_wait_);
|
|||
|
}
|
|||
|
((CButton*)GetDlgItem(IDC_CHECK_REPEAT))->SetCheck(BST_UNCHECKED);
|
|||
|
|
|||
|
KillTimer(TIMER_ID_REFRESH_BULK);
|
|||
|
((CButton*)GetDlgItem(IDC_CHECK_AUTO))->SetCheck(BST_UNCHECKED);
|
|||
|
enable_buttons(pnp != NULL);
|
|||
|
|
|||
|
if (scanner_)
|
|||
|
{
|
|||
|
scanner_->close();
|
|||
|
scanner_->release();
|
|||
|
scanner_ = NULL;
|
|||
|
}
|
|||
|
|
|||
|
if (setting_ui_)
|
|||
|
{
|
|||
|
delete setting_ui_;
|
|||
|
setting_ui_ = NULL;
|
|||
|
}
|
|||
|
|
|||
|
if (pnp)
|
|||
|
{
|
|||
|
int err = 0;
|
|||
|
|
|||
|
scanner_ = new scanner_handler();
|
|||
|
err = scanner_->open_usb_scanner(pnp->device);
|
|||
|
if (err)
|
|||
|
{
|
|||
|
scanner_->release();
|
|||
|
scanner_ = NULL;
|
|||
|
msg_box(m_hWnd, MB_OK, L"Error", L"Open %04X:%04X failed with error %d.", pnp->vid, pnp->pid, err);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
wchar_t buf[128] = { 0 };
|
|||
|
uint8_t h = 0, l = 0;
|
|||
|
|
|||
|
swprintf_s(buf, _countof(buf) - 1, L"%04X:%04X", pnp->vid, pnp->pid);
|
|||
|
::SetWindowTextW(m_hWnd, buf);
|
|||
|
|
|||
|
err = scanner_->get_protocol_version(&h, &l);
|
|||
|
if (err)
|
|||
|
{
|
|||
|
msg_box(m_hWnd, MB_OK, L"Unsupported Scanner", L"Failed to get protocol version with error %d.", err);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
swprintf_s(buf, _countof(buf) - 1, L"%u.%u", h, l);
|
|||
|
SetDlgItemTextW(IDC_EDIT_PROTOCOL_VER, buf);
|
|||
|
|
|||
|
refresh_bulk_status();
|
|||
|
//SetTimer(TIMER_ID_REFRESH_BULK, 1000, NULL);
|
|||
|
RECT r = { 0 };
|
|||
|
std::string all("");
|
|||
|
|
|||
|
scanner_->option_get_all(all);
|
|||
|
scanner_handler::reorder_device_config_json(all);
|
|||
|
sane::reset_opts(all.c_str());
|
|||
|
|
|||
|
GetDlgItem(IDC_STATIC_OPTS)->GetWindowRect(&r);
|
|||
|
ScreenToClient(&r);
|
|||
|
//ClientToScreen(&r);
|
|||
|
setting_ui_ = new dlg_setting(m_hWnd, &sane_api_, (SANE_Handle)this, &r);
|
|||
|
setting_ui_->show(true);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
void CDlgScanner::get_option(const char* name, void* value, size_t size)
|
|||
|
{
|
|||
|
scanner_->option_value_get(name, value, size);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
int CDlgScanner::refresh_bulk_status(void)
|
|||
|
{
|
|||
|
EP0REPLYSTATUS s = { 0 };
|
|||
|
wchar_t buf[128] = { 0 };
|
|||
|
int err = scanner_->get_scanner_status(&s);
|
|||
|
static uint32_t max_sent = 0, max_cmd = 0;
|
|||
|
|
|||
|
if (err == 0)
|
|||
|
{
|
|||
|
SetDlgItemTextW(IDC_EDIT_BUILK_IN, peer_bulk_status(s.in_status, buf));
|
|||
|
if (s.in_status == BULK_STATUS_IO)
|
|||
|
{
|
|||
|
swprintf_s(buf, _countof(buf) - 1, L"BULK_STATUS_IO(Want: %x)", s.bytes_to_sent);
|
|||
|
SetDlgItemTextW(IDC_EDIT_BUILK_IN, buf);
|
|||
|
}
|
|||
|
SetDlgItemTextW(IDC_EDIT_BULK_OUT, peer_bulk_status(s.out_status, buf));
|
|||
|
if (s.out_status == BULK_STATUS_IO)
|
|||
|
{
|
|||
|
swprintf_s(buf, _countof(buf) - 1, L"BULK_STATUS_IO(Need: %x)", s.task_required_bytes);
|
|||
|
SetDlgItemTextW(IDC_EDIT_BULK_OUT, buf);
|
|||
|
}
|
|||
|
|
|||
|
if (max_sent < s.packets_to_sent)
|
|||
|
max_sent = s.packets_to_sent;
|
|||
|
if (max_cmd < s.task_cnt)
|
|||
|
max_cmd = s.task_cnt;
|
|||
|
|
|||
|
swprintf_s(buf, _countof(buf) - 1, L"%u (max: %u)", s.packets_to_sent, max_sent);
|
|||
|
SetDlgItemTextW(IDC_EDIT_SENT_QUE, buf);
|
|||
|
|
|||
|
swprintf_s(buf, _countof(buf) - 1, L"%u (max: %u)", s.task_cnt, max_cmd);
|
|||
|
SetDlgItemTextW(IDC_EDIT_CMD_QUE, buf);
|
|||
|
}
|
|||
|
|
|||
|
return err;
|
|||
|
}
|
|||
|
void CDlgScanner::thread_auto_tx_file(void)
|
|||
|
{
|
|||
|
char loc[256] = { 0 },
|
|||
|
remt[256] = { 0 };
|
|||
|
uint32_t ind = 0, err = 0;
|
|||
|
std::string file(""), prev(""), ext("");
|
|||
|
|
|||
|
::GetDlgItemTextA(m_hWnd, IDC_EDIT_LOCAL, loc, _countof(loc) - 1);
|
|||
|
::GetDlgItemTextA(m_hWnd, IDC_EDIT_REMOTE, remt, _countof(remt) - 1);
|
|||
|
prev = loc;
|
|||
|
ind = prev.rfind('.');
|
|||
|
ext = ")" + prev.substr(ind);
|
|||
|
prev.erase(ind);
|
|||
|
file = loc;
|
|||
|
prev += " (";
|
|||
|
|
|||
|
ind = file.rfind('\\');
|
|||
|
file.erase(ind + 1);
|
|||
|
file += "tx";
|
|||
|
mkdir(file.c_str());
|
|||
|
file = loc;
|
|||
|
prev.insert(ind, "\\tx");
|
|||
|
|
|||
|
auto tx_over = [&](uint64_t size, uint64_t cur, uint32_t err_code) -> int
|
|||
|
{
|
|||
|
err = err_code;
|
|||
|
if (cur >= size || err_code)
|
|||
|
{
|
|||
|
SetEvent(auto_wait_);
|
|||
|
log_cls::log(LOG_LEVEL_DEBUG, "File transfer ended with error code %d\r\n", err_code);
|
|||
|
}
|
|||
|
|
|||
|
return 0;
|
|||
|
};
|
|||
|
|
|||
|
ind = 0;
|
|||
|
while (auto_tx_)
|
|||
|
{
|
|||
|
ResetEvent(auto_wait_);
|
|||
|
scanner_->file_transfer(file.c_str(), remt, true, tx_over);
|
|||
|
if (WaitForSingleObject(auto_wait_, 10 * 60 * 1000) == WAIT_TIMEOUT)
|
|||
|
{
|
|||
|
msg_box(m_hWnd, MB_OK, L"Send file", L"Wait timeouted!\r\nSend: %s", usb::a2u(file.c_str()).c_str());
|
|||
|
((CButton*)GetDlgItem(IDC_CHECK_REPEAT))->SetCheck(BST_UNCHECKED);
|
|||
|
OnBnClickedCheckRepeat();
|
|||
|
break;
|
|||
|
}
|
|||
|
else if (err)
|
|||
|
{
|
|||
|
msg_box(m_hWnd, MB_OK | MB_ICONSTOP, L"Send file", L"Failed with error code : %d", err);
|
|||
|
((CButton*)GetDlgItem(IDC_CHECK_REPEAT))->SetCheck(BST_UNCHECKED);
|
|||
|
OnBnClickedCheckRepeat();
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (!auto_tx_)
|
|||
|
break;
|
|||
|
|
|||
|
Sleep(1000);
|
|||
|
ResetEvent(auto_wait_);
|
|||
|
// file_util::force_move_file(usb::a2u((file + ".reply").c_str()).c_str(), usb::a2u((prev + std::to_string(++ind) + ext).c_str()).c_str());
|
|||
|
file = prev + std::to_string(++ind) + ext;
|
|||
|
scanner_->file_transfer(file.c_str(), remt, false, tx_over);
|
|||
|
if (WaitForSingleObject(auto_wait_, 10 * 60 * 1000) == WAIT_TIMEOUT)
|
|||
|
{
|
|||
|
msg_box(m_hWnd, MB_OK, L"Receive file", L"Wait timeouted!\r\nReceive to %s", usb::a2u(file.c_str()).c_str());
|
|||
|
((CButton*)GetDlgItem(IDC_CHECK_REPEAT))->SetCheck(BST_UNCHECKED);
|
|||
|
OnBnClickedCheckRepeat();
|
|||
|
break;
|
|||
|
}
|
|||
|
else if (err)
|
|||
|
{
|
|||
|
msg_box(m_hWnd, MB_OK | MB_ICONSTOP, L"Receive file", L"Failed with error code : %d", err);
|
|||
|
((CButton*)GetDlgItem(IDC_CHECK_REPEAT))->SetCheck(BST_UNCHECKED);
|
|||
|
OnBnClickedCheckRepeat();
|
|||
|
break;
|
|||
|
}
|
|||
|
Sleep(1000);
|
|||
|
}
|
|||
|
|
|||
|
((CButton*)GetDlgItem(IDC_CHECK_REPEAT))->SetCheck(BST_UNCHECKED);
|
|||
|
auto_tx_ = false;
|
|||
|
enable_buttons(scanner_ != NULL);
|
|||
|
// msg_box(m_hWnd, MB_OK, L"Repeat S/R", L"exited.");
|
|||
|
}
|
|||
|
void CDlgScanner::enable_buttons(bool enable)
|
|||
|
{
|
|||
|
//GetDlgItem(IDC_BUTTON_RESET_BULK)->EnableWindow(enable);
|
|||
|
//GetDlgItem(IDC_CHECK_AUTO)->EnableWindow(enable);
|
|||
|
|
|||
|
GetDlgItem(IDC_BUTTON_SCAN)->EnableWindow(enable);
|
|||
|
GetDlgItem(IDC_BUTTON_SEND)->EnableWindow(enable);
|
|||
|
GetDlgItem(IDC_BUTTON_RECEIVE)->EnableWindow(enable);
|
|||
|
GetDlgItem(IDC_CHECK_REPEAT)->EnableWindow(enable);
|
|||
|
GetDlgItem(IDC_BUTTON_START_PROG)->EnableWindow(enable);
|
|||
|
GetDlgItem(IDC_BUTTON_SEND_EP0)->EnableWindow(enable);
|
|||
|
}
|
|||
|
|
|||
|
BEGIN_MESSAGE_MAP(CDlgScanner, CDialogEx)
|
|||
|
ON_NOTIFY(TCN_SELCHANGE, IDC_TAB_OPER, &CDlgScanner::OnTcnSelchangeTabOper)
|
|||
|
ON_BN_CLICKED(IDOK, &CDlgScanner::OnBnClickedOk)
|
|||
|
ON_BN_CLICKED(IDC_BUTTON_RESET_BULK, &CDlgScanner::OnBnClickedButtonResetBulk)
|
|||
|
ON_BN_CLICKED(IDC_BUTTON_BROWSE_IMG_PATH, &CDlgScanner::OnBnClickedButtonBrowseSavingPath)
|
|||
|
ON_BN_CLICKED(IDC_BUTTON_SCAN, &CDlgScanner::OnBnClickedButtonScan)
|
|||
|
ON_BN_CLICKED(IDC_BUTTON_BROWSE_LOCAL, &CDlgScanner::OnBnClickedButtonBrowseFile)
|
|||
|
ON_BN_CLICKED(IDC_BUTTON_SEND, &CDlgScanner::OnBnClickedButtonSendFile)
|
|||
|
ON_BN_CLICKED(IDC_BUTTON_RECEIVE, &CDlgScanner::OnBnClickedButtonRecvFile)
|
|||
|
ON_BN_CLICKED(IDC_BUTTON_START_PROG, &CDlgScanner::OnBnClickedButtonStartProgram)
|
|||
|
ON_BN_CLICKED(IDC_BUTTON_SEND_EP0, &CDlgScanner::OnBnClickedButtonSendEp0)
|
|||
|
ON_WM_TIMER()
|
|||
|
ON_BN_CLICKED(IDC_CHECK_AUTO, &CDlgScanner::OnBnClickedCheckAuto)
|
|||
|
ON_BN_CLICKED(IDC_BUTTON_REFRESH, &CDlgScanner::OnBnClickedButtonRefresh)
|
|||
|
ON_BN_CLICKED(IDC_CHECK_REPEAT, &CDlgScanner::OnBnClickedCheckRepeat)
|
|||
|
END_MESSAGE_MAP()
|
|||
|
|
|||
|
|
|||
|
// CDlgScanner 消息处理程序
|
|||
|
BOOL CDlgScanner::OnInitDialog()
|
|||
|
{
|
|||
|
CDialogEx::OnInitDialog();
|
|||
|
|
|||
|
// 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
|
|||
|
// 执行此操作
|
|||
|
|
|||
|
// TODO: 在此添加额外的初始化代码
|
|||
|
int ind = 0;
|
|||
|
tab_oper_.InsertItem(ind++, TEXT("Status"));
|
|||
|
tab_oper_.InsertItem(ind++, TEXT("Scan"));
|
|||
|
tab_oper_.InsertItem(ind++, TEXT("File"));
|
|||
|
tab_oper_.InsertItem(ind++, TEXT("Prog"));
|
|||
|
tab_oper_.InsertItem(ind++, TEXT("Ctrl"));
|
|||
|
tab_oper_.SetCurSel(0);
|
|||
|
OnTcnSelchangeTabOper(NULL, (LRESULT*)&ind);
|
|||
|
|
|||
|
SetDlgItemText(IDC_EDIT_LOCAL, TEXT("D:\\boxroom\\usb-tx-file\\VMwareworkstation.exe"));
|
|||
|
SetDlgItemText(IDC_EDIT_REMOTE, TEXT("/root/.scanner/log/VMwareworkstation.exe"));
|
|||
|
|
|||
|
sane_api_.sane_get_devices_api = &sane::sane_get_devices_api;
|
|||
|
sane_api_.sane_open_api = &sane::sane_open_api;
|
|||
|
sane_api_.sane_close_api = &sane::sane_close_api;
|
|||
|
sane_api_.sane_get_option_descriptor_api = &sane::sane_get_option_descriptor_api;
|
|||
|
sane_api_.sane_control_option_api = &sane::sane_control_option_api;
|
|||
|
sane_api_.sane_get_parameters_api = &sane::sane_get_parameters_api;
|
|||
|
sane_api_.sane_start_api = &sane::sane_start_api;
|
|||
|
sane_api_.sane_read_api = &sane::sane_read_api;
|
|||
|
sane_api_.sane_cancel_api = &sane::sane_cancel_api;
|
|||
|
sane_api_.sane_set_io_mode_api = &sane::sane_set_io_mode_api;
|
|||
|
sane_api_.sane_get_select_fd_api = &sane::sane_get_select_fd_api;
|
|||
|
sane_api_.sane_strstatus_api = &sane::sane_strstatus_api;
|
|||
|
sane_api_.sane_io_control_api = &sane::sane_io_control_api;
|
|||
|
sane_api_.sane_init_api = &sane::sane_init_api;
|
|||
|
sane_api_.sane_exit_api = &sane::sane_exit_api;
|
|||
|
|
|||
|
return FALSE; // 除非将焦点设置到控件,否则返回 TRUE
|
|||
|
}
|
|||
|
BOOL CDlgScanner::PreTranslateMessage(MSG* pMsg)
|
|||
|
{
|
|||
|
if (pMsg->message == WM_SHOWWINDOW && pMsg->wParam == 0 && pMsg->lParam == SW_PARENTCLOSING)
|
|||
|
return TRUE;
|
|||
|
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void CDlgScanner::OnTcnSelchangeTabOper(NMHDR* pNMHDR, LRESULT* pResult)
|
|||
|
{
|
|||
|
// TODO: 在此添加控件通知处理程序代码
|
|||
|
UINT statu[] = {IDC_STATIC_BULK_IN, IDC_STATIC_BULK_OUT, IDC_STATIC_CMD_QUE, IDC_STATIC_SENT_QUE
|
|||
|
, IDC_EDIT_BUILK_IN, IDC_EDIT_BULK_OUT, IDC_EDIT_CMD_QUE, IDC_EDIT_SENT_QUE
|
|||
|
, IDC_BUTTON_RESET_BULK, IDC_CHECK_AUTO, IDC_BUTTON_REFRESH},
|
|||
|
scan[] = {IDC_STATIC_IMG_PATH, IDC_STATIC_COUNT, IDC_EDIT_IMG_PATH, IDC_EDIT_COUNT, IDC_BUTTON_BROWSE_IMG_PATH, IDC_BUTTON_SCAN},
|
|||
|
file[] = {IDC_STATIC_LOCAL, IDC_STATIC_REMOTE, IDC_EDIT_LOCAL, IDC_EDIT_REMOTE, IDC_BUTTON_BROWSE_LOCAL
|
|||
|
, IDC_BUTTON_SEND, IDC_BUTTON_RECEIVE, IDC_CHECK_REPEAT},
|
|||
|
prog[] = {IDC_STATIC_CMD, IDC_STATIC_PARAM, IDC_EDIT_CMD, IDC_EDIT_PARAM, IDC_BUTTON_START_PROG},
|
|||
|
ctrl[] = {IDC_STATIC_TYPE, IDC_STATIC_REQ, IDC_STATIC_IND, IDC_STATIC_VAL, IDC_STATIC_LEN, IDC_STATIC_DATA
|
|||
|
, IDC_EDIT_TYPE, IDC_EDIT_REQ, IDC_EDIT_IND, IDC_EDIT_VAL, IDC_EDIT_LEN, IDC_EDIT_DATA
|
|||
|
, IDC_BUTTON_SEND_EP0};
|
|||
|
int sel = tab_oper_.GetCurSel(), show = sel-- == 0 ? SW_SHOW : SW_HIDE;
|
|||
|
|
|||
|
for (auto& v : statu)
|
|||
|
GetDlgItem(v)->ShowWindow(show);
|
|||
|
|
|||
|
show = sel-- == 0 ? SW_SHOW : SW_HIDE;
|
|||
|
for (auto& v : scan)
|
|||
|
GetDlgItem(v)->ShowWindow(show);
|
|||
|
|
|||
|
show = sel-- == 0 ? SW_SHOW : SW_HIDE;
|
|||
|
for (auto& v : file)
|
|||
|
GetDlgItem(v)->ShowWindow(show);
|
|||
|
|
|||
|
show = sel-- == 0 ? SW_SHOW : SW_HIDE;
|
|||
|
for (auto& v : prog)
|
|||
|
GetDlgItem(v)->ShowWindow(show);
|
|||
|
|
|||
|
show = sel-- == 0 ? SW_SHOW : SW_HIDE;
|
|||
|
for (auto& v : ctrl)
|
|||
|
GetDlgItem(v)->ShowWindow(show);
|
|||
|
|
|||
|
*pResult = 0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void CDlgScanner::OnBnClickedOk()
|
|||
|
{
|
|||
|
// TODO: 在此添加控件通知处理程序代码
|
|||
|
if (IsWindow(parent_))
|
|||
|
::PostMessage(parent_, WM_OPENNING_DLG_CLOSED, 0, (LPARAM)this);
|
|||
|
|
|||
|
CDialogEx::OnOK();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void CDlgScanner::OnBnClickedButtonResetBulk()
|
|||
|
{
|
|||
|
// TODO: 在此添加控件通知处理程序代码
|
|||
|
int err = scanner_->reset_message_que();
|
|||
|
msg_box(m_hWnd, MB_OK, L"Reset-Bulk", L"Result = %d", err);
|
|||
|
if (err == 0)
|
|||
|
{
|
|||
|
enable_buttons(true);
|
|||
|
auto_tx_ = false;
|
|||
|
SetEvent(auto_wait_);
|
|||
|
}
|
|||
|
}
|
|||
|
void CDlgScanner::OnBnClickedButtonBrowseSavingPath()
|
|||
|
{
|
|||
|
// TODO: 在此添加控件通知处理程序代码
|
|||
|
}
|
|||
|
void CDlgScanner::OnBnClickedButtonScan()
|
|||
|
{
|
|||
|
// TODO: 在此添加控件通知处理程序代码
|
|||
|
}
|
|||
|
void CDlgScanner::OnBnClickedButtonBrowseFile()
|
|||
|
{
|
|||
|
// TODO: 在此添加控件通知处理程序代码
|
|||
|
}
|
|||
|
void CDlgScanner::OnBnClickedButtonSendFile()
|
|||
|
{
|
|||
|
// TODO: 在此添加控件通知处理程序代码
|
|||
|
char l[256] = { 0 },
|
|||
|
r[256] = { 0 };
|
|||
|
int err = 0;
|
|||
|
|
|||
|
::GetDlgItemTextA(m_hWnd, IDC_EDIT_LOCAL, l, _countof(l) - 1);
|
|||
|
::GetDlgItemTextA(m_hWnd, IDC_EDIT_REMOTE, r, _countof(r) - 1);
|
|||
|
err = scanner_->file_transfer(l, r, true);
|
|||
|
if(err)
|
|||
|
msg_box(m_hWnd, MB_OK, L"Send File", L"Result = %d", err);
|
|||
|
}
|
|||
|
void CDlgScanner::OnBnClickedButtonRecvFile()
|
|||
|
{
|
|||
|
// TODO: 在此添加控件通知处理程序代码
|
|||
|
char l[256] = { 0 },
|
|||
|
r[256] = { 0 };
|
|||
|
int err = 0;
|
|||
|
|
|||
|
::GetDlgItemTextA(m_hWnd, IDC_EDIT_LOCAL, l, _countof(l) - 1);
|
|||
|
::GetDlgItemTextA(m_hWnd, IDC_EDIT_REMOTE, r, _countof(r) - 1);
|
|||
|
err = scanner_->file_transfer(l, r, false);
|
|||
|
if (err)
|
|||
|
msg_box(m_hWnd, MB_OK, L"Receive File", L"Result = %d", err);
|
|||
|
}
|
|||
|
void CDlgScanner::OnBnClickedButtonStartProgram()
|
|||
|
{
|
|||
|
// TODO: 在此添加控件通知处理程序代码
|
|||
|
char key[80] = { 0 }, val[80] = { 0 };
|
|||
|
int err = 0;
|
|||
|
|
|||
|
::GetDlgItemTextA(m_hWnd, IDC_EDIT_CMD, key, _countof(key) - 1);
|
|||
|
err = scanner_->option_value_get(key, val, 40);
|
|||
|
if (err == 0)
|
|||
|
::SetDlgItemTextA(m_hWnd, IDC_EDIT_PARAM, val);
|
|||
|
}
|
|||
|
void CDlgScanner::OnBnClickedButtonSendEp0()
|
|||
|
{
|
|||
|
// TODO: 在此添加控件通知处理程序代码
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void CDlgScanner::OnTimer(UINT_PTR nIDEvent)
|
|||
|
{
|
|||
|
// TODO: 在此添加消息处理程序代码和/或调用默认值
|
|||
|
if(nIDEvent == TIMER_ID_REFRESH_BULK)
|
|||
|
refresh_bulk_status();
|
|||
|
|
|||
|
CDialogEx::OnTimer(nIDEvent);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void CDlgScanner::OnBnClickedCheckAuto()
|
|||
|
{
|
|||
|
// TODO: 在此添加控件通知处理程序代码
|
|||
|
bool checked = ((CButton*)GetDlgItem(IDC_CHECK_AUTO))->GetCheck() == BST_CHECKED;
|
|||
|
|
|||
|
GetDlgItem(IDC_BUTTON_REFRESH)->EnableWindow(!checked);
|
|||
|
if (checked)
|
|||
|
SetTimer(TIMER_ID_REFRESH_BULK, 1000, NULL);
|
|||
|
else
|
|||
|
KillTimer(TIMER_ID_REFRESH_BULK);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void CDlgScanner::OnBnClickedButtonRefresh()
|
|||
|
{
|
|||
|
// TODO: 在此添加控件通知处理程序代码
|
|||
|
refresh_bulk_status();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void CDlgScanner::OnBnClickedCheckRepeat()
|
|||
|
{
|
|||
|
// TODO: 在此添加控件通知处理程序代码
|
|||
|
auto_tx_ = ((CButton*)GetDlgItem(IDC_CHECK_REPEAT))->GetCheck() == BST_CHECKED;
|
|||
|
|
|||
|
enable_buttons(!auto_tx_);
|
|||
|
GetDlgItem(IDC_CHECK_REPEAT)->EnableWindow(TRUE);
|
|||
|
GetDlgItem(IDC_CHECK_AUTO)->EnableWindow(TRUE);
|
|||
|
if (auto_tx_)
|
|||
|
{
|
|||
|
if (auto_tx_file_ == -1)
|
|||
|
auto_tx_file_ = threads_->thread_new(&CDlgScanner::thread_auto_tx_file);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (auto_tx_file_ != -1)
|
|||
|
{
|
|||
|
SetEvent(auto_wait_);
|
|||
|
threads_->thread_stop(auto_tx_file_);
|
|||
|
auto_tx_file_ = -1;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|