supporting string function in logical expression: name.left(cnt)/name.right(cnt)/name.mid(start, cnt); add raw USB test page

This commit is contained in:
gb 2023-11-02 17:10:00 +08:00
parent ed13494e28
commit 3abe71514f
12 changed files with 661 additions and 25 deletions

View File

@ -1006,7 +1006,7 @@
},
"total-cnt": {
"cat": "base",
"group": "只读属性",
"group": "关于",
"title": "历史滚轴计数",
"desc": "扫描仪使用以来扫描纸张总数",
"type": "int",
@ -1014,12 +1014,13 @@
"readonly": true,
"size": 4,
"auto": false,
"ownread": true,
"cur": 0,
"default": 0
},
"dev-vid": {
"cat": "base",
"group": "只读属性",
"group": "关于",
"title": "USB-VID",
"desc": "设备制造商在USB组织的ID",
"type": "int",
@ -1032,7 +1033,7 @@
},
"dev-pid": {
"cat": "base",
"group": "只读属性",
"group": "关于",
"title": "USB-PID",
"desc": "设备在USB组织中的产品ID",
"type": "int",
@ -1045,7 +1046,7 @@
},
"dev-name": {
"cat": "base",
"group": "只读属性",
"group": "关于",
"title": "设备名称",
"desc": "设备名称",
"type": "string",
@ -1058,7 +1059,7 @@
},
"dev-model": {
"cat": "base",
"group": "只读属性",
"group": "关于",
"title": "产品系列",
"desc": "设备所属产品系列名称",
"type": "string",
@ -1071,7 +1072,7 @@
},
"dev-sn": {
"cat": "base",
"group": "只读属性",
"group": "关于",
"title": "序列号",
"desc": "设备序列号",
"type": "string",
@ -1079,12 +1080,13 @@
"readonly": true,
"size": 96,
"auto": false,
"ownread": true,
"cur": "0",
"default": "0"
},
"fmw-ver": {
"cat": "base",
"group": "只读属性",
"group": "关于",
"title": "固件版本",
"desc": "设备固件版本号",
"type": "string",
@ -1092,12 +1094,13 @@
"readonly": true,
"size": 96,
"auto": false,
"ownread": true,
"cur": "0",
"default": "0"
},
"ip-addr": {
"cat": "base",
"group": "只读属性",
"group": "关于",
"title": "IP",
"desc": "设备联网时所分配的IP地址",
"type": "string",
@ -1105,12 +1108,13 @@
"readonly": true,
"size": 96,
"auto": false,
"ownread": true,
"cur": "0",
"default": "0"
},
"mac-addr": {
"cat": "base",
"group": "只读属性",
"group": "关于",
"title": "MAC",
"desc": "设备网卡地址",
"type": "string",
@ -1118,12 +1122,13 @@
"readonly": true,
"size": 96,
"auto": false,
"ownread": true,
"cur": "0",
"default": "0"
},
"roller-life": {
"cat": "base",
"group": "只读属性",
"group": "关于",
"title": "滚轴寿命",
"desc": "该设备滚轴过纸的最大张数",
"type": "int",
@ -1144,12 +1149,13 @@
"readonly": true,
"size": 4,
"auto": false,
"ownread": true,
"cur": false,
"default": false
},
"roll-cnt": {
"cat": "base",
"group": "只读属性",
"group": "用户",
"title": "滚轴计数",
"desc": "当前滚轴已经过纸张数",
"type": "int",
@ -1157,12 +1163,13 @@
"readonly": true,
"size": 4,
"auto": false,
"ownread": true,
"cur": 0,
"default": 0
},
"devs-log": {
"cat": "base",
"group": "高级设置",
"group": "用户",
"title": "设备日志",
"desc": "设备工作日志",
"type": "string",
@ -1170,6 +1177,7 @@
"visible": 1,
"size": 256,
"auto": false,
"ownread": true,
"cur": "0",
"default": "0"
}

View File

@ -11,6 +11,7 @@
#include "CDlgLang.h"
#include "DlgTwain.h"
#include "DlgOptJson.h"
#include "DlgManualUSB.h"
// CDlgMain 对话框
@ -90,6 +91,10 @@ BOOL CDlgMain::OnInitDialog()
page->Create(CDlgOptJson::IDD, this);
insert_page(page, L"Opt-JSON");
page = new CDlgManualUSB(this);
page->Create(CDlgManualUSB::IDD, this);
insert_page(page, L"USB");
tab_.SetCurSel(2);
OnTcnSelchangeTab1(NULL, &lret);

View File

@ -0,0 +1,487 @@
// CDlgManualUSB.cpp: 实现文件
//
#include "stdafx.h"
#include "hgjson.h"
#include "DlgManualUSB.h"
#include "afxdialogex.h"
#include "resource.h"
#include <winioctl.h>
#include <usbscan.h>
// CDlgManualUSB 对话框
extern int get_list_sel(CListCtrl* lc);
std::wstring get_wnd_text(HWND h)
{
int len = GetWindowTextLengthW(h);
wchar_t* buf = new wchar_t[len + 8];
std::wstring ret(L"");
memset(buf, 0, (len + 8) * 2);
GetWindowTextW(h, buf, len + 2);
ret = buf;
delete[] buf;
return std::move(ret);
}
std::wstring now(void)
{
time_t n = time(NULL);
struct tm* t = localtime(&n);
wchar_t buf[40] = { 0 };
swprintf_s(buf, _countof(buf) - 1, L"%04d-%02d-%02d %02d:%02d:%02d"
, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday
, t->tm_hour, t->tm_min, t->tm_sec);
return buf;
}
IMPLEMENT_DYNAMIC(CDlgManualUSB, CDialogEx)
CDlgManualUSB::CDlgManualUSB(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_RAW_USB, pParent)
{
}
CDlgManualUSB::~CDlgManualUSB()
{
close();
DestroyMenu(ep_menu_);
}
void CDlgManualUSB::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_LIST_EP, eps_);
DDX_Control(pDX, IDC_COMBO1, types_);
DDX_Control(pDX, IDC_COMBO_EP, oper_ep_);
}
BEGIN_MESSAGE_MAP(CDlgManualUSB, CDialogEx)
ON_BN_CLICKED(IDC_BUTTON_OPEN, &CDlgManualUSB::OnBnClickedButtonOpen)
ON_BN_CLICKED(IDC_BUTTON_ADD_EP, &CDlgManualUSB::OnBnClickedButtonAddEp)
ON_BN_CLICKED(IDC_BUTTON_CMD, &CDlgManualUSB::OnBnClickedButtonCmd)
ON_BN_CLICKED(IDC_BUTTON_CLOSE, &CDlgManualUSB::OnBnClickedButtonClose)
ON_NOTIFY(NM_RCLICK, IDC_LIST_EP, &CDlgManualUSB::OnNMRClickListEp)
ON_COMMAND(ID_USB_OPEN, &CDlgManualUSB::OnUsbOpen)
ON_COMMAND(ID_USB_CLOSE, &CDlgManualUSB::OnUsbClose)
ON_COMMAND(ID_USB_DELETE, &CDlgManualUSB::OnUsbDelete)
ON_BN_CLICKED(IDC_BUTTON_CLEAR, &CDlgManualUSB::OnBnClickedButtonClear)
END_MESSAGE_MAP()
void CDlgManualUSB::close(void)
{
for (auto& v : endpoints_)
CloseHandle(v.second);
endpoints_.clear();
if (main_ != INVALID_HANDLE_VALUE)
CloseHandle(main_);
main_ = INVALID_HANDLE_VALUE;
for (int i = 0; i < eps_.GetItemCount(); ++i)
{
eps_.SetItemText(i, 3, TEXT("Closed"));
}
oper_ep_.ResetContent();
GetDlgItem(IDC_BUTTON_CMD)->EnableWindow(FALSE);
cur_sel_ = -1;
}
HANDLE CDlgManualUSB::open_usb(const wchar_t* name)
{
return CreateFileW(name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE
, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
}
std::wstring CDlgManualUSB::error_message(int err)
{
if (err == -1)
err = GetLastError();
wchar_t* lpMsgBuf = NULL;
std::wstring msg(L"");
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS
, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)
, (LPWSTR)&lpMsgBuf, 0, NULL);
msg = lpMsgBuf;
LocalFree(lpMsgBuf);
return std::move(msg);
}
void CDlgManualUSB::append_message(const wchar_t* msg)
{
std::wstring prev(get_wnd_text(GetDlgItem(IDC_EDIT_STATUS)->m_hWnd)),
n(now());
n += L": ";
n += msg;
n += L"\r\n";
::SetDlgItemTextW(m_hWnd, IDC_EDIT_STATUS, (prev + n).c_str());
// scroll bottom ...
((CEdit*)GetDlgItem(IDC_EDIT_STATUS))->LineScroll(1);
}
// CDlgManualUSB 消息处理程序
BOOL CDlgManualUSB::OnInitDialog(void)
{
CDialogEx::OnInitDialog();
int ind = 0;
eps_.SetExtendedStyle(eps_.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_INFOTIP);
eps_.InsertColumn(ind++, TEXT("No."), 0, 45);
eps_.InsertColumn(ind++, TEXT("Type"), 0, 75);
eps_.InsertColumn(ind++, TEXT("Address"), 0, 75);
eps_.InsertColumn(ind++, TEXT("Status"), 0, 60);
ep_menu_ = LoadMenu(NULL, MAKEINTRESOURCE(IDR_MENU_USB_EP));
SetDlgItemInt(IDC_EDIT_TYPE, 64);
SetDlgItemInt(IDC_EDIT_REQ, 100);
SetDlgItemInt(IDC_EDIT_IND, 0);
SetDlgItemInt(IDC_EDIT_VAL, 18);
SetDlgItemInt(IDC_EDIT_LEN, 4);
SetDlgItemText(IDC_EDIT_SHORT_NAME, TEXT("\\\\.\\Usbscan2"));
return TRUE;
}
void CDlgManualUSB::OnBnClickedButtonOpen()
{
// TODO: 在此添加控件通知处理程序代码
wchar_t name[256] = { 0 };
::GetDlgItemTextW(m_hWnd, IDC_EDIT_SHORT_NAME, name, _countof(name) - 1);
if (name[0] == 0)
{
MessageBox(TEXT("Input Name please."));
GotoDlgCtrl(GetDlgItem(IDC_EDIT_SHORT_NAME));
}
close();
main_ = open_usb(name);
if (main_ == INVALID_HANDLE_VALUE)
{
int err = GetLastError();
std::wstring msg(error_message(err));
::MessageBoxW(m_hWnd, (std::to_wstring(err) + L": " + msg).c_str(), L"Open failed", MB_OK);
msg.insert(0, std::wstring(L"Open '") + name + L"' failed - ");
append_message(msg.c_str());
}
else
{
GetDlgItem(IDC_EDIT_LONG_NAME)->EnableWindow(FALSE);
GetDlgItem(IDC_EDIT_SHORT_NAME)->EnableWindow(FALSE);
append_message((std::wstring(L"Open '") + name + L"' success").c_str());
oper_ep_.InsertString(-1, TEXT("Control"));
GetDlgItem(IDC_BUTTON_CMD)->EnableWindow(TRUE);
}
}
void CDlgManualUSB::OnBnClickedButtonClose()
{
// TODO: 在此添加控件通知处理程序代码
close();
GetDlgItem(IDC_EDIT_LONG_NAME)->EnableWindow();
GetDlgItem(IDC_EDIT_SHORT_NAME)->EnableWindow();
append_message((L"Closed '" + get_wnd_text(GetDlgItem(IDC_EDIT_SHORT_NAME)->m_hWnd)).c_str());
}
void CDlgManualUSB::OnBnClickedButtonAddEp()
{
// TODO: 在此添加控件通知处理程序代码
int sn = GetDlgItemInt(IDC_EDIT_EP_SN),
addr = GetDlgItemInt(IDC_EDIT_EP_ADDR);
TCHAR type[128] = { 0 }, val[128] = { 0 };
types_.GetWindowText(type, _countof(type) - 1);
for (int i = 0; i < eps_.GetItemCount(); ++i)
{
eps_.GetItemText(i, 0, val, _countof(val) - 1);
if (_ttoi(val) == sn)
{
::MessageBoxW(m_hWnd, (std::wstring(L"An endpoint with sequence ") + std::to_wstring(sn) + L" has already in list!").c_str(), L"Repeat value", MB_OK);
return;
}
}
_stprintf_s(val, _countof(val) - 1, TEXT("%d"), sn);
sn = eps_.InsertItem(eps_.GetItemCount(), val);
eps_.SetItemText(sn, 1, type);
_stprintf_s(val, _countof(val) - 1, TEXT("%d"), addr);
eps_.SetItemText(sn, 2, val);
eps_.SetItemText(sn, 3, TEXT("Closed"));
}
void CDlgManualUSB::OnBnClickedButtonCmd()
{
// TODO: 在此添加控件通知处理程序代码
std::wstring ep(get_wnd_text(oper_ep_.m_hWnd));
if (ep == L"Control")
{
int t = GetDlgItemInt(IDC_EDIT_TYPE),
r = GetDlgItemInt(IDC_EDIT_REQ),
i = GetDlgItemInt(IDC_EDIT_IND),
v = GetDlgItemInt(IDC_EDIT_VAL),
l = GetDlgItemInt(IDC_EDIT_LEN),
tmp = 0;
_IO_BLOCK_EX irp;
OVERLAPPED ovl = { 0 };
PUCHAR data = (PUCHAR)&tmp;
DWORD io = 0;
BOOL ret = FALSE;
std::wstring msg(L"");
ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
irp.bmRequestType = (t >> 5) & 0x03;
irp.bRequest = r;
irp.fTransferDirectionIn = t >> 7;
irp.pbyData = data;
irp.uIndex = i;
irp.uLength = l;
irp.uOffset = v;
ret = DeviceIoControl(main_, IOCTL_SEND_USB_REQUEST, &irp, sizeof(irp), data, l, &io, &ovl);
if (ret)
{
msg = L"success. IO bytes = " + std::to_wstring(io) + L", ovl.Internal = " + std::to_wstring(ovl.Internal)
+ L", ovl.InternalHigg = " + std::to_wstring(ovl.InternalHigh);
}
else
{
if (GetLastError() == ERROR_IO_PENDING)
{
append_message(L"IO PENDING, wait up to 5 seconds ...");
DWORD wait = WaitForSingleObject(ovl.hEvent, 5000);
if (wait == WAIT_OBJECT_0)
{
msg = L"Waited. IO bytes = " + std::to_wstring(io) + L", ovl.Internal = " + std::to_wstring(ovl.Internal)
+ L", ovl.InternalHigg = " + std::to_wstring(ovl.InternalHigh);
}
else
{
msg = error_message();
msg += L". IO bytes = " + std::to_wstring(io) + L", ovl.Internal = " + std::to_wstring(ovl.Internal)
+ L", ovl.InternalHigg = " + std::to_wstring(ovl.InternalHigh);
}
}
else
{
msg = error_message();
msg += L". IO bytes = " + std::to_wstring(io) + L", ovl.Internal = " + std::to_wstring(ovl.Internal)
+ L", ovl.InternalHigg = " + std::to_wstring(ovl.InternalHigh);
}
}
CloseHandle(ovl.hEvent);
append_message((L"Control - " + msg).c_str());
}
else
{
int addr = _wtoi(ep.c_str());
if (endpoints_.count(addr))
{
unsigned char buf[256] = { 0 };
OVERLAPPED ovl = { 0 };
DWORD io = 0;
BOOL ret = FALSE;
std::wstring msg(L""), str(L"");
wchar_t hex[8] = { 0 };
ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (addr & 0x80)
{
bool bulk = true;
for (int i = 0; i < eps_.GetItemCount(); ++i)
{
TCHAR tmp[40] = { 0 };
eps_.GetItemText(i, 2, tmp, _countof(tmp) - 1);
if (_ttoi(tmp) == addr)
{
eps_.GetItemText(i, 1, tmp, _countof(tmp) - 1);
bulk = _tcscmp(tmp, TEXT("bulk")) == 0;
break;
}
}
msg = bulk ? L"BulkRead - " : L"IntRead - ";
if(bulk)
ret = ReadFile(endpoints_[addr], buf, sizeof(buf), &io, &ovl);
else
ret = DeviceIoControl(endpoints_[addr], IOCTL_WAIT_ON_DEVICE_EVENT, NULL, 0, buf, sizeof(buf), &io, &ovl);
if (ret)
{
msg += L"success. IO bytes = " + std::to_wstring(io) + L", ovl.Internal = " + std::to_wstring(ovl.Internal)
+ L", ovl.InternalHigg = " + std::to_wstring(ovl.InternalHigh);
for (int i = 0; i < io; ++i)
{
if ((i % 16) == 0)
{
msg += L" " + str + L"\r\n\t\t";
str = L"";
}
else if ((i % 8) == 0)
msg += L" ";
swprintf_s(hex, _countof(hex) - 1, L"%02X ", buf[i]);
if (buf[i] >= 0x20 && buf[i] < 0x80)
{
hex[0] = buf[i];
hex[1] = 0;
str += hex;
}
else
str += L".";
}
if (str.length())
msg += L" " + str;
}
else
{
if (GetLastError() == ERROR_IO_PENDING)
{
append_message((msg + L"IO PENDING, wait up to 5 seconds ...").c_str());
DWORD wait = WaitForSingleObject(ovl.hEvent, 5000);
if (wait == WAIT_OBJECT_0)
{
msg += L"Waited. IO bytes = " + std::to_wstring(io) + L", ovl.Internal = " + std::to_wstring(ovl.Internal)
+ L", ovl.InternalHigg = " + std::to_wstring(ovl.InternalHigh);
for (int i = 0; i < io; ++i)
{
if ((i % 16) == 0)
{
msg += L" " + str + L"\r\n\t\t";
str = L"";
}
else if ((i % 8) == 0)
msg += L" ";
swprintf_s(hex, _countof(hex) - 1, L"%02X ", buf[i]);
if (buf[i] >= 0x20 && buf[i] < 0x80)
{
hex[0] = buf[i];
hex[1] = 0;
str += hex;
}
else
str += L".";
}
if (str.length())
msg += L" " + str;
}
else
{
msg += error_message();
msg += L"\t. IO bytes = " + std::to_wstring(io) + L", ovl.Internal = " + std::to_wstring(ovl.Internal)
+ L", ovl.InternalHigg = " + std::to_wstring(ovl.InternalHigh);
}
}
else
{
msg = error_message();
msg += L"\t. IO bytes = " + std::to_wstring(io) + L", ovl.Internal = " + std::to_wstring(ovl.Internal)
+ L", ovl.InternalHigg = " + std::to_wstring(ovl.InternalHigh);
}
}
}
else
{
}
CloseHandle(ovl.hEvent);
append_message(msg.c_str());
}
else
{
MessageBox(TEXT("No endpoint found!"));
}
}
}
void CDlgManualUSB::OnNMRClickListEp(NMHDR* pNMHDR, LRESULT* pResult)
{
LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
cur_sel_ = pNMItemActivate->iItem;
if (cur_sel_ != -1 && main_ != INVALID_HANDLE_VALUE)
{
TCHAR status[40] = { 0 };
POINT pt = { 0 };
eps_.GetItemText(cur_sel_, 3, status, _countof(status) - 1);
EnableMenuItem(GetSubMenu(ep_menu_, 0), ID_USB_OPEN, _tcscmp(status, TEXT("Open")) ? MF_ENABLED : MF_DISABLED);
EnableMenuItem(GetSubMenu(ep_menu_, 0), ID_USB_CLOSE, _tcscmp(status, TEXT("Open")) ? MF_DISABLED : MF_ENABLED);
GetCursorPos(&pt);
TrackPopupMenu(GetSubMenu(ep_menu_, 0), 0, pt.x, pt.y, 0, m_hWnd, NULL);
}
*pResult = 0;
}
void CDlgManualUSB::OnUsbOpen()
{
// TODO: 在此添加命令处理程序代码
wchar_t root[128] = { 0 };
TCHAR val[40] = { 0 };
std::wstring name(L"");
::GetDlgItemTextW(m_hWnd, IDC_EDIT_SHORT_NAME, root, _countof(root) - 1);
name = root;
name += L"\\";
eps_.GetItemText(cur_sel_, 0, val, _countof(val) - 1);
swprintf_s(root, _countof(root) - 1, L"%d", _ttoi(val));
name += root;
// open
HANDLE h = open_usb(name.c_str());
if (h == INVALID_HANDLE_VALUE)
append_message((L"Open '" + name + L"' failed with error " + error_message()).c_str());
else
{
eps_.SetItemText(cur_sel_, 3, TEXT("Open"));
eps_.GetItemText(cur_sel_, 2, val, _countof(val) - 1);
endpoints_[_ttoi(val)] = h;
oper_ep_.InsertString(-1, val);
append_message((L"Open '" + name + L"' success").c_str());
}
}
void CDlgManualUSB::OnUsbClose()
{
// TODO: 在此添加命令处理程序代码
TCHAR val[128] = { 0 };
eps_.GetItemText(cur_sel_, 2, val, _countof(val) - 1);
if (endpoints_.count(_ttoi(val)))
{
CloseHandle(endpoints_[_ttoi(val)]);
endpoints_.erase(_ttoi(val));
eps_.SetItemText(cur_sel_, 3, TEXT("Closed"));
}
}
void CDlgManualUSB::OnUsbDelete()
{
// TODO: 在此添加命令处理程序代码
eps_.DeleteItem(cur_sel_);
cur_sel_ = -1;
}
void CDlgManualUSB::OnBnClickedButtonClear()
{
// TODO: 在此添加控件通知处理程序代码
::SetDlgItemTextW(m_hWnd, IDC_EDIT_STATUS, L"");
}

View File

@ -0,0 +1,49 @@
#pragma once
#include <map>
#include <string>
// CDlgManualUSB 对话框
class CDlgManualUSB : public CDialogEx
{
DECLARE_DYNAMIC(CDlgManualUSB)
void close(void);
HANDLE open_usb(const wchar_t* name);
std::wstring error_message(int err = -1);
void append_message(const wchar_t* msg);
public:
CDlgManualUSB(CWnd* pParent = nullptr); // 标准构造函数
virtual ~CDlgManualUSB();
// 对话框数据
#ifdef AFX_DESIGN_TIME
#endif
enum { IDD = IDD_RAW_USB };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
virtual BOOL OnInitDialog(void);
DECLARE_MESSAGE_MAP()
HANDLE main_ = INVALID_HANDLE_VALUE;
std::map<int, HANDLE> endpoints_;
HMENU ep_menu_ = NULL;
int cur_sel_ = -1;
public:
CListCtrl eps_;
CComboBox types_;
CComboBox oper_ep_;
afx_msg void OnBnClickedButtonOpen();
afx_msg void OnBnClickedButtonAddEp();
afx_msg void OnBnClickedButtonCmd();
afx_msg void OnBnClickedButtonClose();
afx_msg void OnNMRClickListEp(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnUsbOpen();
afx_msg void OnUsbClose();
afx_msg void OnUsbDelete();
afx_msg void OnBnClickedButtonClear();
};

View File

@ -344,6 +344,8 @@ known_file_util::IJsonW* CDlgOptJson::SANEOPT::to_json(void)
jsn->set_value(L"size", size);
if (!auto_restore_default)
jsn->set_value(L"auto", auto_restore_default);
if (own_read)
jsn->set_value(L"ownread", own_read);
if (type == L"bool")
{
@ -840,7 +842,8 @@ bool CDlgOptJson::SANEOPT::from_json(known_file_util::IJsonW* jsn)
{
if (!jsn->get_value(L"default", &strv))
jsn->get_value(L"cur", &strv);
cv.val = std::string((const char*)strv, lstrlenW(strv) * 2 + 2);
if(strv)
cv.val = std::string((const char*)strv, lstrlenW(strv) * 2 + 2);
cv.cond = "";
def_val.push_back(cv);
}
@ -852,6 +855,8 @@ bool CDlgOptJson::SANEOPT::from_json(known_file_util::IJsonW* jsn)
jsn->get_value(L"pos", pos);
if (!jsn->get_value(L"readonly", readonly))
readonly = false;
if (!jsn->get_value(L"ownread", own_read))
own_read = false;
int nv = OPT_VISIBLE_ALL;
bool bv = true;
@ -1227,6 +1232,7 @@ void CDlgOptJson::SANEOPT::init(struct _sane_opt_json* opt)
opt->visible.clear();
opt->enable = true;
opt->auto_restore_default = true;
opt->own_read = false;
}
std::wstring CDlgOptJson::get_item_text(UINT id)
@ -1363,6 +1369,7 @@ void CDlgOptJson::from_ui(SANEOPT& sop)
sop.range_type = get_item_text(IDC_COMBO_RANGE);
sop.auto_restore_default = is_button_check(IDC_CHECK_AUTO_RESTORE);
sop.depend = get_item_text(IDC_EDIT_LOGIC);
sop.own_read = is_button_check(IDC_CHECK_OWN_READ);
simple_logic logic;
int pos = 0;
@ -1409,6 +1416,7 @@ void CDlgOptJson::to_ui(const SANEOPT& sop)
fix_id_edit_.set_value(sop.fix_id);
set_button_check(IDC_CHECK_READONLY, sop.readonly);
set_button_check(IDC_CHECK_OWN_READ, sop.own_read);
//set_button_check(IDC_CHECK_PUBLIC, sop.open);
//visible_.SetCurSel(sop.open);
clear_visible();
@ -1885,12 +1893,17 @@ BOOL CDlgOptJson::OnInitDialog()
tooltips_ = new tooltip_wnd();
tooltips_->create(m_hWnd);
tooltips_->add_tool_tip_for_ctrl(::GetDlgItem(m_hWnd, IDC_CHECK_AUTO_RESTORE), L"\u662F\u5426\u652F\u6301\u6062\u590D\u5230\u9ED8\u8BA4\u503C\u7684\u64CD\u4F5C");
tooltips_->add_tool_tip_for_ctrl(::GetDlgItem(m_hWnd, IDC_CHECK_OWN_READ), L"\u8BE5\u5C5E\u6027\u5F53\u524D\u503C\u9700\u8981\u989D\u5916\u64CD\u4F5C\u4EE5\u4FDD\u8BC1\u5B9E\u65F6\u6027");
tooltips_->add_tool_tip_for_ctrl(::GetDlgItem(m_hWnd, IDC_CHECK_PUBLIC), L"\u662F\u5426\u5BF9\u666E\u901A\u7528\u6237\u5F00\u653E");
tooltips_->add_tool_tip_for_ctrl(::GetDlgItem(m_hWnd, IDC_COMBO_AFFECT), L"\u8BE5\u5C5E\u6027\u503C\u53D1\u751F\u6539\u53D8\u540E\uFF0C\u662F\u5426\u5F71\u54CD\u5176\u5B83\u5C5E\u6027\u6216\u8005\u56FE\u50CF\u53C2\u6570\uFF1F");
tooltips_->add_tool_tip_for_ctrl(::GetDlgItem(m_hWnd, IDC_COMBO_CATEGORY), L"\u5C5E\u6027\u5206\u7C7B\u3002\u5982\u679C\u4E3A\u56FE\u50CF\u5206\u7C7B\uFF0C\u4F1A\u6309\u7167\u201Cposition\u201D\u503C\u6392\u5E8F\uFF0C\u4EE5\u786E\u5B9A\u6267\u884C\u7684\u5148\u540E\u987A\u5E8F");
tooltips_->add_tool_tip_for_ctrl(::GetDlgItem(m_hWnd, IDC_EDIT_POSITION), L"\u8BE5\u5C5E\u6027\u5728\u6307\u5B9A\u5206\u7C7B\u4E2D\u7684\u6267\u884C\u987A\u5E8F");
tooltips_->add_tool_tip_for_ctrl(::GetDlgItem(m_hWnd, IDC_EDIT_FIXED_ID), L"\u63D0\u4F9B\u8BE5\u503C\uFF0C\u8BE5\u5C5E\u6027\u5373\u53EF\u88ABTWAIN\u534F\u8BAE\u4FA6\u6D4B\u5230");
tooltips_->add_tool_tip_for_ctrl(::GetDlgItem(m_hWnd, IDC_COMBO_GROUP), L"\u8BE5\u5C5E\u6027\u5728\u754C\u9762\u4E0A\u663E\u793A\u65F6\uFF0C\u6240\u5F52\u5C5E\u7684\u5206\u7EC4\u540D\u79F0");
tooltips_->add_tool_tip_for_ctrl(::GetDlgItem(m_hWnd, IDC_EDIT_FIXED_ID), L"\u63D0\u4F9B\u8BE5\u503C\uFF0C\u8BE5\u5C5E\u6027\u5373\u53EF\u88ABTWAIN\u534F\u8BAE\u4FA6\u6D4B\u5230");
tooltips_->add_tool_tip_for_ctrl(::GetDlgItem(m_hWnd, IDC_EDIT_POSITION), L"\u76F8\u540C\u5206\u7C7B\u201CCategory\u201D\u4E2D\u5C5E\u6027\u7684\u6267\u884C\u987A\u5E8F\uFF0C\u6570\u5B57\u8D8A\u5C0F\u6392\u5728\u8D8A\u524D\u9762\u6267\u884C\u3002\u5982\u679C\u5C5E\u6027ID\u76F8\u540C\uFF0C\u5219\u6309\u8BE5\u503C\u987A\u5E8F\u6267\u884C\uFF1B\u5982\u679C\u8BE5\u503C\u4E5F\u76F8\u540C\uFF0C\u5219\u6309\u6700\u8FD1\u6DFB\u52A0\u7684\u5C5E\u6027\u66FF\u6362\u4E4B\u524D\u7684\u6267\u884C\u3002");
tooltips_->add_tool_tip_for_ctrl(::GetDlgItem(m_hWnd, IDC_EDIT_VER), L"\u5F53\u8BE5\u5C5E\u6027\u6709\u591A\u4E2A\u6E90\u63D0\u4F9B\u65F6\uFF0C\u53D6\u7248\u672C\u9AD8\u8005\u4F7F\u7528\u3002\u7248\u672C\u76F8\u540C\u65F6\uFF0C\u6309\u201CPosition\u201D\u57DF\u6392\u5E8F\u4F7F\u7528\u3002");
return TRUE; // return TRUE unless you set the focus to a control
}
@ -3449,13 +3462,13 @@ void CDlgOptJson::OnBnClickedButtonSetVisible()
}
#include "../../../../code_device/sdk/hginclude/base_opt.h"
namespace test_sane_ui
{
typedef struct _sane_objects
{
device_option dev_opt;
device_opts sane_opt;
sane_options sane_opt;
}SANEOBJ, *LPSANEOBJ;
static void print_err(const char* msg)
{
@ -3466,6 +3479,24 @@ namespace test_sane_ui
OutputDebugStringA(err.c_str());
}
class sane_box : public sane_opt_provider
{
public:
sane_box(char* json)
{
set_opt_json_text(json);
}
protected:
~sane_box()
{}
public:
virtual int set_value(const char* name, void* val)
{
return SCANNER_ERR_OK;
}
};
SANE_Status sane_get_devices_api(const SANE_Device*** device_list, SANE_Bool local_only)
{
@ -3503,7 +3534,16 @@ namespace test_sane_ui
if (err == SCANNER_ERR_RELOAD_OPT_PARAM)
{
std::string text(sane->dev_opt.get_option_value(nullptr, OPT_VAL_JSON));
std::string text(sane->dev_opt.get_option_value(nullptr, SANE_ACTION_GET_ENTIRE_JSON));
{
wchar_t path[MAX_PATH] = { 0 };
std::wstring file(L"");
GetModuleFileNameW(NULL, path, _countof(path) - 1);
file = path;
file += L"-" + local_trans::a2u(desc->name, CP_UTF8) + L".txt";
file_util::save_2_file(text.c_str(), text.length(), file.c_str());
}
sane->sane_opt.init_from(text.c_str(), print_err);
err = 0;
if (info)
@ -3512,7 +3552,7 @@ namespace test_sane_ui
}
else if (action == SANE_ACTION_GET_VALUE)
{
std::string val(sane->dev_opt.get_option_value(desc->name, OPT_VAL_CURRENT));
std::string val(sane->dev_opt.get_option_value(desc->name, SANE_ACTION_GET_VALUE));
memcpy(fixed, val.c_str(), val.length());
}
@ -3611,10 +3651,11 @@ void CDlgOptJson::OnBnClickedButtonShowui()
}
int n = file_util::set_clipboard(text.c_str(), text.length() * 2, CF_UNICODETEXT);
test_sane_ui::sane_box* box = new test_sane_ui::sane_box(&utf8[0]);
text.clear();
if (sane.dev_opt.init(utf8.c_str()))
if (sane.dev_opt.add(box))
{
utf8 = sane.dev_opt.get_option_value(nullptr, OPT_VAL_JSON);
utf8 = sane.dev_opt.get_option_value(nullptr, SANE_ACTION_GET_ENTIRE_JSON);
if (sane.sane_opt.init_from(utf8.c_str(), test_sane_ui::print_err))
{
SANEAPI api = { 0 };
@ -3627,6 +3668,7 @@ void CDlgOptJson::OnBnClickedButtonShowui()
}
}
}
box->release();
}

View File

@ -98,6 +98,7 @@ public:
bool readonly;
bool enable;
bool auto_restore_default;
bool own_read; // 通常读取属性值都返回当前值。如果某属性读操作不同于此,则设置该属性
struct _sane_opt_json()
{

Binary file not shown.

View File

@ -119,6 +119,9 @@
<ClInclude Include="..\..\..\..\code_device\hgdriver\hgdev\user-opt\device_opt.h" />
<ClInclude Include="..\..\..\..\code_device\hgdriver\hgdev\user-opt\simple_logic.h" />
<ClInclude Include="..\..\..\..\code_device\hgsane\sane_opt\sane_opts.h" />
<ClInclude Include="..\..\..\..\code_device\sdk\hginclude\base_opt.h" />
<ClInclude Include="..\..\..\..\code_device\sdk\hginclude\ini_file.h" />
<ClInclude Include="..\..\..\..\code_device\sdk\hginclude\utils.h" />
<ClInclude Include="..\..\..\..\code_device\sdk\json\cJSON.h" />
<ClInclude Include="..\..\..\..\code_device\sdk\json\gb_json.h" />
<ClInclude Include="CDlgLang.h" />
@ -126,6 +129,7 @@
<ClInclude Include="DlgAddWords.h" />
<ClInclude Include="DlgCondition.h" />
<ClInclude Include="DlgInput.h" />
<ClInclude Include="DlgManualUSB.h" />
<ClInclude Include="DlgOptJson.h" />
<ClInclude Include="DlgRange.h" />
<ClInclude Include="DlgTwain.h" />
@ -155,6 +159,18 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\..\..\code_device\sdk\hginclude\base_opt.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\..\..\code_device\sdk\hginclude\ini_file.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\..\..\code_device\sdk\hginclude\utils.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\..\..\code_device\sdk\json\cJSON.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
@ -168,6 +184,7 @@
<ClCompile Include="DlgAddWords.cpp" />
<ClCompile Include="DlgCondition.cpp" />
<ClCompile Include="DlgInput.cpp" />
<ClCompile Include="DlgManualUSB.cpp" />
<ClCompile Include="DlgOptJson.cpp" />
<ClCompile Include="DlgRange.cpp" />
<ClCompile Include="DlgTwain.cpp" />

View File

@ -93,6 +93,18 @@
<ClInclude Include="..\..\..\..\code_device\hgdriver\hgdev\user-opt\simple_logic.h">
<Filter>sane_opt</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\code_device\sdk\hginclude\base_opt.h">
<Filter>sane_opt</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\code_device\sdk\hginclude\utils.h">
<Filter>sane_opt</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\code_device\sdk\hginclude\ini_file.h">
<Filter>sane_opt</Filter>
</ClInclude>
<ClInclude Include="DlgManualUSB.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="hgjson.cpp">
@ -155,6 +167,18 @@
<ClCompile Include="..\..\..\..\code_device\hgdriver\hgdev\user-opt\simple_logic.cpp">
<Filter>sane_opt</Filter>
</ClCompile>
<ClCompile Include="..\..\..\..\code_device\sdk\hginclude\base_opt.cpp">
<Filter>sane_opt</Filter>
</ClCompile>
<ClCompile Include="..\..\..\..\code_device\sdk\hginclude\utils.cpp">
<Filter>sane_opt</Filter>
</ClCompile>
<ClCompile Include="..\..\..\..\code_device\sdk\hginclude\ini_file.cpp">
<Filter>sane_opt</Filter>
</ClCompile>
<ClCompile Include="DlgManualUSB.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="hgjson.rc">

View File

@ -596,6 +596,8 @@ void dlg_base::quit_modal(int non_zero_code)
{
// assert ( non_zero_code );
modal_exit_ = non_zero_code;
if (msg_thread_id_) // 独立的消息循环,则退出
PostMessageW(hwnd_, WM_QUIT, 0, 0);
}
void dlg_base::close(void)
{
@ -1307,9 +1309,9 @@ BOOL dlg_page::on_notify(int ctrl_id, LPNMHDR pnmh)
{
if (pnmh->code != NM_RELEASEDCAPTURE)
{
if (pnmh->code == NM_CUSTOMDRAW && (GetAsyncKeyState(VK_LBUTTON) & 0x8000) && GetFocus() == pnmh->hwndFrom) // drag track ...
;
else
//if (pnmh->code == NM_CUSTOMDRAW && (GetAsyncKeyState(VK_LBUTTON) & 0x8000) && GetFocus() == pnmh->hwndFrom) // drag track ...
// ;
//else
return FALSE;
}
}
@ -1322,7 +1324,8 @@ BOOL dlg_page::on_notify(int ctrl_id, LPNMHDR pnmh)
else if (IS_BUTTON(cls))
return FALSE;
control_action(pnmh->hwndFrom);
if(done_)
control_action(pnmh->hwndFrom);
return TRUE;
}

Binary file not shown.

Binary file not shown.