增加设备选择对话框;按系列统一DS文件

This commit is contained in:
gb 2022-10-09 11:59:45 +08:00
parent b44dd6940c
commit 8ccfa77c1d
9 changed files with 332 additions and 64 deletions

View File

@ -47,47 +47,23 @@ if "%OEM%"=="hw" (
build.bat hw x86 onlytwain 0x8000 nov
build.bat hw x86 onlytwain 0x9000 nov
) else if "%OEM%" == "lsc" (
build.bat lsc x64 0x8200 %NOV%
build.bat lsc x64 onlytwain 0x8420 nov
build.bat lsc x64 onlytwain 0x8429 nov
build.bat lsc x64 0x8420 %NOV%
build.bat lsc x64 onlytwain 0x8520 nov
build.bat lsc x64 onlytwain 0x8529 nov
build.bat lsc x64 onlytwain 0x8620 nov
build.bat lsc x64 onlytwain 0x8629 nov
build.bat lsc x64 onlytwain 0x8730 nov
build.bat lsc x64 onlytwain 0x8739 nov
set CPU=x86
build.bat lsc x86 0x8200 nov
build.bat lsc x86 onlytwain 0x8420 nov
build.bat lsc x86 onlytwain 0x8429 nov
build.bat lsc x86 0x8420 nov
build.bat lsc x86 onlytwain 0x8520 nov
build.bat lsc x86 onlytwain 0x8529 nov
build.bat lsc x86 onlytwain 0x8620 nov
build.bat lsc x86 onlytwain 0x8629 nov
build.bat lsc x86 onlytwain 0x8730 nov
build.bat lsc x86 onlytwain 0x8739 nov
) else (
build.bat x64 0x100 %NOV%
build.bat x64 onlytwain 0x139 nov
build.bat x64 onlytwain 0x200 nov
build.bat x64 onlytwain 0x239 nov
build.bat x64 onlytwain 0x300 nov
build.bat x64 onlytwain 0x302 nov
build.bat x64 onlytwain 0x339 nov
build.bat x64 onlytwain 0x400 nov
build.bat x64 onlytwain 0x402 nov
build.bat x64 onlytwain 0x439 nov
build.bat x64 onlytwain 0x7823 nov
set CPU=x86
build.bat x86 0x100 nov
build.bat x86 onlytwain 0x139 nov
build.bat x86 onlytwain 0x200 nov
build.bat x86 onlytwain 0x239 nov
build.bat x86 onlytwain 0x300 nov
build.bat x86 onlytwain 0x302 nov
build.bat x86 onlytwain 0x339 nov
build.bat x86 onlytwain 0x400 nov
build.bat x86 onlytwain 0x402 nov
build.bat x86 onlytwain 0x439 nov
build.bat x86 onlytwain 0x7823 nov
)

View File

@ -5,6 +5,10 @@
#include "resource.h"
#include "scanned_img.h" // for local_trans
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// dlg_choose_dev
// CDlgIndicator 对话框
#define WM_SCAN_WORKING WM_USER + 1 // WPARAM: unused; LPARAM: unsed
#define WM_USB_PACKET_RECEIVED WM_USER + 2 // WPARAM: unused; LPARAM: unsed
@ -148,3 +152,113 @@ void dlg_indicator::notify_working(void)
PostMessage(hwnd_, WM_SCAN_WORKING, 0, 0);
}
// CDlgIndicator 消息处理程序
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// dlg_choose_dev
///
dlg_choose_dev::dlg_choose_dev(HWND parent, const std::map<std::string, std::string>& devs) : dlg_base(parent, IDD_CHOOSE_DEV), item_(-1)
{
create();
HWND lst = GetDlgItem(hwnd_, IDC_LIST1);
LV_COLUMNW col = { 0 };
int ind = 0;
ListView_SetExtendedListViewStyle(lst, ListView_GetExtendedListViewStyle(lst) | LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT);
SetWindowLong(lst, GWL_STYLE, GetWindowLong(lst, GWL_STYLE) | LVS_SINGLESEL);
col.mask = LVCF_TEXT | LVCF_WIDTH;
col.cx = 180;
col.pszText = (wchar_t*)L"\u8BBE\u5907\u540D\u79F0";
SendMessageW(lst, LVM_INSERTCOLUMN, ind++, (LPARAM)&col);
col.pszText = (wchar_t*)L"\u5E8F\u5217\u53F7";
SendMessageW(lst, LVM_INSERTCOLUMN, ind++, (LPARAM)&col);
for (std::map<std::string, std::string>::const_iterator it = devs.begin();
it != devs.end(); ++it)
{
std::wstring n(local_trans::a2u(it->first.c_str(), CP_UTF8)),
s(local_trans::a2u(it->second.c_str(), CP_UTF8));
LV_ITEM item = { 0 };
int ind = 0;
item.mask = LVIF_TEXT;
item.pszText = &n[0];
item.iItem = ListView_GetItemCount(lst);
ind = SendMessageW(lst, LVM_INSERTITEMW, 0, (LPARAM)&item);
item.pszText = &s[0];
item.iSubItem = 1;
item.iItem = ind;
SendMessageW(lst, LVM_SETITEMTEXTW, ind, (LPARAM)&item);
if (it == devs.begin())
{
item_ = 0;
ListView_SetItemState(lst, ind, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
}
}
}
dlg_choose_dev::~dlg_choose_dev()
{}
BOOL dlg_choose_dev::handle_message(UINT msg, WPARAM wp, LPARAM lp)
{
wchar_t text[40] = { 0 };
BOOL ret = TRUE;
switch (msg)
{
case WM_COMMAND:
handle_command(HIWORD(wp), LOWORD(wp), (HWND)lp);
break;
case WM_NOTIFY:
handle_notify(wp, (LPNMHDR)lp);
break;
default:
ret = FALSE;
break;
}
return ret;
}
void dlg_choose_dev::handle_command(WORD code, WORD id, HANDLE ctrl)
{
if (id == IDOK)
{
HWND lst = GetDlgItem(hwnd_, IDC_LIST1);
if (item_ >= 0 && item_ < ListView_GetItemCount(lst))
{
wchar_t buf[128] = { 0 };
ListView_GetItemText(lst, item_, 0, buf, _countof(buf) - 1);
sel_ = local_trans::u2a(buf, CP_UTF8);
}
id = IDCANCEL;
}
if (id == IDCANCEL)
{
abandon_hold_ = true;
PostMessage(hwnd_, 0, 0, 0);
}
}
void dlg_choose_dev::handle_notify(UINT id, LPNMHDR pnhdr)
{
if (pnhdr->hwndFrom == GetDlgItem(hwnd_, IDC_LIST1))
{
if (pnhdr->code == LVN_ITEMCHANGED)
{
LPNMHEADER h = (LPNMHEADER)pnhdr;
item_ = h->iItem;
}
else if (pnhdr->code == NM_DBLCLK)
{
handle_command(0, IDOK, NULL);
}
}
}
std::string dlg_choose_dev::get_selected_device(void)
{
return sel_;
}

View File

@ -2,6 +2,7 @@
#include <Windows.h>
#include <string>
#include <map>
#include "DlgPage.h"
@ -28,3 +29,20 @@ public:
void notify_scan_over(const char* msg, bool err);
void notify_working(void);
};
class dlg_choose_dev : public dlg_base
{
std::string sel_;
int item_;
BOOL handle_message(UINT msg, WPARAM wp, LPARAM lp) override;
void handle_command(WORD code, WORD id, HANDLE ctrl);
void handle_notify(UINT id, LPNMHDR pnhdr);
public:
dlg_choose_dev(HWND parent, const std::map<std::string, std::string>& devs);
~dlg_choose_dev();
public:
std::string get_selected_device(void);
};

View File

@ -176,7 +176,7 @@ HWND dlg_base::hwnd(void)
{
return hwnd_;
}
void dlg_base::show(bool visible)
void dlg_base::show(bool visible, bool hold)
{
UINT cmd = visible ? SW_SHOW : SW_HIDE;
DWORD style = GetWindowLong(hwnd_, GWL_STYLE);
@ -187,6 +187,7 @@ void dlg_base::show(bool visible)
{
RECT r0 = { 0 }, rp = { 0 }, rme = { 0 };
POINT pt = { 0 };
HWND after = HWND_TOP;
if (IsWindow(parent_))
{
@ -202,6 +203,7 @@ void dlg_base::show(bool visible)
{
GetWindowRect(GetDesktopWindow(), &r0);
rp = r0;
after = HWND_TOPMOST;
}
GetWindowRect(hwnd_, &rme);
pt.x = rp.left + (RECT_W(rp) - RECT_W(rme)) / 2;
@ -214,12 +216,28 @@ void dlg_base::show(bool visible)
pt.y = r0.bottom - RECT_H(rme);
if (pt.y < r0.top)
pt.y = r0.top;
SetWindowPos(hwnd_, HWND_TOP, pt.x, pt.y, RECT_W(rme), RECT_H(rme), SWP_NOSIZE);
SetWindowPos(hwnd_, after, pt.x, pt.y, RECT_W(rme), RECT_H(rme), SWP_NOSIZE);
UpdateWindow(hwnd_);
}
EnableWindow(parent_, !visible);
}
ShowWindow(hwnd_, cmd);
if (hold)
{
MSG msg = { 0 };
BOOL ret = FALSE;
abandon_hold_ = false;
while ((ret = GetMessageW(&msg, NULL, 0, 0)))
{
if (ret == -1 || abandon_hold_)
break;
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
}
void dlg_base::enable(bool enable)
{

View File

@ -26,6 +26,7 @@ protected:
HWND hwnd_;
HWND parent_;
UINT idd_;
bool abandon_hold_;
void(__stdcall* ui_event_notify_)(int uev, void* sender, void* param);
void* ui_notify_param_;
static std::wstring prop_name;
@ -50,7 +51,7 @@ public:
public:
void set_ui_event_notify(void(__stdcall* notify)(int, void*, void*), void* param);
HWND hwnd(void);
void show(bool visible);
void show(bool visible, bool hold = false);
void enable(bool enable);
void screen_2_client(LPRECT r);
void client_2_screen(LPRECT r);

View File

@ -2,11 +2,13 @@
// Microsoft Visual C++ 生成的包含文件。
// 供 sane.rc 使用
//
#define IDCANCEL2 3
#define IDD_INDICATOR 101
#define IDD_SETTING 103
#define IDD_PAGE 105
#define IDD_AREA 106
#define IDD_GAMMA 107
#define IDD_CHOOSE_DEV 108
#define IDC_EDIT_PAPER 1001
#define IDC_EDIT_IMAGE 1002
#define IDC_STATIC_PAPER 1003
@ -28,6 +30,7 @@
#define IDC_CHANNEL 1017
#define IDC_EDIT_INPUT 1018
#define IDC_EDIT_OUTPUT 1019
#define IDC_LIST1 1020
// Next default values for new objects
//
@ -35,7 +38,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 109
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1020
#define _APS_NEXT_CONTROL_VALUE 1021
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@ -125,6 +125,16 @@ BEGIN
EDITTEXT IDC_EDIT_INPUT,33,205,18,12,ES_AUTOHSCROLL | ES_NUMBER
END
IDD_CHOOSE_DEV DIALOGEX 0, 0, 267, 96
STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_CAPTION
CAPTION "ÇëÑ¡ÔñÉ豸"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
PUSHBUTTON "È¡Ïû",IDCANCEL,7,77,42,12
PUSHBUTTON "È·¶¨",IDOK,218,77,42,12
CONTROL "",IDC_LIST1,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,7,253,62
END
/////////////////////////////////////////////////////////////////////////////
//
@ -173,6 +183,14 @@ BEGIN
TOPMARGIN, 7
BOTTOMMARGIN, 217
END
IDD_CHOOSE_DEV, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 260
TOPMARGIN, 7
BOTTOMMARGIN, 89
END
END
#endif // APSTUDIO_INVOKED
@ -207,6 +225,11 @@ BEGIN
0
END
IDD_CHOOSE_DEV AFX_DIALOG_LAYOUT
BEGIN
0
END
/////////////////////////////////////////////////////////////////////////////
//
@ -248,8 +271,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,29,10000,22272
PRODUCTVERSION 4,29,10000,22272
FILEVERSION 4,30,10000,22281
PRODUCTVERSION 4,30,10000,22281
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -266,12 +289,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "宁波华高信息科技有限公司"
VALUE "FileDescription", "华高扫描仪应用程序"
VALUE "FileVersion", "4.29.10000.22272"
VALUE "FileVersion", "4.30.10000.22281"
VALUE "InternalName", "sane.dll"
VALUE "LegalCopyright", "Copyright (C) HUAGOScan 2022"
VALUE "OriginalFilename", "sane.dll"
VALUE "ProductName", "HUAGOScan"
VALUE "ProductVersion", "4.29.10000.22272"
VALUE "ProductVersion", "4.30.10000.22281"
END
END
BLOCK "VarFileInfo"

View File

@ -267,32 +267,86 @@ scanner::~scanner()
delete cfg_;
}
std::string scanner::get_scanner_name(SCANNERID id)
bool scanner::is_belong_serial(int vid, int pid, SCANNERID serial)
{
if (vid == PRODUCT_VENDOR_HG)
{
if (GET_SCANNER_VID(serial) == PRODUCT_VENDOR_HG)
{
if (GET_SCANNER_PID(serial) == 0x100)
{
return pid == 0x100 || pid == 0x139 ;
}
else if (GET_SCANNER_PID(serial) == 0x200)
{
return pid == 0x200 || pid == 0x239;
}
else if (GET_SCANNER_PID(serial) == 0x300)
{
return pid == 0x300 || pid == 0x302 || pid == 0x339;
}
else if (GET_SCANNER_PID(serial) == 0x400)
{
return pid == 0x400 || pid == 0x402 || pid == 0x439;
}
}
}
else if (vid == PRODUCT_VENDOR_HG1)
{
return pid == 0x7823 && GET_SCANNER_VID(serial) == PRODUCT_VENDOR_HG && GET_SCANNER_PID(serial) == 0x200;
}
else if (vid == PRODUCT_VENDOR_HW)
{
return GET_SCANNER_VID(serial) == vid && GET_SCANNER_PID(serial) == pid;
}
else if (vid == PRODUCT_VENDOR_LSC)
{
if (GET_SCANNER_VID(serial) == PRODUCT_VENDOR_LSC)
{
if (GET_SCANNER_PID(serial) == 0x8420)
{
return pid == 0x8200 || pid == 0x8420 || pid == 0x8429;
}
else if (GET_SCANNER_PID(serial) == 0x8520)
{
return pid == 0x8520 || pid == 0x8529;
}
else if (GET_SCANNER_PID(serial) == 0x8620)
{
return pid == 0x8620 || pid == 0x8629;
}
else if (GET_SCANNER_PID(serial) == 0x8730)
{
return pid == 0x8730 || pid == 0x8739;
}
}
}
return false;
}
void scanner::get_scanner_name(SCANNERID id, std::vector<std::string>& names)
{
ScannerInfo* devs = NULL;
long count = 0;
std::string name("");
names.clear();
if (hg_scanner_enum(devs, &count, true) == SCANNER_ERR_INSUFFICIENT_MEMORY)
{
count++;
devs = new ScannerInfo[count];
memset(devs, 0, count * sizeof(*devs));
if (hg_scanner_enum(devs, &count, true) == SCANNER_ERR_OK)
{
for (int i = 0; i < count; ++i)
{
if (devs[i].vid == GET_SCANNER_VID(id) &&
devs[i].pid == GET_SCANNER_PID(id))
if (scanner::is_belong_serial(devs[i].vid, devs[i].pid, id))
{
name = devs[i].name;
break;
names.push_back(devs[i].name);
}
}
}
delete[] devs;
}
return name;
}
value_type scanner::from_sane_type(SANE_Value_Type type)
{
@ -316,6 +370,26 @@ value_limit scanner::from_sane_constraint(SANE_Constraint_Type type)
else
return VAL_LIMIT_NONE;
}
int scanner::control_read_string(SANE_Handle hdev, int code, std::string& str)
{
char* buf = NULL;
unsigned len = 0;
int err = hg_sane_middleware::instance()->io_control(hdev, code, buf, &len);
str = "";
if (err == SANE_STATUS_NO_MEM)
{
len += 4;
buf = new char[len];
memset(buf, 0, len);
err = hg_sane_middleware::instance()->io_control(hdev, code, buf, &len);
if (err == SANE_STATUS_GOOD)
str = buf;
delete[] buf;
}
return err;
}
int __stdcall scanner::to_int(SANE_Int v)
{
@ -457,15 +531,63 @@ void scanner::on_ui_event(int uev, void* sender)
events_.save(uev);
}
}
std::string scanner::choose_scanner(const std::vector<std::string>& scanners)
{
if (scanners.empty())
return "";
std::map<std::string, std::string> devs;
std::string sel("");
for (size_t i = 0; i < scanners.size(); ++i)
{
SANE_Handle h = NULL;
int ret = hg_sane_middleware::instance()->open_device(scanners[i].c_str(), &h);
if (h)
{
std::string sn("");
scanner::control_read_string(h, IO_CTRL_CODE_GET_SERIAL, sn);
if (sn.length())
devs[scanners[i]] = sn;
hg_sane_middleware::instance()->close_device(h);
}
}
if (devs.size() == 0)
sel = scanners[0];
else if (devs.size() == 1)
sel = devs.begin()->first;
else
{
dlg_choose_dev dlg(NULL, devs);
dlg.show(true, true);
sel = dlg.get_selected_device();
}
return sel;
}
int scanner::open(void)
{
int ret = close();
std::string name(scanner::get_scanner_name(id_));
std::vector<std::string> que;
std::string name("");
scanner::get_scanner_name(id_, que);
scanner_name_ = L"";
if (name.empty())
if (que.empty())
return SCANNER_ERR_DEVICE_NOT_FOUND;
if (que.size() == 1)
name = que[0];
else
{
name = choose_scanner(que);
if (name.empty())
return SCANNER_ERR_USER_CANCELED;
}
ret = hg_sane_middleware::instance()->open_device(name.c_str(), &handle_);
if (ret == SANE_STATUS_GOOD)
{
@ -649,23 +771,7 @@ int scanner::init_options_id(void)
}
int scanner::control_read_string(int code, std::string& ret)
{
char* buf = NULL;
unsigned len = 0;
int err = hg_sane_middleware::instance()->io_control(handle_, code, buf, &len);
ret = "";
if (err == SANE_STATUS_NO_MEM)
{
len += 4;
buf = new char[len];
memset(buf, 0, len);
err = hg_sane_middleware::instance()->io_control(handle_, code, buf, &len);
if (err == SANE_STATUS_GOOD)
ret = buf;
delete[] buf;
}
return err;
return scanner::control_read_string(handle_, code, ret);
}
void scanner::extension_none(int id)
@ -2012,7 +2118,9 @@ COM_API_IMPLEMENT(scanner, bool, get_first_image_header(SANE_Parameters* header,
}
COM_API_IMPLEMENT(scanner, bool, is_online(void))
{
return !scanner::get_scanner_name(id_).empty();
std::string sn("");
return handle_ && control_read_string(IO_CTRL_CODE_GET_SERIAL, sn) != SCANNER_ERR_DEVICE_NOT_FOUND;
}
COM_API_IMPLEMENT(scanner, bool, is_paper_on(void))
{
@ -2659,7 +2767,11 @@ __declspec(dllimport)
#endif
bool __stdcall is_scanner_online(SCANNERID scanner_id)
{
return !scanner::get_scanner_name(scanner_id).empty();
std::vector<std::string> que;
scanner::get_scanner_name(scanner_id, que);
return !que.empty();
}
#ifdef EXPORT_SANE_API
__declspec(dllexport)

View File

@ -59,6 +59,7 @@ class scanner : public ISaneInvoker, virtual public refer
void save_config(const wchar_t* file);
void apply_config(void);
void on_ui_event(int uev, void* sender);
std::string choose_scanner(const std::vector<std::string>& scanners);
int open(void);
int close(void);
int init_options_id(void);
@ -187,9 +188,11 @@ protected:
~scanner();
public:
static std::string get_scanner_name(SCANNERID id);
static bool is_belong_serial(int vid, int pid, SCANNERID serial);
static void get_scanner_name(SCANNERID id, std::vector<std::string>& names);
static value_type from_sane_type(SANE_Value_Type type);
static value_limit from_sane_constraint(SANE_Constraint_Type type);
static int control_read_string(SANE_Handle hdev, int code, std::string& str);
// IRef
public: