doc_and_tools/tools/apps/hg-helper/DlgBase.cpp

680 lines
15 KiB
C++

// DlgIndicator.cpp: 实现文件
//
#include "DlgBase.h"
#include "resource.h"
// #pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#pragma warning(disable: 4996)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
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_))
{
SetPropW(hwnd_, dlg_base::prop_name.c_str(), NULL);
//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;
}
std::wstring dlg_base::get_wnd_text(HWND h)
{
int len = GetWindowTextLengthW(h);
wchar_t* buf = new wchar_t[len + 8];
std::wstring ret(L"");
memset(buf, 0, (len + 8) * 2);
GetWindowTextW(h, buf, len + 2);
ret = buf;
delete[] buf;
return std::move(ret);
}
std::wstring dlg_base::get_menu_text(HMENU menu, int ind)
{
MENUITEMINFOW mi = { 0 };
wchar_t text[128] = { 0 };
mi.cbSize = sizeof(mi);
mi.fMask = mi.fType = MIIM_STRING; // MFT_STRING;
mi.dwTypeData = text;
mi.cch = _countof(text) - 1;
GetMenuItemInfoW(menu, ind, MF_BYPOSITION, &mi);
return text;
}
void dlg_base::center_window(HWND wnd, HWND parent)
{
RECT rme = { 0 }, rp = { 0 };
int x = 0, y = 0;
GetWindowRect(wnd, &rme);
if (!IsWindow(parent))
parent = GetDesktopWindow();
GetWindowRect(parent, &rp);
x = rp.left + (RECT_W(rp) - RECT_W(rme)) / 2;
y = rp.top + (RECT_H(rp) - RECT_H(rme)) / 2;
OffsetRect(&rme, x - rme.left, y - rme.top);
MoveWindow(wnd, rme.left, rme.top, RECT_W(rme), RECT_H(rme), FALSE);
}
int dlg_base::get_combox_cur_sel(HWND wnd)
{
return SendMessageW(wnd, CB_GETCURSEL, 0, 0);
}
int dlg_base::get_button_check(HWND wnd)
{
return SendMessageW(wnd, BM_GETCHECK, 0, 0);
}
int dlg_base::list_insert_column(HWND list_wnd, const wchar_t* text, int cx, int ind)
{
LVCOLUMNW col = { 0 };
if (ind == -1)
ind = dlg_base::list_get_column_count(list_wnd);
col.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
col.pszText = (LPWSTR)text;
col.iSubItem = 0;
col.cx = cx;
return ListView_InsertColumn(list_wnd, ind, &col);
}
int dlg_base::list_insert_item(HWND list_wnd, const wchar_t* text, int ind)
{
LV_ITEMW item = { 0 };
if (ind == -1)
ind = dlg_base::list_get_item_count(list_wnd);
item.mask = LVIF_TEXT;
item.pszText = (PWSTR)text;
item.iItem = ind;
return ListView_InsertItem(list_wnd, &item);
}
int dlg_base::list_get_item_count(HWND list_wnd)
{
return ListView_GetItemCount(list_wnd);
}
int dlg_base::list_get_column_count(HWND list_wnd)
{
return ListView_GetItemCount((HWND)ListView_GetHeader(list_wnd));
}
std::wstring dlg_base::list_get_text(HWND list_wnd, int ind, int sub)
{
LV_ITEMW item = { 0 };
wchar_t text[128] = { 0 };
item.mask = LVIF_TEXT;
item.pszText = (PWSTR)text;
item.iItem = ind;
item.iSubItem = sub;
item.cchTextMax = _countof(text) - 1;
ListView_GetItem(list_wnd, &item);
return text;
}
void dlg_base::list_get_selected_items(HWND list_wnd, std::vector<int>& sels)
{
LV_ITEMW item = { 0 };
item.mask = LVIF_STATE;
for (int i = 0; i < dlg_base::list_get_item_count(list_wnd); ++i)
{
item.iItem = i;
item.stateMask = LVIS_SELECTED;
ListView_GetItem(list_wnd, &item);
if (item.state & LVIS_SELECTED)
sels.push_back(i);
}
}
int dlg_base::list_set_item_text(HWND list_wnd, int item, int sub_item, const wchar_t* text)
{
LV_ITEMW lvi = { 0 };
lvi.iItem = item;
lvi.iSubItem = sub_item;
lvi.pszText = (LPWSTR)text;
lvi.mask = LVIF_TEXT;
return ListView_SetItem(list_wnd, &lvi) ? 0 : 1;
}
int dlg_base::get_tab_count(HWND tab)
{
int count = -1;
if (IsWindow(tab))
count = TabCtrl_GetItemCount(tab);
return count;
}
int dlg_base::insert_page_to_tab(HWND tab, dlg_base* page, const wchar_t* title)
{
TC_ITEMW item = { 0 };
int ind = 0;
std::wstring t(title);
item.mask = TCIF_PARAM | TCIF_TEXT;
item.lParam = (LPARAM)page;
item.pszText = &t[0];
ind = TabCtrl_InsertItem(tab, dlg_base::get_tab_count(tab), &item);
return ind;
}
void* dlg_base::get_tab_item_data(HWND tab, int index)
{
TCITEMW item = { 0 };
item.mask = TCIF_PARAM;
TabCtrl_GetItem(tab, index, &item);
return (void*)item.lParam;
}
std::string dlg_base::u2m(const wchar_t* u, int page)
{
char* ansi = NULL;
int len = 0;
std::string mb("");
len = WideCharToMultiByte(page, 0, u, lstrlenW(u), NULL, 0, NULL, NULL);
ansi = new char[len + 2];
len = WideCharToMultiByte(page, 0, u, lstrlenW(u), ansi, len, NULL, NULL);
ansi[len--] = 0;
mb = ansi;
delete[] ansi;
return mb;
}
std::wstring dlg_base::m2u(const char* m, int page)
{
wchar_t* unic = NULL;
int len = 0;
std::wstring u(L"");
len = MultiByteToWideChar(page, 0, m, lstrlenA(m), NULL, 0);
unic = new wchar_t[len + 2];
len = MultiByteToWideChar(page, 0, m, lstrlenA(m), unic, len);
unic[len--] = 0;
u = unic;
delete[] unic;
return u;
}
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_);
}
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);
}
}
}
int dlg_base::do_modal(HWND parent)
{
BOOL enable_parent = FALSE,
got = TRUE;
MSG msg = { 0 };
modal_exit_ = 0;
if (IsWindow(parent) && parent != GetDesktopWindow())
{
EnableWindow(parent, FALSE);
enable_parent = TRUE;
}
dlg_base::center_window(hwnd(), parent);
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 (modal_exit_)
break;
}
ShowWindow(hwnd(), SW_HIDE);
if (enable_parent)
{
EnableWindow(parent, TRUE);
}
return modal_exit_;
}
void dlg_base::quit_modal(int non_zero_code)
{
// assert ( non_zero_code );
modal_exit_ = non_zero_code;
}
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, HWND wnd)
{
if (!wnd)
wnd = hwnd_;
HDC hdc = GetWindowDC(wnd);
SIZE size = { 0 };
GetTextExtentPointW(hdc, str, lstrlenW(str), &size);
ReleaseDC(wnd, hdc);
return size.cx;
}
bool dlg_base::get_item_rect(UINT id, LPRECT r, bool client)
{
if (client)
return GetClientRect(GetDlgItem(hwnd_, id), r) == TRUE;
else
return GetWindowRect(GetDlgItem(hwnd_, id), r) == TRUE;
}
std::wstring dlg_base::get_item_text(UINT id)
{
return std::move(dlg_base::get_wnd_text(get_item(id)));
}
int dlg_base::get_width_diff_as_text_length(UINT id)
{
RECT r = { 0 };
get_item_rect(id, &r);
return get_string_width(get_item_text(id).c_str()) - RECT_W(r);
}
void dlg_base::offset_item(HWND wnd, int dx, int dy)
{
RECT r = { 0 };
GetWindowRect(wnd, &r);
OffsetRect(&r, dx, dy);
screen_2_client(&r);
MoveWindow(wnd, r.left, r.top, RECT_W(r), RECT_H(r), FALSE);
}
void dlg_base::offset_item(UINT id, int dx, int dy)
{
offset_item(get_item(id), dx, dy);
}
void dlg_base::expand_item(UINT id, int dx, int dy)
{
RECT r = { 0 };
get_item_rect(id, &r, false);
r.right += dx;
r.bottom += dy;
screen_2_client(&r);
MoveWindow(get_item(id), r.left, r.top, RECT_W(r), RECT_H(r), FALSE);
}
bool dlg_base::set_item_text(UINT id, const wchar_t* text)
{
return SetWindowTextW(GetDlgItem(hwnd_, id), text) == TRUE;
}
int dlg_base::set_item_fit_to_text(UINT id)
{
HWND wnd = get_item(id);
std::wstring text(get_item_text(id));
RECT r = { 0 };
int w = get_string_width(text.c_str(), wnd);
get_item_rect(id, &r, false);
if (w > RECT_W(r) || w <= RECT_W(r) / 2)
{
if (w > RECT_W(r))
w -= RECT_W(r);
else
w -= RECT_W(r) / 2;
expand_item(id, w, 0);
}
else
w = 0;
return w;
}
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;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//