// DlgIndicator.cpp: 实现文件 // #include "DlgPage.h" #include "resource.h" #include "scanned_img.h" // for local_trans #include "DlgArea.h" #include "DlgGamma.h" #include "gb_json.h" // #pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // #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) #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"; 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(); hwnd_ = CreateDialogParamW(g_my_inst, MAKEINTRESOURCE(idd_), parent_, (DLGPROC)&dlg_base::dlg_proc, (LPARAM)this); } void dlg_base::notify_ui_event(int ev) { if (ui_event_notify_) ui_event_notify_(ev, this, ui_notify_param_); } gb::sane_config* dlg_base::get_config(void) { gb::sane_config* cfg = NULL; 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) { ui_event_notify_ = notify; ui_notify_param_ = param; } HWND dlg_base::hwnd(void) { return hwnd_; } void dlg_base::show(bool visible, bool hold) { UINT cmd = visible ? SW_SHOW : SW_HIDE; DWORD style = GetWindowLong(hwnd_, GWL_STYLE); if (!(style & WS_CHILD)) { if (visible) { RECT r0 = { 0 }, rp = { 0 }, rme = { 0 }; POINT pt = { 0 }; HWND after = HWND_TOP; 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; } 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); 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) { 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); } 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; } 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); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // 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 对话框 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; int dlg_page::gap_y = 15; int dlg_page::spin_w = 8; int dlg_page::sb_adden = 30; 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) , 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; pos_.x = 12; pos_.y = 8; create(); tips_wnd_.create(hwnd()); } dlg_page::~dlg_page() { for (auto& v : ctrls_) DestroyWindow(v); } BOOL dlg_page::handle_message(UINT msg, WPARAM wp, LPARAM lp) { 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; 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; default: ret = FALSE; } return ret; } void dlg_page::on_font_changed(void) { HFONT font = get_font(); LOGFONTW lf = { 0 }; } 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; size->cx = (LONG)((upper - lower + step - 1) / step + .5f); 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& vals, const wchar_t* cur_val, LPSIZE size) { int h = vals.size() * 2 * size->cy; HWND wnd = NULL; for (int i = 0; i < (int)vals.size(); ++i) { if (size->cx < get_string_width(vals[i].c_str())) size->cx = get_string_width(vals[i].c_str()); } size->cx += 20; 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); for (int i = 0; i < (int)vals.size(); ++i) { 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); return wnd; } 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; 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); ctrls_.push_back(wnd); if (now) SendMessage(wnd, BM_SETCHECK, (WPARAM)BST_CHECKED, 0); return wnd; } HWND dlg_page::create_control_int(int sn, const SANE_Option_Descriptor* desc, void* cur_val, const wchar_t* title, LPSIZE text_size) { // 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 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 = 100; 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; return wnd; } HWND dlg_page::create_control_float(int sn, const SANE_Option_Descriptor* desc, void* cur_val, const wchar_t* title, LPSIZE text_size) { // 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 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; return wnd; } HWND dlg_page::create_control_string(int sn, const SANE_Option_Descriptor* desc, void* cur_val, const wchar_t* title, LPSIZE text_size) { HWND wnd = NULL; int x = pos_.x; std::wstring now(local_trans::a2u((char*)cur_val, CP_UTF8)); 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 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; } HWND dlg_page::create_control_button(int sn, const SANE_Option_Descriptor* desc, void* cur_val, const wchar_t* title, LPSIZE text_size) { 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); x = (float)SANE_UNFIX(sf); sane_.sane_control_option_api(dev_, id_custom_top_, SANE_ACTION_GET_VALUE, &sf, NULL); y = (float)SANE_UNFIX(sf); sane_.sane_control_option_api(dev_, id_custom_right_, SANE_ACTION_GET_VALUE, &sf, NULL); w = (float)SANE_UNFIX(sf) - x; sane_.sane_control_option_api(dev_, id_custom_bottom_, SANE_ACTION_GET_VALUE, &sf, NULL); 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* cfg = get_config(); sane_.sane_control_option_api(dev_, id_custom_left_, SANE_ACTION_SET_VALUE, &val, &after); 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); 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); 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); 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); 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) { len = sizeof(gamma); dlg.get_gamma(&gamma); sane_.sane_io_control_api(dev_, IO_CTRL_CODE_SET_CUSTOM_GAMMA, &gamma, &len); } return; } } } control_action((HWND)ctrl); } BOOL dlg_page::on_notify(int ctrl_id, LPNMHDR pnmh) { wchar_t cls[128] = { 0 }; pnmh->code == NM_TOOLTIPSCREATED; GetClassNameW((HWND)pnmh->hwndFrom, cls, _countof(cls) - 1); if (IS_TRACKBAR(cls)) { if (pnmh->code != NM_RELEASEDCAPTURE && pnmh->code != NM_CUSTOMDRAW) return FALSE; } else if (IS_UPDOWN_ARROW(cls)) { HWND host = (HWND)GetPropW(pnmh->hwndFrom, dlg_page::property_host.c_str()); if (IsWindow(host) && (int)GetPropW(host, dlg_page::property_type.c_str()) == SANE_TYPE_INT) return FALSE; } else if (IS_BUTTON(cls)) return FALSE; 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]; GetWindowTextW(ctrl, buf, len + 6); 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; std::string utf8(local_trans::u2a(buf, CP_UTF8)); ret = new char[len + 2]; if ((int)utf8.length() > len) 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; } 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)) { 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); } } else if (IS_TRACKBAR(cls)) { 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)) { 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()); } else if (IS_UPDOWN_ARROW(cls)) { 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; for (; ind < (int)ctrls_.size(); ++ind) { if (GetWindowLong(ctrls_[ind], GWL_ID) == id) break; } for (; ind < (int)ctrls_.size(); ++ind) { 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; for (int i = 0; i < (int)ctrls_.size(); ++i) { 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; SANE_Status statu = sane_.sane_control_option_api(dev_, id - dlg_page::dyn_id_base, SANE_ACTION_SET_VALUE, val, &after); gb::sane_config* cfg = get_config(); done_ = false; 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); } set_ctrl_value(wnd, type, val, false, !(after || statu)); done_ = true; if (id == dlg_page::dyn_id_base + id_dpi_) { if (type == SANE_TYPE_FIXED) 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); if (after || statu) 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; } 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; 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} }; if (strcmp(SANE_STD_OPT_NAME_CUSTOM_AREA_LEFT, desc->name) == 0) id_custom_left_ = sn; else if (strcmp(SANE_STD_OPT_NAME_CUSTOM_AREA_TOP, desc->name) == 0) id_custom_top_ = sn; else if (strcmp(SANE_STD_OPT_NAME_CUSTOM_AREA_BOTTOM, desc->name) == 0) id_custom_bottom_ = sn; 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) { 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) { 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) { for (; pos < (int)ctrls_.size(); ++pos) EnableWindow(ctrls_[pos], FALSE); } 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); } else if (strcmp(SANE_STD_OPT_NAME_PAPER, desc->name) == 0) { paper_ = local_trans::a2u((char*)cur_val, CP_UTF8); id_paper_ = sn; } else if (strcmp(SANE_STD_OPT_NAME_RESOLUTION, desc->name) == 0) { if (desc->type == SANE_TYPE_FIXED) dpi_ = (float)SANE_UNFIX(*(SANE_Fixed*)cur_val); else dpi_ = (float)(int)*(SANE_Int*)cur_val; id_dpi_ = sn; } else if (strcmp(SANE_STD_OPT_NAME_IS_CUSTOM_GAMMA, desc->name) == 0) { // custom gamma control ... 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); } if (size_.cx < pos_.x + text.cx + 10) size_.cx = pos_.x + text.cx + 10; pos_.y += text.cy + dlg_page::gap_y; } break; } } } size_.cy = pos_.y; size_view_ = size_; return ret; } 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); } 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; for (; ind < (int)ctrls_.size(); ++ind) { if (GetWindowLong(ctrls_[ind], GWL_ID) == sn) { found = true; break; } } done_ = false; for (; ind < (int)ctrls_.size(); ++ind) { 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); } } } done_ = true; return found; } const wchar_t* dlg_page::name(void) { return name_.c_str(); } 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); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //