// 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& 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; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //