WindowsWindowEffect.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. #include "WindowsWindowEffect.h"
  2. #include "utils/Win32Utils.h"
  3. #include <dwmapi.h>
  4. #include <QMessageBox>
  5. #include <QtWin>
  6. WindowsWindowEffect::WindowsWindowEffect(QWidget *parent) : QWidget(parent)
  7. {
  8. winCompAttrData.Attribute = WINDOWCOMPOSITIONATTRIB::WCA_ACCENT_POLICY;
  9. winCompAttrData.SizeOfData = sizeof(accentPolicy);
  10. winCompAttrData.Data = &accentPolicy;
  11. }
  12. bool WindowsWindowEffect::setAcrylicEffect(HWND hWnd, std::string gradientColor, bool enableShadow,
  13. uint32_t animationId)
  14. {
  15. if (!Win32Utils::isGreaterEqualWin10()) {
  16. QMessageBox::warning(nullptr, "warning", "The acrylic effect is only available on Win10+");
  17. return false;
  18. }
  19. std::string gradientColorBigEndian;
  20. for (int index = gradientColor.size(); index > 0; index -= 2) {
  21. gradientColorBigEndian += gradientColor.substr(index - 2, 2);
  22. }
  23. DWORD gradientColorValue = strtol(gradientColorBigEndian.c_str(), NULL, 16);
  24. DWORD accentFlags = 0;
  25. if (enableShadow) {
  26. accentFlags = 0x20 | 0x40 | 0x80 | 0x100;
  27. }
  28. this->accentPolicy.AccentState = ACCENT_STATE::ACCENT_ENABLE_BLURBEHIND;
  29. this->accentPolicy.GradientColor = gradientColorValue;
  30. this->accentPolicy.AccentFlags = accentFlags;
  31. this->accentPolicy.AnimationId = animationId;
  32. this->winCompAttrData.Attribute = WINDOWCOMPOSITIONATTRIB::WCA_ACCENT_POLICY;
  33. HMODULE huser = GetModuleHandle(L"user32.dll");
  34. if (huser) {
  35. SetWindowCompositionAttribute setWindowCompositionAttribute =
  36. (SetWindowCompositionAttribute)GetProcAddress(huser, "SetWindowCompositionAttribute");
  37. if (setWindowCompositionAttribute) {
  38. setWindowCompositionAttribute(hWnd, &this->winCompAttrData);
  39. return true;
  40. }
  41. }
  42. return false;
  43. }
  44. /**
  45. * @brief WindowsWindowEffect::setMicaEffect
  46. * @param hWnd: Window handle
  47. * @param isDarkMode: whether to use dark mode mica effect
  48. * @return
  49. */
  50. bool WindowsWindowEffect::setMicaEffect(HWND hWnd, bool isDarkMode)
  51. {
  52. if (!Win32Utils::isGreaterEqualWin11()) {
  53. QMessageBox::warning(nullptr, "warning", "The Mica effect is only available on Win11");
  54. return false;
  55. }
  56. MARGINS margins = { -1, -1, -1, -1 };
  57. if (S_OK != DwmExtendFrameIntoClientArea(hWnd, &margins)) {
  58. return false;
  59. }
  60. this->winCompAttrData.Attribute = WINDOWCOMPOSITIONATTRIB::WCA_ACCENT_POLICY;
  61. this->accentPolicy.AccentState = ACCENT_STATE::ACCENT_ENABLE_HOSTBACKDROP;
  62. HMODULE huser = GetModuleHandle(L"user32.dll");
  63. if (!huser) {
  64. return false;
  65. }
  66. SetWindowCompositionAttribute setWindowCompositionAttribute =
  67. (SetWindowCompositionAttribute)GetProcAddress(huser, "SetWindowCompositionAttribute");
  68. if (!setWindowCompositionAttribute) {
  69. return false;
  70. }
  71. setWindowCompositionAttribute(hWnd, &this->winCompAttrData);
  72. if (isDarkMode) {
  73. this->winCompAttrData.Attribute = WINDOWCOMPOSITIONATTRIB::WCA_USEDARKMODECOLORS;
  74. setWindowCompositionAttribute(hWnd, &this->winCompAttrData);
  75. }
  76. if (QOperatingSystemVersion::current().microVersion() < 22523) {
  77. DWORD V = 1;
  78. if (S_OK != DwmSetWindowAttribute(hWnd, 1029, &V, 4)) {
  79. return false;
  80. }
  81. } else {
  82. DWORD V = 2;
  83. if (S_OK != DwmSetWindowAttribute(hWnd, 38, &V, 4)) {
  84. return false;
  85. }
  86. }
  87. return true;
  88. }
  89. bool WindowsWindowEffect::setAeroEffect(HWND hWnd)
  90. {
  91. this->winCompAttrData.Attribute = WINDOWCOMPOSITIONATTRIB::WCA_ACCENT_POLICY;
  92. this->accentPolicy.AccentState = ACCENT_STATE::ACCENT_ENABLE_BLURBEHIND;
  93. HMODULE huser = GetModuleHandle(L"user32.dll");
  94. if (huser) {
  95. SetWindowCompositionAttribute setWindowCompositionAttribute =
  96. (SetWindowCompositionAttribute)GetProcAddress(huser, "SetWindowCompositionAttribute");
  97. if (setWindowCompositionAttribute) {
  98. setWindowCompositionAttribute(hWnd, &this->winCompAttrData);
  99. return true;
  100. }
  101. }
  102. return false;
  103. }
  104. bool WindowsWindowEffect::removeBackgroundEffect(HWND hWnd)
  105. {
  106. this->accentPolicy.AccentState = ACCENT_STATE::ACCENT_DISABLED;
  107. HMODULE huser = GetModuleHandle(L"user32.dll");
  108. if (huser) {
  109. SetWindowCompositionAttribute setWindowCompositionAttribute =
  110. (SetWindowCompositionAttribute)GetProcAddress(huser, "SetWindowCompositionAttribute");
  111. if (setWindowCompositionAttribute) {
  112. setWindowCompositionAttribute(hWnd, &this->winCompAttrData);
  113. return true;
  114. }
  115. }
  116. return false;
  117. }
  118. void WindowsWindowEffect::moveWindow(HWND hWnd)
  119. {
  120. ReleaseCapture();
  121. SendMessage(hWnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
  122. }
  123. /**
  124. * @brief Add DWM shadow to window
  125. * @param hWnd
  126. * @return
  127. */
  128. bool WindowsWindowEffect::addShadowEffect(HWND hWnd)
  129. {
  130. if (!QtWin::isCompositionEnabled()) {
  131. return false;
  132. }
  133. MARGINS margins = { -1, -1, -1, -1 };
  134. if (S_OK != DwmExtendFrameIntoClientArea(hWnd, &margins)) {
  135. return false;
  136. }
  137. return true;
  138. }
  139. /**
  140. * @brief Add DWM shadow to menu
  141. * @param hWnd
  142. * @return
  143. */
  144. bool WindowsWindowEffect::addMenuShadowEffect(HWND hWnd)
  145. {
  146. if (!QtWin::isCompositionEnabled()) {
  147. return false;
  148. }
  149. DWORD attribute = DWMNCRENDERINGPOLICY::DWMNCRP_ENABLED;
  150. if (S_OK != DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE::DWMWA_NCRENDERING_POLICY, &attribute, 4)) {
  151. return false;
  152. }
  153. MARGINS margins = { -1, -1, -1, -1 };
  154. if (S_OK != DwmExtendFrameIntoClientArea(hWnd, &margins)) {
  155. return false;
  156. }
  157. return true;
  158. }
  159. /**
  160. * @brief Remove DWM shadow from the window
  161. * @param hWnd
  162. * @return
  163. */
  164. bool WindowsWindowEffect::removeShadowEffect(HWND hWnd)
  165. {
  166. DWORD attribute = DWMNCRENDERINGPOLICY::DWMNCRP_DISABLED;
  167. if (S_OK != DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE::DWMWA_NCRENDERING_POLICY, &attribute, 4)) {
  168. return false;
  169. }
  170. return true;
  171. }
  172. /**
  173. * @brief Remove shadow from pop-up menu
  174. * @param hWnd
  175. * @return
  176. */
  177. void WindowsWindowEffect::removeMenuShadowEffect(HWND hWnd)
  178. {
  179. DWORD style = GetClassLong(hWnd, GCL_STYLE);
  180. style &= ~CS_DROPSHADOW;
  181. SetClassLong(hWnd, GCL_STYLE, style);
  182. }
  183. /**
  184. * @brief Enables the maximize and minimize animation of the window
  185. * @param hWnd
  186. */
  187. void WindowsWindowEffect::addWindowAnimation(HWND hWnd)
  188. {
  189. DWORD style = GetClassLong(hWnd, GCL_STYLE);
  190. SetWindowLong(hWnd, GWL_STYLE, style | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CAPTION | CS_DBLCLKS | WS_THICKFRAME);
  191. }