Win32Utils.cpp 7.0 KB

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