// DlgIndicator.cpp: 实现文件 // #include "DlgArea.h" #include "resource.h" #include "scanned_img.h" // for local_trans #include "mem_dc.h" // CDlgIndicator 对话框 #define MM_PER_INCH 25.4f int dlg_area::area_min_pixel = 50; dlg_area::dlg_area(HWND parent) : dlg_base(parent, IDD_AREA) , unit_(PAPER_UNIT_MM), paper_w_(210), paper_h_(297), dpi_(200) , x_(0), y_(0), w_(paper_w_), h_(paper_h_) , exit_code_(0), paper_(L"A4") , paper_w_0_(paper_w_), paper_h_0_(paper_h_), cursor_(NULL), drag_(DRAG_POS_NONE) , in_set_func_(false) { create(); SendMessageW(get_item(IDC_UNIT), CB_ADDSTRING, 0, (LPARAM)L"\u6beb\u7c73\uff08mm\uff09"); SendMessageW(get_item(IDC_UNIT), CB_ADDSTRING, 0, (LPARAM)L"\u82f1\u5bf8\uff08inch\uff09"); SendMessageW(get_item(IDC_UNIT), CB_ADDSTRING, 0, (LPARAM)L"\u50cf\u7d20\uff08px\uff09"); SendMessage(get_item(IDC_UNIT), CB_SETCURSEL, 0, 0); } dlg_area::~dlg_area() { } float dlg_area::mm_2_pixel(float mm, float dpi) { return inches_2_pixel(mm_2_inches(mm), dpi); } float dlg_area::mm_2_inches(float mm) { return mm / MM_PER_INCH; } float dlg_area::inches_2_pixel(float inch, float dpi) { return inch * dpi; } float dlg_area::inches_2_mm(float inch) { return inch * MM_PER_INCH; } float dlg_area::pixel_2_mm(float px, float dpi) { return inches_2_mm(pixel_2_inches(px, dpi)); } float dlg_area::pixel_2_inches(float px, float dpi) { return px / dpi; } BOOL dlg_area::handle_message(UINT msg, WPARAM wp, LPARAM lp) { wchar_t text[40] = { 0 }; BOOL ret = TRUE; switch (msg) { case WM_INITDIALOG: UpdateWindow(hwnd()); break; case WM_COMMAND: handle_command(HIWORD(wp), LOWORD(wp), (HWND)lp); break; case WM_PAINT: { PAINTSTRUCT ps = { 0 }; HDC hdc = BeginPaint(hwnd(), &ps); { compatible_dc dc(hdc); on_paint(dc.get_dc()); } EndPaint(hwnd(), &ps); } break; case WM_MOUSEMOVE: on_mouse_move(wp, LOWORD(lp), HIWORD(lp)); break; case WM_LBUTTONDOWN: on_lbutton_down(LOWORD(lp), HIWORD(lp)); break; case WM_LBUTTONUP: on_lbutton_up(LOWORD(lp), HIWORD(lp)); break; default: ret = FALSE; } return ret; } void dlg_area::handle_command(WORD code, WORD id, HANDLE ctrl) { if (id == IDC_UNIT) { if (code == CBN_SELCHANGE) { on_unit_changed((HWND)ctrl); } } else if (id == IDCANCEL) { exit_code_ = id; } else if (id == IDOK) { exit_code_ = id; } else if (id == IDC_BUTTON_RESET) { clear_area(); } else if (id == IDC_EDIT_x || id == IDC_EDIT_y || id == IDC_EDIT_W || id == IDC_EDIT_H) { if (code == EN_CHANGE && !in_set_func_) { wchar_t val[80] = { 0 }; float num = .0f; GetWindowTextW((HWND)ctrl, val, _countof(val) - 1); num = (float)_wtof(val); if (id == IDC_EDIT_x) { if (num < .0f) num = .0f; if (num > paper_w_ - dlg_area::area_min_pixel) num = paper_w_ - dlg_area::area_min_pixel; x_ = num; user_sel_.left = whole_.left + (LONG)(x_ / ratio_); if (x_ + w_ > paper_w_) w_ = paper_w_ - x_; user_sel_.right = user_sel_.left + (LONG)(w_ / ratio_); refresh_paper_info(); InvalidateRect(hwnd(), &whole_, FALSE); } else if (id == IDC_EDIT_y) { if (num < .0f) num = .0f; if (num > paper_h_ - dlg_area::area_min_pixel) num = paper_h_ - dlg_area::area_min_pixel; y_ = num; user_sel_.top = whole_.top + (LONG)(y_ / ratio_); if (y_ + h_ > paper_h_) h_ = paper_h_ - y_; user_sel_.bottom = user_sel_.top + (LONG)(h_ / ratio_); refresh_paper_info(); InvalidateRect(hwnd(), &whole_, FALSE); } else if (id == IDC_EDIT_W) { if (num < dlg_area::area_min_pixel) num = (float)dlg_area::area_min_pixel; if (num > paper_w_) num = paper_w_; w_ = num; user_sel_.right = user_sel_.left + (LONG)(w_ / ratio_); if (user_sel_.right > whole_.right) { OffsetRect(&user_sel_, whole_.right - user_sel_.right, 0); if (user_sel_.left < whole_.left) { user_sel_.left = whole_.left; x_ = 0; } } refresh_paper_info(); InvalidateRect(hwnd(), &whole_, FALSE); } else if (id == IDC_EDIT_H) { if (num < dlg_area::area_min_pixel) num = (float)dlg_area::area_min_pixel; if (num > paper_h_) num = paper_h_; h_ = num; user_sel_.bottom = user_sel_.top + (LONG)(h_ / ratio_); if (user_sel_.bottom > whole_.bottom) { OffsetRect(&user_sel_, 0, whole_.bottom - user_sel_.bottom); if (user_sel_.top < whole_.top) { user_sel_.top = whole_.top; y_ = 0; } } refresh_paper_info(); InvalidateRect(hwnd(), &whole_, FALSE); } } } } float dlg_area::as_mm(float v) { if (unit_ == PAPER_UNIT_INCH) return dlg_area::inches_2_mm(v); else if (unit_ == PAPER_UNIT_PIXEL) return dlg_area::pixel_2_mm(v, dpi_); else return v; } float dlg_area::from_mm(float v) { if (unit_ == PAPER_UNIT_INCH) return dlg_area::mm_2_inches(v); else if (unit_ == PAPER_UNIT_PIXEL) return dlg_area::mm_2_pixel(v, dpi_); else return v; } float dlg_area::as_inches(float v) { if (unit_ == PAPER_UNIT_MM) return dlg_area::mm_2_inches(v); else if (unit_ == PAPER_UNIT_PIXEL) return dlg_area::pixel_2_inches(v, dpi_); else return v; } float dlg_area::as_pixels(float v) { if (unit_ == PAPER_UNIT_MM) return dlg_area::mm_2_pixel(v, dpi_); else if (unit_ == PAPER_UNIT_INCH) return dlg_area::inches_2_pixel(v, dpi_); else return v; } std::wstring dlg_area::format_number(float v) { wchar_t str[40] = { 0 }; if (unit_ == PAPER_UNIT_PIXEL) swprintf_s(str, _countof(str) - 1, L"%d", (int)(v + .5f)); else swprintf_s(str, _countof(str) - 1, L"%.2f", v); return str; } void dlg_area::refresh_paper_info(void) { SetWindowTextW(get_item(IDC_EDIT_PAPER), (paper_ + L"(" + format_number(paper_w_) + L"\u00d7" + format_number(paper_h_) + L")").c_str()); SetDlgItemInt(hwnd(), IDC_EDIT_DPI, UINT(dpi_), FALSE); in_set_func_ = true; SetWindowTextW(get_item(IDC_EDIT_x), format_number(x_).c_str()); SetWindowTextW(get_item(IDC_EDIT_y), format_number(y_).c_str()); SetWindowTextW(get_item(IDC_EDIT_W), format_number(w_).c_str()); SetWindowTextW(get_item(IDC_EDIT_H), format_number(h_).c_str()); in_set_func_ = false; InvalidateRect(hwnd(), &whole_, FALSE); } void dlg_area::to_unit(paper_unit unit) { float(dlg_area:: * conv)(float) = NULL; if (unit == PAPER_UNIT_INCH) { conv = &dlg_area::as_inches; paper_w_ = dlg_area::mm_2_inches(paper_w_0_); paper_h_ = dlg_area::mm_2_inches(paper_h_0_); } else if (unit == PAPER_UNIT_PIXEL) { conv = &dlg_area::as_pixels; paper_w_ = dlg_area::mm_2_pixel(paper_w_0_, dpi_); paper_h_ = dlg_area::mm_2_pixel(paper_h_0_, dpi_); } else // if (unit == PAPER_UNIT_MM) { conv = &dlg_area::as_mm; paper_w_ = paper_w_0_; paper_h_ = paper_h_0_; } #define CONV_UNIT(v) \ v = (this->*conv)(v); CONV_UNIT(x_); CONV_UNIT(y_); CONV_UNIT(w_); CONV_UNIT(h_); unit_ = unit; refresh_paper_info(); } void dlg_area::clear_area(void) { x_ = y_ = 0; w_ = paper_w_; h_ = paper_h_; user_sel_ = whole_; refresh_paper_info(); } void dlg_area::drag_blocks(std::vector& blocks) { int l = 5; DRAGRECT r; r.left = user_sel_.left; r.top = user_sel_.top; r.right = r.left + l; r.bottom = r.top + l; r.pos = DRAG_POS_LT; blocks.clear(); blocks.push_back(r); OffsetRect(&r, (user_sel_.right - user_sel_.left) / 2 - l / 2, 0); r.pos = DRAG_POS_MT; blocks.push_back(r); OffsetRect(&r, (user_sel_.right - r.right), 0); r.pos = DRAG_POS_RT; blocks.push_back(r); OffsetRect(&r, 0, (user_sel_.bottom - user_sel_.top) / 2 - l / 2); r.pos = DRAG_POS_RM; blocks.push_back(r); OffsetRect(&r, 0, (user_sel_.bottom - r.bottom)); r.pos = DRAG_POS_RB; blocks.push_back(r); OffsetRect(&r, -((user_sel_.right - user_sel_.left) / 2 - l / 2), 0); r.pos = DRAG_POS_MB; blocks.push_back(r); OffsetRect(&r, user_sel_.left - r.left, 0); r.pos = DRAG_POS_LB; blocks.push_back(r); OffsetRect(&r, 0, -((user_sel_.bottom - user_sel_.top) / 2 - l / 2)); r.pos = DRAG_POS_LM; blocks.push_back(r); } float dlg_area::pos_2_area(int val, bool x) { float r = x ? (float)(val - whole_.left) : (float)(val - whole_.top); r *= ratio_; if (unit_ == PAPER_UNIT_INCH) r = dlg_area::mm_2_inches(r); else if (unit_ == PAPER_UNIT_PIXEL) r = dlg_area::mm_2_pixel(r, dpi_); return r; } void dlg_area::valid_x(int& x, bool left) { if (left) { if (x < whole_.left) x = whole_.left; if (x > user_sel_.right - dlg_area::area_min_pixel) x = user_sel_.right - dlg_area::area_min_pixel; } else { if (x > whole_.right) x = whole_.right; if (x < user_sel_.left + dlg_area::area_min_pixel) x = user_sel_.left + dlg_area::area_min_pixel; } } void dlg_area::valid_y(int& y, bool top) { if (top) { if (y < whole_.top) y = whole_.top; if (y > user_sel_.bottom - dlg_area::area_min_pixel) y = user_sel_.bottom - dlg_area::area_min_pixel; } else { if (y > whole_.bottom) y = whole_.bottom; if (y < user_sel_.top + dlg_area::area_min_pixel) y = user_sel_.top + dlg_area::area_min_pixel; } } void dlg_area::on_unit_changed(HWND wnd) { wchar_t text[80] = { 0 }; GetWindowTextW(wnd, text, _countof(text) - 1); if (wcsstr(text, L"mm")) { if (unit_ != PAPER_UNIT_MM) { to_unit(PAPER_UNIT_MM); } } else if (wcsstr(text, L"inch")) { if (unit_ != PAPER_UNIT_INCH) { to_unit(PAPER_UNIT_INCH); } } else { if (unit_ != PAPER_UNIT_PIXEL) { to_unit(PAPER_UNIT_PIXEL); } } } void dlg_area::on_paint(HDC hdc) { HBRUSH brsh_all = CreateSolidBrush(RGB(192, 192, 192)), brsh_drag = CreateSolidBrush(RGB(255, 0, 0)), brsh_sel = CreateSolidBrush(RGB(255, 255, 255)); HPEN pen_border = CreatePen(PS_SOLID, 1, RGB(0, 255, 0)), pen_ruler = CreatePen(PS_SOLID, 1, RGB(0, 0, 0)), pen_old = (HPEN)SelectObject(hdc, pen_border); int step = 3, minor = 3, major = 5, count = 1, len = 0; FillRect(hdc, &whole_, brsh_all); FillRect(hdc, &user_sel_, brsh_sel); Rectangle(hdc, user_sel_.left, user_sel_.top, user_sel_.right, user_sel_.bottom); SelectObject(hdc, pen_ruler); for (int i = whole_.left + step; i < whole_.right; i += step) { ++count; len = (count % 5) == 0 ? major : minor; MoveToEx(hdc, i, whole_.top, NULL); LineTo(hdc, i, whole_.top + len); MoveToEx(hdc, i, whole_.bottom, NULL); LineTo(hdc, i, whole_.bottom - len); } count = 1; for (int i = whole_.top + step; i < whole_.bottom; i += step) { ++count; len = (count % 5) == 0 ? major : minor; MoveToEx(hdc, whole_.left, i, NULL); LineTo(hdc, whole_.left + len, i); MoveToEx(hdc, whole_.right, i, NULL); LineTo(hdc, whole_.right - len, i); } std::vector r; drag_blocks(r); for(size_t i = 0; i < r.size(); ++i) FillRect(hdc, &r[i], brsh_drag); SelectObject(hdc, pen_old); DeleteObject(pen_border); DeleteObject(pen_ruler); DeleteObject(brsh_all); DeleteObject(brsh_sel); DeleteObject(brsh_drag); } void dlg_area::on_mouse_move(DWORD key, int x, int y) { if (key == MK_LBUTTON) { if (drag_ == DRAG_POS_NONE) return; float dif = .0f; SetCursor(LoadCursorW(NULL, cursor_)); if (drag_ == DRAG_POS_LT) { valid_x(x, true); valid_y(y, true); user_sel_.left = x; user_sel_.top = y; dif = x_; x_ = pos_2_area(x, true); w_ -= x_ - dif; dif = y_; y_ = pos_2_area(y, false); h_ -= y_ - dif; } else if (drag_ == DRAG_POS_MT) { valid_y(y, true); user_sel_.top = y; dif = y_; y_ = pos_2_area(y, false); h_ -= y_ - dif; } else if(drag_ == DRAG_POS_RT) { valid_x(x, false); valid_y(y, true); user_sel_.right = x; user_sel_.top = y; w_ = pos_2_area(x, true) - x_; if (x_ + w_ > paper_w_) w_ = paper_w_ - x_; dif = y_; y_ = pos_2_area(y, false); h_ -= y_ - dif; } else if (drag_ == DRAG_POS_LM) { valid_x(x, true); user_sel_.left = x; dif = x_; x_ = pos_2_area(x, true); w_ -= x_ - dif; } else if (drag_ == DRAG_POS_RM) { valid_x(x, false); user_sel_.right = x; w_ = pos_2_area(x, true) - x_; if (x_ + w_ > paper_w_) w_ = paper_w_ - x_; } else if (drag_ == DRAG_POS_LB) { valid_x(x, true); valid_y(y, false); user_sel_.left = x; user_sel_.bottom = y; dif = x_; x_ = pos_2_area(x, true); w_ -= x_ - dif; h_ = pos_2_area(y, false) - y_; } else if (drag_ == DRAG_POS_MB) { valid_y(y, false); user_sel_.bottom = y; h_ = pos_2_area(y, false) - y_; if (y_ + h_ > paper_h_) h_ = paper_h_ - y_; } else if (drag_ == DRAG_POS_RB) { valid_x(x, false); valid_y(y, false); user_sel_.right = x; user_sel_.bottom = y; w_ = pos_2_area(x, true) - x_; if (x_ + w_ > paper_w_) w_ = paper_w_ - x_; h_ = pos_2_area(y, false) - y_; if (y_ + h_ > paper_h_) h_ = paper_h_ - y_; } else if (drag_ == DRAG_POS_MOVE) { x += move_.x; y += move_.y; OffsetRect(&user_sel_, x - user_sel_.left, y - user_sel_.top); if (user_sel_.left < whole_.left) OffsetRect(&user_sel_, whole_.left - user_sel_.left, 0); if (user_sel_.right > whole_.right) OffsetRect(&user_sel_, whole_.right - user_sel_.right, 0); if (user_sel_.top < whole_.top) OffsetRect(&user_sel_, 0, whole_.top - user_sel_.top); if (user_sel_.bottom > whole_.bottom) OffsetRect(&user_sel_, 0, whole_.bottom - user_sel_.bottom); x_ = pos_2_area(user_sel_.left, true); if (x_ + w_ > paper_w_) x_ = paper_w_ - w_; y_ = pos_2_area(user_sel_.top, false); if (y_ + h_ > paper_h_) y_ = paper_h_ - h_; } refresh_paper_info(); InvalidateRect(hwnd(), &whole_, FALSE); return; } POINT pt = { x, y }; std::vector r; bool handled = false; drag_blocks(r); for (size_t i = 0; i < r.size(); ++i) { if (PtInRect(&r[i], pt)) { handled = true; if (r[i].pos == DRAG_POS_LT || r[i].pos == DRAG_POS_RB) cursor_ = IDC_SIZENWSE; else if(r[i].pos == DRAG_POS_RT || r[i].pos == DRAG_POS_LB) cursor_ = IDC_SIZENESW; else if(r[i].pos == DRAG_POS_MT || r[i].pos == DRAG_POS_MB) cursor_ = IDC_SIZENS; else cursor_ = IDC_SIZEWE; drag_ = r[i].pos; SetCursor(LoadCursor(NULL, cursor_)); break; } } if (!handled) { if (PtInRect(&user_sel_, pt)) { drag_ = DRAG_POS_MOVE; cursor_ = IDC_SIZEALL; SetCursor(LoadCursor(NULL, cursor_)); } else { drag_ = DRAG_POS_NONE; cursor_ = NULL; } } } void dlg_area::on_lbutton_down(int x, int y) { move_.x = user_sel_.left - x; move_.y = user_sel_.top - y; if (cursor_) SetCursor(LoadCursorW(NULL, cursor_)); SetCapture(hwnd()); } void dlg_area::on_lbutton_up(int x, int y) { drag_ = DRAG_POS_NONE; cursor_ = NULL; ReleaseCapture(); } void dlg_area::set_paper(const wchar_t* name, float width_mm, float height_mm, float dpi) { wchar_t paper[40] = { 0 }; dpi_ = dpi; paper_ = name; paper_w_0_ = width_mm; paper_h_0_ = height_mm; if (unit_ == PAPER_UNIT_INCH) { paper_w_ = dlg_area::mm_2_inches(width_mm); paper_h_ = dlg_area::mm_2_inches(height_mm); } else if (unit_ == PAPER_UNIT_PIXEL) { paper_w_ = dlg_area::mm_2_pixel(width_mm, dpi_); paper_h_ = dlg_area::mm_2_pixel(height_mm, dpi_); } else { paper_w_ = width_mm; paper_h_ = height_mm; } RECT r = { 0 }; float xr = 1.0f, yr = 1.0f; GetWindowRect(get_item(IDC_STATIC_PAINT), &r); screen_2_client(&r); xr = paper_w_0_ / (r.right - r.left); yr = paper_h_0_ / (r.bottom - r.top); ratio_ = xr >= yr ? xr : yr; xr = paper_w_0_ / ratio_; xr = (r.right - r.left - xr) / 2; yr = paper_h_0_ / ratio_; yr = (r.bottom - r.top - yr) / 2; whole_.left = r.left + (LONG)xr; whole_.right = r.right - (LONG)xr; whole_.top = r.top + (LONG)yr; whole_.bottom = r.bottom - (LONG)yr; clear_area(); } void dlg_area::set_area(float x, float y, float w, float h) { x_ = from_mm(x); y_ = from_mm(y); w_ = from_mm(w); h_ = from_mm(h); if (x_ > paper_w_) { if (w_ < paper_w_) x_ = paper_w_ - w_; else x_ = 0; } if (w_ + x_ > paper_w_) w_ = paper_w_ - x_; if (y_ > paper_h_) { if (h_ < paper_h_) y_ = paper_h_ - h_; else y_ = 0; } if (h_ + y_ > paper_h_) h_ = paper_h_ - y_; user_sel_.left = whole_.left + (LONG)(x_ / ratio_); user_sel_.top = whole_.top + (LONG)(y_ / ratio_); user_sel_.right = user_sel_.left + (LONG)(w_ / ratio_); user_sel_.bottom = user_sel_.top + (LONG)(h_ / ratio_); refresh_paper_info(); } int dlg_area::do_modal(HWND parent) { BOOL enable_parent = FALSE, got = TRUE; MSG msg = { 0 }; if (IsWindow(parent) && parent != GetDesktopWindow()) { EnableWindow(parent, FALSE); enable_parent = TRUE; } ShowWindow(hwnd(), SW_SHOW); while ((got = GetMessage(&msg, NULL, 0, 0))) { if ((DWORD)got == -1) break; //if (enable_parent && msg.hwnd == parent && // msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST && // msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST) // continue; TranslateMessage(&msg); DispatchMessage(&msg); if (exit_code_ == IDOK || exit_code_ == IDCANCEL) break; } ShowWindow(hwnd(), SW_HIDE); if (enable_parent) { EnableWindow(parent, TRUE); } return exit_code_; } float dlg_area::x_in_mm(void) { return as_mm(x_); } float dlg_area::y_in_mm(void) { return as_mm(y_); } float dlg_area::w_in_mm(void) { return as_mm(w_); } float dlg_area::h_in_mm(void) { return as_mm(h_); }