From 356be76a2e2ff4aced6abedee0dda1c0821f4ee4 Mon Sep 17 00:00:00 2001 From: gb <741021719@qq.com> Date: Sat, 27 Jan 2024 17:57:15 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=94=B6=E5=9B=BE=E6=B5=81?= =?UTF-8?q?=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sln/usb_tools/DlgScanner.cpp | 124 ++++++++++++++++++++++-- sln/usb_tools/DlgScanner.h | 5 + sln/usb_tools/opt_ui/DlgPage.h | 1 + sln/usb_tools/usb_tools.vcxproj | 8 ++ sln/usb_tools/usb_tools.vcxproj.filters | 9 ++ 5 files changed, 137 insertions(+), 10 deletions(-) diff --git a/sln/usb_tools/DlgScanner.cpp b/sln/usb_tools/DlgScanner.cpp index 4d7ec94..fd49afc 100644 --- a/sln/usb_tools/DlgScanner.cpp +++ b/sln/usb_tools/DlgScanner.cpp @@ -15,6 +15,7 @@ #include + #define TIMER_ID_REFRESH_BULK 1001 HMODULE g_my_inst; @@ -718,19 +719,16 @@ const wchar_t* scanner_status(int s, wchar_t unk[20]) } static DWORD thread_open_id_ = 0; -static safe_fifo images_("images"); +static safe_fifo images_("images"); static DWORD WINAPI thread_open_image(void* lp) { while (1) { - std::string file(""); + std::wstring file(L""); if (images_.take(file, true)) - { - if (file.empty()) - break; - - ShellExecuteA(NULL, "Open", file.c_str(), NULL, NULL, SW_SHOWNORMAL); - } + ShellExecuteW(NULL, L"Open", file.c_str(), NULL, NULL, SW_SHOWNORMAL); + else + break; } return 0; @@ -783,7 +781,7 @@ CDlgScanner::CDlgScanner(CWnd* pParent /*=nullptr*/) CDlgScanner::~CDlgScanner() { ::PostThreadMessage(thread_open_id_, WM_USER + 1001, 0, 0); - images_.save("", true); + images_.trigger(); if (scanner_) { scanner_->close(); @@ -970,6 +968,83 @@ int CDlgScanner::set_option(const char* name, void* value, int type, size_t len, return 0; } +void CDlgScanner::thread_fetch_image(void) +{ + size_t size = SIZE_MB(1), off = 0, rd = 0; + uint8_t *buf = new uint8_t[size]; + int dpi = scanner_->get_resolution(); + + while (1) + { + SANE_Parameters sp; + + memset(&sp, 0, sizeof(sp)); + scanner_->get_image_info(&sp); + off = 0; + rd = size; + if (scanner_->read_image_data(buf, &rd) == SCANNER_ERR_NO_DATA && rd == 0) + break; + + std::string bih(utils::bitmap_info_header(sp.pixels_per_line, sp.lines, sp.format == SANE_FRAME_RGB ? 3 * sp.depth : sp.depth, dpi)), + bfh(utils::bitmap_file_header((LPBITMAPINFOHEADER)&bih[0])); + LPBITMAPINFOHEADER head = (LPBITMAPINFOHEADER)&bih[0]; + int line_l = BMP_LINE_BYTES(head->biWidth * head->biBitCount), err = SCANNER_ERR_OK; + char pad[4] = { 0 }; + wchar_t name[40] = { 0 }; + FILE *dst = nullptr; + + swprintf_s(name, _countof(name) - 1, L"\\scanner_%04u.bmp", img_cnt_ + 1); + dst = _wfopen((save_root_ + name).c_str(), L"wb"); + if (dst) + { + fwrite(bfh.c_str(), 1, bfh.length(), dst); + fwrite(bih.c_str(), 1, bih.length(), dst); + } + while (rd) + { + if (dst) + { + if (line_l == sp.bytes_per_line) + { + fwrite(buf, 1, rd, dst); + } + else + { + rd += off; + off = 0; + while (rd >= sp.bytes_per_line) + { + fwrite(buf + off, 1, sp.bytes_per_line, dst); + rd -= sp.bytes_per_line; + off += sp.bytes_per_line; + fwrite(pad, 1, line_l - sp.bytes_per_line, dst); + } + if (rd) + { + memcpy(buf, buf + off, rd); + off = rd; + } + else + off = 0; + } + } + if (SCANNER_ERR_NO_DATA == err) + break; + rd = size - off; + err = scanner_->read_image_data(buf + off, &rd); + } + if (dst) + { + fclose(dst); + if (auto_open_img_) + images_.save(save_root_ + name, true); + } + + img_cnt_++; + ::PostMessage(m_hWnd, WM_TX_IMAGE_CNT, 0, img_cnt_); + } + delete[] buf; +} int CDlgScanner::refresh_bulk_status(bool en_dev_log) { @@ -1233,6 +1308,8 @@ BEGIN_MESSAGE_MAP(CDlgScanner, CDialogEx) ON_CBN_SELCHANGE(IDC_COMBO_BUF_SIZE, &CDlgScanner::OnCbnSelchangeComboBufSize) ON_WM_DESTROY() ON_MESSAGE(WM_SCAN_FINISHED, &CDlgScanner::OnScanFinished) + ON_MESSAGE(WM_TX_IMAGE_CNT, &CDlgScanner::OnImageFetched) + ON_BN_CLICKED(IDC_CHECK_AUTO_OPEN_IMG, &CDlgScanner::OnBnClickedCheckAutoOpenImg) END_MESSAGE_MAP() @@ -1400,11 +1477,16 @@ void CDlgScanner::OnBnClickedButtonBrowseSavingPath() void CDlgScanner::OnBnClickedButtonScan() { // TODO: 在此添加控件通知处理程序代码 - wchar_t title[40] = { 0 }; + wchar_t title[MAX_PATH] = { 0 }; ::GetDlgItemTextW(m_hWnd, IDC_BUTTON_SCAN, title, _countof(title) - 1); if (wcsicmp(title, L"Scan") == 0) { + ::GetDlgItemTextW(m_hWnd, IDC_EDIT_IMG_PATH, title, _countof(title) - 1); + save_root_ = title; + file_util::force_create_folder(title); + + threads_.stop("thread_fetch_image"); img_cnt_ = 0; paper_cnt_ = 0; SetDlgItemInt(IDC_EDIT_COUNT, img_cnt_); @@ -1418,9 +1500,18 @@ void CDlgScanner::OnBnClickedButtonScan() int err = scanner_->start(&cfg, over); utils::to_log(LOG_LEVEL_DEBUG, "Start to scan = %s\r\n", usb::u2a(scanner_status(err, title)).c_str()); if (err) + { + OnDeviceStatus(0, (LPARAM)err); msg_box(m_hWnd, MB_OK, L"Error", L"Failed in starting scanning with code: %s", scanner_status(err, title)); + } else { + auto rcv = [this]() -> void + { + thread_fetch_image(); + }; + + threads_.start(rcv, "thread_fetch_image"); utils::to_log(LOG_LEVEL_DEBUG, "Device configuration: %s\n", cfg.c_str()); ::SetDlgItemTextW(m_hWnd, IDC_BUTTON_SCAN, L"Stop"); OnDeviceStatus(0, (LPARAM)SCANNER_ERR_DEVICE_BUSY); @@ -1542,6 +1633,12 @@ void CDlgScanner::OnBnClickedButtonRefresh() refresh_bulk_status(); } +void CDlgScanner::OnBnClickedCheckAutoOpenImg() +{ + // TODO: 在此添加控件通知处理程序代码 + auto_open_img_ = ((CButton*)GetDlgItem(IDC_CHECK_AUTO_OPEN_IMG))->GetCheck() == BST_CHECKED; +} + void CDlgScanner::OnBnClickedCheckRepeat() { @@ -1655,6 +1752,12 @@ LRESULT CDlgScanner::OnScanFinished(WPARAM wp, LPARAM lp) return 0; } +LRESULT CDlgScanner::OnImageFetched(WPARAM wp, LPARAM lp) +{ + SetDlgItemInt(IDC_EDIT_COUNT, lp, FALSE); + + return 0; +} void CDlgScanner::OnCbnSelchangeComboBufSize() @@ -1685,3 +1788,4 @@ void CDlgScanner::OnDestroy() // TODO: 在此处添加消息处理程序代码 set_device(NULL); } + diff --git a/sln/usb_tools/DlgScanner.h b/sln/usb_tools/DlgScanner.h index 44ea00d..aedc994 100644 --- a/sln/usb_tools/DlgScanner.h +++ b/sln/usb_tools/DlgScanner.h @@ -72,6 +72,8 @@ class CDlgScanner : public CDialogEx uint32_t max_cmd_; uint32_t bulk_statu_tick_ = 0; safe_thread threads_; + std::wstring save_root_; + volatile bool auto_open_img_ = false; public: CDlgScanner(CWnd* pParent = nullptr); // 标准构造函数 @@ -104,6 +106,7 @@ public: void get_option(const char* name, void* value, size_t size); int get_all_option(std::string& opts_json); int set_option(const char* name, void* value, int type, size_t len, size_t max_len, int* after); + void thread_fetch_image(void); public: CTabCtrl tab_opt_; @@ -131,8 +134,10 @@ public: afx_msg LRESULT OnTransDiretion(WPARAM wp, LPARAM lp); afx_msg LRESULT OnTransProgress(WPARAM wp, LPARAM lp); afx_msg LRESULT OnScanFinished(WPARAM wp, LPARAM lp); + afx_msg LRESULT OnImageFetched(WPARAM wp, LPARAM lp); afx_msg void OnCbnSelchangeComboBufSize(); CComboBox buf_; afx_msg void OnDestroy(); CProgressCtrl tx_prog_; + afx_msg void OnBnClickedCheckAutoOpenImg(); }; diff --git a/sln/usb_tools/opt_ui/DlgPage.h b/sln/usb_tools/opt_ui/DlgPage.h index 2ba1a00..41def3f 100644 --- a/sln/usb_tools/opt_ui/DlgPage.h +++ b/sln/usb_tools/opt_ui/DlgPage.h @@ -34,6 +34,7 @@ #define WM_DEVICE_STATTUS WM_USER + 324 // WPARAM: unused; LPARAM: scanner_status #define WM_TX_DIRECTION WM_USER + 325 // WPARAM: unused; LPARAM: bool - true: send; false - receive #define WM_TX_PROGRESS WM_USER + 326 // WPARAM: high of double; LPARAM: low of double +#define WM_TX_IMAGE_CNT WM_USER + 327 // WPARAM: unused; LPARAM: count extern HMODULE g_my_inst; diff --git a/sln/usb_tools/usb_tools.vcxproj b/sln/usb_tools/usb_tools.vcxproj index 49a087e..adaa545 100644 --- a/sln/usb_tools/usb_tools.vcxproj +++ b/sln/usb_tools/usb_tools.vcxproj @@ -207,8 +207,10 @@ + + @@ -268,6 +270,12 @@ NotUsing NotUsing + + NotUsing + NotUsing + NotUsing + NotUsing + NotUsing NotUsing diff --git a/sln/usb_tools/usb_tools.vcxproj.filters b/sln/usb_tools/usb_tools.vcxproj.filters index 7033155..2547ede 100644 --- a/sln/usb_tools/usb_tools.vcxproj.filters +++ b/sln/usb_tools/usb_tools.vcxproj.filters @@ -132,6 +132,12 @@ opt-ui + + Imports\sdk + + + Imports\sdk + @@ -215,6 +221,9 @@ opt-ui + + Imports\sdk +