Magpie/src/Magpie.App/CaptionButtonsControl.cpp
刘旭 914c683f98
自定义标题栏 (#624)
* feat: 去除标题栏

* chore: 添加注释

* feat: 保存最大化状态

* fix: 优化最大化状态

* feat: Win11 无需绘制上边框

* feat: 添加 TitlebarControl

* UI: 更改主界面样式

* fix: 修复一个隐蔽的bug

* feat: 添加 CaptionButtonsControl

* feat: 优化上边框颜色

* feat: 实现标题栏的 UI

* fix: 修复标题栏按钮不跟随主题的问题

* fix: 优化主窗口最小尺寸

* fix: 修复上边框绘制错误

* UI: 优化样式

* UI: 稍微优化标题按钮样式

* UI: 优化标题按钮样式

* UI: 优化标题按钮样式

* UI: 优化标题栏样式

* feat: 实现拖拽功能

* fix: 修复调整窗口大小时闪烁的问题

* fix: 更改上边框的实现方式

* feat: 实现上边框调整尺寸和支持 Win11 的贴靠布局

* feat: 实现标题栏按钮的 hover

* feat: 实现标题栏按钮的功能

* perf: 优化性能和添加注释

* fix: 修复一个小错误

* fix: 小修复

* fix: 优化最大化状态

* fix: 修复标题栏上右键菜单

* chore: 添加注释

* fix: 修复 Win10 中以最大化启动时一瞬间显示主题色背景的问题

* UI: 更新 ToggleSwitch 样式

* fix: 修复以最大化显示时的窗口动画

* fix: 修复 Win11 21H1/21H2 的背景

* chore: 优化注释

* feat: 在标题栏显示图标

* UI: 为标题栏添加动画

* fix: 修复导航栏菜单覆盖标题栏的问题

* fix: 修复标题按钮下方的可拖动区域

* feat: 导航栏不再支持 Minimal 状态

* chore: 删除不再需要的代码

* UI: 修正配置文件页面图标位置

* docs: 更新主窗口截图
2023-05-31 19:40:18 +08:00

134 lines
4.4 KiB
C++

#include "pch.h"
#include "CaptionButtonsControl.h"
#if __has_include("CaptionButtonsControl.g.cpp")
#include "CaptionButtonsControl.g.cpp"
#endif
namespace winrt::Magpie::App::implementation {
Size CaptionButtonsControl::CaptionButtonSize() const noexcept {
ResourceDictionary resources = Resources();
return {
(float)unbox_value<double>(resources.Lookup(box_value(L"CaptionButtonWidth"))),
(float)unbox_value<double>(resources.Lookup(box_value(L"CaptionButtonHeight")))
};
}
// 鼠标移动到某个按钮上时调用
void CaptionButtonsControl::HoverButton(CaptionButton button) {
if (_pressedButton) {
bool hoveringOnPressedButton = _pressedButton.value() == button;
_allInNormal = !hoveringOnPressedButton;
VisualStateManager::GoToState(MinimizeButton(),
hoveringOnPressedButton && button == CaptionButton::Minimize ? L"Pressed" : L"Normal", false);
VisualStateManager::GoToState(MaximizeButton(),
hoveringOnPressedButton && button == CaptionButton::Maximize ? L"Pressed" : L"Normal", false);
VisualStateManager::GoToState(CloseButton(),
hoveringOnPressedButton && button == CaptionButton::Close ? L"Pressed" : L"Normal", false);
} else {
_allInNormal = false;
VisualStateManager::GoToState(MinimizeButton(),
button == CaptionButton::Minimize ? L"PointerOver" : L"Normal", false);
VisualStateManager::GoToState(MaximizeButton(),
button == CaptionButton::Maximize ? L"PointerOver" : L"Normal", false);
VisualStateManager::GoToState(CloseButton(),
button == CaptionButton::Close ? L"PointerOver" : L"Normal", false);
}
}
// 在某个按钮上按下鼠标时调用
void CaptionButtonsControl::PressButton(CaptionButton button) {
_allInNormal = false;
_pressedButton = button;
VisualStateManager::GoToState(MinimizeButton(),
button == CaptionButton::Minimize ? L"Pressed" : L"Normal", false);
VisualStateManager::GoToState(MaximizeButton(),
button == CaptionButton::Maximize ? L"Pressed" : L"Normal", false);
VisualStateManager::GoToState(CloseButton(),
button == CaptionButton::Close ? L"Pressed" : L"Normal", false);
}
// 在标题栏按钮上释放鼠标时调用
void CaptionButtonsControl::ReleaseButton(CaptionButton button) {
// 在某个按钮上按下然后释放视为点击,即使中途离开过也是如此,因为 HoverButton 和
// LeaveButtons 都不改变 _pressedButton
const bool clicked = _pressedButton && _pressedButton.value() == button;
if (clicked) {
// 用户点击了某个按钮
HWND hwndMain = (HWND)Application::Current().as<App>().HwndMain();
switch (_pressedButton.value()) {
case CaptionButton::Minimize:
PostMessage(hwndMain, WM_SYSCOMMAND, SC_MINIMIZE | HTMINBUTTON, 0);
break;
case CaptionButton::Maximize:
{
POINT cursorPos;
GetCursorPos(&cursorPos);
PostMessage(
hwndMain,
WM_SYSCOMMAND,
(_isWindowMaximized ? SC_RESTORE : SC_MAXIMIZE) | HTMAXBUTTON,
MAKELPARAM(cursorPos.x, cursorPos.y)
);
break;
}
case CaptionButton::Close:
PostMessage(hwndMain, WM_SYSCOMMAND, SC_CLOSE, 0);
break;
}
}
_pressedButton.reset();
// 如果点击了某个按钮则清空状态,因为此时窗口状态已改变。如果在某个按钮上按下然后在
// 其他按钮上释放,不视为点击,则将当前鼠标所在的按钮状态置为 PointerOver
_allInNormal = clicked;
VisualStateManager::GoToState(MinimizeButton(),
!clicked && button == CaptionButton::Minimize ? L"PointerOver" : L"Normal", false);
VisualStateManager::GoToState(MaximizeButton(),
!clicked && button == CaptionButton::Maximize ? L"PointerOver" : L"Normal", false);
VisualStateManager::GoToState(CloseButton(),
!clicked && button == CaptionButton::Close ? L"PointerOver" : L"Normal", false);
}
// 在非标题按钮上释放鼠标时调用
void CaptionButtonsControl::ReleaseButtons() {
if (!_pressedButton) {
return;
}
_pressedButton.reset();
LeaveButtons();
}
// 离开标题按钮时调用,不更改 _pressedButton
void CaptionButtonsControl::LeaveButtons() {
if (_allInNormal) {
return;
}
_allInNormal = true;
VisualStateManager::GoToState(MinimizeButton(), L"Normal", true);
VisualStateManager::GoToState(MaximizeButton(), L"Normal", true);
VisualStateManager::GoToState(CloseButton(), L"Normal", true);
}
void CaptionButtonsControl::IsWindowMaximized(bool value) {
if (_isWindowMaximized == value) {
return;
}
if (VisualStateManager::GoToState(MaximizeButton(),
value ? L"WindowStateMaximized" : L"WindowStateNormal", false))
{
_isWindowMaximized = value;
}
}
}