调整界面模型,兼容模块频繁加载&卸载

This commit is contained in:
gb 2023-10-23 11:14:25 +08:00
parent bdc0b30ffa
commit 0ad34a90c4
8 changed files with 327 additions and 110 deletions

View File

@ -12,10 +12,11 @@
// CDlgIndicator 对话框 // CDlgIndicator 对话框
dlg_indicator::dlg_indicator(HWND parent) : dlg_base(parent, IDD_INDICATOR) dlg_indicator::dlg_indicator(HWND parent, bool sole_thread) : dlg_base(parent, IDD_INDICATOR)
, papers_(0), images_(0), err_(false), finish_(false) , papers_(0), images_(0), err_(false), finish_(false)
{ {
create(); del_at_destroy_ = true;
create(sole_thread);
SetWindowLongW(GetDlgItem(hwnd_, IDC_STATIC_ERR), GWL_STYLE, GetWindowLong(GetDlgItem(hwnd_, IDC_STATIC_ERR), GWL_STYLE) | SS_OWNERDRAW); SetWindowLongW(GetDlgItem(hwnd_, IDC_STATIC_ERR), GWL_STYLE, GetWindowLong(GetDlgItem(hwnd_, IDC_STATIC_ERR), GWL_STYLE) | SS_OWNERDRAW);
if (!dlg_base::is_language_pack_default_code_page()) if (!dlg_base::is_language_pack_default_code_page())
@ -34,9 +35,9 @@ dlg_indicator::dlg_indicator(HWND parent) : dlg_base(parent, IDD_INDICATOR)
set_item_text(IDCANCEL, text.c_str()); set_item_text(IDCANCEL, text.c_str());
int paper = get_width_diff_as_text_length(IDC_STATIC_PAPER), int paper = get_width_diff_as_text_length(IDC_STATIC_PAPER),
img = get_width_diff_as_text_length(IDC_STATIC_IMAGE), img = get_width_diff_as_text_length(IDC_STATIC_IMAGE),
btn = get_width_diff_as_text_length(IDCANCEL), btn = get_width_diff_as_text_length(IDCANCEL),
diff = paper >= img + btn ? paper : img + btn; diff = paper >= img + btn ? paper : img + btn;
if (diff > 0) if (diff > 0)
{ {
@ -157,7 +158,11 @@ void dlg_indicator::handle_command(WORD code, WORD id, HANDLE ctrl)
{ {
if (id == IDCANCEL) if (id == IDCANCEL)
{ {
KillTimer(hwnd(), 1);
EnableWindow((HWND)ctrl, FALSE);
notify_over(!finish_); notify_over(!finish_);
if (!finish_)
SetWindowTextW(hwnd(), local_trans::lang_trans_between_hz936(L"\u6B63\u5728\u505C\u6B62\u626B\u63CF\u2026\u2026").c_str());
} }
} }
void dlg_indicator::notify_over(bool cancel) void dlg_indicator::notify_over(bool cancel)
@ -187,6 +192,7 @@ void dlg_indicator::notify_scan_over(const char* msg, bool err)
delete mstr; delete mstr;
notify_over(false); notify_over(false);
} }
EnableWindow(get_item(IDCANCEL), TRUE);
} }
void dlg_indicator::notify_working(void) void dlg_indicator::notify_working(void)
{ {

View File

@ -20,7 +20,7 @@ class dlg_indicator : public dlg_base
void notify_over(bool cancel); void notify_over(bool cancel);
public: public:
dlg_indicator(HWND parent); dlg_indicator(HWND parent, bool sole_thread);
~dlg_indicator(); ~dlg_indicator();
public: public:

View File

@ -24,49 +24,129 @@ static IMPLEMENT_OPTION_STRING_COMPARE(is_sane_opt);
extern HMODULE g_my_inst; extern HMODULE g_my_inst;
std::wstring dlg_base::prop_name = L"dlg_base_object_prop_name"; std::wstring dlg_base::prop_name = L"dlg_base_object_prop_name";
volatile bool dlg_base::msg_thread_exited_ = true;
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(HWND parent, UINT idd) : parent_(parent), hwnd_(NULL), idd_(idd), ui_event_notify_(NULL), ui_notify_param_(NULL)
, msg_thread_id_(0), destroyed_(false), child_(false), del_at_destroy_(false)
{ {
} }
dlg_base::~dlg_base() dlg_base::~dlg_base()
{ {
if (IsWindow(hwnd_)) //if (IsWindow(hwnd_))
{ //{
SetPropW(hwnd_, dlg_base::prop_name.c_str(), NULL); // //SetPropW(hwnd_, dlg_base::prop_name.c_str(), NULL);
//if (GetCurrentThreadId() == GetWindowThreadProcessId(hwnd_, NULL)) // //if (GetCurrentThreadId() == GetWindowThreadProcessId(hwnd_, NULL))
DestroyWindow(hwnd_); // // DestroyWindow(hwnd_);
} // //show(false);
EnableWindow(parent_, TRUE); // //PostMessage(hwnd_, WM_DESTROY, 0, 0);
BringWindowToTop(parent_); //}
//if (!child_)
//{
// EnableWindow(parent_, TRUE);
// BringWindowToTop(parent_);
//}
//if (msg_thread_.get())
//{
// PostThreadMessageW(msg_thread_id_, WM_QUIT_MSG_THREAD, 0, 0);
// if (msg_thread_->joinable())
// msg_thread_->join();
//}
//else
//{
// destroyed_ = false;
// //PostMessageW(hwnd(), WM_DESTROY, 0, 0);
// //while (!destroyed_)
// //{
// // MSG msg = { 0 };
// // PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE);
// //}
//}
} }
BOOL CALLBACK dlg_base::dlg_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) BOOL CALLBACK dlg_base::dlg_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{ {
// https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nc-winuser-dlgproc:
// 尽管对话框过程类似于窗口过程,但它不得调用 DefWindowProc 函数来处理不需要的消息
dlg_base* obj = (dlg_base*)GetPropW(hwnd, dlg_base::prop_name.c_str());
BOOL ret = FALSE;
if (msg == WM_INITDIALOG) if (msg == WM_INITDIALOG)
{ {
dlg_base* obj = (dlg_base*)lp; obj = (dlg_base*)lp;
SetPropW(hwnd, dlg_base::prop_name.c_str(), (HANDLE)obj); SetPropW(hwnd, dlg_base::prop_name.c_str(), (HANDLE)obj);
obj->hwnd_ = hwnd; obj->hwnd_ = hwnd;
obj->child_ = (GetWindowLong(hwnd, GWL_STYLE) & WS_CHILD) == WS_CHILD;
} }
else if (msg == WM_DESTROY) else if (msg == WM_NCDESTROY)
{ {
dlg_base* obj = (dlg_base*)GetPropW(hwnd, dlg_base::prop_name.c_str());
SetPropW(hwnd, dlg_base::prop_name.c_str(), NULL); 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) if (obj)
{ {
ret = obj->handle_message(msg, wp, lp); ret = obj->handle_message(msg, wp, lp);
if (msg == WM_INITDIALOG)
obj->ready_ = true;
else if (msg == WM_CLOSE)
{
DestroyWindow(hwnd);
ret = TRUE;
}
else if (msg == WM_NCDESTROY)
{
if (!obj->child_)
{
EnableWindow(obj->parent_, TRUE);
BringWindowToTop(obj->parent_);
}
obj->destroyed_ = true;
if(obj->del_at_destroy_)
delete obj;
}
} }
return ret; return ret;
} }
DWORD WINAPI dlg_base::start_thread(LPVOID lp)
{
dlg_base::msg_thread_exited_ = false;
((dlg_base*)lp)->thread_pump_message();
dlg_base::msg_thread_exited_ = true;
return 0;
}
void dlg_base::thread_pump_message(void)
{
msg_thread_id_ = GetCurrentThreadId();
hwnd_ = CreateDialogParamW(g_my_inst, MAKEINTRESOURCE(idd_), parent_, (DLGPROC)&dlg_base::dlg_proc, (LPARAM)this);
if (IsWindow(hwnd_))
{
MSG msg = { 0 };
BOOL ret = TRUE;
HWND hwnd = hwnd_;
while ((ret = GetMessageW(&msg, NULL, 0, 0)))
{
if (ret == -1 || msg.message == WM_QUIT_MSG_THREAD)
break;
TranslateMessage(&msg);
DispatchMessageW(&msg);
//if (msg.message == WM_DESTROY)
//{
// if (msg.hwnd == hwnd)
// break;
//}
}
DestroyWindow(hwnd);
//if (del_at_destroy_)
// delete this;
}
}
void dlg_base::screen_2_client(HWND wnd, LPRECT r) void dlg_base::screen_2_client(HWND wnd, LPRECT r)
{ {
@ -178,6 +258,10 @@ void dlg_base::center_window(HWND wnd, HWND parent)
OffsetRect(&rme, x - rme.left, y - rme.top); OffsetRect(&rme, x - rme.left, y - rme.top);
MoveWindow(wnd, rme.left, rme.top, RECT_W(rme), RECT_H(rme), FALSE); MoveWindow(wnd, rme.left, rme.top, RECT_W(rme), RECT_H(rme), FALSE);
} }
bool dlg_base::is_message_thread_exited(void)
{
return dlg_base::msg_thread_exited_;
}
int dlg_base::list_insert_column(HWND list_wnd, const wchar_t* text, int cx, int ind) int dlg_base::list_insert_column(HWND list_wnd, const wchar_t* text, int cx, int ind)
{ {
LVCOLUMNW col = { 0 }; LVCOLUMNW col = { 0 };
@ -259,15 +343,63 @@ void dlg_base::on_font_changed(void)
{ {
} }
void dlg_base::create(void) void dlg_base::create(bool sole_thread)
{ {
// InitCommonControls(); // InitCommonControls();
hwnd_ = CreateDialogParamW(g_my_inst, MAKEINTRESOURCE(idd_), parent_, (DLGPROC)&dlg_base::dlg_proc, (LPARAM)this); if (sole_thread)
{
HANDLE h = CreateThread(NULL, 0, &dlg_base::start_thread, this, 0, &msg_thread_id_);
if (h)
{
CloseHandle(h);
while (!IsWindow(hwnd_))
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
else
hwnd_ = CreateDialogParamW(g_my_inst, MAKEINTRESOURCE(idd_), parent_, (DLGPROC)&dlg_base::dlg_proc, (LPARAM)this);
}
namespace notify
{
typedef struct _notify_param
{
void(__stdcall* ui_event_notify)(int uev, void* sender, void* param);
void* param;
int ev;
void* sender;
}NOTIFYPARAM, *LPNOTIFYPARAM;
static DWORD WINAPI thread_notify(LPVOID lp)
{
LPNOTIFYPARAM param = (LPNOTIFYPARAM)lp;
param->ui_event_notify(param->ev, param->sender, param->param);
delete param;
return 0;
}
static void notify(void(__stdcall* f)(int, void*, void*), int ev, void* sender, void* param)
{
LPNOTIFYPARAM p = new NOTIFYPARAM;
HANDLE h = NULL;
p->ui_event_notify = f;
p->sender = sender;
p->ev = ev;
p->param = param;
h = CreateThread(NULL, 0, thread_notify, p, 0, NULL);
if (h)
CloseHandle(h);
else
delete p;
}
} }
void dlg_base::notify_ui_event(int ev) void dlg_base::notify_ui_event(int ev)
{ {
if (ui_event_notify_) if (ev == SANE_EVENT_UI_SCAN_COMMAND && ui_event_notify_)
ui_event_notify_(ev, this, ui_notify_param_); ui_event_notify_(ev, this, ui_notify_param_);
else
notify::notify(ui_event_notify_, ev, this, ui_notify_param_);
} }
gb::sane_config_schm* dlg_base::get_config(bool* create) gb::sane_config_schm* dlg_base::get_config(bool* create)
{ {
@ -289,6 +421,12 @@ HWND dlg_base::hwnd(void)
} }
void dlg_base::show(bool visible, bool hold) void dlg_base::show(bool visible, bool hold)
{ {
while (!ready_)
{
MSG msg = { 0 };
PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE);
}
UINT cmd = visible ? SW_SHOW : SW_HIDE; UINT cmd = visible ? SW_SHOW : SW_HIDE;
DWORD style = GetWindowLong(hwnd_, GWL_STYLE); DWORD style = GetWindowLong(hwnd_, GWL_STYLE);
@ -329,6 +467,7 @@ void dlg_base::show(bool visible, bool hold)
pt.y = r0.top; pt.y = r0.top;
SetWindowPos(hwnd_, after, pt.x, pt.y, RECT_W(rme), RECT_H(rme), SWP_NOSIZE); SetWindowPos(hwnd_, after, pt.x, pt.y, RECT_W(rme), RECT_H(rme), SWP_NOSIZE);
UpdateWindow(hwnd_); UpdateWindow(hwnd_);
center_window(hwnd_, parent_);
} }
EnableWindow(parent_, !visible); EnableWindow(parent_, !visible);
} }
@ -353,7 +492,8 @@ void dlg_base::show(bool visible, bool hold)
int dlg_base::do_modal(HWND parent) int dlg_base::do_modal(HWND parent)
{ {
BOOL enable_parent = FALSE, BOOL enable_parent = FALSE,
got = TRUE; got = TRUE,
wait_destory = FALSE;
MSG msg = { 0 }; MSG msg = { 0 };
modal_exit_ = 0; modal_exit_ = 0;
@ -378,13 +518,21 @@ int dlg_base::do_modal(HWND parent)
TranslateMessage(&msg); TranslateMessage(&msg);
DispatchMessage(&msg); DispatchMessage(&msg);
if (modal_exit_) if (modal_exit_)
break; {
} if (destroyed_)
ShowWindow(hwnd(), SW_HIDE); break;
else if (!wait_destory)
{
wait_destory = true;
ShowWindow(hwnd(), SW_HIDE);
if (enable_parent) if (enable_parent)
{ {
EnableWindow(parent, TRUE); EnableWindow(parent, TRUE);
}
close();
}
}
} }
return modal_exit_; return modal_exit_;
@ -394,6 +542,13 @@ void dlg_base::quit_modal(int non_zero_code)
// assert ( non_zero_code ); // assert ( non_zero_code );
modal_exit_ = non_zero_code; modal_exit_ = non_zero_code;
} }
void dlg_base::close(void)
{
if(msg_thread_id_) // 独立的消息循环,则退出
PostMessageW(hwnd_, WM_QUIT, 0, 0);
else // 共用父窗口消息循环,则关闭窗口。关闭窗口消息由自己处理,不提交到默认过程
PostMessageW(hwnd_, WM_CLOSE, 0, 0);
}
void dlg_base::enable(bool enable) void dlg_base::enable(bool enable)
{ {
EnableWindow(hwnd_, enable); EnableWindow(hwnd_, enable);
@ -640,16 +795,16 @@ dlg_page::dlg_page(HWND parent, const wchar_t* name
, id_custom_gamma_(-1), id_paper_(-1), paper_(L"A4"), id_dpi_(-1), dpi_(200), vsb_pos_(0), hsb_pos_(0) , 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) , vsb_(false), hsb_(false)
{ {
del_at_destroy_ = true;
create();
tips_wnd_.create(hwnd());
size_.cx = size_.cy = 0; size_.cx = size_.cy = 0;
pos_.x = 12; pos_.x = 12;
pos_.y = 15; pos_.y = 15;
create();
tips_wnd_.create(hwnd());
} }
dlg_page::~dlg_page() dlg_page::~dlg_page()
{ {
for (auto& v : ctrls_)
DestroyWindow(v);
} }
BOOL dlg_page::handle_message(UINT msg, WPARAM wp, LPARAM lp) BOOL dlg_page::handle_message(UINT msg, WPARAM wp, LPARAM lp)
@ -679,6 +834,10 @@ BOOL dlg_page::handle_message(UINT msg, WPARAM wp, LPARAM lp)
track_mouse_hover(); track_mouse_hover();
on_mouse_hover(LOWORD(lp), HIWORD(lp), wp); on_mouse_hover(LOWORD(lp), HIWORD(lp), wp);
break; break;
case WM_DESTROY:
for (auto& v : ctrls_)
DestroyWindow(v);
break;
default: default:
ret = FALSE; ret = FALSE;
} }

View File

@ -21,6 +21,7 @@
#define RECT_W(r) (r.right - r.left) #define RECT_W(r) (r.right - r.left)
#define RECT_H(r) (r.bottom - r.top) #define RECT_H(r) (r.bottom - r.top)
#define WM_QUIT_MSG_THREAD WM_USER + 300
#define WM_SCAN_WORKING WM_USER + 301 // WPARAM: unused; LPARAM: unsed #define WM_SCAN_WORKING WM_USER + 301 // WPARAM: unused; LPARAM: unsed
#define WM_USB_PACKET_RECEIVED WM_USER + 302 #define WM_USB_PACKET_RECEIVED WM_USER + 302
#define WM_IMAGE_RECEIVED WM_USER + 303 #define WM_IMAGE_RECEIVED WM_USER + 303
@ -35,15 +36,29 @@ namespace gb
class sane_config_schm; class sane_config_schm;
} }
#include <thread>
#include <memory>
class dlg_base class dlg_base
{ {
int modal_exit_; // set non-ZERO code to exit modal dialog int modal_exit_; // set non-ZERO code to exit modal dialog
DWORD msg_thread_id_;
volatile bool destroyed_;
bool child_;
static volatile bool msg_thread_exited_;
static DWORD WINAPI start_thread(LPVOID lp);
void thread_pump_message(void);
protected: protected:
HWND hwnd_; HWND hwnd_;
HWND parent_; HWND parent_;
UINT idd_; UINT idd_;
bool abandon_hold_; bool abandon_hold_;
bool del_at_destroy_; // 是否在窗口销毁时,自动释放对象
volatile bool ready_ = false;
void(__stdcall* ui_event_notify_)(int uev, void* sender, void* param); void(__stdcall* ui_event_notify_)(int uev, void* sender, void* param);
void* ui_notify_param_; void* ui_notify_param_;
static std::wstring prop_name; static std::wstring prop_name;
@ -51,7 +66,7 @@ protected:
virtual BOOL handle_message(UINT msg, WPARAM wp, LPARAM lp); virtual BOOL handle_message(UINT msg, WPARAM wp, LPARAM lp);
virtual void on_font_changed(void); virtual void on_font_changed(void);
void create(void); void create(bool sole_thread = false);
void notify_ui_event(int ev); void notify_ui_event(int ev);
gb::sane_config_schm* get_config(bool* create); gb::sane_config_schm* get_config(bool* create);
@ -68,6 +83,7 @@ public:
static bool is_language_pack_default_code_page(void); static bool is_language_pack_default_code_page(void);
static std::wstring get_menu_text(HMENU menu, int ind); static std::wstring get_menu_text(HMENU menu, int ind);
static void center_window(HWND wnd, HWND parent); static void center_window(HWND wnd, HWND parent);
static bool is_message_thread_exited(void);
static int list_insert_column(HWND list_wnd, const wchar_t* text, int cx = 20, int ind = -1); static int list_insert_column(HWND list_wnd, const wchar_t* text, int cx = 20, int ind = -1);
static int list_insert_item(HWND list_wnd, const wchar_t* text, int ind = -1); static int list_insert_item(HWND list_wnd, const wchar_t* text, int ind = -1);
@ -81,8 +97,9 @@ public:
void set_ui_event_notify(void(__stdcall* notify)(int, void*, void*), void* param); void set_ui_event_notify(void(__stdcall* notify)(int, void*, void*), void* param);
HWND hwnd(void); HWND hwnd(void);
void show(bool visible, bool hold = false); void show(bool visible, bool hold = false);
int do_modal(HWND parent); int do_modal(HWND parent); // 该函数调用之后,自动销毁窗口。如果要反复使用,需要调整窗口创建时机,放到该函数入口处。(FIXED ME ...
void quit_modal(int non_zero_code); void quit_modal(int non_zero_code);
void close(void);
void enable(bool enable); void enable(bool enable);
void screen_2_client(LPRECT r); void screen_2_client(LPRECT r);
void client_2_screen(LPRECT r); void client_2_screen(LPRECT r);

View File

@ -19,39 +19,25 @@
static IMPLEMENT_OPTION_STRING_COMPARE(cmp_sane_opt); static IMPLEMENT_OPTION_STRING_COMPARE(cmp_sane_opt);
dlg_setting::dlg_setting(HWND parent, LPSANEAPI api, SANE_Handle dev, bool with_scan, const wchar_t* name) : dlg_base(parent, IDD_SETTING) dlg_setting::dlg_setting(HWND parent, LPSANEAPI api, SANE_Handle dev, bool with_scan, const wchar_t* name, bool sole_thread) : dlg_base(parent, IDD_SETTING)
, sane_api_(*api), sane_dev_(dev), with_scan_(with_scan) , sane_api_(*api), sane_dev_(dev), with_scan_(with_scan)
, papers_(0), images_(0), err_(false), tab_(NULL), cfg_(NULL), cfg_file_(L""), twain_set_(nullptr), twain_schm_(nullptr) , papers_(0), images_(0), err_(false), tab_(NULL), cfg_(NULL), cfg_file_(L""), twain_set_(nullptr), twain_schm_(nullptr)
, schm_from_empty_(false) , schm_from_empty_(false), name_(name ? name : L"")
{ {
std::wstring setting(local_trans::lang_trans_between_hz936(CONST_STRING_SETTING)); del_at_destroy_ = true;
create();
SetWindowTextW(hwnd(), (std::wstring(name) + L" " + setting).c_str());
cfg_menu_ = CreatePopupMenu(); cfg_menu_ = CreatePopupMenu();
InsertMenuW(cfg_menu_, 0, MF_BYPOSITION, MENU_CMD_0, local_trans::lang_trans_between_hz936(CONST_STRING_SAVE_CUR_CFG_AS).c_str()); InsertMenuW(cfg_menu_, 0, MF_BYPOSITION, MENU_CMD_0, local_trans::lang_trans_between_hz936(CONST_STRING_SAVE_CUR_CFG_AS).c_str());
InsertMenuA(cfg_menu_, 1, MF_BYPOSITION | MF_SEPARATOR, MENU_CMD_0 + 1, ""); InsertMenuA(cfg_menu_, 1, MF_BYPOSITION | MF_SEPARATOR, MENU_CMD_0 + 1, "");
std::wstring setting(local_trans::lang_trans_between_hz936(CONST_STRING_SETTING));
create(sole_thread);
SetWindowTextW(hwnd(), (name_ + L" " + setting).c_str());
} }
dlg_setting::~dlg_setting() dlg_setting::~dlg_setting()
{ {
if (IsWindow(tab_)) if (cfg_)
{ cfg_->release();
for (int i = 0; i < get_tab_count(); ++i)
{
TCITEMW item = { 0 };
item.mask = TCIF_PARAM;
TabCtrl_GetItem(tab_, i, &item);
if (item.lParam)
delete (dlg_page*)item.lParam;
}
DestroyWindow(tab_);
}
if (twain_schm_)
twain_schm_->release();
cfg_->save(local_trans::u2a(cfg_file_.c_str()).c_str());
DestroyMenu(cfg_menu_);
} }
BOOL dlg_setting::handle_message(UINT msg, WPARAM wp, LPARAM lp) BOOL dlg_setting::handle_message(UINT msg, WPARAM wp, LPARAM lp)
@ -100,6 +86,26 @@ BOOL dlg_setting::handle_message(UINT msg, WPARAM wp, LPARAM lp)
} }
} }
break; break;
case WM_DESTROY:
if (IsWindow(tab_))
{
for (int i = 0; i < get_tab_count(); ++i)
{
TCITEMW item = { 0 };
item.mask = TCIF_PARAM;
TabCtrl_GetItem(tab_, i, &item);
if (item.lParam)
DestroyWindow(((dlg_page*)item.lParam)->hwnd());
}
DestroyWindow(tab_);
}
if (twain_schm_)
twain_schm_->release();
cfg_->save(local_trans::u2a(cfg_file_.c_str()).c_str());
DestroyMenu(cfg_menu_);
break;
default: default:
ret = FALSE; ret = FALSE;
break; break;
@ -195,6 +201,8 @@ void dlg_setting::handle_command(WORD code, WORD id, HANDLE ctrl)
{ {
save_changes_to_cur_scheme(SAVE_REASON_QUIT_UI); save_changes_to_cur_scheme(SAVE_REASON_QUIT_UI);
notify_over(); notify_over();
//PostMessageW(hwnd(), WM_CLOSE, 0, 0);
//PostQuitMessage(0);
} }
else if (id == IDC_BUTTON_HELP) else if (id == IDC_BUTTON_HELP)
{ {
@ -624,11 +632,15 @@ void dlg_setting::save_changes_to_cur_scheme(int reason)
void dlg_setting::set_config(gb::scanner_cfg* cfg, const wchar_t* file, void(__stdcall* apply)(gb::sane_config_schm*, void*), void* param, bool* twain_set) void dlg_setting::set_config(gb::scanner_cfg* cfg, const wchar_t* file, void(__stdcall* apply)(gb::sane_config_schm*, void*), void* param, bool* twain_set)
{ {
if (cfg_)
cfg_->release();
cfg_ = cfg; cfg_ = cfg;
cfg_file_ = file; cfg_file_ = file;
apply_scheme_ = apply; apply_scheme_ = apply;
apply_param_ = param; apply_param_ = param;
twain_set_ = twain_set; twain_set_ = twain_set;
if(cfg_)
cfg_->add_ref();
if (twain_set && *twain_set && cfg_) if (twain_set && *twain_set && cfg_)
{ {

View File

@ -34,6 +34,7 @@ class dlg_setting : public dlg_base
bool *twain_set_; bool *twain_set_;
gb::sane_config_schm* twain_schm_; gb::sane_config_schm* twain_schm_;
bool schm_from_empty_; bool schm_from_empty_;
std::wstring name_;
HMENU cfg_menu_; HMENU cfg_menu_;
void(__stdcall* apply_scheme_)(gb::sane_config_schm*, void*); void(__stdcall* apply_scheme_)(gb::sane_config_schm*, void*);
@ -59,7 +60,7 @@ class dlg_setting : public dlg_base
void save_changes_to_cur_scheme(int reason); void save_changes_to_cur_scheme(int reason);
public: public:
dlg_setting(HWND parent, LPSANEAPI api, SANE_Handle dev, bool with_scan, const wchar_t* name); dlg_setting(HWND parent, LPSANEAPI api, SANE_Handle dev, bool with_scan, const wchar_t* name, bool sole_thread);
~dlg_setting(); ~dlg_setting();
public: public:

View File

@ -558,6 +558,12 @@ scanner::~scanner()
cfg_->remove_all_schemes(); // schemes would add_ref on cfg_, so we clear them first. NOTE: do not call save after this !!! cfg_->remove_all_schemes(); // schemes would add_ref on cfg_, so we clear them first. NOTE: do not call save after this !!!
cfg_->release(); cfg_->release();
cfg_ = NULL; cfg_ = NULL;
while (!dlg_base::is_message_thread_exited())
{
MSG msg = { 0 };
PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE);
}
} }
} }
@ -788,28 +794,30 @@ void scanner::scan_done(void)
while (images_.count()) while (images_.count())
std::this_thread::sleep_for(std::chrono::milliseconds(5)); std::this_thread::sleep_for(std::chrono::milliseconds(5));
if (indicator_.get()) if (indicator_)
indicator_->notify_scan_over(&msg[0], err_ != SCANNER_ERR_OK); indicator_->notify_scan_over(&msg[0], err_ != SCANNER_ERR_OK);
else if (ui_notify) else if (ui_notify)
ui_notify(SANE_EVENT_SCAN_FINISHED, &msg[0], err_); ui_notify(SANE_EVENT_SCAN_FINISHED, &msg[0], err_);
else else
{ is_scanning_ = false;
if (err_) //else
{ //{
if (callback::show_messagebox_ui) // if (err_)
{ // {
callback::show_messagebox_ui(app_wnd_, SANE_EVENT_SCAN_FINISHED, (void*)&msg[0], 0); // if (callback::show_messagebox_ui)
} // {
else // windows message box ... // callback::show_messagebox_ui(app_wnd_, SANE_EVENT_SCAN_FINISHED, (void*)&msg[0], 0);
{ // }
std::wstring text(local_trans::a2u(msg.c_str(), CP_UTF8)); // else // windows message box ...
if (!IsWindow(app_wnd_)) // {
callback::bring_message_box_topmost(local_trans::lang_trans_between_hz936(CONST_STRING_ERROR).c_str()); // std::wstring text(local_trans::a2u(msg.c_str(), CP_UTF8));
MessageBoxW(app_wnd_, text.c_str(), local_trans::lang_trans_between_hz936(CONST_STRING_ERROR).c_str(), MB_OK); // if (!IsWindow(app_wnd_))
} // callback::bring_message_box_topmost(local_trans::lang_trans_between_hz936(CONST_STRING_ERROR).c_str());
} // MessageBoxW(app_wnd_, text.c_str(), local_trans::lang_trans_between_hz936(CONST_STRING_ERROR).c_str(), MB_OK);
on_ui_event(SANE_EVENT_SCAN_FINISHED, (void*)SANE_EVENT_SCAN_FINISHED); // }
} // }
// on_ui_event(SANE_EVENT_SCAN_FINISHED, (void*)SANE_EVENT_SCAN_FINISHED);
//}
// is_scanning_ = false; // is_scanning_ = false;
} }
@ -927,14 +935,16 @@ void scanner::on_ui_event(int uev, void* sender)
{ {
// setting UI closed ... // setting UI closed ...
is_scanning_ = is_show_setting_ = false; is_scanning_ = is_show_setting_ = false;
if (setting_.get()) if (setting_)
setting_.reset(); setting_->close();
setting_ = NULL;
} }
else if (uev == SANE_EVENT_UI_CLOSE_NORMAL) else if (uev == SANE_EVENT_UI_CLOSE_NORMAL)
{ {
// scan complete // scan complete
if (indicator_.get()) if (indicator_)
indicator_.reset(); indicator_->close();
indicator_ = NULL;
// FIX on 2023-05-30: restore scan finished status, whether close UI is up to APP // FIX on 2023-05-30: restore scan finished status, whether close UI is up to APP
//is_scanning_ = is_show_setting_; //is_scanning_ = is_show_setting_;
@ -944,8 +954,9 @@ void scanner::on_ui_event(int uev, void* sender)
else if (uev == SANE_EVENT_UI_CLOSE_CANCEL) else if (uev == SANE_EVENT_UI_CLOSE_CANCEL)
{ {
// scan cancelled // scan cancelled
if (indicator_.get()) //if (indicator_)
indicator_.reset(); // indicator_->close();
//indicator_ = NULL;
stop(); // nothing to do, the finishing work do in SANE_EVENT_SCAN_FINISHED stop(); // nothing to do, the finishing work do in SANE_EVENT_SCAN_FINISHED
} }
@ -2719,7 +2730,7 @@ COM_API_IMPLEMENT(scanner, int, start(void))
user_cancel_ = false; user_cancel_ = false;
fetch_imgs_ = 0; fetch_imgs_ = 0;
is_scanning_ = true; is_scanning_ = true;
app_wnd_ = setting_.get() ? setting_->hwnd() : callback::find_main_wnd(); app_wnd_ = setting_ ? setting_->hwnd() : callback::find_main_wnd();
if (thread_starting_.get() && thread_starting_->joinable()) if (thread_starting_.get() && thread_starting_->joinable())
thread_starting_->join(); thread_starting_->join();
@ -2866,7 +2877,7 @@ COM_API_IMPLEMENT(scanner, int, image_fetched(IScanImg* tx))
fetch_imgs_++; fetch_imgs_++;
if (ui_notify) if (ui_notify)
ui_notify(SANE_EVENT_IMG_UPLOADED, NULL, fetch_imgs_); ui_notify(SANE_EVENT_IMG_UPLOADED, NULL, fetch_imgs_);
else if (indicator_.get()) else if (indicator_)
indicator_->notify_data_arrived(false); indicator_->notify_data_arrived(false);
{ {
@ -3478,15 +3489,16 @@ COM_API_IMPLEMENT(scanner, bool, ui_show_setting(HWND parent, bool with_scan, bo
size_t pid = scanner_name_.find(L" - "); size_t pid = scanner_name_.find(L" - ");
if (pid == -1) if (pid == -1)
pid = scanner_name_.length(); pid = scanner_name_.length();
setting_.reset(new dlg_setting(parent, &sane_api_, handle_, with_scan, scanner_name_.substr(0, pid).c_str())); if (setting_)
setting_->close();
setting_ = new dlg_setting(parent, &sane_api_, handle_, with_scan, scanner_name_.substr(0, pid).c_str(), true);
setting_->set_ui_event_notify(&scanner::ui_callback, this); setting_->set_ui_event_notify(&scanner::ui_callback, this);
setting_->set_config(cfg_, (cfg_path_ + scanner_name_.substr(0, pid) + L".cfg").c_str(), &scanner::apply_scheme, this, &twain_set_); setting_->set_config(cfg_, (cfg_path_ + scanner_name_.substr(0, pid) + L".cfg").c_str(), &scanner::apply_scheme, this, &twain_set_);
indicator_.reset(); //if (indicator)
if (indicator) //{
{ // indicator_.reset(new dlg_indicator(setting_->hwnd(), false));
indicator_.reset(new dlg_indicator(setting_->hwnd())); // indicator_->set_ui_event_notify(&scanner::ui_callback, this);
indicator_->set_ui_event_notify(&scanner::ui_callback, this); //}
}
setting_->show(true); setting_->show(true);
} }
@ -3528,12 +3540,18 @@ COM_API_IMPLEMENT(scanner, bool, ui_show_progress(HWND parent, bool bIndicator))
} }
else if(bIndicator) else if(bIndicator)
{ {
if (setting_.get() && IsWindowVisible(setting_->hwnd())) bool sole_thread = true;
if (setting_ && IsWindowVisible(setting_->hwnd()))
{
parent = setting_->hwnd(); parent = setting_->hwnd();
sole_thread = false;
}
else if (!IsWindow(parent)) else if (!IsWindow(parent))
parent = callback::find_main_wnd(); parent = callback::find_main_wnd();
indicator_.reset(new dlg_indicator(parent)); if (indicator_)
indicator_->close();
indicator_ = new dlg_indicator(parent, sole_thread);
indicator_->set_ui_event_notify(&scanner::ui_callback, this); indicator_->set_ui_event_notify(&scanner::ui_callback, this);
indicator_->show(true); indicator_->show(true);
} }
@ -3542,10 +3560,13 @@ COM_API_IMPLEMENT(scanner, bool, ui_show_progress(HWND parent, bool bIndicator))
} }
COM_API_IMPLEMENT(scanner, void, ui_hide(void)) COM_API_IMPLEMENT(scanner, void, ui_hide(void))
{ {
if (indicator_.get()) if (indicator_)
indicator_.reset(); indicator_->close();
if (setting_.get()) indicator_ = NULL;
setting_.reset();
if (setting_)
setting_->close();
setting_ = NULL;
if (callback::close_ui) if (callback::close_ui)
callback::close_ui(UI_INDICATOR | UI_SETTING | UI_MSG_BOX); callback::close_ui(UI_INDICATOR | UI_SETTING | UI_MSG_BOX);
@ -3562,11 +3583,12 @@ COM_API_IMPLEMENT(scanner, bool, ui_is_ok(void))
// called from device-layer ... // called from device-layer ...
int scanner::handle_device_event(int ev_code, void* data, unsigned int* len) int scanner::handle_device_event(int ev_code, void* data, unsigned int* len)
{ {
dlg_indicator* prog = indicator_;
if (ev_code == SANE_EVENT_WORKING) if (ev_code == SANE_EVENT_WORKING)
{ {
img_ind_ = 0; img_ind_ = 0;
if (indicator_.get()) if (prog)
indicator_->notify_working(); prog->notify_working();
else if (callback::show_progress_ui && is_bIndicator) else if (callback::show_progress_ui && is_bIndicator)
ui_notify(ev_code, data, *len); ui_notify(ev_code, data, *len);
on_ui_event(ev_code, (void*)ev_code); on_ui_event(ev_code, (void*)ev_code);
@ -3627,8 +3649,8 @@ int scanner::handle_device_event(int ev_code, void* data, unsigned int* len)
{ {
img->release(); img->release();
} }
if (indicator_.get()) if (prog)
indicator_->notify_data_arrived(true); prog->notify_data_arrived(true);
else if (ui_notify) else if (ui_notify)
ui_notify(ev_code, data, img_ind_); ui_notify(ev_code, data, img_ind_);
@ -3640,8 +3662,8 @@ int scanner::handle_device_event(int ev_code, void* data, unsigned int* len)
} }
else if (ev_code == SANE_EVENT_USB_DATA_RECEIVED) else if (ev_code == SANE_EVENT_USB_DATA_RECEIVED)
{ {
//if (indicator_.get()) //if (prog)
// indicator_->notify_data_arrived(false); // prog->notify_data_arrived(false);
//else if (ui_notify) //else if (ui_notify)
// ui_notify(ev_code, data, 0); // ui_notify(ev_code, data, 0);
} }

View File

@ -74,8 +74,8 @@ class scanner : public ISaneInvoker, virtual public refer
safe_queue<int> events_; //如果有界面,则全部保存从界面传回的消息;否则只保存开始扫描和结束扫描的事件 safe_queue<int> events_; //如果有界面,则全部保存从界面传回的消息;否则只保存开始扫描和结束扫描的事件
int ev_cnt_; int ev_cnt_;
SANE_FinalImgFormat img_fmt_; SANE_FinalImgFormat img_fmt_;
std::unique_ptr<dlg_indicator> indicator_; dlg_indicator* indicator_ = NULL;
std::unique_ptr<dlg_setting> setting_; dlg_setting* setting_ = NULL;
gb::scanner_cfg* cfg_; gb::scanner_cfg* cfg_;
bool twain_set_; bool twain_set_;
SANEAPI sane_api_; SANEAPI sane_api_;