code_twain/sane/DlgPage.cpp

1455 lines
40 KiB
C++
Raw Permalink Normal View History

// DlgIndicator.cpp: 实现文件
//
#include "DlgPage.h"
#include "resource.h"
#include "scanned_img.h" // for local_trans
#include "DlgArea.h"
2022-06-24 09:01:00 +00:00
#include "DlgGamma.h"
2022-07-01 07:24:58 +00:00
#include "gb_json.h"
2022-11-29 01:34:45 +00:00
#include "../../code_device/hgsane/sane_hg_mdw.h" // for
2022-09-24 02:58:26 +00:00
// #pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
2022-06-21 09:23:26 +00:00
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
#define FLOAT_FORMAT L"%.2f"
#define IS_STR_EQUAL(s1, s2) (wcscmp(s1, s2) == 0)
#define IS_EDIT(cls) IS_STR_EQUAL(cls, WC_EDITW)
#define IS_COMBOX(cls) IS_STR_EQUAL(cls, WC_COMBOBOXW)
#define IS_BUTTON(cls) IS_STR_EQUAL(cls, WC_BUTTONW)
2022-06-21 09:23:26 +00:00
#define IS_TRACKBAR(cls) IS_STR_EQUAL(cls, TRACKBAR_CLASSW)
#define IS_UPDOWN_ARROW(cls) IS_STR_EQUAL(cls, UPDOWN_CLASSW)
static IMPLEMENT_OPTION_STRING_COMPARE(is_sane_opt);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// dlg_base 对话框
extern HMODULE g_my_inst;
std::wstring dlg_base::prop_name = L"dlg_base_object_prop_name";
2022-06-27 01:38:12 +00:00
dlg_base::dlg_base(HWND parent, UINT idd) : parent_(parent), hwnd_(NULL), idd_(idd), ui_event_notify_(NULL), ui_notify_param_(NULL)
{
}
dlg_base::~dlg_base()
{
if (IsWindow(hwnd_))
{
//if (GetCurrentThreadId() == GetWindowThreadProcessId(hwnd_, NULL))
DestroyWindow(hwnd_);
}
EnableWindow(parent_, TRUE);
BringWindowToTop(parent_);
}
BOOL CALLBACK dlg_base::dlg_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
if (msg == WM_INITDIALOG)
{
dlg_base* obj = (dlg_base*)lp;
SetPropW(hwnd, dlg_base::prop_name.c_str(), (HANDLE)obj);
obj->hwnd_ = hwnd;
}
else if (msg == WM_DESTROY)
{
dlg_base* obj = (dlg_base*)GetPropW(hwnd, dlg_base::prop_name.c_str());
SetPropW(hwnd, dlg_base::prop_name.c_str(), NULL);
return FALSE;
}
dlg_base *obj = (dlg_base*)GetPropW(hwnd, dlg_base::prop_name.c_str());
BOOL ret = FALSE;
if (obj)
{
ret = obj->handle_message(msg, wp, lp);
}
return ret;
}
void dlg_base::screen_2_client(HWND wnd, LPRECT r)
{
POINT pt = { r->left, r->top };
ScreenToClient(wnd, &pt);
OffsetRect(r, pt.x - r->left, pt.y - r->top);
}
void dlg_base::client_2_screen(HWND wnd, LPRECT r)
{
POINT pt = { r->left, r->top };
ClientToScreen(wnd, &pt);
OffsetRect(r, pt.x - r->left, pt.y - r->top);
}
bool dlg_base::get_max_size(SIZE& dst, const SIZE& src)
{
bool changed = false;
if (dst.cx < src.cx)
{
dst.cx = src.cx;
changed = true;
}
if (dst.cy < src.cy)
{
dst.cy = src.cy;
changed = true;
}
return changed;
}
bool dlg_base::get_max_size(SIZE& dst, int cx, int cy)
{
bool changed = false;
if (dst.cx < cx)
{
dst.cx = cx;
changed = true;
}
if (dst.cy < cy)
{
dst.cy = cy;
changed = true;
}
return changed;
}
int dlg_base::select_combo_text(HWND combo, const wchar_t* text)
{
int ind = SendMessageW(combo, CB_SELECTSTRING, -1, (LPARAM)text),
ret = ind;
while (ind >= 0)
{
wchar_t buf[256] = { 0 };
GetWindowTextW(combo, buf, _countof(buf) - 1);
if (wcsicmp(buf, text) == 0)
break;
ret = ind;
ind = SendMessageW(combo, CB_SELECTSTRING, ret, (LPARAM)text);
}
return ret;
}
BOOL dlg_base::handle_message(UINT msg, WPARAM wp, LPARAM lp)
{
return FALSE;
}
void dlg_base::on_font_changed(void)
{
}
void dlg_base::create(void)
{
// InitCommonControls();
2022-08-05 09:34:18 +00:00
hwnd_ = CreateDialogParamW(g_my_inst, MAKEINTRESOURCE(idd_), parent_, (DLGPROC)&dlg_base::dlg_proc, (LPARAM)this);
}
void dlg_base::notify_ui_event(int ev)
2022-06-27 01:38:12 +00:00
{
if (ui_event_notify_)
ui_event_notify_(ev, this, ui_notify_param_);
}
gb::sane_config_schm* dlg_base::get_config(void)
2022-07-01 07:24:58 +00:00
{
gb::sane_config_schm* cfg = NULL;
2022-07-01 07:24:58 +00:00
SendMessage(parent_, WM_GET_CONFIG_OBJ, 0, (LPARAM)&cfg);
return cfg;
}
void dlg_base::set_ui_event_notify(void(__stdcall* notify)(int, void*, void*), void* param)
2022-06-27 01:38:12 +00:00
{
ui_event_notify_ = notify;
ui_notify_param_ = param;
}
HWND dlg_base::hwnd(void)
{
return hwnd_;
}
void dlg_base::show(bool visible, bool hold)
2022-07-01 07:24:58 +00:00
{
UINT cmd = visible ? SW_SHOW : SW_HIDE;
DWORD style = GetWindowLong(hwnd_, GWL_STYLE);
2022-07-01 07:24:58 +00:00
if (!(style & WS_CHILD))
{
if (visible)
2022-07-01 07:24:58 +00:00
{
RECT r0 = { 0 }, rp = { 0 }, rme = { 0 };
POINT pt = { 0 };
HWND after = HWND_TOP;
2022-07-01 07:24:58 +00:00
if (IsWindow(parent_))
{
HMONITOR mon = MonitorFromWindow(parent_, MONITOR_DEFAULTTOPRIMARY);
MONITORINFO mi = { 0 };
mi.cbSize = sizeof(mi);
GetMonitorInfoW(mon, &mi);
r0 = mi.rcWork;
GetWindowRect(parent_, &rp);
}
else
{
GetWindowRect(GetDesktopWindow(), &r0);
rp = r0;
after = HWND_TOPMOST;
2022-07-01 07:24:58 +00:00
}
GetWindowRect(hwnd_, &rme);
pt.x = rp.left + (RECT_W(rp) - RECT_W(rme)) / 2;
pt.y = rp.top + (RECT_H(rp) - RECT_H(rme)) / 2;
if (pt.x + RECT_W(rme) > r0.right)
pt.x = r0.right - RECT_W(rme);
if (pt.x < r0.left)
pt.x = r0.left;
if (pt.y + RECT_H(rme) > r0.bottom)
pt.y = r0.bottom - RECT_H(rme);
if (pt.y < r0.top)
pt.y = r0.top;
SetWindowPos(hwnd_, after, pt.x, pt.y, RECT_W(rme), RECT_H(rme), SWP_NOSIZE);
2022-07-01 07:24:58 +00:00
UpdateWindow(hwnd_);
}
EnableWindow(parent_, !visible);
2022-07-01 07:24:58 +00:00
}
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);
}
}
2022-07-01 07:24:58 +00:00
}
2022-06-27 01:38:12 +00:00
void dlg_base::enable(bool enable)
{
EnableWindow(hwnd_, enable);
}
void dlg_base::screen_2_client(LPRECT r)
{
POINT pt = { r->left, r->top };
ScreenToClient(hwnd_, &pt);
OffsetRect(r, pt.x - r->left, pt.y - r->top);
}
void dlg_base::client_2_screen(LPRECT r)
{
POINT pt = { r->left, r->top };
ClientToScreen(hwnd_, &pt);
OffsetRect(r, pt.x - r->left, pt.y - r->top);
}
HWND dlg_base::get_item(UINT id)
{
return GetDlgItem(hwnd_, id);
}
BOOL dlg_base::set_font(HFONT font)
{
BOOL ret = SendMessage(hwnd_, WM_SETFONT, (WPARAM)font, 1) == 0;
if (ret)
on_font_changed();
return ret;
}
HFONT dlg_base::get_font(void)
{
return (HFONT)SendMessage(hwnd_, WM_GETFONT, 0, 0);
}
2022-06-21 09:23:26 +00:00
int dlg_base::get_string_width(const wchar_t* str)
{
HDC hdc = GetWindowDC(hwnd_);
SIZE size = { 0 };
GetTextExtentPointW(hdc, str, lstrlenW(str), &size);
ReleaseDC(hwnd_, hdc);
return size.cx;
}
2022-09-20 08:23:31 +00:00
void dlg_base::show_scroll_bar(int bar, bool show)
{
DWORD style = GetWindowLong(hwnd(), GWL_STYLE);
if (bar == SB_VERT || bar == SB_BOTH)
{
if (show)
style |= WS_VSCROLL;
else
style &= ~WS_VSCROLL;
SetWindowLong(hwnd(), GWL_STYLE, style);
}
else if (bar == SB_HORZ || bar == SB_BOTH)
{
if (show)
style |= WS_HSCROLL;
else
style &= ~WS_HSCROLL;
SetWindowLong(hwnd(), GWL_STYLE, style);
}
}
bool dlg_base::track_mouse_hover(void)
{
return true;
TRACKMOUSEEVENT tme = { 0 };
tme.cbSize = sizeof(tme);
tme.dwFlags = TME_HOVER;
tme.dwHoverTime = HOVER_DEFAULT;
tme.hwndTrack = hwnd_;
return TrackMouseEvent(&tme);
}
2022-09-24 02:58:26 +00:00
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// tooltip_wnd
tooltip_wnd::tooltip_wnd() : hwnd_(NULL), parent_(NULL)
{
}
tooltip_wnd::~tooltip_wnd()
{
DestroyWindow(hwnd_);
}
bool tooltip_wnd::create(HWND parent)
{
if (!IsWindow(hwnd_))
{
parent_ = parent;
hwnd_ = CreateWindowExW(NULL, TOOLTIPS_CLASSW, NULL,
WS_POPUP | TTS_ALWAYSTIP | TTS_BALLOON,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
parent_, NULL,
GetModuleHandle(NULL), NULL);
SetWindowPos(hwnd_, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
return IsWindow(hwnd_);
}
void tooltip_wnd::enable(bool enabled)
{
if (enabled)
{
}
else
{
}
}
bool tooltip_wnd::add_tool_tip_for_rect(const RECT& r, const wchar_t* tips)
{
TTTOOLINFOW toolInfo = { 0 };
toolInfo.cbSize = sizeof(toolInfo) - sizeof(toolInfo.lpReserved); // TOOLTIPS_CLASSW in old style, not with member 'lpReserved'
toolInfo.hwnd = parent_;
toolInfo.uFlags = TTF_SUBCLASS;
toolInfo.lpszText = (wchar_t*)(DWORD_PTR)tips; // LPSTR_TEXTCALLBACK - WM_NOTIFY.TTN_GETDISPINFO
toolInfo.hinst = GetModuleHandle(NULL);
memcpy(&toolInfo.rect, &r, sizeof(toolInfo.rect));
return SendMessageW(hwnd_, TTM_ADDTOOL, 0, (LPARAM)&toolInfo) == TRUE;
}
bool tooltip_wnd::add_tool_tip_for_ctrl(HWND ctrl, const wchar_t* tips)
{
TTTOOLINFOW toolInfo = { 0 };
toolInfo.cbSize = sizeof(toolInfo) - sizeof(toolInfo.lpReserved); // TOOLTIPS_CLASSW in old style, not with member 'lpReserved'
toolInfo.hwnd = parent_;
toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
toolInfo.uId = (UINT_PTR)ctrl;
toolInfo.lpszText = (wchar_t*)(DWORD_PTR)tips; // LPSTR_TEXTCALLBACK - WM_NOTIFY.TTN_GETDISPINFO
toolInfo.hinst = GetModuleHandle(NULL);
return SendMessageW(hwnd_, TTM_ADDTOOL, 0, (LPARAM)&toolInfo) == TRUE;
}
bool tooltip_wnd::remove_tool_tip_for_ctrl(HWND ctrl)
{
TTTOOLINFOW toolInfo = { 0 };
toolInfo.cbSize = sizeof(toolInfo) - sizeof(toolInfo.lpReserved); // TOOLTIPS_CLASSW in old style, not with member 'lpReserved'
toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
toolInfo.hwnd = parent_;
toolInfo.uId = (UINT_PTR)ctrl;
return SendMessageW(hwnd_, TTM_DELTOOL, 0, (LPARAM)&toolInfo) == TRUE;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// dlg_page 对话框
2022-06-21 09:23:26 +00:00
std::wstring dlg_page::property_type = L"option_type";
std::wstring dlg_page::property_host = L"option_host_wnd";
std::wstring dlg_page::property_size = L"option_size";
UINT dlg_page::dyn_id_base = 3000;
int dlg_page::gap_x = 20;
2022-06-21 09:23:26 +00:00
int dlg_page::gap_y = 15;
int dlg_page::spin_w = 8;
2022-09-20 08:23:31 +00:00
int dlg_page::sb_adden = 30;
2022-06-21 09:23:26 +00:00
dlg_page::dlg_page(HWND parent, const wchar_t* name
, LPSANEAPI api, SANE_Handle dev)
: dlg_base(parent, IDD_PAGE), name_(name ? name : L""), ctrl_id_(0)
, sane_(*api), dev_(dev), done_(false)
, id_custom_area_(-1), id_custom_left_(-1), id_custom_right_(-1), id_custom_top_(-1), id_custom_bottom_(-1)
2022-09-20 08:23:31 +00:00
, id_custom_gamma_(-1), id_paper_(-1), paper_(L"A4"), id_dpi_(-1), dpi_(200), vsb_pos_(0), hsb_pos_(0)
, vsb_(false), hsb_(false)
{
size_.cx = size_.cy = 0;
2022-06-21 09:23:26 +00:00
pos_.x = 12;
pos_.y = 8;
create();
2022-09-24 02:58:26 +00:00
tips_wnd_.create(hwnd());
}
dlg_page::~dlg_page()
2022-06-21 09:23:26 +00:00
{
for (auto& v : ctrls_)
DestroyWindow(v);
}
BOOL dlg_page::handle_message(UINT msg, WPARAM wp, LPARAM lp)
{
2022-06-21 09:23:26 +00:00
BOOL ret = TRUE;
switch (msg)
{
case WM_MOUSEWHEEL:
ret = on_mouse_wheel(LOWORD(wp), HIWORD(wp), LOWORD(lp), HIWORD(lp));
break;
case WM_NOTIFY:
ret = on_notify((int)wp, (LPNMHDR)lp);
break;
case WM_COMMAND:
handle_command(HIWORD(wp), LOWORD(wp), (HWND)lp);
break;
2022-09-20 08:23:31 +00:00
case WM_VSCROLL:
if(vsb_)
on_vscroll(HIWORD(wp), LOWORD(wp));
break;
case WM_HSCROLL:
if(hsb_)
on_hscroll(HIWORD(wp), LOWORD(wp));
break;
case WM_MOUSEHOVER:
track_mouse_hover();
on_mouse_hover(LOWORD(lp), HIWORD(lp), wp);
break;
2022-06-21 09:23:26 +00:00
default:
ret = FALSE;
}
return ret;
}
void dlg_page::on_font_changed(void)
{
HFONT font = get_font();
LOGFONTW lf = { 0 };
2022-06-21 09:23:26 +00:00
}
HWND dlg_page::create_label(int sn, const wchar_t* title, int x, int y, SIZE size)
{
HWND wnd = CreateWindowW(WC_STATICW, title, WS_CHILD | WS_VISIBLE, x, y, size.cx, size.cy, hwnd(), NULL, g_my_inst, NULL);
ShowWindow(wnd, SW_SHOW);
SendMessage(wnd, WM_SETFONT, (WPARAM)get_font(), 1);
SetWindowLong(wnd, GWL_ID, dlg_page::dyn_id_base + sn);
ctrls_.push_back(wnd);
return wnd;
}
HWND dlg_page::create_slider(int sn, int x, int y, double lower, double upper, double step, double pos, LPSIZE size, bool is_double)
{
// lower slider upper
HWND wnd = NULL;
wchar_t limit[20] = { 0 };
const wchar_t *fmt = is_double ? FLOAT_FORMAT : L"%d";
int w = x, ticks_limit = is_double ? 500 : 5;
DWORD style = WS_CHILD | WS_VISIBLE | TBS_HORZ;
if (IS_DOUBLE_EQUAL(step, 0))
step = 1.0f;
if(is_double)
swprintf_s(limit, _countof(limit) - 1, fmt, lower);
else
swprintf_s(limit, _countof(limit) - 1, fmt, (int)lower);
size->cx = get_string_width(limit);
create_label(sn, limit, x, y, *size);
x += size->cx;
2022-07-18 02:55:01 +00:00
size->cx = (LONG)((upper - lower + step - 1) / step + .5f);
2022-06-21 09:23:26 +00:00
size->cx += 100;
size->cx /= 200;
size->cx *= 100;
if (size->cx < 100)
size->cx = 100;
if (size->cx > 300)
size->cx = 300;
if (upper > lower && size->cx / (upper - lower) < ticks_limit)
style |= TBS_NOTICKS;
else
style |= TBS_AUTOTICKS;
wnd = CreateWindowW(TRACKBAR_CLASSW, L"", style, x, y, size->cx, size->cy, hwnd(), NULL, g_my_inst, NULL);
if (is_double)
{
SendMessage(wnd, TBM_SETRANGEMIN, 1, (LPARAM)int(lower * 100.0f + .5f));
SendMessage(wnd, TBM_SETRANGEMAX, 1, (LPARAM)int(upper * 100.0f + .5f));
SendMessage(wnd, TBM_SETPOS, TRUE, (LPARAM)int(pos * 100.0f + .5f));
}
else
{
SendMessage(wnd, TBM_SETRANGEMIN, 1, (LPARAM)int(lower * 1.0f + .5f));
SendMessage(wnd, TBM_SETRANGEMAX, 1, (LPARAM)int(upper * 1.0f + .5f));
SendMessage(wnd, TBM_SETPOS, TRUE, (LPARAM)int(pos * 1.0f + .5f));
}
SetWindowLong(wnd, GWL_ID, dlg_page::dyn_id_base + sn);
ShowWindow(wnd, SW_SHOW);
ctrls_.push_back(wnd);
x += size->cx;
if(is_double)
swprintf_s(limit, _countof(limit) - 1, fmt, upper);
else
swprintf_s(limit, _countof(limit) - 1, fmt, (int)upper);
size->cx = get_string_width(limit);
create_label(sn, limit, x, y, *size);
size->cx = x + size->cx - w;
return wnd;
}
HWND dlg_page::create_edit(int sn, int x, int y, int h, int w)
{
HWND edit = CreateWindowExW(WS_EX_CLIENTEDGE, WC_EDITW, L"", WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL, x, y, w, h, hwnd(), NULL, g_my_inst, NULL);
SetWindowLong(edit, GWL_ID, dlg_page::dyn_id_base + sn);
SendMessage(edit, WM_SETFONT, (WPARAM)get_font(), 1);
ShowWindow(edit, SW_SHOW);
ctrls_.push_back(edit);
return edit;
}
HWND dlg_page::create_combox(int sn, int x, int y, std::vector<std::wstring>& vals, const wchar_t* cur_val, LPSIZE size)
{
int h = vals.size() * 2 * size->cy;
HWND wnd = NULL;
2022-07-18 02:55:01 +00:00
for (int i = 0; i < (int)vals.size(); ++i)
2022-06-21 09:23:26 +00:00
{
if (size->cx < get_string_width(vals[i].c_str()))
size->cx = get_string_width(vals[i].c_str());
}
2022-07-18 02:55:01 +00:00
size->cx += 20;
2022-06-21 09:23:26 +00:00
wnd = CreateWindowW(WC_COMBOBOXW, L"", WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL, x, y, size->cx, h, hwnd(), NULL, g_my_inst, NULL);
SendMessage(wnd, CB_SETDROPPEDWIDTH, size->cx, 0);
2022-07-18 02:55:01 +00:00
for (int i = 0; i < (int)vals.size(); ++i)
2022-06-21 09:23:26 +00:00
{
SendMessageW(wnd, CB_ADDSTRING, 0, (LPARAM)vals[i].c_str());
if (vals[i] == cur_val)
SendMessageW(wnd, CB_SETCURSEL, i, 0);
}
SetWindowLong(wnd, GWL_ID, dlg_page::dyn_id_base + sn);
SendMessage(wnd, WM_SETFONT, (WPARAM)get_font(), 1);
ShowWindow(wnd, SW_SHOW);
ctrls_.push_back(wnd);
2022-06-21 09:23:26 +00:00
return wnd;
}
2022-06-21 09:23:26 +00:00
HWND dlg_page::create_spin(int sn, HWND edit, double pos, double lower, double upper, bool is_double)
{
RECT r = { 0 };
HWND wnd = NULL;
GetWindowRect(edit, &r);
screen_2_client(&r);
wnd = CreateWindowW(UPDOWN_CLASSW, L"", WS_CHILD | WS_VISIBLE | UDS_SETBUDDYINT, r.right - 1, r.top, dlg_page::spin_w, r.bottom - r.top, hwnd(), NULL, g_my_inst, NULL);
SetWindowLong(wnd, GWL_ID, dlg_page::dyn_id_base + sn);
SendMessage(wnd, WM_SETFONT, (WPARAM)get_font(), 1);
if (is_double)
{
SendMessage(wnd, UDM_SETRANGE32, WPARAM(lower * 100.f + .5f), LPARAM(upper * 100.0f + .5f));
SendMessage(wnd, UDM_SETPOS32, 0, LPARAM(pos * 100.0f + .5f));
}
else
{
SendMessage(wnd, UDM_SETRANGE32, (WPARAM)(int)lower, (LPARAM)(int)upper);
SendMessage(wnd, UDM_SETPOS32, 0, (LPARAM)(int)pos);
}
ShowWindow(wnd, SW_SHOW);
ctrls_.push_back(wnd);
SetPropW(wnd, dlg_page::property_host.c_str(), edit);
if(!is_double)
SendMessage(wnd, UDM_SETBUDDY, (WPARAM)edit, 0);
return wnd;
}
HWND dlg_page::create_control_bool(int sn, const SANE_Option_Descriptor* desc, void* cur_val, const wchar_t* title, LPSIZE text_size)
{
bool now = *(SANE_Bool*)cur_val == SANE_TRUE ? true : false;
2022-06-21 09:23:26 +00:00
HWND wnd = NULL;
text_size->cx += 18 + dlg_page::gap_x;
wnd = CreateWindowW(WC_BUTTONW, title, WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, pos_.x, pos_.y, text_size->cx, text_size->cy, hwnd(), NULL, g_my_inst, NULL);
SetWindowLong(wnd, GWL_ID, dlg_page::dyn_id_base + sn);
SendMessage(wnd, WM_SETFONT, (WPARAM)get_font(), 1);
ShowWindow(wnd, SW_SHOW);
2022-06-21 09:23:26 +00:00
ctrls_.push_back(wnd);
if (now)
SendMessage(wnd, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
2022-06-21 09:23:26 +00:00
return wnd;
}
2022-06-21 09:23:26 +00:00
HWND dlg_page::create_control_int(int sn, const SANE_Option_Descriptor* desc, void* cur_val, const wchar_t* title, LPSIZE text_size)
{
2022-06-21 09:23:26 +00:00
// title: combox
// title: [slider] edit spin
HWND label = create_label(sn, title, pos_.x, pos_.y, *text_size), slider = NULL, wnd = NULL, spin = NULL;
int now = *(SANE_Int*)cur_val,
x = pos_.x,
w = 50;
SIZE size(*text_size);
wchar_t text[20] = { 0 };
x += text_size->cx + dlg_page::gap_x;
swprintf_s(text, _countof(text) - 1, L"%d", now);
if (desc->constraint_type == SANE_CONSTRAINT_WORD_LIST)
{
const SANE_Word *v = desc->constraint.word_list;
std::vector<std::wstring> vals;
for (int i = 0; i < v[0]; ++i)
{
swprintf_s(text, _countof(text) - 1, L"%d", v[i + 1]);
vals.push_back(text);
}
swprintf_s(text, _countof(text) - 1, L"%d", now);
wnd = create_combox(sn, x, pos_.y, vals, text, &size);
x += size.cx;
}
else
{
int lower = 0, upper = 10000;
2022-06-21 09:23:26 +00:00
if (desc->constraint_type == SANE_CONSTRAINT_RANGE)
{
lower = desc->constraint.range->min;
upper = desc->constraint.range->max;
slider = create_slider(sn, x, pos_.y, lower, upper, desc->constraint.range->quant, now, &size, false);
x += size.cx + dlg_page::gap_x;
}
wnd = create_edit(sn, x, pos_.y - 2, text_size->cy, w);
x += w;
SetWindowTextW(wnd, text);
if (IsWindow(slider))
SetPropW(slider, dlg_page::property_host.c_str(), wnd);
spin = create_spin(sn, wnd, now, lower, upper, false);
x += dlg_page::spin_w;
}
text_size->cx = x + dlg_page::gap_x;
2022-06-21 09:23:26 +00:00
return wnd;
}
2022-06-21 09:23:26 +00:00
HWND dlg_page::create_control_float(int sn, const SANE_Option_Descriptor* desc, void* cur_val, const wchar_t* title, LPSIZE text_size)
{
2022-06-21 09:23:26 +00:00
// title: combox
// title: [slider] edit spin
HWND label = create_label(sn, title, pos_.x, pos_.y, *text_size), slider = NULL, wnd = NULL, spin = NULL;
int now = *(SANE_Int*)cur_val,
x = pos_.x,
w = 50;
SIZE size(*text_size);
wchar_t text[20] = { 0 };
x += text_size->cx + dlg_page::gap_x;
swprintf_s(text, _countof(text) - 1, FLOAT_FORMAT, SANE_UNFIX(*(SANE_Word*)cur_val));
if (desc->constraint_type == SANE_CONSTRAINT_WORD_LIST)
{
const SANE_Word *v = desc->constraint.word_list;
std::vector<std::wstring> vals;
wchar_t cur[40] = { 0 };
for (int i = 0; i < v[0]; ++i)
{
swprintf_s(text, _countof(text) - 1, FLOAT_FORMAT, SANE_UNFIX(v[i + 1]));
vals.push_back(text);
if (v[i + 1] == *(SANE_Word*)cur_val)
wcscpy_s(cur, _countof(cur) - 1, text);
}
wnd = create_combox(sn, x, pos_.y, vals, cur, &size);
x += size.cx;
}
else
{
double lower = .0f, upper = 100.0f;
if (desc->constraint_type == SANE_CONSTRAINT_RANGE)
{
lower = SANE_UNFIX(desc->constraint.range->min);
upper = SANE_UNFIX(desc->constraint.range->max);
slider = create_slider(sn, x, pos_.y, lower, upper, SANE_UNFIX(desc->constraint.range->quant), SANE_UNFIX(*(SANE_Word*)cur_val), &size, true);
x += size.cx + dlg_page::gap_x;
}
wnd = create_edit(sn, x, pos_.y - 2, text_size->cy, w);
x += w;
SetWindowTextW(wnd, text);
if (IsWindow(slider))
SetPropW(slider, dlg_page::property_host.c_str(), wnd);
spin = create_spin(sn, wnd, SANE_UNFIX(*(SANE_Word*)cur_val), lower, upper, true);
x += dlg_page::spin_w;
}
text_size->cx = x + dlg_page::gap_x;
2022-06-21 09:23:26 +00:00
return wnd;
}
2022-06-21 09:23:26 +00:00
HWND dlg_page::create_control_string(int sn, const SANE_Option_Descriptor* desc, void* cur_val, const wchar_t* title, LPSIZE text_size)
{
2022-06-21 09:23:26 +00:00
HWND wnd = NULL;
int x = pos_.x;
std::wstring now(local_trans::a2u((char*)cur_val, CP_UTF8));
2022-06-21 09:23:26 +00:00
create_label(sn, title, x, pos_.y, *text_size);
x += text_size->cx + dlg_page::gap_x;
if (desc->constraint_type == SANE_CONSTRAINT_STRING_LIST)
{
std::vector<std::wstring> vals;
const SANE_String_Const *str = desc->constraint.string_list;
SIZE size(*text_size);
for (int i = 0; str[i]; ++i)
{
std::wstring text(local_trans::a2u(str[i], CP_UTF8));
vals.push_back(text);
}
wnd = create_combox(sn, x, pos_.y, vals, now.c_str(), &size);
x += size.cx;
}
else
{
wnd = create_edit(sn, x, pos_.y, text_size->cy, 200);
SetWindowTextW(wnd, now.c_str());
x += 200;
}
text_size->cx = x + dlg_page::gap_x;
return wnd;
}
2022-06-21 09:23:26 +00:00
HWND dlg_page::create_control_button(int sn, const SANE_Option_Descriptor* desc, void* cur_val, const wchar_t* title, LPSIZE text_size)
{
2022-06-21 09:23:26 +00:00
HWND wnd = NULL;
return wnd;
}
void dlg_page::handle_command(WORD code, WORD id, HANDLE ctrl)
{
wchar_t cls[128] = { 0 };
GetClassNameW((HWND)ctrl, cls, _countof(cls) - 1);
if (IS_EDIT(cls) && code != EN_CHANGE ||
IS_COMBOX(cls) && code != CBN_SELCHANGE)
{
return;
}
if (IS_BUTTON(cls))
{
HWND host = (HWND)GetPropW((HWND)ctrl, dlg_page::property_host.c_str());
if (IsWindow(host))
{
if (id == dlg_page::dyn_id_base + id_custom_area_)
{
unsigned int size = 0;
std::string utf8(local_trans::u2a(paper_.c_str(), CP_UTF8));
dlg_area dlg(parent_);
float x = .0f, y = .0f, w = .0f, h = .0f;
SANE_Fixed sf;
sane_.sane_io_control_api(dev_, IO_CTRL_CODE_GET_PAPER_SIZE, &utf8[0], &size);
dlg.set_paper(paper_.c_str(), (float)(size & 0x0ffff), float(size >> 16), dpi_);
sane_.sane_control_option_api(dev_, id_custom_left_, SANE_ACTION_GET_VALUE, &sf, NULL);
2022-07-18 02:55:01 +00:00
x = (float)SANE_UNFIX(sf);
sane_.sane_control_option_api(dev_, id_custom_top_, SANE_ACTION_GET_VALUE, &sf, NULL);
2022-07-18 02:55:01 +00:00
y = (float)SANE_UNFIX(sf);
sane_.sane_control_option_api(dev_, id_custom_right_, SANE_ACTION_GET_VALUE, &sf, NULL);
2022-07-18 02:55:01 +00:00
w = (float)SANE_UNFIX(sf) - x;
sane_.sane_control_option_api(dev_, id_custom_bottom_, SANE_ACTION_GET_VALUE, &sf, NULL);
2022-07-18 02:55:01 +00:00
h = (float)SANE_UNFIX(sf) - y;
dlg.set_area(x, y, w, h);
if (dlg.do_modal(parent_) == IDOK)
{
SANE_Fixed val = SANE_FIX(dlg.x_in_mm());
SANE_Int after = 0;
gb::sane_config_schm* cfg = get_config();
2022-07-01 07:24:58 +00:00
sane_.sane_control_option_api(dev_, id_custom_left_, SANE_ACTION_SET_VALUE, &val, &after);
2022-07-01 07:24:58 +00:00
if (cfg)
cfg->config_changed(id_custom_left_, (char*)&val, sizeof(val));
val = SANE_FIX(dlg.y_in_mm());
sane_.sane_control_option_api(dev_, id_custom_top_, SANE_ACTION_SET_VALUE, &val, &after);
2022-07-01 07:24:58 +00:00
if (cfg)
cfg->config_changed(id_custom_top_, (char*)&val, sizeof(val));
val = SANE_FIX(dlg.x_in_mm() + dlg.w_in_mm());
sane_.sane_control_option_api(dev_, id_custom_right_, SANE_ACTION_SET_VALUE, &val, &after);
2022-07-01 07:24:58 +00:00
if (cfg)
cfg->config_changed(id_custom_right_, (char*)&val, sizeof(val));
val = SANE_FIX(dlg.y_in_mm() + dlg.h_in_mm());
sane_.sane_control_option_api(dev_, id_custom_bottom_, SANE_ACTION_SET_VALUE, &val, &after);
2022-07-01 07:24:58 +00:00
if (cfg)
cfg->config_changed(id_custom_bottom_, (char*)&val, sizeof(val));
}
return;
}
else if (id == dlg_page::dyn_id_base + id_custom_gamma_)
{
dlg_gamma dlg(parent_, true);
SANE_Gamma gamma = { 0 };
unsigned int len = sizeof(gamma);
2022-06-24 09:01:00 +00:00
sane_.sane_io_control_api(dev_, IO_CTRL_CODE_GET_CUSTOM_GAMMA, &gamma, &len);
dlg.set_gamma(&gamma, len < 2);
if (dlg.do_modal(parent_) == IDOK)
2022-06-24 09:01:00 +00:00
{
len = sizeof(gamma);
2022-06-24 09:01:00 +00:00
dlg.get_gamma(&gamma);
sane_.sane_io_control_api(dev_, IO_CTRL_CODE_SET_CUSTOM_GAMMA, &gamma, &len);
gb::sane_config_schm* cfg = get_config();
if (cfg)
cfg->config_changed(id_custom_gamma_, (char*)&gamma, sizeof(gamma), true);
2022-06-24 09:01:00 +00:00
}
return;
}
}
}
2022-06-21 09:23:26 +00:00
control_action((HWND)ctrl);
}
BOOL dlg_page::on_notify(int ctrl_id, LPNMHDR pnmh)
{
wchar_t cls[128] = { 0 };
pnmh->code == NM_TOOLTIPSCREATED;
2022-06-21 09:23:26 +00:00
GetClassNameW((HWND)pnmh->hwndFrom, cls, _countof(cls) - 1);
if (IS_TRACKBAR(cls))
{
if (pnmh->code != NM_RELEASEDCAPTURE)
{
if (pnmh->code == NM_CUSTOMDRAW && (GetAsyncKeyState(VK_LBUTTON) & 0x8000) && GetFocus() == pnmh->hwndFrom) // drag track ...
;
else
return FALSE;
}
2022-06-21 09:23:26 +00:00
}
else if (IS_UPDOWN_ARROW(cls))
{
HWND host = (HWND)GetPropW(pnmh->hwndFrom, dlg_page::property_host.c_str());
2022-07-01 07:24:58 +00:00
if (IsWindow(host) && (int)GetPropW(host, dlg_page::property_type.c_str()) == SANE_TYPE_INT)
2022-06-21 09:23:26 +00:00
return FALSE;
}
2022-07-01 07:24:58 +00:00
else if (IS_BUTTON(cls))
return FALSE;
2022-06-21 09:23:26 +00:00
control_action(pnmh->hwndFrom);
return TRUE;
}
void* dlg_page::value_from_ctrl(HWND ctrl, SANE_Value_Type* type)
{
void* ret = NULL;
HWND host = (HWND)GetPropW(ctrl, dlg_page::property_host.c_str());
wchar_t cls[40] = { 0 };
SANE_Value_Type tp = SANE_TYPE_INT;
int(__cdecl * cmpstr)(const wchar_t*, const wchar_t*) = wcscmp;
if (!IsWindow(host))
host = ctrl;
tp = (SANE_Value_Type)(DWORD)GetPropW(host, dlg_page::property_type.c_str());
if (type)
*type = tp;
GetClassNameW(ctrl, cls, _countof(cls) - 1);
if (cmpstr(cls, WC_BUTTONW) == 0)
{
if (tp == SANE_TYPE_BOOL)
{
ret = new char[sizeof(SANE_Bool)];
*(SANE_Bool*)ret = SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED ? SANE_TRUE : SANE_FALSE;
}
}
else if (cmpstr(cls, TRACKBAR_CLASSW) == 0)
{
if (tp == SANE_TYPE_INT)
{
ret = new char[sizeof(SANE_Int)];
*(SANE_Int*)ret = SendMessage(ctrl, TBM_GETPOS, 0, 0);
}
else if (tp == SANE_TYPE_FIXED)
{
double pos = (double)SendMessage(ctrl, TBM_GETPOS, 0, 0);
ret = new char[sizeof(SANE_Fixed)];
*(SANE_Fixed*)ret = SANE_FIX(pos / 100.0f);
}
}
else if (cmpstr(cls, WC_EDITW) == 0 || cmpstr(cls, WC_COMBOBOXW) == 0)
{
int len = (int)GetPropW(host, dlg_page::property_size.c_str());
wchar_t* buf = new wchar_t[len + 8];
2022-06-21 09:23:26 +00:00
GetWindowTextW(ctrl, buf, len + 6);
2022-06-21 09:23:26 +00:00
if (tp == SANE_TYPE_INT)
{
ret = new char[sizeof(SANE_Int)];
*(SANE_Int*)ret = _wtoi(buf);
}
else if (tp == SANE_TYPE_FIXED)
{
ret = new char[sizeof(SANE_Fixed)];
*(SANE_Fixed*)ret = SANE_FIX(_wtof(buf));
}
else if (tp == SANE_TYPE_STRING)
{
buf[len] = 0;
2022-06-21 09:23:26 +00:00
std::string utf8(local_trans::u2a(buf, CP_UTF8));
ret = new char[len + 2];
2022-07-18 02:55:01 +00:00
if ((int)utf8.length() > len)
2022-06-21 09:23:26 +00:00
utf8.erase(len);
strcpy((char*)ret, utf8.c_str());
((char*)ret)[len] = 0;
}
delete[] buf;
}
else if (cmpstr(cls, UPDOWN_CLASSW) == 0)
{
if (tp == SANE_TYPE_INT)
{
ret = new char[sizeof(SANE_Int)];
*(SANE_Int*)ret = (int)SendMessage(ctrl, UDM_GETPOS, 0, 0);
}
else if (tp == SANE_TYPE_FIXED)
{
double pos = (double)(int)SendMessage(ctrl, UDM_GETPOS32, 0, 0);
ret = new char[sizeof(SANE_Fixed)];
*(SANE_Fixed*)ret = SANE_FIX(pos / 100.0f);
}
}
return ret;
}
2022-06-21 09:23:26 +00:00
void dlg_page::set_ctrl_value(HWND ctrl, SANE_Value_Type type, void* val, bool only_me, bool skip_ctrl)
{
if (only_me)
{
bool finish = done_;
wchar_t cls[128] = { 0 };
GetClassNameW(ctrl, cls, _countof(cls) - 1);
done_ = false;
if (IS_BUTTON(cls))
2022-06-21 09:23:26 +00:00
{
if (type == SANE_TYPE_BOOL)
{
DWORD id = GetWindowLong(ctrl, GWL_ID);
HWND host = (HWND)GetPropW(ctrl, dlg_page::property_host.c_str());
if (IsWindow(host) && (id == id_custom_area_ || id == id_custom_gamma_))
EnableWindow(ctrl, *(SANE_Bool*)val == SANE_TRUE);
else
SendMessage(ctrl, BM_SETCHECK, *(SANE_Bool*)val == SANE_TRUE ? (WPARAM)BST_CHECKED : (WPARAM)BST_UNCHECKED, 0);
}
2022-06-21 09:23:26 +00:00
}
else if (IS_TRACKBAR(cls))
2022-06-21 09:23:26 +00:00
{
if (type == SANE_TYPE_INT)
SendMessage(ctrl, TBM_SETPOS, 1, (LPARAM)*(SANE_Int*)val);
else if (type == SANE_TYPE_FIXED)
{
double pos = SANE_UNFIX(*(SANE_Fixed*)val);
SendMessage(ctrl, TBM_SETPOS, TRUE, (LPARAM)int(pos * 100.0f + .5f));
}
}
else if (IS_EDIT(cls) || IS_COMBOX(cls))
2022-06-21 09:23:26 +00:00
{
wchar_t buf[40] = { 0 };
std::wstring text(L"");
if (type == SANE_TYPE_INT)
{
swprintf_s(buf, _countof(buf) - 1, L"%d", *(SANE_Int*)val);
text = buf;
}
else if (type == SANE_TYPE_FIXED)
{
swprintf_s(buf, _countof(buf) - 1, FLOAT_FORMAT, SANE_UNFIX(*(SANE_Fixed*)val));
text = buf;
}
else if (type == SANE_TYPE_STRING)
{
text = local_trans::a2u((char*)val, CP_UTF8);
}
if (IS_EDIT(cls))
SetWindowTextW(ctrl, text.c_str());
else
dlg_base::select_combo_text(ctrl, text.c_str());
2022-06-21 09:23:26 +00:00
}
else if (IS_UPDOWN_ARROW(cls))
2022-06-21 09:23:26 +00:00
{
if (type == SANE_TYPE_INT)
{
SendMessage(ctrl, UDM_SETPOS32, 0, *(SANE_Int*)val);
}
else if (type == SANE_TYPE_FIXED)
{
double pos = SANE_UNFIX(*(SANE_Fixed*)val);
}
}
done_ = finish;
}
else
{
int id = GetWindowLong(ctrl, GWL_ID);
int ind = 0;
2022-07-18 02:55:01 +00:00
for (; ind < (int)ctrls_.size(); ++ind)
2022-06-21 09:23:26 +00:00
{
if (GetWindowLong(ctrls_[ind], GWL_ID) == id)
break;
}
2022-07-18 02:55:01 +00:00
for (; ind < (int)ctrls_.size(); ++ind)
2022-06-21 09:23:26 +00:00
{
if (GetWindowLong(ctrls_[ind], GWL_ID) != id)
break;
if (skip_ctrl && ctrl == ctrls_[ind])
continue;
set_ctrl_value(ctrls_[ind], type, val, true);
}
}
}
void dlg_page::free_ctrl_value(void* val)
{
if (val)
{
char* v = (char*)val;
delete[] v;
}
}
int dlg_page::find_control_ind(HWND wnd)
{
int ind = -1;
2022-07-18 02:55:01 +00:00
for (int i = 0; i < (int)ctrls_.size(); ++i)
2022-06-21 09:23:26 +00:00
{
if (ctrls_[i] == wnd)
{
ind = i;
break;
}
}
return ind;
}
void dlg_page::control_action(HWND wnd)
{
if (done_)
{
SANE_Value_Type type = (SANE_Value_Type)-1;
int id = GetWindowLong(wnd, GWL_ID);
void* val = value_from_ctrl(wnd, &type);
if (val)
{
SANE_Int after = 0;
2022-11-29 01:34:45 +00:00
std::string to_v(hg_sane_middleware::option_value_2_string(type, val));
2022-06-21 09:23:26 +00:00
SANE_Status statu = sane_.sane_control_option_api(dev_, id - dlg_page::dyn_id_base, SANE_ACTION_SET_VALUE, val, &after);
gb::sane_config_schm* cfg = get_config();
2022-06-21 09:23:26 +00:00
done_ = false;
2022-07-01 07:24:58 +00:00
if (cfg)
{
size_t len = 0;
switch (type)
{
case SANE_TYPE_BOOL:
len = sizeof(SANE_Bool);
break;
case SANE_TYPE_INT:
len = sizeof(SANE_Int);
break;
case SANE_TYPE_FIXED:
len = sizeof(SANE_Fixed);
break;
case SANE_TYPE_STRING:
len = lstrlenA((char*)val);
break;
default:
break;
}
if (len)
cfg->config_changed(id - dlg_page::dyn_id_base, (char*)val, len);
}
2022-11-29 01:34:45 +00:00
if (statu == SANE_STATUS_INVAL)
{
std::wstring attr(L"\u6B64\u8BBE\u5907\u4E0D\u652F\u6301\u5C06 \u201C" + local_trans::a2u(sane_.sane_get_option_descriptor_api(dev_, id - dlg_page::dyn_id_base)->title, CP_UTF8) + L"\u201D \u8BBE\u7F6E\u4E3A\uFF1A"),
attr_v(local_trans::a2u(to_v.c_str(), CP_UTF8));
MessageBoxW(hwnd(), (attr + attr_v).c_str(), L"\u53C2\u6570\u9519\u8BEF", MB_OK);
set_ctrl_value(wnd, type, val, true);
}
else
{
std::string tov(hg_sane_middleware::option_value_2_string(type, val));
if (tov != to_v)
{
std::wstring attr(L"\u539F\u53C2\u6570 \u201C" + local_trans::a2u(to_v.c_str(), CP_UTF8) + L"\u201D \u4E0D\u7CBE\u786E\u6216\u8BBE\u5907\u4E0D\u652F\u6301\uFF0C\u5DF2\u8C03\u6574\u4E3A\uFF1A"),
attr_v(local_trans::a2u(tov.c_str(), CP_UTF8));
MessageBoxW(hwnd(), (attr + attr_v).c_str(), L"\u53C2\u6570\u8C03\u6574", MB_OK);
}
set_ctrl_value(wnd, type, val, false, !(after || statu));
}
2022-06-21 09:23:26 +00:00
done_ = true;
if (id == dlg_page::dyn_id_base + id_dpi_)
{
if (type == SANE_TYPE_FIXED)
2022-07-18 02:55:01 +00:00
dpi_ = (float)SANE_UNFIX(*(SANE_Fixed*)val);
else
dpi_ = (float)(int)*(SANE_Int*)val;
}
else if (id == dlg_page::dyn_id_base + id_paper_)
paper_ = local_trans::a2u((char*)val, CP_UTF8);
2022-11-29 01:34:45 +00:00
if (after || (statu && statu != SANE_STATUS_INVAL))
2022-06-21 09:23:26 +00:00
PostMessage(parent_, WM_REFRESH_OPTION, id - dlg_page::dyn_id_base, 0);
free_ctrl_value(val);
}
}
}
BOOL dlg_page::on_mouse_wheel(WORD vkey, short delta, short x, short y)
{
POINT pt = { x, y };
HWND wnd = WindowFromPoint(pt);
BOOL handled = FALSE;
if (IsWindow(wnd))
{
wchar_t cls[128] = { 0 };
GetClassNameW(wnd, cls, _countof(cls) - 1);
if (IS_EDIT(cls))
{
SANE_Value_Type type = (SANE_Value_Type)(DWORD)GetPropW(wnd, dlg_page::property_type.c_str());
if (type == SANE_TYPE_INT || type == SANE_TYPE_FIXED)
{
int s = delta < 0 ? -1 : 1;
GetWindowTextW(wnd, cls, _countof(cls) - 1);
handled = TRUE;
if (type == SANE_TYPE_INT)
swprintf_s(cls, _countof(cls) - 1, L"%d", _wtoi(cls) + 1 * s);
else
swprintf_s(cls, _countof(cls) - 1, FLOAT_FORMAT, _wtof(cls) + .01f * s);
SetWindowTextW(wnd, cls);
}
}
}
return handled;
}
2022-09-20 08:23:31 +00:00
void dlg_page::on_vscroll(int pos, int sb_ev)
{
int old = vsb_pos_;
if (sb_ev == SB_THUMBPOSITION || sb_ev == SB_THUMBTRACK)
{
vsb_pos_ = pos;
}
else if (sb_ev == SB_LINEUP || sb_ev == SB_TOP)
vsb_pos_--;
else if (sb_ev == SB_LINEDOWN || sb_ev == SB_BOTTOM)
vsb_pos_++;
else if (sb_ev == SB_PAGEUP)
vsb_pos_ -= size_view_.cy;
else if (sb_ev == SB_PAGEDOWN)
vsb_pos_ += size_view_.cy;
else
{
return;
}
if (vsb_pos_ < 0)
vsb_pos_ = 0;
else if (vsb_pos_ > desired_size().cy - size_view_.cy + dlg_page::sb_adden)
vsb_pos_ = desired_size().cy - size_view_.cy + dlg_page::sb_adden;
if (old != vsb_pos_)
{
ScrollWindow(hwnd(), 0, old - vsb_pos_, NULL, NULL);
SetScrollPos(hwnd(), SB_VERT, vsb_pos_, TRUE);
}
}
void dlg_page::on_hscroll(int pos, int sb_ev)
{
int old = hsb_pos_;
if (sb_ev == SB_THUMBPOSITION || sb_ev == SB_THUMBTRACK)
{
hsb_pos_ = pos;
}
else if (sb_ev == SB_LINEUP || sb_ev == SB_TOP)
hsb_pos_--;
else if (sb_ev == SB_LINEDOWN || sb_ev == SB_BOTTOM)
hsb_pos_++;
else if (sb_ev == SB_PAGEUP)
hsb_pos_ -= size_view_.cx;
else if (sb_ev == SB_PAGEDOWN)
hsb_pos_ += size_view_.cx;
else
{
return;
}
if (hsb_pos_ < 0)
hsb_pos_ = 0;
else if (hsb_pos_ > desired_size().cx - size_view_.cx + dlg_page::sb_adden)
hsb_pos_ = desired_size().cx - size_view_.cx + dlg_page::sb_adden;
if (old != hsb_pos_)
{
ScrollWindow(hwnd(), old - hsb_pos_, 0, NULL, NULL);
SetScrollPos(hwnd(), SB_HORZ, hsb_pos_, TRUE);
}
}
void dlg_page::on_mouse_hover(int x, int y, int flag)
{
POINT pt = { x, y };
HWND ctrl = NULL;
ClientToScreen(hwnd_, &pt);
ctrl = WindowFromPoint(pt);
if (IsWindow(ctrl))
{
int id = GetWindowLong(ctrl, GWL_ID);
if (id > dlg_page::dyn_id_base)
{
id -= dlg_page::dyn_id_base;
const SANE_Option_Descriptor* desc = sane_.sane_get_option_descriptor_api(dev_, id);
if (desc)
{
std::wstring tips(local_trans::a2u(desc->title, CP_UTF8));
// MessageBoxW(NULL, tips.c_str(), L"Tips", MB_OK);
}
}
}
}
bool dlg_page::add_control(int sn, const SANE_Option_Descriptor* desc, void* cur_val)
{
bool ret = false;
struct
{
int sane_type;
2022-06-21 09:23:26 +00:00
HWND(dlg_page::* func)(int, const SANE_Option_Descriptor*, void*, const wchar_t*, LPSIZE);
}creat[] = { {SANE_TYPE_BOOL, &dlg_page::create_control_bool}
, {SANE_TYPE_INT, &dlg_page::create_control_int}
, {SANE_TYPE_FIXED, &dlg_page::create_control_float}
, {SANE_TYPE_STRING, &dlg_page::create_control_string}
, {SANE_TYPE_BUTTON, &dlg_page::create_control_button}
};
2022-10-07 09:51:09 +00:00
if (strcmp(SANE_STD_OPT_NAME_CUSTOM_AREA_LEFT, desc->name) == 0)
id_custom_left_ = sn;
2022-10-07 09:51:09 +00:00
else if (strcmp(SANE_STD_OPT_NAME_CUSTOM_AREA_TOP, desc->name) == 0)
id_custom_top_ = sn;
2022-10-07 09:51:09 +00:00
else if (strcmp(SANE_STD_OPT_NAME_CUSTOM_AREA_BOTTOM, desc->name) == 0)
id_custom_bottom_ = sn;
2022-10-07 09:51:09 +00:00
else if (strcmp(SANE_STD_OPT_NAME_CUSTOM_AREA_RIGHT, desc->name) == 0)
id_custom_right_ = sn;
else
{
for (int i = 0; i < _countof(creat); ++i)
{
if (creat[i].sane_type == desc->type)
2022-06-21 09:23:26 +00:00
{
std::wstring title(local_trans::a2u(desc->title, CP_UTF8));
HDC hdc = GetWindowDC(hwnd());
SIZE text = { 0 };
HWND wnd = NULL;
int pos = ctrls_.size();
GetTextExtentPointW(hdc, title.c_str(), title.length(), &text);
ReleaseDC(hwnd(), hdc);
wnd = (this->*creat[i].func)(sn, desc, cur_val, title.c_str(), &text);
ret = IsWindow(wnd);
if (ret)
2022-06-21 09:23:26 +00:00
{
2022-09-24 02:58:26 +00:00
if (desc->desc && *desc->desc)
tips_wnd_.add_tool_tip_for_ctrl(wnd, local_trans::a2u(desc->desc, CP_UTF8).c_str());
SetPropW(wnd, dlg_page::property_type.c_str(), (HANDLE)creat[i].sane_type);
SetPropW(wnd, dlg_page::property_size.c_str(), (HANDLE)desc->size);
if (desc->cap & SANE_CAP_INACTIVE)
{
2022-07-18 02:55:01 +00:00
for (; pos < (int)ctrls_.size(); ++pos)
EnableWindow(ctrls_[pos], FALSE);
}
2022-10-07 09:51:09 +00:00
if (strcmp(SANE_STD_OPT_NAME_CUSTOM_AREA, desc->name) == 0)
{
// custom area ...
int w = 69;
HWND host = wnd;
id_custom_area_ = sn;
wnd = CreateWindowW(WC_BUTTONW, L"\u8bbe\u7f6e\u533a\u57df", WS_CHILD | WS_VISIBLE, pos_.x + text.cx, pos_.y - 1, w, text.cy + 3, hwnd(), NULL, g_my_inst, NULL);
text.cx += w + dlg_page::gap_x;
EnableWindow(wnd, (desc->cap & SANE_CAP_INACTIVE) == 0 && *(SANE_Bool*)cur_val == SANE_TRUE);
SetWindowLong(wnd, GWL_ID, dlg_page::dyn_id_base + sn);
SendMessage(wnd, WM_SETFONT, (WPARAM)get_font(), 1);
SetPropW(wnd, dlg_page::property_host.c_str(), host);
ctrls_.push_back(wnd);
}
2022-10-07 09:51:09 +00:00
else if (strcmp(SANE_STD_OPT_NAME_PAPER, desc->name) == 0)
{
paper_ = local_trans::a2u((char*)cur_val, CP_UTF8);
id_paper_ = sn;
}
2022-10-07 09:51:09 +00:00
else if (strcmp(SANE_STD_OPT_NAME_RESOLUTION, desc->name) == 0)
{
if (desc->type == SANE_TYPE_FIXED)
2022-07-18 02:55:01 +00:00
dpi_ = (float)SANE_UNFIX(*(SANE_Fixed*)cur_val);
else
dpi_ = (float)(int)*(SANE_Int*)cur_val;
id_dpi_ = sn;
}
2022-10-07 09:51:09 +00:00
else if (strcmp(SANE_STD_OPT_NAME_IS_CUSTOM_GAMMA, desc->name) == 0)
{
// custom gamma control ...
2022-06-24 09:01:00 +00:00
int w = 78;
HWND host = wnd;
id_custom_gamma_ = sn;
wnd = CreateWindowW(WC_BUTTONW, L"\u8bbe\u7f6e\u8272\u8c03\u66f2\u7ebf", WS_CHILD | WS_VISIBLE, pos_.x + text.cx, pos_.y - 1, w, text.cy + 3, hwnd(), NULL, g_my_inst, NULL);
text.cx += w + dlg_page::gap_x;
EnableWindow(wnd, (desc->cap& SANE_CAP_INACTIVE) == 0 && *(SANE_Bool*)cur_val == SANE_TRUE);
SetWindowLong(wnd, GWL_ID, dlg_page::dyn_id_base + sn);
SendMessage(wnd, WM_SETFONT, (WPARAM)get_font(), 1);
SetPropW(wnd, dlg_page::property_host.c_str(), host);
ctrls_.push_back(wnd);
}
2022-09-20 08:23:31 +00:00
if (size_.cx < pos_.x + text.cx + 10)
size_.cx = pos_.x + text.cx + 10;
pos_.y += text.cy + dlg_page::gap_y;
2022-06-21 09:23:26 +00:00
}
break;
2022-06-21 09:23:26 +00:00
}
}
}
2022-06-21 09:23:26 +00:00
size_.cy = pos_.y;
2022-09-20 08:23:31 +00:00
size_view_ = size_;
return ret;
}
2022-06-21 09:23:26 +00:00
void dlg_page::add_control_done(void)
{
done_ = true;
}
SIZE dlg_page::desired_size(void)
{
return size_;
}
void dlg_page::show(void)
{
ShowWindow(hwnd_, SW_SHOW);
}
void dlg_page::hide(void)
{
ShowWindow(hwnd_, SW_HIDE);
}
2022-06-21 09:23:26 +00:00
bool dlg_page::refresh(int sn, const SANE_Option_Descriptor* desc, void* cur_val)
{
bool found = false;
int ind = 0;
sn += dlg_page::dyn_id_base;
2022-07-18 02:55:01 +00:00
for (; ind < (int)ctrls_.size(); ++ind)
2022-06-21 09:23:26 +00:00
{
if (GetWindowLong(ctrls_[ind], GWL_ID) == sn)
{
found = true;
break;
}
}
done_ = false;
2022-07-18 02:55:01 +00:00
for (; ind < (int)ctrls_.size(); ++ind)
2022-06-21 09:23:26 +00:00
{
if (GetWindowLong(ctrls_[ind], GWL_ID) != sn)
break;
set_ctrl_value(ctrls_[ind], desc->type, cur_val, true);
EnableWindow(ctrls_[ind], (desc->cap & SANE_CAP_INACTIVE) != SANE_CAP_INACTIVE);
HWND host = (HWND)GetPropW(ctrls_[ind], dlg_page::property_host.c_str());
if (IsWindow(host))
{
BOOL checked = SendMessage(host, BM_GETCHECK, 0, 0) == BST_CHECKED;
checked &= (desc->cap & SANE_CAP_INACTIVE) != SANE_CAP_INACTIVE;
if (sn - dlg_page::dyn_id_base == id_custom_area_)
{
EnableWindow(ctrls_[ind], checked);
}
else if (sn - dlg_page::dyn_id_base == id_custom_gamma_)
{
EnableWindow(ctrls_[ind], checked);
}
}
2022-06-21 09:23:26 +00:00
}
done_ = true;
return found;
}
const wchar_t* dlg_page::name(void)
{
return name_.c_str();
}
2022-09-20 08:23:31 +00:00
void dlg_page::set_view_size(SIZE size)
{
int h = size.cy;
vsb_ = h < desired_size().cy;
if (!vsb_)
{
show_scroll_bar(SB_VERT, false);
}
else
{
size_view_.cy = h;
show_scroll_bar(SB_VERT, true);
SetScrollRange(hwnd(), SB_VERT, 0, desired_size().cy - h + dlg_page::sb_adden, FALSE);
}
int w = size.cx;
hsb_ = w < desired_size().cx;
if (!hsb_)
{
show_scroll_bar(SB_HORZ, false);
}
else
{
size_view_.cx = w;
show_scroll_bar(SB_HORZ, true);
SetScrollRange(hwnd(), SB_HORZ, 0, desired_size().cx - w + dlg_page::sb_adden, FALSE);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2022-06-24 09:01:00 +00:00
//