#pragma once #include <boost/noncopyable.hpp> #include <windows.h> #include <objbase.h> #include <Shobjidl.h> #include <string> #include <vector> #include "utf8.h" #include "win32/MyWSAError.h" #include "win32/path_op.h" #if _WIN32_WINNT > _WIN32_WINNT_WINXP #include "win32/file_op.h" #endif #include "win32/memory_micros.h" #include "win32/clipboard.h" namespace utf8 { inline bool mbcs_to_u16(const char* mbcs, wchar_t* u16buffer, size_t u16size) { size_t request_size = MultiByteToWideChar(CP_ACP, 0, mbcs, -1, NULL, 0); if (0 < request_size && request_size < u16size) { MultiByteToWideChar(CP_ACP, 0, mbcs, -1, u16buffer, request_size); return true; } return false; }; inline std::wstring mbcs_to_u16(const std::string& mbcs) { std::wstring res = L""; size_t request_size = MultiByteToWideChar(CP_ACP, 0, mbcs.c_str(), -1, NULL, 0); if (0 < request_size) { auto u16buffer = new wchar_t[request_size]; MultiByteToWideChar(CP_ACP, 0, mbcs.c_str(), -1, u16buffer, request_size); res = u16buffer; delete[] u16buffer; } return res; } inline std::string u16_to_mbcs(const std::wstring& u16) { std::string res = ""; size_t request_size = WideCharToMultiByte(CP_ACP, 0, u16.c_str(), -1, 0, 0, 0, 0); if (0 < request_size) { auto mbcs_buffer = new char[request_size]; WideCharToMultiByte(CP_ACP, 0, u16.c_str(), -1, mbcs_buffer, request_size, 0, 0); res = mbcs_buffer; delete[] mbcs_buffer; } return res; } inline std::string mbcs_to_utf8(const std::wstring& mbcs) { std::string res = ""; size_t request_size = WideCharToMultiByte(CP_UTF8, 0, mbcs.c_str(), -1, 0, 0, 0, 0); if (0 < request_size) { auto mbcs_buffer = new char[request_size]; WideCharToMultiByte(CP_UTF8, 0, mbcs.c_str(), -1, mbcs_buffer, request_size, 0, 0); res = mbcs_buffer; delete[] mbcs_buffer; } return res; } }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// namespace jlib { inline DWORD daemon(const std::wstring& path, bool wait_app_exit = true, bool show = true) { STARTUPINFOW si = { 0 }; si.cb = sizeof(si); si.dwFlags |= STARTF_USESHOWWINDOW; si.wShowWindow = show ? SW_SHOW : SW_HIDE; PROCESS_INFORMATION pi; DWORD dwCreationFlags = show ? 0 : CREATE_NO_WINDOW; BOOL bRet = CreateProcessW(NULL, (LPWSTR)(path.c_str()), NULL, NULL, FALSE, dwCreationFlags, NULL, NULL, &si, &pi); if (bRet) { WaitForSingleObject(pi.hProcess, wait_app_exit ? INFINITE : 0); DWORD dwExit; ::GetExitCodeProcess(pi.hProcess, &dwExit); CloseHandle(pi.hThread); CloseHandle(pi.hProcess); return dwExit; } return 0xFFFFFFFF; } inline DWORD daemon(const std::string& path, bool wait_app_exit = true, bool show = true) { return daemon(utf8::a2w(path), wait_app_exit, show); } inline BOOL Win32CenterWindow(HWND hwndWindow) { HWND hwndParent; RECT rectWindow, rectParent; if ((hwndParent = GetParent(hwndWindow)) == NULL) { hwndParent = GetDesktopWindow(); } // make the window relative to its parent if (hwndParent != NULL) { GetWindowRect(hwndWindow, &rectWindow); GetWindowRect(hwndParent, &rectParent); int nWidth = rectWindow.right - rectWindow.left; int nHeight = rectWindow.bottom - rectWindow.top; int nX = ((rectParent.right - rectParent.left) - nWidth) / 2 + rectParent.left; int nY = ((rectParent.bottom - rectParent.top) - nHeight) / 2 + rectParent.top; int nScreenWidth = GetSystemMetrics(SM_CXSCREEN); int nScreenHeight = GetSystemMetrics(SM_CYSCREEN); // make sure that the dialog box never moves outside of the screen if (nX < 0) nX = 0; if (nY < 0) nY = 0; if (nX + nWidth > nScreenWidth) nX = nScreenWidth - nWidth; if (nY + nHeight > nScreenHeight) nY = nScreenHeight - nHeight; MoveWindow(hwndWindow, nX, nY, nWidth, nHeight, FALSE); return TRUE; } return FALSE; } class auto_timer : public boost::noncopyable { private: int m_timer_id; DWORD m_time_out; HWND m_hWnd; public: auto_timer(HWND hWnd, int timerId, DWORD timeout) : m_hWnd(hWnd), m_timer_id(timerId), m_time_out(timeout) { KillTimer(hWnd, m_timer_id); } ~auto_timer() { SetTimer(m_hWnd, m_timer_id, m_time_out, nullptr); } }; namespace rc_detail { inline long Width(::LPCRECT rc) { return rc->right - rc->left; } inline long Height(::LPCRECT rc) { return rc->bottom - rc->top; } inline void DeflateRect(::LPRECT rc, int l, int t, int r, int b) { rc->left += l; rc->top += t; rc->right -= r; rc->bottom -= b; } inline void InflateRect(::LPRECT rc, int l, int t, int r, int b) { rc->left -= l; rc->top -= t; rc->right += r; rc->bottom += b; } } // ������ƽ���ָ��n��,���2*gap, n is x^2, x={1,2,3...} inline std::vector<::RECT> split_rect(::LPCRECT rc, int n, int gap = 50) { using namespace rc_detail; std::vector<::RECT> v; for (int i = 0; i < n; i++) { v.push_back(*rc); } double l = sqrt(n); int line = int(l); int col_step = (int)(Width(rc) / line); int row_step = (int)(Height(rc) / line); for (int i = 0; i < n; i++) { v[i].left = rc->left + (i % line) * col_step; v[i].right = v[i].left + col_step; v[i].top = rc->top + (i / line) * row_step; v[i].bottom = v[i].top + row_step; DeflateRect(&v[i], gap, gap, gap, gap); } return v; }; // ������ˮƽƽ���ָ�Ϊn�ݾ���, ��hgap==-1ʱ���ָ���ľ�����Դ���α��ֱ��� inline std::vector<::RECT> split_rect_horizontal(::LPCRECT rc, int n, int wgap = 50, int hgap = -1) { using namespace rc_detail; std::vector<::RECT> v; int w = (Width(rc) - (n + 1) * wgap) / n; if (hgap == -1) { double ratio = (rc->right - rc->left) * 1.0 / (rc->bottom - rc->top); int h = static_cast<int>(w / ratio); hgap = (Height(rc) - h) / 2; } for (int i = 0; i < n; i++) { ::RECT r = *rc; r.left += i*w + (i + 1)*wgap; r.right = r.left + w; r.top = rc->top + hgap; r.bottom = rc->bottom - hgap; v.push_back(r); } return v; } // rc's width / spliter = (rc's width - hexagon's side length) / 2 inline std::vector<::POINT> get_hexagon_vertexes_from_rect(::LPCRECT rc, float spliter = 3.0) { if (!rc) { return std::vector<::POINT>(); } if (spliter == 0.0) { spliter = 3.0; } std::vector<::POINT> v; auto w = rc->right - rc->left; auto h = rc->bottom - rc->top; auto ww = static_cast<int>(w / spliter); auto hh = static_cast<int>(h / spliter); ::POINT pt; pt.x = rc->left; pt.y = rc->top + hh; v.push_back(pt); pt.x = rc->left + ww; pt.y = rc->top; v.push_back(pt); pt.x = rc->right - ww; v.push_back(pt); pt.x = rc->right; pt.y = rc->top + hh; v.push_back(pt); pt.y = rc->bottom - hh; v.push_back(pt); pt.x = rc->right - ww; pt.y = rc->bottom; v.push_back(pt); pt.x = rc->left + ww; v.push_back(pt); pt.x = rc->left; pt.y = rc->bottom - hh; v.push_back(pt); return v; } };