code_twain/sane/DlgArea.cpp

747 lines
17 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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<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 ? (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<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 + (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_);
}