├── README.md ├── Resources ├── close.png ├── close_h.png ├── close_p.png ├── default.qss ├── logo.png ├── maximize.png ├── maximize_h.png ├── maximize_p.png ├── menu.png ├── menu_h.png ├── menu_p.png ├── minimize.png ├── minimize_h.png ├── minimize_p.png ├── pin.png ├── pin_h.png ├── pin_p.png ├── restore.png ├── restore_h.png ├── restore_p.png ├── unpin.png ├── unpin_h.png └── unpin_p.png ├── StyleWindow.sln ├── StyleWindow.vcxproj ├── StyleWindow.vcxproj.filters ├── StyleWindow.vcxproj.user ├── framelesswindow.cpp ├── framelesswindow.h ├── main.cpp ├── resource.h ├── stdafx.cpp ├── stdafx.h ├── stylewindow.cpp ├── stylewindow.h ├── stylewindow.ico ├── stylewindow.qrc ├── stylewindow.rc ├── titlebar.cpp ├── titlebar.h ├── windoweffect.cpp └── windoweffect.h /README.md: -------------------------------------------------------------------------------- 1 | # 项目简介 2 | 一款基于Qt/QWidget的无边框窗口框架,支持拖拽,缩放,阴影,桌面吸附等特性。 3 | 4 | # 窗口特性 5 | * Win11圆角/Win10直角边框自动适配 6 | * 多显示器且不同dpi下表现接近完美 7 | * 支持aero阴影 8 | * 自定义标题栏按钮 9 | * 最大/还原按钮图片能自动切换 10 | * Win快捷键+上下左右吸附 11 | * Win快捷键+左右可跨屏移动 12 | * 标题栏按钮悬浮/点击/弹起时有不同效果 13 | * 上下左右边框可鼠标拉伸 14 | * 最大化状态下拖拽标题栏可以还原窗口 15 | * 通过qss文件定义标题按钮,方便替换 16 | 17 | # 功能演示 18 | ![image](https://user-images.githubusercontent.com/3926845/145587636-22c51bf9-1f82-4d14-adea-3f4a6e5c4185.gif) 19 | 20 | ![image](https://user-images.githubusercontent.com/3926845/145599689-c87fdc32-61b5-4d72-82fd-441ace757ebb.gif) 21 | -------------------------------------------------------------------------------- /Resources/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcaihao/StyleWindow/869c9c2a4b071457902c7ba09071152558a0290a/Resources/close.png -------------------------------------------------------------------------------- /Resources/close_h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcaihao/StyleWindow/869c9c2a4b071457902c7ba09071152558a0290a/Resources/close_h.png -------------------------------------------------------------------------------- /Resources/close_p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcaihao/StyleWindow/869c9c2a4b071457902c7ba09071152558a0290a/Resources/close_p.png -------------------------------------------------------------------------------- /Resources/default.qss: -------------------------------------------------------------------------------- 1 | #logoLabel 2 | { 3 | margin-left:3px; 4 | margin-right:3px; 5 | min-height:32px; 6 | min-width:32px; 7 | max-height:32px; 8 | max-width:32px; 9 | border-image:url(:/StyleWindow/Resources/logo.png) 10 | } 11 | 12 | #minToolButton 13 | { 14 | min-height:38px; 15 | min-width:38px; 16 | max-height:38px; 17 | max-width:38px; 18 | border-image:url(:/StyleWindow/Resources/minimize.png); 19 | } 20 | 21 | #minToolButton:hover 22 | { 23 | min-height:38px; 24 | min-width:38px; 25 | max-height:38px; 26 | max-width:38px; 27 | border-image:url(:/StyleWindow/Resources/minimize_h.png); 28 | } 29 | 30 | #minToolButton:pressed 31 | { 32 | min-height:38px; 33 | min-width:38px; 34 | max-height:38px; 35 | max-width:38px; 36 | border-image:url(:/StyleWindow/Resources/minimize_p.png); 37 | } 38 | 39 | #minToolButton:checked 40 | { 41 | min-height:38px; 42 | min-width:38px; 43 | max-height:38px; 44 | max-width:38px; 45 | border-image:url(:/StyleWindow/Resources/minimize_p.png); 46 | } 47 | 48 | #maxToolButton[MaxState="false"] 49 | { 50 | min-height:38px; 51 | min-width:38px; 52 | max-height:38px; 53 | max-width:38px; 54 | border-image:url(:/StyleWindow/Resources/maximize.png); 55 | } 56 | 57 | #maxToolButton:hover[MaxState="false"] 58 | { 59 | min-height:38px; 60 | min-width:38px; 61 | max-height:38px; 62 | max-width:38px; 63 | border-image:url(:/StyleWindow/Resources/maximize_h.png); 64 | } 65 | #maxToolButton:pressed[MaxState="false"] 66 | { 67 | min-height:38px; 68 | min-width:38px; 69 | max-height:38px; 70 | max-width:38px; 71 | border-image:url(:/StyleWindow/Resources/maximize_p.png); 72 | } 73 | 74 | #maxToolButton:checked[MaxState="false"] 75 | { 76 | min-height:38px; 77 | min-width:38px; 78 | max-height:38px; 79 | max-width:38px; 80 | border-image:url(:/StyleWindow/Resources/maximize_p.png); 81 | } 82 | 83 | #maxToolButton[MaxState="true"] 84 | { 85 | min-height:38px; 86 | min-width:38px; 87 | max-height:38px; 88 | max-width:38px; 89 | border-image:url(:/StyleWindow/Resources/restore.png); 90 | } 91 | 92 | #maxToolButton:hover[MaxState="true"] 93 | { 94 | min-height:38px; 95 | min-width:38px; 96 | max-height:38px; 97 | max-width:38px; 98 | border-image:url(:/StyleWindow/Resources/restore_h.png); 99 | } 100 | 101 | #maxToolButton:pressed[MaxState="true"] 102 | { 103 | min-height:38px; 104 | min-width:38px; 105 | max-height:38px; 106 | max-width:38px; 107 | border-image:url(:/StyleWindow/Resources/restore_p.png); 108 | } 109 | 110 | #maxToolButton:checked[MaxState="true"] 111 | { 112 | min-height:38px; 113 | min-width:38px; 114 | max-height:38px; 115 | max-width:38px; 116 | border-image:url(:/StyleWindow/Resources/restore_p.png); 117 | } 118 | 119 | #closeToolButton 120 | { 121 | min-height:38px; 122 | min-width:38px; 123 | max-height:38px; 124 | max-width:38px; 125 | border-image:url(:/StyleWindow/Resources/close.png); 126 | } 127 | 128 | #closeToolButton:hover 129 | { 130 | min-height:38px; 131 | min-width:38px; 132 | max-height:38px; 133 | max-width:38px; 134 | border-image:url(:/StyleWindow/Resources/close_h.png); 135 | } 136 | 137 | #closeToolButton:pressed 138 | { 139 | min-height:38px; 140 | min-width:38px; 141 | max-height:38px; 142 | max-width:38px; 143 | border-image:url(:/StyleWindow/Resources/close_p.png); 144 | } 145 | 146 | #closeToolButton:checked 147 | { 148 | min-height:38px; 149 | min-width:38px; 150 | max-height:38px; 151 | max-width:38px; 152 | border-image:url(:/StyleWindow/Resources/close_p.png); 153 | } 154 | -------------------------------------------------------------------------------- /Resources/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcaihao/StyleWindow/869c9c2a4b071457902c7ba09071152558a0290a/Resources/logo.png -------------------------------------------------------------------------------- /Resources/maximize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcaihao/StyleWindow/869c9c2a4b071457902c7ba09071152558a0290a/Resources/maximize.png -------------------------------------------------------------------------------- /Resources/maximize_h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcaihao/StyleWindow/869c9c2a4b071457902c7ba09071152558a0290a/Resources/maximize_h.png -------------------------------------------------------------------------------- /Resources/maximize_p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcaihao/StyleWindow/869c9c2a4b071457902c7ba09071152558a0290a/Resources/maximize_p.png -------------------------------------------------------------------------------- /Resources/menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcaihao/StyleWindow/869c9c2a4b071457902c7ba09071152558a0290a/Resources/menu.png -------------------------------------------------------------------------------- /Resources/menu_h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcaihao/StyleWindow/869c9c2a4b071457902c7ba09071152558a0290a/Resources/menu_h.png -------------------------------------------------------------------------------- /Resources/menu_p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcaihao/StyleWindow/869c9c2a4b071457902c7ba09071152558a0290a/Resources/menu_p.png -------------------------------------------------------------------------------- /Resources/minimize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcaihao/StyleWindow/869c9c2a4b071457902c7ba09071152558a0290a/Resources/minimize.png -------------------------------------------------------------------------------- /Resources/minimize_h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcaihao/StyleWindow/869c9c2a4b071457902c7ba09071152558a0290a/Resources/minimize_h.png -------------------------------------------------------------------------------- /Resources/minimize_p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcaihao/StyleWindow/869c9c2a4b071457902c7ba09071152558a0290a/Resources/minimize_p.png -------------------------------------------------------------------------------- /Resources/pin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcaihao/StyleWindow/869c9c2a4b071457902c7ba09071152558a0290a/Resources/pin.png -------------------------------------------------------------------------------- /Resources/pin_h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcaihao/StyleWindow/869c9c2a4b071457902c7ba09071152558a0290a/Resources/pin_h.png -------------------------------------------------------------------------------- /Resources/pin_p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcaihao/StyleWindow/869c9c2a4b071457902c7ba09071152558a0290a/Resources/pin_p.png -------------------------------------------------------------------------------- /Resources/restore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcaihao/StyleWindow/869c9c2a4b071457902c7ba09071152558a0290a/Resources/restore.png -------------------------------------------------------------------------------- /Resources/restore_h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcaihao/StyleWindow/869c9c2a4b071457902c7ba09071152558a0290a/Resources/restore_h.png -------------------------------------------------------------------------------- /Resources/restore_p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcaihao/StyleWindow/869c9c2a4b071457902c7ba09071152558a0290a/Resources/restore_p.png -------------------------------------------------------------------------------- /Resources/unpin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcaihao/StyleWindow/869c9c2a4b071457902c7ba09071152558a0290a/Resources/unpin.png -------------------------------------------------------------------------------- /Resources/unpin_h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcaihao/StyleWindow/869c9c2a4b071457902c7ba09071152558a0290a/Resources/unpin_h.png -------------------------------------------------------------------------------- /Resources/unpin_p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcaihao/StyleWindow/869c9c2a4b071457902c7ba09071152558a0290a/Resources/unpin_p.png -------------------------------------------------------------------------------- /StyleWindow.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31911.196 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StyleWindow", "StyleWindow.vcxproj", "{453E9FD7-1CEC-46BC-A4A2-9B39B7AB874E}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x86 = Debug|x86 11 | Release|x86 = Release|x86 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {453E9FD7-1CEC-46BC-A4A2-9B39B7AB874E}.Debug|x86.ActiveCfg = Debug|Win32 15 | {453E9FD7-1CEC-46BC-A4A2-9B39B7AB874E}.Debug|x86.Build.0 = Debug|Win32 16 | {453E9FD7-1CEC-46BC-A4A2-9B39B7AB874E}.Release|x86.ActiveCfg = Release|Win32 17 | {453E9FD7-1CEC-46BC-A4A2-9B39B7AB874E}.Release|x86.Build.0 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {5489DF14-C131-4BE3-BBEC-8806F1B19CA1} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /StyleWindow.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {453E9FD7-1CEC-46BC-A4A2-9B39B7AB874E} 15 | QtVS_v304 16 | 10.0.19041.0 17 | 10.0.19041.0 18 | $(MSBuildProjectDirectory)\QtMsBuild 19 | StyleWindow 20 | 21 | 22 | 23 | Application 24 | v142 25 | 26 | 27 | Application 28 | v142 29 | 30 | 31 | 32 | 33 | 34 | 35 | 5.15.2_msvc2019 36 | core;gui;widgets 37 | debug 38 | 39 | 40 | 5.15.2_msvc2019 41 | core;gui;widgets 42 | release 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | Use 65 | 66 | 67 | 68 | 69 | Use 70 | 71 | 72 | 73 | 74 | true 75 | true 76 | ProgramDatabase 77 | Disabled 78 | MultiThreadedDebugDLL 79 | Use 80 | stdafx.h 81 | 82 | 83 | Windows 84 | true 85 | 86 | 87 | stdafx.h;%(PrependInclude) 88 | 89 | 90 | 91 | 92 | true 93 | true 94 | None 95 | MaxSpeed 96 | MultiThreadedDLL 97 | Use 98 | stdafx.h 99 | 100 | 101 | Windows 102 | false 103 | 104 | 105 | stdafx.h;%(PrependInclude) 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | Create 123 | Create 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /StyleWindow.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | qrc;rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {99349809-55BA-4b9d-BF79-8FDBB0286EB3} 18 | ui 19 | 20 | 21 | {639EADAA-A684-42e4-A9AD-28FC9BCB8F7C} 22 | ts 23 | 24 | 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Header Files 31 | 32 | 33 | Source Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | Source Files 40 | 41 | 42 | 43 | 44 | Source Files 45 | 46 | 47 | Source Files 48 | 49 | 50 | Source Files 51 | 52 | 53 | Source Files 54 | 55 | 56 | 57 | 58 | Header Files 59 | 60 | 61 | Header Files 62 | 63 | 64 | Header Files 65 | 66 | 67 | 68 | 69 | Header Files 70 | 71 | 72 | 73 | 74 | Resource Files 75 | 76 | 77 | -------------------------------------------------------------------------------- /StyleWindow.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 2021-12-10T10:27:12.3705982Z 6 | 7 | 8 | 2021-12-10T10:27:12.9377735Z 9 | 10 | -------------------------------------------------------------------------------- /framelesswindow.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "framelesswindow.h" 3 | #include "titlebar.h" 4 | #include "windoweffect.h" 5 | 6 | FramelessWindow::FramelessWindow(QWidget* parent) 7 | : QWidget(parent) 8 | { 9 | memset(&monitorInfo, 0, sizeof(MONITORINFO)); 10 | monitorInfo.cbSize = sizeof(MONITORINFO); 11 | 12 | QVBoxLayout* layout = new QVBoxLayout(this); 13 | layout->setSpacing(0); 14 | layout->setContentsMargins(0, 0, 0, 0); 15 | 16 | titleBar = new TitleBar(this); 17 | titleBar->setObjectName("titleBar"); 18 | titleBar->setStyleSheet("background: rgb(47,70,146);"); 19 | layout->addWidget(titleBar); 20 | 21 | QLabel* testLabel = new QLabel(this); 22 | testLabel->setObjectName("testLabel"); 23 | testLabel->setStyleSheet("background: rgb(240, 240, 240);"); 24 | layout->addWidget(testLabel); 25 | 26 | setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint); 27 | 28 | WindowEffect::addWindowAnimation((HWND)winId()); 29 | WindowEffect::addShadowEffect((HWND)winId()); 30 | 31 | connect(windowHandle(), &QWindow::screenChanged, this, [=] { 32 | auto hWnd = reinterpret_cast(windowHandle()->winId()); 33 | SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); 34 | }); 35 | } 36 | 37 | bool FramelessWindow::nativeEvent(const QByteArray& eventType, void* message, long* result) 38 | { 39 | MSG* msg = reinterpret_cast(message); 40 | if (msg->message == WM_NCHITTEST) 41 | { 42 | int xPos = (LOWORD(msg->lParam) - frameGeometry().x()) % 65536; 43 | int yPos = HIWORD(msg->lParam) - frameGeometry().y(); 44 | int w = width(); 45 | int h = height(); 46 | bool lx = xPos < BORDER_WIDTH; 47 | bool rx = xPos > w - BORDER_WIDTH; 48 | bool ty = yPos < BORDER_WIDTH; 49 | bool by = yPos > h - BORDER_WIDTH; 50 | 51 | if (lx && ty) 52 | { 53 | *result = HTTOPLEFT; 54 | return true; 55 | } 56 | else if (rx && by) 57 | { 58 | *result = HTBOTTOMRIGHT; 59 | return true; 60 | } 61 | else if (rx && ty) { 62 | *result = HTTOPRIGHT; 63 | return true; 64 | } 65 | else if (lx && by) { 66 | *result = HTBOTTOMLEFT; 67 | return true; 68 | } 69 | else if (ty) { 70 | *result = HTTOP; 71 | return true; 72 | } 73 | else if (by) { 74 | *result = HTBOTTOM; 75 | return true; 76 | } 77 | else if (lx) { 78 | *result = HTLEFT; 79 | return true; 80 | } 81 | else if (rx) { 82 | *result = HTRIGHT; 83 | return true; 84 | } 85 | } 86 | else if (msg->message == WM_NCCALCSIZE) 87 | { 88 | if (isWindowMaximized(msg->hwnd)) 89 | { 90 | monitorNCCALCSIZE(msg); 91 | } 92 | 93 | *result = HTNOWHERE; 94 | return true; 95 | } 96 | else if (msg->message == WM_GETMINMAXINFO) 97 | { 98 | if (isWindowMaximized(msg->hwnd)) 99 | { 100 | RECT window_rect; 101 | if (!GetWindowRect(msg->hwnd, &window_rect)) 102 | { 103 | *result = HTNOWHERE; 104 | return false; 105 | } 106 | 107 | HMONITOR hMonitor = MonitorFromRect(&window_rect, MONITOR_DEFAULTTONULL); 108 | if (!hMonitor) 109 | { 110 | *result = HTNOWHERE; 111 | return false; 112 | } 113 | 114 | GetMonitorInfoW(hMonitor, &monitorInfo); 115 | RECT monitor_rect = monitorInfo.rcMonitor; 116 | RECT work_area = monitorInfo.rcWork; 117 | 118 | LPMINMAXINFO info = reinterpret_cast(msg->lParam); 119 | 120 | info->ptMaxSize.x = work_area.right - work_area.left; 121 | info->ptMaxSize.y = work_area.bottom - work_area.top; 122 | info->ptMaxTrackSize.x = info->ptMaxSize.x; 123 | info->ptMaxTrackSize.y = info->ptMaxSize.y; 124 | 125 | info->ptMaxPosition.x = abs(window_rect.left - monitor_rect.left); 126 | info->ptMaxPosition.y = abs(window_rect.top - monitor_rect.top); 127 | *result = HTCLIENT; 128 | return true; 129 | } 130 | } 131 | 132 | return QWidget::nativeEvent(eventType, message, result); 133 | } 134 | 135 | void FramelessWindow::changeEvent(QEvent* event) 136 | { 137 | if (event->type() == QEvent::WindowStateChange) 138 | { 139 | RefreshStyle(titleBar->findChild("maxToolButton"), "MaxState", isMaximized()); 140 | } 141 | 142 | return QWidget::changeEvent(event); 143 | } 144 | 145 | bool FramelessWindow::isWindowMaximized(HWND hWnd) 146 | { 147 | WINDOWPLACEMENT wp; 148 | wp.length = sizeof(WINDOWPLACEMENT); 149 | if (!GetWindowPlacement(hWnd, &wp)) 150 | { 151 | 152 | } 153 | return wp.showCmd == SW_MAXIMIZE; 154 | } 155 | 156 | void FramelessWindow::monitorNCCALCSIZE(MSG* msg) 157 | { 158 | HMONITOR hMonitor = MonitorFromWindow(msg->hwnd, MONITOR_DEFAULTTONULL); 159 | if (hMonitor != NULL) 160 | { 161 | GetMonitorInfoW(hMonitor, &monitorInfo); 162 | } 163 | 164 | NCCALCSIZE_PARAMS& params = *reinterpret_cast(msg->lParam); 165 | params.rgrc[0].left = monitorInfo.rcWork.left; 166 | params.rgrc[0].top = monitorInfo.rcWork.top; 167 | params.rgrc[0].right = monitorInfo.rcWork.right; 168 | params.rgrc[0].bottom = monitorInfo.rcWork.bottom; 169 | 170 | //qDebug() << params.rgrc[0].left << params.rgrc[0].top << params.rgrc[0].right << params.rgrc[0].bottom; 171 | } -------------------------------------------------------------------------------- /framelesswindow.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "windows.h" 6 | 7 | class TitleBar; 8 | 9 | class FramelessWindow : public QWidget 10 | { 11 | public: 12 | FramelessWindow(QWidget* parent = Q_NULLPTR); 13 | protected: 14 | bool nativeEvent(const QByteArray& eventType, void* message, long* result); 15 | void changeEvent(QEvent* event); 16 | private: 17 | bool isWindowMaximized(HWND hWnd); 18 | void monitorNCCALCSIZE(MSG* msg); 19 | 20 | TitleBar* titleBar; 21 | MONITORINFO monitorInfo; 22 | RECT monitor_rect; 23 | RECT work_area; 24 | }; 25 | 26 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "stylewindow.h" 3 | #include 4 | 5 | #pragma comment(lib, "Dwmapi.lib") 6 | 7 | int main(int argc, char *argv[]) 8 | { 9 | QApplication a(argc, argv); 10 | LoadStyle(DEFAULT_STYLE); 11 | 12 | StyleWindow w; 13 | w.show(); 14 | return a.exec(); 15 | } 16 | -------------------------------------------------------------------------------- /resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by stylewindow.rc 4 | 5 | // Next default values for new objects 6 | // 7 | #ifdef APSTUDIO_INVOKED 8 | #ifndef APSTUDIO_READONLY_SYMBOLS 9 | #define _APS_NEXT_RESOURCE_VALUE 101 10 | #define _APS_NEXT_COMMAND_VALUE 40001 11 | #define _APS_NEXT_CONTROL_VALUE 1001 12 | #define _APS_NEXT_SYMED_VALUE 101 13 | #endif 14 | #endif 15 | -------------------------------------------------------------------------------- /stdafx.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | void RefreshStyle(QWidget* widget, const char* name, QVariant value) 4 | { 5 | widget->setProperty(name, value); 6 | 7 | qApp->style()->unpolish(widget); 8 | qApp->style()->polish(widget); 9 | 10 | widget->update(); 11 | } 12 | 13 | void LoadStyle(QString filePath) 14 | { 15 | QString styleSheet; 16 | 17 | QFile file(filePath); 18 | if (file.open(QFile::ReadOnly)) 19 | { 20 | styleSheet.append(QString::fromLocal8Bit(file.readAll())); 21 | 22 | file.close(); 23 | } 24 | 25 | qApp->setStyleSheet(styleSheet); 26 | 27 | } -------------------------------------------------------------------------------- /stdafx.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define BORDER_WIDTH 5 4 | #define TITLE_HEIGHT 38 5 | #define BUTTON_WIDTH 38 6 | 7 | #define DEFAULT_STYLE ":/StyleWindow/Resources/default.qss" 8 | 9 | extern void RefreshStyle(QWidget* widget, const char* name, QVariant value); 10 | extern void LoadStyle(QString filePath); -------------------------------------------------------------------------------- /stylewindow.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "stylewindow.h" 3 | #include "stdafx.h" 4 | 5 | StyleWindow::StyleWindow(QWidget* parent) 6 | : FramelessWindow(parent) 7 | { 8 | resize(800, 600); 9 | } 10 | -------------------------------------------------------------------------------- /stylewindow.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "framelesswindow.h" 6 | 7 | class StyleWindow : public FramelessWindow 8 | { 9 | Q_OBJECT 10 | 11 | public: 12 | StyleWindow(QWidget *parent = Q_NULLPTR); 13 | 14 | protected: 15 | private: 16 | 17 | }; 18 | -------------------------------------------------------------------------------- /stylewindow.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcaihao/StyleWindow/869c9c2a4b071457902c7ba09071152558a0290a/stylewindow.ico -------------------------------------------------------------------------------- /stylewindow.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | Resources/default.qss 4 | Resources/logo.png 5 | Resources/close.png 6 | Resources/close_h.png 7 | Resources/close_p.png 8 | Resources/maximize.png 9 | Resources/maximize_h.png 10 | Resources/maximize_p.png 11 | Resources/menu.png 12 | Resources/menu_h.png 13 | Resources/menu_p.png 14 | Resources/minimize.png 15 | Resources/minimize_h.png 16 | Resources/minimize_p.png 17 | Resources/restore.png 18 | Resources/restore_h.png 19 | Resources/restore_p.png 20 | Resources/pin.png 21 | Resources/pin_h.png 22 | Resources/pin_p.png 23 | Resources/unpin.png 24 | Resources/unpin_h.png 25 | Resources/unpin_p.png 26 | 27 | 28 | -------------------------------------------------------------------------------- /stylewindow.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hcaihao/StyleWindow/869c9c2a4b071457902c7ba09071152558a0290a/stylewindow.rc -------------------------------------------------------------------------------- /titlebar.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "titlebar.h" 3 | #include "windows.h" 4 | 5 | #include 6 | 7 | TitleBar::TitleBar(QWidget* parent) 8 | : QWidget(parent) 9 | { 10 | //resize(1360, 38); 11 | setFixedHeight(TITLE_HEIGHT); 12 | setAttribute(Qt::WA_StyledBackground); 13 | 14 | QHBoxLayout* layout = new QHBoxLayout(this); 15 | layout->setSpacing(0); 16 | layout->setContentsMargins(0, 0, 0, 0); 17 | 18 | QLabel* logoLabel = new QLabel(this); 19 | logoLabel->setObjectName("logoLabel"); 20 | layout->addWidget(logoLabel); 21 | layout->addStretch(1); 22 | 23 | QToolButton* minToolButton = new QToolButton(this); 24 | minToolButton->setObjectName("minToolButton"); 25 | connect(minToolButton, &QToolButton::clicked, this->window(), &QWidget::showMinimized); 26 | layout->addWidget(minToolButton); 27 | 28 | QToolButton* maxToolButton = new QToolButton(this); 29 | maxToolButton->setObjectName("maxToolButton"); 30 | connect(maxToolButton, &QToolButton::clicked, this, &TitleBar::toggleMaxState); 31 | maxToolButton->setProperty("MaxState", false); 32 | layout->addWidget(maxToolButton); 33 | 34 | QToolButton* closeToolButton = new QToolButton(this); 35 | closeToolButton->setObjectName("closeToolButton"); 36 | connect(closeToolButton, &QToolButton::clicked, this->window(), &QWidget::close); 37 | layout->addWidget(closeToolButton); 38 | } 39 | 40 | TitleBar::~TitleBar() 41 | { 42 | } 43 | 44 | void TitleBar::mouseDoubleClickEvent(QMouseEvent* event) 45 | { 46 | toggleMaxState(); 47 | } 48 | 49 | void TitleBar::mousePressEvent(QMouseEvent* event) 50 | { 51 | ReleaseCapture(); 52 | SendMessage((HWND)window()->winId(), WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0); 53 | event->ignore(); 54 | } 55 | 56 | void TitleBar::toggleMaxState() 57 | { 58 | if (window()->isMaximized()) 59 | { 60 | window()->showNormal(); 61 | } 62 | else 63 | { 64 | window()->showMaximized(); 65 | } 66 | } -------------------------------------------------------------------------------- /titlebar.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | class TitleBar : public QWidget 9 | { 10 | Q_OBJECT 11 | 12 | public: 13 | TitleBar(QWidget *parent); 14 | ~TitleBar(); 15 | protected: 16 | void mousePressEvent(QMouseEvent* event); 17 | void mouseDoubleClickEvent(QMouseEvent* event); 18 | private: 19 | void toggleMaxState(); 20 | }; 21 | -------------------------------------------------------------------------------- /windoweffect.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "windoweffect.h" 3 | 4 | #include 5 | 6 | namespace WindowEffect 7 | { 8 | void moveWindow(HWND hWnd) 9 | { 10 | ReleaseCapture(); 11 | SendMessage(hWnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0); 12 | } 13 | 14 | void addShadowEffect(HWND hWnd) 15 | { 16 | DWMNCRENDERINGPOLICY ncrp = DWMNCRP_ENABLED; 17 | ::DwmSetWindowAttribute(hWnd, DWMWA_NCRENDERING_POLICY, &ncrp, sizeof(ncrp)); 18 | 19 | MARGINS margins = { -1 }; 20 | ::DwmExtendFrameIntoClientArea(hWnd, &margins); 21 | } 22 | 23 | void removeShadowEffect(HWND hWnd) 24 | { 25 | DWMNCRENDERINGPOLICY ncrp = DWMNCRP_DISABLED; 26 | ::DwmSetWindowAttribute(hWnd, DWMWA_NCRENDERING_POLICY, &ncrp, sizeof(ncrp)); 27 | } 28 | 29 | void removeMenuShadowEffect(HWND hWnd) 30 | { 31 | DWORD style = GetClassLong(hWnd, GCL_STYLE); 32 | style &= ~0x00020000; // CS_DROPSHADOW; 33 | SetClassLong(hWnd, GCL_STYLE, style); 34 | } 35 | 36 | void addWindowAnimation(HWND hWnd) 37 | { 38 | DWORD style = GetWindowLong(hWnd, GWL_STYLE); 39 | SetWindowLong(hWnd, GWL_STYLE, style 40 | | WS_MAXIMIZEBOX 41 | | WS_CAPTION 42 | | CS_DBLCLKS 43 | | WS_THICKFRAME 44 | ); 45 | } 46 | } -------------------------------------------------------------------------------- /windoweffect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "windows.h" 4 | 5 | namespace WindowEffect 6 | { 7 | void moveWindow(HWND hWnd); 8 | void addShadowEffect(HWND hWnd); 9 | void removeShadowEffect(HWND hWnd); 10 | void removeMenuShadowEffect(HWND hWnd); 11 | void addWindowAnimation(HWND hWnd); 12 | }; 13 | 14 | --------------------------------------------------------------------------------