code_twain/sane/DlgArea.cpp

734 lines
16 KiB
C++
Raw Normal View History

// DlgIndicator.cpp: 实现文件
//
#include "DlgArea.h"
#include "resource.h"
#include "scanned_img.h" // for local_trans
2022-06-24 09:01:00 +00:00
#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();
2022-06-24 09:01:00 +00:00
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 = _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 + x_ / ratio_;
if (x_ + w_ > paper_w_)
w_ = paper_w_ - x_;
user_sel_.right = user_sel_.left + 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 + y_ / ratio_;
if (y_ + h_ > paper_h_)
h_ = paper_h_ - y_;
user_sel_.bottom = user_sel_.top + h_ / ratio_;
refresh_paper_info();
InvalidateRect(hwnd(), &whole_, FALSE);
}
else if (id == IDC_EDIT_W)
{
if (num < dlg_area::area_min_pixel)
num = dlg_area::area_min_pixel;
if (num > paper_w_)
num = paper_w_;
w_ = num;
user_sel_.right = user_sel_.left + 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 = dlg_area::area_min_pixel;
if (num > paper_h_)
num = paper_h_;
h_ = num;
user_sel_.bottom = user_sel_.top + 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::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<DRAGRECT>& blocks)
{
int l = 5;
DRAGRECT r = { user_sel_.left, user_sel_.top, user_sel_.left + l, user_sel_.top + l, 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 ? val - whole_.left : 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<DRAGRECT> 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<DRAGRECT> 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 + xr; whole_.right = r.right - xr;
whole_.top = r.top + yr; whole_.bottom = r.bottom - yr;
clear_area();
}
void dlg_area::set_area(int x, int y, int w, int h)
{
x_ = x;
y_ = y;
w_ = w;
h_ = 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_;
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_;
}
int dlg_area::x_in_mm(void)
{
return as_mm(x_);
}
int dlg_area::y_in_mm(void)
{
return as_mm(y_);
}
int dlg_area::w_in_mm(void)
{
return as_mm(w_);
}
int dlg_area::h_in_mm(void)
{
return as_mm(h_);
}