// DlgScanner.cpp: 实现文件 // #include "pch.h" #include "usb_tools.h" #include "DlgScanner.h" #include "afxdialogex.h" #include #include #define TIMER_ID_REFRESH_BULK 1001 #include #include HMODULE g_my_inst; namespace sane { #define ALIGN_INTEGER(v) ALIGN_INT(v, sizeof(int)) static std::vector 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& 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; // 硬件可设置默认�? 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& 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; // 硬件可设置默认�? 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& 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; // 硬件可设置默认�? 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 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 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 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; // 关联�? 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 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 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(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; } } }