Win32Utils.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. #include "Win32Utils.h"
  2. #include <QWindow>
  3. #include <QtWin>
  4. namespace Win32Utils {
  5. bool isMaximized(HWND hWnd)
  6. {
  7. WINDOWPLACEMENT wPos;
  8. BOOL windowPlacement = GetWindowPlacement(hWnd, &wPos);
  9. if (!windowPlacement)
  10. return false;
  11. return wPos.showCmd == SW_MAXIMIZE;
  12. }
  13. bool isFullScreen(HWND hWnd)
  14. {
  15. if (!hWnd)
  16. return false;
  17. RECT winRect;
  18. if (!GetWindowRect(hWnd, &winRect)) {
  19. return false;
  20. }
  21. MONITORINFO mi = { sizeof(mi) };
  22. if (!getMonitorInfo(hWnd, MONITOR_DEFAULTTOPRIMARY, &mi)) {
  23. return false;
  24. }
  25. return (mi.rcMonitor.left == winRect.left) && (mi.rcMonitor.right == winRect.right)
  26. && (mi.rcMonitor.bottom == winRect.bottom) && (mi.rcMonitor.top == winRect.top);
  27. }
  28. /**
  29. * @brief getMonitorInfo
  30. * @param hWnd: window handle
  31. * @param dwFlags: Determines the return value if the window does not intersect any display monitor
  32. * @param lpmi
  33. * @return
  34. */
  35. bool getMonitorInfo(HWND hWnd, DWORD dwFlags, LPMONITORINFO lpmi)
  36. {
  37. HMONITOR monitor = MonitorFromWindow(hWnd, dwFlags);
  38. if (!monitor) {
  39. return false;
  40. }
  41. return GetMonitorInfo(monitor, lpmi);
  42. }
  43. /**
  44. * @brief getResizeBorderThickness
  45. * @param hWnd: window handle
  46. * @param horizontal: (dpiScale) whether to use dpi scale
  47. * @return
  48. */
  49. int getResizeBorderThickness(HWND hWnd, bool horizontal)
  50. {
  51. QWindow *window = findWindow(hWnd);
  52. if (!window) {
  53. return 0;
  54. }
  55. int frame = SM_CXSIZEFRAME;
  56. if (!horizontal) {
  57. frame = SM_CYSIZEFRAME;
  58. }
  59. #ifdef Q_CC_MSVC
  60. UINT dpi = GetDpiForWindow(hWnd);
  61. int result = GetSystemMetricsForDpi(frame, dpi) + GetSystemMetricsForDpi(92, dpi);
  62. if (result > 0)
  63. return result;
  64. #endif
  65. int thickness;
  66. if (QtWin::isCompositionEnabled()) {
  67. thickness = 8;
  68. } else {
  69. thickness = 4;
  70. }
  71. return qRound(thickness * window->devicePixelRatio());
  72. }
  73. QWindow *findWindow(HWND hWnd)
  74. {
  75. if (!hWnd) {
  76. return nullptr;
  77. }
  78. QWindowList windows = QGuiApplication::topLevelWindows();
  79. for (auto win : windows) {
  80. if (win && (SIZE_T(win->winId()) == SIZE_T(hWnd))) {
  81. return win;
  82. }
  83. }
  84. return nullptr;
  85. }
  86. bool isGreaterEqualVersion(QOperatingSystemVersion version)
  87. {
  88. return QOperatingSystemVersion::current() >= version;
  89. }
  90. bool isWin7()
  91. {
  92. return QOperatingSystemVersion::current().majorVersion() == QOperatingSystemVersion::Windows7.majorVersion();
  93. }
  94. bool isGreaterEqualWin8_1()
  95. {
  96. return isGreaterEqualVersion(QOperatingSystemVersion::Windows8_1);
  97. }
  98. bool isGreaterEqualWin10()
  99. {
  100. return isGreaterEqualVersion(QOperatingSystemVersion::Windows10);
  101. }
  102. /**
  103. * @brief Win8以后GetVersionEx废弃,操作不正常,用黑魔法实现版本查询
  104. * @param lpVersionInformation
  105. * @return
  106. */
  107. BOOL GetVersionEx2(LPOSVERSIONINFOW lpVersionInformation)
  108. {
  109. HMODULE hNtDll = GetModuleHandle(L"NTDLL"); // 获取ntdll.dll的句柄
  110. typedef NTSTATUS(NTAPI * tRtlGetVersion)(PRTL_OSVERSIONINFOW povi); // RtlGetVersion的原型
  111. tRtlGetVersion pRtlGetVersion = NULL;
  112. if (hNtDll) {
  113. pRtlGetVersion = (tRtlGetVersion)GetProcAddress(hNtDll, "RtlGetVersion"); // 获取RtlGetVersion地址
  114. }
  115. if (pRtlGetVersion) {
  116. return pRtlGetVersion((PRTL_OSVERSIONINFOW)lpVersionInformation) >= 0; // 调用RtlGetVersion
  117. }
  118. return FALSE;
  119. }
  120. bool isGreaterEqualWin11()
  121. {
  122. #if 0
  123. OSVERSIONINFOW osi;
  124. osi.dwOSVersionInfoSize = sizeof(osi);
  125. if (!GetVersionEx2(&osi)) {
  126. return false;
  127. }
  128. if (osi.dwMajorVersion < 10) {
  129. return false;
  130. }
  131. if (osi.dwBuildNumber >= 22000) {
  132. return true;
  133. }
  134. return false;
  135. #endif
  136. QOperatingSystemVersion os = QOperatingSystemVersion::current();
  137. if (os.majorVersion() >= 10 && os.microVersion() >= 22000) {
  138. return true;
  139. }
  140. return false;
  141. }
  142. /**
  143. * @brief detect whether the taskbar is hidden automatically
  144. * @return
  145. */
  146. bool Taskbar::isAutoHide()
  147. {
  148. APPBARDATA appbarData;
  149. appbarData.cbSize = sizeof(APPBARDATA);
  150. appbarData.hWnd = 0;
  151. appbarData.uCallbackMessage = 0;
  152. appbarData.uEdge = 0;
  153. appbarData.rc = { 0, 0, 0, 0 };
  154. appbarData.lParam = 0;
  155. UINT uState = (UINT)SHAppBarMessage(ABM_GETSTATE, &appbarData);
  156. return uState == ABS_AUTOHIDE;
  157. }
  158. /**
  159. * @brief get the position of auto-hide task bar`
  160. * @param hWnd
  161. * @return
  162. */
  163. Taskbar::Position Taskbar::getPosition(HWND hWnd)
  164. {
  165. APPBARDATA appbarData;
  166. if (isGreaterEqualWin8_1()) {
  167. MONITORINFO mi = { sizeof(mi) };
  168. if (!getMonitorInfo(hWnd, MONITOR_DEFAULTTONEAREST, &mi)) {
  169. return NO_POSITION;
  170. }
  171. RECT monitor = mi.rcMonitor;
  172. appbarData = APPBARDATA { sizeof(APPBARDATA), 0, 0, 0, monitor, 0 };
  173. const QVector<Position> positions = { LEFT, TOP, RIGHT, BOTTOM };
  174. for (auto positon : positions) {
  175. appbarData.uEdge = positon;
  176. // ABM_GETAUTOHIDEBAREX = 11
  177. if (SHAppBarMessage(11, &appbarData)) {
  178. return positon;
  179. }
  180. }
  181. return NO_POSITION;
  182. }
  183. appbarData = APPBARDATA { sizeof(APPBARDATA), FindWindow(L"Shell_TrayWnd", NULL), 0, 0, RECT { 0, 0, 0, 0 }, 0 };
  184. if (appbarData.hWnd) {
  185. HMONITOR windowMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
  186. if (!windowMonitor) {
  187. return NO_POSITION;
  188. }
  189. HMONITOR taskbarMonitor = MonitorFromWindow(appbarData.hWnd, MONITOR_DEFAULTTOPRIMARY);
  190. if (!taskbarMonitor) {
  191. return NO_POSITION;
  192. }
  193. if (windowMonitor == taskbarMonitor) {
  194. SHAppBarMessage(ABM_GETTASKBARPOS, &appbarData);
  195. return (Position)appbarData.uEdge;
  196. }
  197. }
  198. return NO_POSITION;
  199. }
  200. void WindowsMoveResize::startSystemMove(QWidget *window, QPoint globalPos)
  201. {
  202. Q_UNUSED(globalPos)
  203. ReleaseCapture();
  204. SendMessage((HWND)window->winId(), WM_SYSCOMMAND, SC_MOVE | HTCAPTION, 0);
  205. }
  206. void WindowsMoveResize::starSystemResize(QWidget *window, QPoint globalPos, Qt::Edges edges)
  207. {
  208. Q_UNUSED(window)
  209. Q_UNUSED(globalPos)
  210. Q_UNUSED(edges)
  211. }
  212. } // namespace Win32Utils