diff --git a/.gitignore b/.gitignore
index 9738585..014630f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,7 @@
build/*
build64/*
-demo/*
\ No newline at end of file
+_temp/
+_bin/
+temp/
+bin/
+.vs/
\ No newline at end of file
diff --git a/CLAUDE.md b/CLAUDE.md
index d91ec52..95f74f9 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -9,20 +9,26 @@ EzUI 是一个基于原生 Win32 消息机制和 Direct2D 的 C++ 桌面 UI 框
## 构建命令
```bash
-build.bat # 构建 32 位版本
-build64.bat # 构建 64 位版本
+build.bat # 构建 32 位静态库
+build64.bat # 构建 64 位静态库
```
-或使用 CMake 直接构建:
+CMake 构建:
```bash
cmake -B build
cmake --build build
```
+静态库/动态库切换:
+```bash
+cmake -B build -DBUILD_SHARED_LIBS=ON # 动态库
+cmake -B build -DBUILD_SHARED_LIBS=OFF # 静态库(默认)
+```
+
## 核心架构
### 窗口类型 (继承层次)
-- `Window` - 经典边框窗口
+- `Window` - 经典带边框窗口
- `BorderlessWindow` - 无边框带阴影窗口
- `LayeredWindow` - 分层透明窗口,支持异形
- `PopupWindow` - 失焦自动关闭的弹出窗口
@@ -32,7 +38,13 @@ cmake --build build
- 基础控件:`Label`, `Button`, `TextBox`, `PictureBox`
- 选择控件:`CheckBox`, `RadioButton`, `ComboBox`
- 布局容器:`HLayout`, `VLayout`, `HListView`, `VListView`, `TileListView`, `TabLayout`
-- 功能控件:`ScrollBar`, `Menu`, `NotifyIcon`, `ProgressBar`
+- 功能控件:`ScrollBar`, `Menu`, `NotifyIcon`, `ProgressBar`, `TreeView`, `Spacer`
+
+### 布局系统
+- **尺寸优先级**:比例尺寸 (`SetRateWidth/Height`) > 绝对尺寸 (`SetFixedSize`) > 控件内容大小
+- **自动布局**:`SetAutoWidth/Height` 让控件根据内容自动调整大小
+- **停靠布局**:`SetDockStyle` 支持 Fill/Vertical/Horizontal 停靠
+- **布局状态**:`TryPendLayout`/`ResumeLayout` 批量添加控件后统一布局
### 样式与渲染
- `UIManager` - UI 样式与资源管理,支持 XML 布局加载
@@ -41,7 +53,20 @@ cmake --build build
- `RenderTypes` - 颜色、对齐方式等绘图类型
### 事件系统
-支持事件冒泡机制,可实现事件捕获与穿透。Debug 模式下按 F11 可查看布局信息和控件边界。
+- 支持事件冒泡机制,可实现事件捕获与穿透
+- `NotifyFlags` 控制控件哪些事件需要通知窗口
+- `Event` 枚举定义所有事件类型,支持位运算组合
+- Debug 模式下按 F11 可查看布局信息和控件边界
+
+### 线程模型
+- UI 线程:`Application::Run` 启动消息循环
+- 跨线程调用:`BeginInvoke`(异步)/ `Invoke`(同步)
+- 全局隐藏窗口 `__EzUI_MessageWnd` 用于线程通讯
+
+### 资源管理
+- 控件树内存由父控件自动管理:`Attach`/`Detach`
+- 图片资源通过 `PtrManager` 自动释放
+- XML 布局加载后由 `UIManager` 管理生命周期
## 开发约定
@@ -49,3 +74,4 @@ cmake --build build
- 源文件位于 `sources/` 目录
- 一切皆控件,纯代码组合 UI
- 使用 CSS 驱动视觉,结构与样式分离
+- 中文注释,中文沟通
diff --git a/build_x64.bat b/build_x64.bat
new file mode 100644
index 0000000..c5116bd
--- /dev/null
+++ b/build_x64.bat
@@ -0,0 +1,4 @@
+chcp 65001
+@echo off
+cmake -S . -B build_x64 -A x64 -DBUILD_EZUI=OFF
+pause
diff --git a/build_x86.bat b/build_x86.bat
new file mode 100644
index 0000000..30b6f82
--- /dev/null
+++ b/build_x86.bat
@@ -0,0 +1,4 @@
+chcp 65001
+@echo off
+cmake -S . -B build_x86 -A Win32 -DBUILD_EZUI=OFF
+pause
diff --git a/demo/Adminstor/Adminstor.sln b/demo/Adminstor/Adminstor.sln
new file mode 100644
index 0000000..e57994d
--- /dev/null
+++ b/demo/Adminstor/Adminstor.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.14.36811.4 d17.14
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Adminstor", "Adminstor\Adminstor.vcxproj", "{EE06DEDC-52B5-4B5D-8B52-7FEB02D77E6B}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {EE06DEDC-52B5-4B5D-8B52-7FEB02D77E6B}.Debug|x64.ActiveCfg = Debug|x64
+ {EE06DEDC-52B5-4B5D-8B52-7FEB02D77E6B}.Debug|x64.Build.0 = Debug|x64
+ {EE06DEDC-52B5-4B5D-8B52-7FEB02D77E6B}.Debug|x86.ActiveCfg = Debug|Win32
+ {EE06DEDC-52B5-4B5D-8B52-7FEB02D77E6B}.Debug|x86.Build.0 = Debug|Win32
+ {EE06DEDC-52B5-4B5D-8B52-7FEB02D77E6B}.Release|x64.ActiveCfg = Release|x64
+ {EE06DEDC-52B5-4B5D-8B52-7FEB02D77E6B}.Release|x64.Build.0 = Release|x64
+ {EE06DEDC-52B5-4B5D-8B52-7FEB02D77E6B}.Release|x86.ActiveCfg = Release|Win32
+ {EE06DEDC-52B5-4B5D-8B52-7FEB02D77E6B}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {AC1EAB6C-7DC1-484D-92AE-6736232936CA}
+ EndGlobalSection
+EndGlobal
diff --git a/demo/Adminstor/Adminstor/Adminstor.vcxproj b/demo/Adminstor/Adminstor/Adminstor.vcxproj
new file mode 100644
index 0000000..7f6ec2d
--- /dev/null
+++ b/demo/Adminstor/Adminstor/Adminstor.vcxproj
@@ -0,0 +1,203 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 17.0
+ Win32Proj
+ {ee06dedc-52b5-4b5d-8b52-7feb02d77e6b}
+ Adminstor
+ 10.0
+
+
+
+ Application
+ true
+ v143
+ Unicode
+
+
+ Application
+ false
+ v143
+ true
+ Unicode
+
+
+ Application
+ true
+ v143
+ Unicode
+
+
+ Application
+ false
+ v143
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ..\_bin\
+ ..\_temp\$(Platform)$(Configuration)$(ProjectName)\
+ ..\ThirdParty\EzUI\include;$(IncludePath)
+ ..\ThirdParty\EzUI\lib;$(LibraryPath)
+ $(ProjectName)_$(Configuration)_$(Platform)
+
+
+ ..\_bin\
+ ..\_temp\$(Platform)$(Configuration)$(ProjectName)\
+ ..\ThirdParty\EzUI\include;$(IncludePath)
+ ..\ThirdParty\EzUI\lib;$(LibraryPath)
+ $(ProjectName)_$(Configuration)_$(Platform)
+
+
+ ..\_bin\
+ ..\_temp\$(Platform)$(Configuration)$(ProjectName)\
+ ..\ThirdParty\EzUI\include;$(IncludePath)
+ ..\ThirdParty\EzUI\lib;$(LibraryPath)
+ $(ProjectName)_$(Configuration)_$(Platform)
+
+
+ ..\_bin\
+ ..\_temp\$(Platform)$(Configuration)$(ProjectName)\
+ ..\ThirdParty\EzUI\include;$(IncludePath)
+ ..\ThirdParty\EzUI\lib;$(LibraryPath)
+ $(ProjectName)_$(Configuration)_$(Platform)
+
+
+
+ Level3
+ true
+
+
+ true
+ stdcpp17
+ MultiThreadedDebug
+ Use
+ pch.h
+
+
+ Windows
+ true
+ EzUI_$(Configuration)_$(Platform).lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+ true
+ true
+
+
+ true
+ stdcpp17
+ MultiThreaded
+ Use
+ pch.h
+
+
+ Windows
+ false
+ EzUI_$(Configuration)_$(Platform).lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+
+
+ true
+ stdcpp17
+ MultiThreadedDebug
+ Use
+ pch.h
+
+
+ Windows
+ true
+ EzUI_$(Configuration)_$(Platform).lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+ true
+ true
+
+
+ true
+ stdcpp17
+ MultiThreaded
+ Use
+ pch.h
+
+
+ Windows
+ false
+ EzUI_$(Configuration)_$(Platform).lib;%(AdditionalDependencies)
+
+
+
+
+
+
+
+
+
+
+
+
+ Create
+ Create
+ Create
+ Create
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demo/Adminstor/Adminstor/Adminstor.vcxproj.filters b/demo/Adminstor/Adminstor/Adminstor.vcxproj.filters
new file mode 100644
index 0000000..1f2e86f
--- /dev/null
+++ b/demo/Adminstor/Adminstor/Adminstor.vcxproj.filters
@@ -0,0 +1,55 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ 头文件
+
+
+ 头文件
+
+
+ 头文件
+
+
+ 头文件
+
+
+
+
+ 源文件
+
+
+ 源文件
+
+
+ 源文件
+
+
+
+
+ 资源文件
+
+
+ 资源文件
+
+
+
+
+ 资源文件
+
+
+
\ No newline at end of file
diff --git a/demo/Adminstor/Adminstor/Adminstor.vcxproj.user b/demo/Adminstor/Adminstor/Adminstor.vcxproj.user
new file mode 100644
index 0000000..88a5509
--- /dev/null
+++ b/demo/Adminstor/Adminstor/Adminstor.vcxproj.user
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/demo/Adminstor/Adminstor/DemoUi.cpp b/demo/Adminstor/Adminstor/DemoUi.cpp
new file mode 100644
index 0000000..950bf8e
--- /dev/null
+++ b/demo/Adminstor/Adminstor/DemoUi.cpp
@@ -0,0 +1,16 @@
+#include "pch.h"
+#include "loginForm.h"
+
+int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
+{
+ //app类
+ Application app(hInstance);
+ app.EnableHighDpi();//启用高DPI
+
+
+ //创建登录创建
+ loginForm loginFrm;
+ loginFrm.Show();
+
+ return app.Exec();//进行消息循环
+}
\ No newline at end of file
diff --git a/demo/Adminstor/Adminstor/DemoUi.ico b/demo/Adminstor/Adminstor/DemoUi.ico
new file mode 100644
index 0000000..b3ec03b
Binary files /dev/null and b/demo/Adminstor/Adminstor/DemoUi.ico differ
diff --git a/demo/Adminstor/Adminstor/DemoUi.rc b/demo/Adminstor/Adminstor/DemoUi.rc
new file mode 100644
index 0000000..8d170ab
Binary files /dev/null and b/demo/Adminstor/Adminstor/DemoUi.rc differ
diff --git a/demo/Adminstor/Adminstor/Resource.h b/demo/Adminstor/Adminstor/Resource.h
new file mode 100644
index 0000000..5f0a4d8
--- /dev/null
+++ b/demo/Adminstor/Adminstor/Resource.h
@@ -0,0 +1,14 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by DemoUi.rc
+
+// ¶һĬֵ
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/demo/Adminstor/Adminstor/framework.h b/demo/Adminstor/Adminstor/framework.h
new file mode 100644
index 0000000..4b84f0f
--- /dev/null
+++ b/demo/Adminstor/Adminstor/framework.h
@@ -0,0 +1,21 @@
+#pragma once
+#include "resource.h"
+
+#include
+
+
+#include "ezui/Application.h" //app类
+#include "EzUI/Window.h" //基础窗口类
+#include "EzUI/Button.h" //按钮
+#include "EzUI/TextBox.h" //文本框
+#include "EzUI/CheckBox.h" //复选框
+#include "EzUI/PictureBox.h" //图片控件
+#include "EzUI/TabLayout.h" //选项卡控件
+#include "EzUI/VLayout.h" //垂直布局
+#include "EzUI/HLayout.h"//水平布局
+#include "EzUI/VListView.h"//垂直带滚动条列表
+#include "EzUI/HListView.h"//水平带滚动条列表
+#include "EzUI/TileListView.h"//瓦片列表
+#include "EzUI/LayeredWindow.h"//分层窗口类-可以异型透明窗口
+#include "ezui/UIManager.h"//ui管理类(使用xml生成控件)
+
diff --git a/demo/Adminstor/Adminstor/loginForm.cpp b/demo/Adminstor/Adminstor/loginForm.cpp
new file mode 100644
index 0000000..2a24f9f
--- /dev/null
+++ b/demo/Adminstor/Adminstor/loginForm.cpp
@@ -0,0 +1,47 @@
+#include "pch.h"
+#include "loginForm.h"
+
+void loginForm::OnNotify(Control* sender, EventArgs& args)
+{
+ if (args.EventType == Event::OnMouseDown) {
+ if (sender->Name == "btnLogin") {
+ TextBox* editUser = (TextBox*)FindControl("user");
+ TextBox* editpwd = (TextBox*)FindControl("pwd");
+ CheckBox* ckbox = (CheckBox*)FindControl("ckbox");
+ if (!ckbox->GetCheck()) {
+ ::MessageBoxW(Hwnd(), L"ĶЭ鲢ѡ!", L"ʾ", MB_OK);
+ return;
+ }
+ UIString user = editUser->GetText();
+ UIString pwd = editpwd->GetText();
+ if (user == "718987717" && pwd == "123456") {
+ ::MessageBoxW(Hwnd(), L"¼ɹ!", L"ʾ", MB_OK);
+ }
+ else {
+ ::MessageBoxW(Hwnd(), L"û!", L"ʾ", MB_OK);
+ }
+ }
+ if (sender->Name == "btnExit") {
+ Application::Exit();
+ }
+ if (!sender->GetAttribute("url").empty()) {
+ ::ShellExecuteA(0, "open", sender->GetAttribute("url").c_str(), "", "", SW_SHOW);
+ }
+ }
+ __super::OnNotify(sender, args);
+}
+
+void loginForm::OnClose(bool& close)
+{
+ Application::Exit();
+}
+
+loginForm::loginForm() :LayeredWindow(320, 448)
+{
+ umg.LoadXml("res/loginForm.htm");//xmlĿؼʽ
+ umg.SetupUI(this);
+}
+
+loginForm::~loginForm()
+{
+}
diff --git a/demo/Adminstor/Adminstor/loginForm.h b/demo/Adminstor/Adminstor/loginForm.h
new file mode 100644
index 0000000..9454133
--- /dev/null
+++ b/demo/Adminstor/Adminstor/loginForm.h
@@ -0,0 +1,23 @@
+#pragma once
+#include "pch.h"
+
+using namespace ezui;
+
+using Form = LayeredWindow; //֧(Ӱ)
+//using Form = BorderlessWindow; //ޱ߿(Ӱ)
+//using Form = Window; //(ϵͳ)
+
+// ½
+class loginForm :public Form
+{
+private:
+ //ui
+ UIManager umg;
+protected:
+ virtual void OnNotify(Control* sender, EventArgs& args)override;//¼֪ͨ
+ virtual void OnClose(bool& close)override;//ڹرյʱ
+public:
+ loginForm();
+ virtual ~loginForm();
+};
+
diff --git a/demo/Adminstor/Adminstor/pch.cpp b/demo/Adminstor/Adminstor/pch.cpp
new file mode 100644
index 0000000..1730571
--- /dev/null
+++ b/demo/Adminstor/Adminstor/pch.cpp
@@ -0,0 +1 @@
+#include "pch.h"
\ No newline at end of file
diff --git a/demo/Adminstor/Adminstor/pch.h b/demo/Adminstor/Adminstor/pch.h
new file mode 100644
index 0000000..c9c7883
--- /dev/null
+++ b/demo/Adminstor/Adminstor/pch.h
@@ -0,0 +1,2 @@
+#pragma once
+#include "framework.h"
diff --git a/demo/Adminstor/Adminstor/small.ico b/demo/Adminstor/Adminstor/small.ico
new file mode 100644
index 0000000..b3ec03b
Binary files /dev/null and b/demo/Adminstor/Adminstor/small.ico differ
diff --git a/demo/Adminstor/ThirdParty/EzUI/include/EzUI/Animation.h b/demo/Adminstor/ThirdParty/EzUI/include/EzUI/Animation.h
new file mode 100644
index 0000000..1b7cf2e
--- /dev/null
+++ b/demo/Adminstor/ThirdParty/EzUI/include/EzUI/Animation.h
@@ -0,0 +1,29 @@
+#pragma once
+#include "EzUI.h"
+#include "Timer.h"
+
+namespace ezui {
+
+ class UI_EXPORT Animation : public Object {
+ private:
+ Timer *m_timer;
+ float m_startValue = 0;
+ float m_endValue = 0;
+ float m_currValue = 0;
+ float m_speedPerMs = 0;
+ std::chrono::steady_clock::time_point m_lastTime;
+ public:
+ //当值更改的时候发生的事件(请绑定此函数进行回调,请自行线程同步)
+ std::function ValueChanged;
+ Animation(Object* parentObject = NULL);
+ virtual ~Animation();
+ void SetStartValue(float value);
+ void SetEndValue(float value);
+ //开始动画
+ void Start(int durationMs, int fps = 90);
+ //动画是否已经停止
+ bool IsStopped();
+ void Stop();
+ };
+
+};
diff --git a/demo/Adminstor/ThirdParty/EzUI/include/EzUI/Application.h b/demo/Adminstor/ThirdParty/EzUI/include/EzUI/Application.h
new file mode 100644
index 0000000..65d70ab
--- /dev/null
+++ b/demo/Adminstor/ThirdParty/EzUI/include/EzUI/Application.h
@@ -0,0 +1,24 @@
+#pragma once
+#include "Window.h"
+#include "Resource.h"
+
+namespace ezui {
+ class UI_EXPORT Application
+ {
+ public:
+ //退出消息循环
+ static void Exit(int exitCode = 0);
+ //获取程序启动路径
+ static UIString StartPath();
+ public:
+ Application(HINSTANCE hInstance = NULL);
+ //使用本地文件名称或者资源中的名称加载资源包
+ //填入vs中的资源ID名称 或者 本地文件名 一个Application只允许有一个资源文件
+ bool SetResource(const UIString& localOrResName);
+ //启用高DPI适配
+ void EnableHighDpi();
+ virtual ~Application();
+ //执行消息循环
+ int Exec();
+ };
+};
\ No newline at end of file
diff --git a/demo/Adminstor/ThirdParty/EzUI/include/EzUI/Bitmap.h b/demo/Adminstor/ThirdParty/EzUI/include/EzUI/Bitmap.h
new file mode 100644
index 0000000..92baee6
--- /dev/null
+++ b/demo/Adminstor/ThirdParty/EzUI/include/EzUI/Bitmap.h
@@ -0,0 +1,34 @@
+#pragma once
+#include "EzUI.h"
+
+namespace ezui {
+ //BGRA 32位图
+ class UI_EXPORT Bitmap {
+ private:
+ int m_width = 0;
+ int m_height = 0;
+ HBITMAP m_bmp = NULL;
+ HDC m_hdc = NULL;
+ byte* m_point = NULL;
+ BITMAPINFO m_bmpInfo;
+ Bitmap(const Bitmap& hBitmap) = delete;
+ void operator=(const Bitmap& hBitmap) = delete;
+ protected:
+ void Create(int width, int height);
+ public:
+ int Width()const;
+ int Height()const;
+ //BGRA 32位图
+ Bitmap(int width, int height);
+ Bitmap(HDC dc, const Rect& rect);
+ void SetPixel(int x, int y, const Color& color);
+ Color GetPixel(int x, int y)const;
+ byte* GetPixel();
+ void Earse(const Rect& rect);//抹除矩形内容
+ HBITMAP GetHBITMAP();
+ HDC GetDC();
+ bool Save(const UIString& fileName);
+ Bitmap* Clone()const;
+ virtual ~Bitmap();
+ };
+};
diff --git a/demo/Adminstor/ThirdParty/EzUI/include/EzUI/BorderlessWindow.h b/demo/Adminstor/ThirdParty/EzUI/include/EzUI/BorderlessWindow.h
new file mode 100644
index 0000000..4b1185b
--- /dev/null
+++ b/demo/Adminstor/ThirdParty/EzUI/include/EzUI/BorderlessWindow.h
@@ -0,0 +1,38 @@
+#pragma once
+#include "Window.h"
+#include "ShadowBox.h"
+
+namespace ezui {
+ ///
+ /// BorderlessWindow //无边框 带阴影
+ ///
+ class UI_EXPORT BorderlessWindow :public Window {
+ private:
+ int m_shadowWeight = 20;
+ ShadowBox* m_shadowBox = NULL;
+ float m_shadowScale = 1.0f;
+ //是否支持缩放
+ bool m_bResize = false;
+ protected:
+ virtual LRESULT WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)override;
+ virtual void OnMove(const Point& location) override;
+ virtual void OnSize(const Size& sz) override;
+ virtual void OnDpiChange(float systemScale, const Rect& newRect);//当dpi发生更改时
+ virtual HWND GetShadowHwnd()override;//获取阴影窗口句柄
+ public:
+ //设置阴影宽度
+ void SetShadow(int weight);
+ BorderlessWindow(int width, int height, HWND owner = NULL, DWORD dwStyle = NULL, DWORD dwExStyle = NULL);
+ virtual ~BorderlessWindow();
+ //更新窗口阴影
+ void UpdateShadowBox();
+ //获取阴影窗口
+ ShadowBox* GetShadowBox();
+ //关闭窗口阴影 关掉阴影窗口 已有的边框也会随之消失
+ void CloseShadowBox();
+ //设置窗口缩放支持
+ void SetResizable(bool resize);
+ //是否支持调整大小
+ bool IsResizable();
+ };
+};
diff --git a/demo/Adminstor/ThirdParty/EzUI/include/EzUI/Button.h b/demo/Adminstor/ThirdParty/EzUI/include/EzUI/Button.h
new file mode 100644
index 0000000..31902af
--- /dev/null
+++ b/demo/Adminstor/ThirdParty/EzUI/include/EzUI/Button.h
@@ -0,0 +1,14 @@
+#pragma once
+#include "Label.h"
+
+namespace ezui {
+ class UI_EXPORT Button :
+ public Label
+ {
+ private:
+ void Init();
+ public:
+ Button(Object* parentObject = NULL);
+ virtual ~Button();
+ };
+};
\ No newline at end of file
diff --git a/demo/Adminstor/ThirdParty/EzUI/include/EzUI/CheckBox.h b/demo/Adminstor/ThirdParty/EzUI/include/EzUI/CheckBox.h
new file mode 100644
index 0000000..efe5000
--- /dev/null
+++ b/demo/Adminstor/ThirdParty/EzUI/include/EzUI/CheckBox.h
@@ -0,0 +1,33 @@
+#pragma once
+#include "Label.h"
+
+namespace ezui {
+
+ class UI_EXPORT CheckBox :
+ public Label
+ {
+ private:
+ bool m_checked = false;
+ public:
+ //选中样式
+ ControlStyle CheckedStyle;
+ //选中状态发送变化的回调函数
+ std::function CheckedChanged = NULL;
+ protected:
+ virtual ControlStyle& GetStyle(const ControlState& _state)override;
+ virtual void OnMouseDown(const MouseEventArgs& arg)override;
+ virtual void OnDpiChange(const DpiChangeEventArgs& args)override;
+ virtual void OnMouseEnter(const MouseEventArgs& args)override;
+ virtual void OnMouseUp(const MouseEventArgs& args)override;
+ virtual void OnMouseLeave(const MouseEventArgs& args)override;
+ public:
+ CheckBox(Object* parentObject = NULL);
+ virtual void SetAttribute(const UIString& key, const UIString& value)override;
+ //设置选中状态
+ virtual void SetCheck(bool checked);
+ //获取选中状态
+ virtual bool GetCheck();
+ virtual ~CheckBox();
+ };
+
+};
\ No newline at end of file
diff --git a/demo/Adminstor/ThirdParty/EzUI/include/EzUI/ComboBox.h b/demo/Adminstor/ThirdParty/EzUI/include/EzUI/ComboBox.h
new file mode 100644
index 0000000..d2ecc02
--- /dev/null
+++ b/demo/Adminstor/ThirdParty/EzUI/include/EzUI/ComboBox.h
@@ -0,0 +1,51 @@
+#pragma once
+#include "TextBox.h"
+#include "Label.h"
+#include "VListView.h"
+#include "PopupWindow.h"
+#include "HLayout.h"
+
+namespace ezui {
+ //简易的下拉列表框
+ class UI_EXPORT ComboBox :public HLayout {
+ private:
+ //添加选项请使用AddItem
+ virtual Control* Add(Control* childCtl)override;
+ //移除选项请使用RemoveItem
+ virtual void Remove(Control* childCtl, bool freeCtrl)override;
+ private:
+ //下拉菜单选项
+ class MenuContent :public PopupWindow {
+ public:
+ Control* m_hittestCtl;
+ MenuContent(Control* ownerCtl, Control* hittestCtl);
+ virtual void OnKillFocus(HWND wnd) override;
+ virtual ~MenuContent();
+ };
+ private:
+ //下拉菜单窗口
+ MenuContent* m_menuWnd = NULL;
+ //选择之后显示的文本框
+ TextBox m_textBox;
+ //展开菜单的按钮
+ Label m_UpDown;
+
+ VListView m_list;
+ int m_index = -1;
+ void Init();
+ protected:
+ virtual void OnLayout()override;
+ public:
+ ComboBox(Object* parentObject = NULL);
+ //获取选中的文字
+ UIString GetText();
+ //获取选中的下标
+ int GetCheck();
+ //选中某个下标
+ bool SetCheck(int pos);
+ virtual ~ComboBox();
+ //添加一个item并返回新item的下标
+ int AddItem(const UIString& text);
+ void RemoveItem(int index);
+ };
+};
diff --git a/demo/Adminstor/ThirdParty/EzUI/include/EzUI/Control.h b/demo/Adminstor/ThirdParty/EzUI/include/EzUI/Control.h
new file mode 100644
index 0000000..d785119
--- /dev/null
+++ b/demo/Adminstor/ThirdParty/EzUI/include/EzUI/Control.h
@@ -0,0 +1,527 @@
+#pragma once
+#include "EzUI.h"
+
+namespace ezui {
+ class UI_EXPORT Control :public Object
+ {
+ private:
+
+ //顶层窗口句柄
+ HWND m_hWnd = NULL;
+
+ // 控件是否已经被移除或释放
+ bool* m_bRemove = NULL;
+
+ //控件是否被为按住状态
+ bool m_pressed = false;
+
+ // 控件是否启用,禁止状态下鼠标键盘消息将不可用
+ bool m_enabled = true;
+
+ // 控件是否可见。此标志为 true 时,控件为显示状态
+ bool m_bVisible = true;
+
+ // 当前控件的 DPI 缩放比例
+ float m_scale = 1.0f;
+
+ // 子控件集合
+ Controls m_controls;
+
+ // 管理图片的释放
+ PtrManager m_imgs;
+
+ // 布局状态
+ // AddControl、InsertControl、RemoveControl、OnSize 时此标志为挂起状态
+ // 调用 ResumeLayout 标志为布局中
+ // 调用 OnLayout() 之后标志为 None
+ ezui::LayoutState m_layoutState = ezui::LayoutState::None;
+
+ // 鼠标悬浮提示文字
+ UIString m_tipsText;
+
+ // 上一次位置
+ Point m_lastLocation;
+
+ // 上一次大小
+ Size m_lastSize;
+
+ // 是否根据内容自动宽度
+ bool m_bAutoWidth = false;
+
+ // 根据内容自动高度变化
+ bool m_bAutoHeight = false;
+
+ // 控件内容宽高
+ Size m_contentSize;
+
+ // 绝对尺寸
+ Size m_fixedSize;
+
+ //比例尺寸(优先级最高)
+ SizeF m_rateSize;
+
+ // 控件矩形区域(基于父控件)
+ Rect m_rect;
+
+ // 控件在窗口中的可见区域
+ Rect m_viewRect;
+
+ // dock 样式
+ DockStyle m_dock = DockStyle::None;
+
+ // 控件是否可以被命中(值为false情况下就是穿透效果)
+ bool m_hitTestEnabled = true;
+ protected:
+ // 基于控件中的可见控件集合
+ Controls ViewControls;
+ // 控件当前状态
+ ControlState State = ControlState::Static;
+ public:
+ // 外边距
+ // 让容器独占一行或一列时,设置边距会使控件变小,不可设置为负数
+ Distance Margin;
+
+ // 控件的 ObjectName ID
+ UIString Name;
+
+ // 控件行为
+ ControlAction Action = ControlAction::None;
+
+ // 静态默认样式
+ ControlStyle Style;
+
+ //禁用状态样式
+ ControlStyle DisabledStyle;
+
+ // 鼠标悬浮样式
+ ControlStyle HoverStyle;
+
+ // 鼠标按下样式
+ ControlStyle ActiveStyle;
+
+ // 父控件指针
+ Control* Parent = NULL;
+
+ //是否添加到所在窗口/IFrame中的OnNotify函数中
+ Event NotifyFlags = Event::OnMouseEvent | Event::OnKeyBoardEvent;
+ // 事件处理器
+ std::function EventHandler = NULL;
+
+ private:
+ // 禁止拷贝构造
+ Control(const Control&) = delete;
+
+ // 禁止赋值
+ Control& operator=(const Control&) = delete;
+
+ // 计算基于父控件的裁剪区域
+ void ComputeClipRect();
+
+ // 所有事件优先进入此函数(内部处理)
+ void OnEvent(EventArgs& arg);
+
+ protected:
+ //属性或者css样式都适用(css样式和属性都可以设置这些,只对静态样式生效)
+ virtual bool ApplyStyleProperty(const UIString& key, const UIString& value);
+
+ // 设置内容宽度,仅限子类使用
+ virtual void SetContentWidth(int width);
+
+ // 设置内容高度,仅限子类使用
+ virtual void SetContentHeight(int height);
+
+ // 设置内容尺寸,仅限子类使用
+ virtual void SetContentSize(const Size& size);
+
+ // 绘制之前
+ virtual void OnPaintBefore(PaintEventArgs& args);
+
+ // 控件绘制
+ virtual void OnPaint(PaintEventArgs& args);
+
+ // 子控件绘制,可重载此函数优化鼠标操作性能
+ virtual void OnChildPaint(PaintEventArgs& args);
+
+ // 背景绘制
+ virtual void OnBackgroundPaint(PaintEventArgs& painter);
+
+ // 前景绘制
+ virtual void OnForePaint(PaintEventArgs& e);
+
+ // 边框绘制
+ virtual void OnBorderPaint(PaintEventArgs& painter, const Border& border);
+
+ // 坐标发生改变
+ virtual void OnMove(const MoveEventArgs& arg);
+
+ // 大小发生改变
+ virtual void OnSize(const SizeEventArgs& arg);
+
+ // DPI 发生改变
+ virtual void OnDpiChange(const DpiChangeEventArgs& arg);
+
+ // 控件布局逻辑,需重写布局请重写此函数
+ virtual void OnLayout();
+
+ // 鼠标在控件上移动
+ virtual void OnMouseMove(const MouseEventArgs& arg);
+
+ // 鼠标离开控件
+ virtual void OnMouseLeave(const MouseEventArgs& args);
+
+ // 鼠标滚轮事件
+ virtual void OnMouseWheel(const MouseEventArgs& arg);
+
+ // 鼠标按下事件
+ virtual void OnMouseDown(const MouseEventArgs& arg);
+
+ // 鼠标弹起事件
+ virtual void OnMouseUp(const MouseEventArgs& arg);
+
+ // 鼠标双击事件
+ virtual void OnMouseDoubleClick(const MouseEventArgs& arg);
+
+ // 鼠标移入控件
+ virtual void OnMouseEnter(const MouseEventArgs& arg);
+
+ // 鼠标事件统一入口
+ virtual void OnMouseEvent(const MouseEventArgs& args);
+
+ // 键盘事件统一入口
+ virtual void OnKeyBoardEvent(const KeyboardEventArgs& _args);
+
+ // 字符输入事件(WM_CHAR)
+ virtual void OnKeyChar(const KeyboardEventArgs& _args);
+
+ // 键盘按下事件(WM_KEYDOWN)
+ virtual void OnKeyDown(const KeyboardEventArgs& _args);
+
+ // 键盘弹起事件(WM_KEYUP)
+ virtual void OnKeyUp(const KeyboardEventArgs& _args);
+
+ // 获得焦点事件
+ virtual void OnFocus(const FocusEventArgs& _args);
+
+ // 失去焦点事件
+ virtual void OnKillFocus(const KillFocusEventArgs& _args);
+
+ // 被移除时执行的逻辑
+ virtual void OnRemove();
+
+ public:
+ // 获取当前控件状态下的样式信息
+ virtual ControlStyle& GetStyle(const ControlState& _state);
+
+ // 获取左上圆角半径
+ int GetBorderTopLeftRadius(ControlState _state = ControlState::None);
+
+ // 获取右上圆角半径
+ int GetBorderTopRightRadius(ControlState _state = ControlState::None);
+
+ // 获取右下圆角半径
+ int GetBorderBottomRightRadius(ControlState _state = ControlState::None);
+
+ // 获取左下圆角半径
+ int GetBorderBottomLeftRadius(ControlState _state = ControlState::None);
+
+ // 获取左边框宽度
+ int GetBorderLeft(ControlState _state = ControlState::None);
+
+ // 获取上边框宽度
+ int GetBorderTop(ControlState _state = ControlState::None);
+
+ // 获取右边框宽度
+ int GetBorderRight(ControlState _state = ControlState::None);
+
+ // 获取下边框宽度
+ int GetBorderBottom(ControlState _state = ControlState::None);
+
+ // 获取边框颜色
+ Color GetBorderColor(ControlState _state = ControlState::None);
+
+ //获取边框样式
+ StrokeStyle GetBorderStyle(ControlState _state = ControlState::None);
+
+ // 获取前景图片
+ Image* GetForeImage(ControlState _state = ControlState::None);
+
+ // 获取背景图片
+ Image* GetBackImage(ControlState _state = ControlState::None);
+
+ // 获取背景颜色
+ Color GetBackColor(ControlState _state = ControlState::None);
+
+ // 获取旋转角度
+ float GetAngle(ControlState _state = ControlState::None);
+
+ //获取当前控件的鼠标光标
+ virtual HCURSOR GetCursor(ControlState _state = ControlState::None);
+
+ // 获取前景颜色
+ Color GetForeColor(ControlState _state = ControlState::None);
+
+ // 获取字体 Family
+ std::wstring GetFontFamily(ControlState _state = ControlState::None);
+
+ // 获取字体大小
+ int GetFontSize(ControlState _state = ControlState::None);
+
+ //获取公共数据
+ WindowData* GetPublicData();
+
+ //获取上层Frame容器
+ IFrame* GetFrame();
+ public:
+
+ // 构造函数 可传入父对象(由父对象自动管理内存)
+ Control(Object* parentObject = NULL);
+
+ // 析构函数
+ virtual ~Control();
+
+ //绑定对象(跟随释放)
+ using Object::Attach;
+
+ //分离对象(解除跟随释放)
+ using Object::Detach;
+
+ //绑定图片(跟随释放)
+ Image* Attach(Image* img);
+
+ //分离图片(解除跟随释放)
+ void Detach(Image* img);
+
+ //窗口句柄
+ HWND Hwnd();
+
+ //设置窗口句柄
+ void SetHwnd(HWND hWnd);
+
+ // 以下函数请保证在父控件布局已完成的情况下使用,使用 ResumeLayout() 执行布局
+ // 获取 X 坐标
+ int X();
+
+ // 获取 Y 坐标
+ int Y();
+
+ // 获取宽度
+ int Width();
+
+ // 获取高度
+ int Height();
+
+ // 设置 X 坐标
+ void SetX(int X);
+
+ // 设置 Y 坐标
+ void SetY(int Y);
+
+ // 移动相对于父控件的位置
+ void SetLocation(const Point& pt);
+
+ // 设置控件大小(当重绘控件时不建议多次使用,影响性能,会调用 SetRect 函数)
+ void SetSize(const Size& size);
+
+ // 设置绝对宽高
+ void SetFixedSize(const Size& size);
+
+ // 设置宽度(当重绘控件时不建议多次使用,影响性能,会调用 SetRect 函数)
+ void SetWidth(int width);
+
+ // 设置高度(当重绘控件时不建议多次使用,影响性能,会调用 SetRect 函数)
+ void SetHeight(int height);
+
+ // 设置绝对宽度
+ void SetFixedWidth(int fixedWidth);
+
+ // 设置绝对高度
+ void SetFixedHeight(int fixedHeight);
+
+ //设置宽度比例(优先级最高)
+ void SetRateWidth(float rateWidth);
+
+ //设置高度比例(优先级最高)
+ void SetRateHeight(float rateHeight);
+
+ // 设置相对父控件矩形,返回实际的 rect
+ const Rect& SetRect(const Rect& rect);
+
+ // 获取绝对宽度
+ int GetFixedWidth();
+
+ // 获取绝对高度
+ int GetFixedHeight();
+
+ // 获取光标位置
+ virtual Rect GetCareRect();
+
+ // 是否自动宽度
+ virtual bool IsAutoWidth();
+
+ // 是否自动高度
+ virtual bool IsAutoHeight();
+
+ // 设置自动宽度
+ virtual void SetAutoWidth(bool flag);
+
+ // 设置自动高度
+ virtual void SetAutoHeight(bool flag);
+
+ // 设置自动大小
+ virtual void SetAutoSize(bool flag);
+
+ // 获取控件内容大小
+ virtual const Size& GetContentSize();
+
+ // 获取控件大小
+ Size GetSize();
+
+ // 获取控件位置
+ Point GetLocation();
+
+ // 获取相对于父控件的矩形(布局计算后)
+ virtual const Rect& GetRect();
+
+ // 获取基于客户端区域的矩形
+ Rect GetClientRect();
+
+ //获取控件基于屏幕的矩形位置
+ Rect GetScreenRect();
+
+ // 获取控件的 DockStyle(停靠方式)
+ DockStyle GetDockStyle();
+
+ // 设置控件的 DockStyle
+ void SetDockStyle(const DockStyle& dockStyle);
+
+ // 获取控件的缩放系数
+ float GetScale();
+
+ // 是否存在挂起的布局
+ bool IsPendLayout();
+
+ // 尝试挂起布局,返回当前布局状态
+ const LayoutState TryPendLayout();
+
+ // 获取当前布局状态
+ const LayoutState GetLayoutState();
+
+ // 结束当前布局(使其立即生效)
+ void EndLayout();
+
+ // 立即强制刷新布局
+ virtual void RefreshLayout();
+
+ // 设置提示文字(类似 tooltip)
+ void SetTips(const UIString& text);
+
+ // 获取提示文字
+ const UIString& GetTips();
+
+ // 获取控件的滚动条对象
+ virtual ScrollBar* GetScrollBar();
+
+ // 派发事件(如鼠标单击事件等...)返回true则事件成功派发 返回false代表派发途中当前控件已被释放
+ void SendEvent(const EventArgs& arg);
+
+ // 设置控件属性
+ virtual void SetAttribute(const UIString& attrName, const UIString& attrValue);
+
+ // 获取当前可见的子控件集合
+ const Controls& GetViewControls();
+
+ // 获取所有子控件(不建议直接修改)
+ const Controls& GetControls();
+
+ // 使用下标获取控件,自动跳过 spacer 类控件
+ Control* GetControl(int pos);
+
+ // 是否包含指定控件(递归遍历所有子控件)
+ bool Contains(Control* ctl);
+
+ // 获取指定子控件的索引
+ int IndexOf(Control* childCtl);
+
+ // 根据 name 查找控件(包括自身)
+ Control* FindControl(const UIString& ctlName);
+
+ // 根据属性查找所有匹配控件(包括自身)
+ Controls FindControl(const UIString& attrName, const UIString& attrValue);
+
+ // 根据属性查找第一个匹配控件(包括自身)
+ Control* FindSingleControl(const UIString& attrName, const UIString& attrValue);
+
+ // 根据 name 查找子控件(仅限直接子集)
+ Control* FindChild(const UIString& ctlName);
+
+ // 根据属性查找所有匹配的子控件(仅限直接子集)
+ Controls FindChild(const UIString& attrName, const UIString& attrValue);
+
+ // 根据属性查找第一个匹配的子控件(仅限直接子集)
+ Control* FindSingleChild(const UIString& attrName, const UIString& attrValue);
+
+ // 交换两个子控件的位置
+ virtual bool SwapChild(Control* childCtl, Control* childCt2);
+
+ //是否启用控件
+ void SetEnabled(bool flag);
+
+ //是否禁用控件
+ void SetDisabled(bool flag);
+
+ //控件是否已启用
+ bool IsEnabled();
+
+ // 在指定位置插入子控件
+ virtual void Insert(int pos, Control* childCtl);
+
+ // 添加控件到末尾(如果是弹簧控件,在释放时将自动销毁)
+ virtual Control* Add(Control* childCtl);
+
+ // 移除控件,freeCtrl 标志是否释放控件内存
+ virtual void Remove(Control* childCtl, bool freeCtrl = false);
+
+ // 设置控件的父控件
+ virtual void SetParent(Control* parentCtl);
+
+ // 清空所有子控件
+ virtual void Clear();
+
+ // 清空所有子控件,freeChilds 决定是否释放子控件内存
+ virtual void Clear(bool freeChilds);
+
+ // 设置控件可见性
+ virtual void SetVisible(bool flag);
+
+ // 获取控件可见性状态
+ virtual bool IsVisible();
+
+ //设置控件是否可以被鼠标命中(false则是鼠标穿透效果)
+ void SetHitTestVisible(bool bEnable);
+
+ //控件是否可以被命中
+ bool IsHitTestVisible();
+
+ //隐藏控件
+ void Hide();
+
+ //显示控件
+ void Show();
+
+ // 标记控件区域为无效(将会延迟刷新UI)
+ virtual bool Invalidate();
+
+ // 立即强制刷新控件区域并更新无效区域(且立即触发布局)
+ virtual void Refresh();
+
+ //传入Style的引用 处理key value
+ virtual void SetStyle(ControlStyle& style, const UIString& key, const UIString& value);
+
+ //传入状态并分析样式字符串
+ virtual void SetStyleSheet(ControlState state, const UIString& styleStr);
+
+ //控件是否被按住
+ bool IsPressed();
+ };
+
+};
\ No newline at end of file
diff --git a/demo/Adminstor/ThirdParty/EzUI/include/EzUI/Direct2DRender.h b/demo/Adminstor/ThirdParty/EzUI/include/EzUI/Direct2DRender.h
new file mode 100644
index 0000000..2dad49a
--- /dev/null
+++ b/demo/Adminstor/ThirdParty/EzUI/include/EzUI/Direct2DRender.h
@@ -0,0 +1,268 @@
+#pragma once
+#include "UIDef.h"
+#if USED_DIRECT2D
+#ifndef UI_EXPORT
+#define UI_EXPORT
+#endif
+
+#include
+#include
+#include
+#include
+#include "RenderTypes.h"
+
+namespace ezui {
+ UI_EXPORT void RenderInitialize();//全局初始化direct2d
+ UI_EXPORT void RenderUnInitialize();//释放direct2d
+ UI_EXPORT float GetMaxRadius(float width, float height, float _radius);//获取最大半径 用于自动适应border-radius属性
+ class UI_EXPORT Font {
+ private:
+ Font() = delete;
+ std::wstring m_fontFamily;
+ float m_fontSize = 0;
+ IDWriteTextFormat* m_value = NULL;
+ bool m_ref = false;
+ void Copy(const Font& _copy);
+ public:
+ Font(const Font& _copy);
+ Font(const std::wstring& fontFamily, float fontSize);
+ float GetFontSize()const;
+ const std::wstring& GetFontFamily()const;
+ IDWriteTextFormat* Get() const;
+ bool operator==(const Font& _right);
+ virtual ~Font();
+ };
+
+ //文本命中测试数据
+ class UI_EXPORT HitTestMetrics {
+ public:
+ int Length;
+ int TextPos;//命中的下标
+ RectF FontBox;//文字的矩形位置
+ bool IsTrailingHit;//命中位置是否在尾部
+ public:
+ Rect GetCare() {
+ float x = FontBox.X;
+ if (IsTrailingHit) {
+ x += FontBox.Width;
+ }
+ float y = FontBox.Y;
+ return Rect((int)x, (int)y, 1, (int)(FontBox.Height + 0.5));
+ }
+ int GetFontHeight() {
+ return int(FontBox.Height + 0.5);
+ }
+ };
+
+ class UI_EXPORT TextLayout {
+ private:
+ TextLayout(const TextLayout& rightValue) = delete;
+ IDWriteTextLayout* m_textLayout = NULL;
+ std::wstring m_fontFamily;
+ DWRITE_TEXT_METRICS m_textMetrics = {};
+ std::vector m_lineRects;
+ int m_unicodeSize = 0;
+ float m_fontSize = 0;
+ public:
+ void GetMetrics();
+ TextLayout(const std::wstring& text, const Font& font, const SizeF& maxSize = SizeF{ EZUI_FLOAT_MAX,EZUI_FLOAT_MAX }, TextAlign textAlgin = TextAlign::TopLeft);
+ Point HitTestPoint(const Point& pt, int* outTextPos, BOOL* outIsTrailingHit, int* fontHeight);
+ void HitTestPoint(const Point& pt, HitTestMetrics* hitTestMetrics);//根据坐标执行命中测试
+ Point HitTestTextPosition(int textPos, BOOL isTrailingHit);//根据文字下标执行命中测试
+ const std::wstring& GetFontFamily();
+ float GetFontSize();
+ int Width();
+ int Height();
+ //获取文本整体的占用空间
+ Size GetFontBox();
+ //获取每行文字的矩形位置
+ const std::vector& GetLineRects();
+ int GetFontHeight();//获取字体高度
+ int GetLineCount();//获取一共有多少行
+ IDWriteTextLayout* Get() const;
+ void SetTextAlign(TextAlign textAlign);
+ void SetUnderline(int pos = 0, int count = 0);
+ virtual ~TextLayout();
+ };
+
+ //几何图形基础类(支持自定义路径)
+ class UI_EXPORT Geometry {
+ protected:
+ ID2D1GeometrySink* m_pSink = NULL;
+ ID2D1Geometry* m_rgn = NULL;
+ Geometry(const Geometry& rightCopy) = delete;
+ public:
+ Geometry();
+ virtual ~Geometry();
+ void AddArc(const PointF& endPoint, float radius);
+ void AddAcr(const D2D1_ARC_SEGMENT& arc);
+ void AddLine(const PointF& endPoint);
+ void BeginFigure(const PointF& startPoint, D2D1_FIGURE_BEGIN figureBegin = D2D1_FIGURE_BEGIN_FILLED);
+ void CloseFigure(D2D1_FIGURE_END figureEnd = D2D1_FIGURE_END_CLOSED);
+ ID2D1Geometry* Get()const;
+ public:
+ ///
+ /// 将两个几何图形通过指定的合并模式(Union、Intersect、Xor、Exclude)合并到一个输出几何中。
+ ///
+ /// 合并结果输出到该 Geometry。
+ /// 参与合并的第一个 Geometry。
+ /// 参与合并的第二个 Geometry。
+ /// 几何合并模式,取值如 D2D1_COMBINE_MODE_UNION、INTERSECT、XOR、EXCLUDE。
+ static void Combine(Geometry& out, const Geometry& a, const Geometry& b, D2D1_COMBINE_MODE COMBINE_MODE);
+
+ ///
+ /// 合并两个区域,取它们的联合部分(即最大边界区域)。
+ ///
+ static void Union(Geometry& out, const Geometry& a, const Geometry& b) {
+ Combine(out, a, b, D2D1_COMBINE_MODE::D2D1_COMBINE_MODE_UNION);
+ }
+
+ ///
+ /// 获取两个区域的交集部分。
+ ///
+ static void Intersect(Geometry& out, const Geometry& a, const Geometry& b) {
+ Combine(out, a, b, D2D1_COMBINE_MODE::D2D1_COMBINE_MODE_INTERSECT);
+ }
+
+ ///
+ /// 合并两个区域,保留不重叠的部分(异或运算)。
+ ///
+ static void Xor(Geometry& out, const Geometry& a, const Geometry& b) {
+ Combine(out, a, b, D2D1_COMBINE_MODE::D2D1_COMBINE_MODE_XOR);
+ }
+
+ ///
+ /// 从第一个区域中排除第二个区域的部分(差集)。
+ ///
+ static void Exclude(Geometry& out, const Geometry& a, const Geometry& b) {
+ Combine(out, a, b, D2D1_COMBINE_MODE::D2D1_COMBINE_MODE_EXCLUDE);
+ }
+ };
+
+ //矩形(已经完成闭合)
+ class UI_EXPORT RectangleGeometry :public Geometry {
+ private:
+ void Create(float x, float y, float width, float height, float _radius);
+ public:
+ RectangleGeometry(float x, float y, float width, float height, float _radius = 0);
+ RectangleGeometry(const RectF& _rect, float radius = 0);
+ RectangleGeometry(const RectF& _rect, float topLeftRadius, float topRightRadius, float bottomRightRadius, float bottomLeftRadius);
+ virtual ~RectangleGeometry() {};
+ };
+
+ //扇形(已经完成闭合)
+ class UI_EXPORT PieGeometry :public Geometry {
+ public:
+ PieGeometry(const RectF& rectF, float startAngle, float endAngle);
+ virtual ~PieGeometry() {};
+ };
+
+ //圆形/椭圆(已经完成闭合)
+ class UI_EXPORT EllipseGeometry :public PieGeometry {
+ public:
+ EllipseGeometry(const RectF& rectF) :PieGeometry(rectF, 0, 360) {}
+ virtual ~EllipseGeometry() {};
+ };
+
+ class UI_EXPORT DXImage : public IImage {
+ struct GifFrame
+ {
+ IWICBitmap* wicBitmap; // 存一份完整帧
+ UINT delay;
+ };
+ protected:
+ std::vector m_frames;
+ IWICBitmapDecoder* m_bitmapdecoder = NULL;
+ IWICBitmapFrameDecode* m_pframe = NULL;
+ IWICFormatConverter* m_fmtcovter = NULL;//从文件加载
+ IWICBitmap* m_bitMap = NULL;//从HBITMAP中加载
+ int m_width = 0;
+ int m_height = 0;
+ ID2D1Bitmap* m_d2dBitmap = NULL;
+ private:
+ void CreateFormStream(IStream* istram);
+ void CreateFromFile(const std::wstring& file);
+ void Init();
+ public:
+ bool Visible = true;
+ void DecodeOfRender(ID2D1RenderTarget* render);
+ //如果HBITMAP带有透明通道 确保传入的图像颜色值已经与 Alpha 通道预乘
+ DXImage(HBITMAP hBitmap);
+ DXImage(IStream* istram);
+ DXImage(const std::wstring& file);
+ //创建带预乘Alpha的BGRA图片
+ DXImage(int width, int height);
+ DXImage(const void* data, size_t count);
+ ID2D1Bitmap* Get();
+ IWICBitmap* GetIWICBitmap();
+ int Width();
+ int Height();
+ virtual WORD NextFrame()override;
+ DXImage* Clone();
+ virtual ~DXImage();
+ };
+
+ class Bezier {
+ public:
+ Point point1;
+ Point point2;
+ Point point3;
+ };
+};
+
+namespace ezui {
+
+ class UI_EXPORT DXRender {
+ private:
+ ID2D1DCRenderTarget* m_render = NULL;
+ ID2D1SolidColorBrush* m_brush = NULL;
+ Font* m_font = NULL;
+ ID2D1StrokeStyle* m_pStrokeStyle = NULL;
+ Point m_offset;
+ PointF m_rotatePoint;
+ float m_angle = 0;
+ private:
+ DXRender(const DXRender& rightValue) = delete;
+ public:
+ ID2D1SolidColorBrush* GetBrush();
+ ID2D1StrokeStyle* GetStrokeStyle();
+ public:
+ DXRender(DXImage* dxImage);
+ DXRender(HDC dc, int x, int y, int width, int height);//创建dx绘图对象
+ virtual ~DXRender();
+ void SetFont(const std::wstring& fontFamily, float fontSize);//必须先调用
+ void SetFont(const Font& _copy_font);//必须先调用
+ void SetColor(const __EzUI__Color& color);//会之前必须调用
+ void SetStrokeStyle(StrokeStyle strokeStyle = StrokeStyle::Solid);//设置样式 虚线/实线
+ void DrawTextLayout(const TextLayout& textLayout, const PointF & = { 0,0 });//根据已有的布局绘制文字
+ void DrawString(const std::wstring& text, const RectF& _rect, ezui::TextAlign textAlign);//绘制文字
+ void DrawLine(const PointF& _A, const PointF& _B, float width = 1);//绘制一条线
+ void DrawRectangle(const RectF& _rect, float _radius = 0, float width = 1);//绘制矩形
+ void FillRectangle(const RectF& _rect, float _radius = 0);
+ //填充矩形
+ void PushLayer(const Geometry& dxGeometry);
+ void PopLayer();
+ void PushAxisAlignedClip(const RectF& rectBounds);
+ void PopAxisAlignedClip();
+ void SetTransform(float offsetX, float offsetY);//对画布进行旋转和偏移
+ void SetTransform(float startX, float startY, float angle);//设置旋转起始点与旋转角度
+ void SetTransform(float offsetX, float offsetY, float startX, float startY, float angle);
+ void DrawImage(DXImage* _image, const RectF& tagRect, float opacity = 1);//绘制图像
+ void DrawBezier(const PointF& startPoint, const Bezier& points, float width = 1);//贝塞尔线
+ void DrawBezier(const PointF& startPoint, std::list& points, float width = 1);//贝塞尔线
+ void DrawEllipse(const RectF& rectF, float width = 1);
+ void FillEllipse(const RectF& rectF);
+ void DrawPie(const RectF& rectF, float startAngle, float endAngle, float strokeWidth = 1);
+ void FillPie(const RectF& rectF, float startAngle, float endAngle);
+ void DrawPoint(const PointF& pt);
+ void DrawArc(const RectF& rect, float startAngle, float sweepAngle, float width = 1);//未实现
+ void DrawArc(const PointF& point1, const PointF& point2, const PointF& point3, float width = 1);
+ void DrawGeometry(ID2D1Geometry* path, float width = 1);
+ void FillGeometry(ID2D1Geometry* path);
+ void DrawGeometry(Geometry* path, float width = 1);
+ void FillGeometry(Geometry* path);
+ void Flush();
+ ID2D1DCRenderTarget* Get();//获取原生DX对象
+ };
+};
+#endif
\ No newline at end of file
diff --git a/demo/Adminstor/ThirdParty/EzUI/include/EzUI/EzUI.h b/demo/Adminstor/ThirdParty/EzUI/include/EzUI/EzUI.h
new file mode 100644
index 0000000..cc19161
--- /dev/null
+++ b/demo/Adminstor/ThirdParty/EzUI/include/EzUI/EzUI.h
@@ -0,0 +1,530 @@
+/*/
+Author:yang
+Email:19980103ly@gmail.com/718987717@qq.com
+*/
+
+#pragma once
+
+#include "UIDef.h"
+#include "UIString.h"
+#include "Resource.h"
+#include "RenderTypes.h"
+#include "Direct2DRender.h"
+
+#undef LoadCursor
+#undef LoadIcon
+
+namespace ezui {
+ struct MonitorInfo;
+ class Object;
+ class EventArgs;
+ class ControlStyle;
+ class IFrame;
+ class Control;
+ class Window;
+ class Spacer;
+ class ScrollBar;
+ class Bitmap;
+ enum class Cursor :ULONG_PTR;
+
+#if 1
+ typedef std::vector Controls;
+#else
+ class UI_EXPORT Controls :public std::list {
+ public:
+ //不要频繁使用此函数
+ inline Control* operator[](size_t right_pos)const
+ {
+ size_t pos = 0;
+ for (auto& it : *this) {
+ if (pos == right_pos) {
+ return it;
+ }
+ ++pos;
+ }
+ return NULL;
+ }
+ };
+#endif
+
+ //全局资源句柄
+ extern UI_VAR_EXPORT HMODULE __EzUI__HINSTANCE;//全局实例
+ extern UI_VAR_EXPORT Resource* __EzUI__Resource;//文件中的全局资源句柄
+ extern UI_VAR_EXPORT DWORD __EzUI__ThreadId;//UI的线程Id
+ extern UI_VAR_EXPORT HWND __EzUI_MessageWnd;//用于UI通讯的隐形窗口
+ extern UI_VAR_EXPORT const std::list __EzUI__MonitorInfos;//所有监视器信息
+
+ //判断两个float是相等(两数是否接近)
+ extern UI_EXPORT bool IsFloatEqual(float num1, float num2);
+ //加载HICON
+ extern UI_EXPORT HICON LoadIcon(const UIString& fileName);
+ //装载字体
+ extern UI_EXPORT void InstallFont(const UIString& fontFileName);
+ //卸载字体
+ extern UI_EXPORT void UnstallFont(const UIString& fontFileName);
+ //复制内容到剪切板
+ extern UI_EXPORT bool CopyToClipboard(int uFormat, void* pData, size_t size, HWND hWnd = NULL);
+ //打开剪切板
+ extern UI_EXPORT bool GetClipboardData(int uFormat, std::function Callback, HWND hWnd = NULL);
+ //复制unicode文字
+ extern UI_EXPORT bool CopyToClipboard(const std::wstring& str, HWND hWnd = NULL);
+ //粘贴unicode文字
+ extern UI_EXPORT bool GetClipboardData(std::wstring* outStr, HWND hWnd = NULL);
+ //自动获取文件资源(本地文件/资源文件)
+ extern UI_EXPORT bool GetResource(const UIString& fileName, std::string* outData);
+ //获取当前所有监视器的信息
+ extern UI_EXPORT size_t GetMonitor(std::list* outMonitorInfo);
+ //获取用户当前所在的显示器
+ extern UI_EXPORT void GetMontior(MonitorInfo* outInfo, HWND hWnd = NULL);
+ //使用窗口的矩形位置获取所在的显示器
+ extern UI_EXPORT void GetMontior(MonitorInfo* outInfo, const Rect& rect);
+ //加载光标
+ extern UI_EXPORT HCURSOR LoadCursor(Cursor cursorType);
+ //加载光标(//需要释放)
+ extern UI_EXPORT HCURSOR LoadCursor(const UIString& fileName);
+ //释放光标
+ extern UI_EXPORT void FreeCursor(HCURSOR hCursor);
+ //默认处理OnNotify函数(处理一些控件的基础行为)
+ extern UI_EXPORT void DefaultNotify(Control* sender, EventArgs& args);
+
+ class UI_EXPORT Color :public ezui::__EzUI__Color {
+ public:
+ Color(const ezui::__EzUI__Color& copy) { this->BGRA = copy.GetValue(); }
+ Color(const DWORD& rgba = 0) :ezui::__EzUI__Color(rgba) {}
+ Color(BYTE r, BYTE g, BYTE b, BYTE a = 255) :ezui::__EzUI__Color(r, g, b, a) {}
+ public:
+ //构建一个Color
+ static Color Make(const UIString& colorStr, bool* isGood = NULL);
+ virtual ~Color() {}
+ };
+
+#if USED_DIRECT2D
+ class UI_EXPORT Image :public DXImage {
+ private:
+#ifdef _DEBUG
+ UIString m_path;
+#endif
+ public:
+ virtual ~Image() {}
+ //创建带预乘Alpha的BGRA图片
+ Image(int width, int height) :DXImage(width, height) {}
+ Image(HBITMAP hBitmap) :DXImage(hBitmap) {}
+ Image(Bitmap* bitmap);
+ Image(IStream* iStream) :DXImage(iStream) {}
+ Image(const std::wstring& fileName) :DXImage(fileName) {}
+ Image(const void* data, size_t dataCount) :DXImage(data, dataCount) {}
+ public:
+ //从资源或者本地文件自动构建一个Image
+ static Image* Make(const UIString& fileOrRes);
+ };
+#endif
+ // 定义用于保存显示器信息的结构体
+ struct MonitorInfo {
+ HMONITOR Monitor = NULL;
+ //显示器的位置 多显示器下Y轴可能出现负数或者大于0的时候代表显示器在设置里面显示器是错位的(多显示器没有平行);
+ //逻辑宽高
+ ezui::Rect Rect;
+ //工作区域
+ ezui::Rect WorkRect;
+ //显示器物理宽高
+ Size Physical;
+ //显示器缩放比例 1.0 1.25 1.5 1.75 2.0
+ float Scale = 1.0f;
+ //显示器帧率
+ float FPS = 60;
+ //是否为主显示器
+ bool Primary = false;
+ };
+ struct WindowData {
+ //缩放率
+ float Scale = 1.0f;
+ //单次绘图数量
+ int PaintCount = 0;
+#ifdef _DEBUG
+ //是否开启debug模式
+ bool Debug = false;
+ //调试模式下的特有字段
+ int ColorIndex = 0;
+ Color DebugColor;
+ std::vector DebugColors{ Color::Red,Color::Green,Color::Blue,Color::Black,Color::White };
+#endif
+ //主窗类的实例
+ ezui::Window* Window = NULL;
+ //使一个区域无效
+ std::function InvalidateRect = NULL;
+ //立即更新全部无效区域
+ std::function Refresh = NULL;
+ //清空控件标记等等...
+ std::function CleanControl = NULL;
+ //内部移动窗口的函数
+ std::function MoveWindow = NULL;
+ //内部使用标题部分移动窗口的函数
+ std::function TitleMoveWindow = NULL;
+ //处理消息过程的回调函数
+ std::function WndProc = NULL;
+
+#ifdef _DEBUG
+ virtual ~WindowData() {
+ }
+#endif
+
+ };
+
+ enum class LayoutState {
+ //无状态 (无需布局)
+ None,
+ //挂起中
+ Pend,
+ //布局中
+ Layouting
+ };
+ enum Event :long long {
+ None = 1,
+ OnMouseWheel = 2,
+ OnMouseEnter = 4,
+ OnMouseMove = 8,
+ OnMouseLeave = 16,
+ OnMouseDoubleClick = 32,
+ OnMouseDown = 64,
+ OnMouseUp = 128,
+ OnKeyDown = 256,
+ OnKeyUp = 512,
+ OnPaint = 1024,
+ OnFocus = 2048,
+ OnKillFocus = 4096,
+ OnKeyChar = 8192,
+ OnMove = 16384,
+ OnSize = 32768,
+ OnRect = 65536,
+ OnDpiChange = 131072,
+ OnActive = OnMouseDown | OnMouseUp,
+ OnHover = OnMouseEnter | OnMouseLeave,
+ OnMouseDrag = OnMouseDown | OnMouseMove,
+ OnMouseEvent = OnMouseWheel | OnMouseEnter | OnMouseMove | OnMouseLeave | OnMouseDoubleClick | OnMouseDown | OnMouseUp,
+ OnKeyBoardEvent = OnKeyDown | OnKeyUp | OnKeyChar
+ };
+ //重载枚举的 | 运算符
+ inline Event operator|(Event left, Event right)
+ {
+ return static_cast(static_cast(left) | static_cast(right));
+ }
+ //控件行为
+ enum class ControlAction {
+ None,
+ Title,//具有移动窗口 双击最大化窗口的行为
+ MoveWindow,//移动窗口
+ Mini,//最小化
+ Max,//最大化|恢复
+ Close//关闭
+ };
+ enum class ControlState :int {
+ None = 1,//无状态 则是使用_nowStyle缓存样式
+ Static = 2,//静态
+ Disabled = 4,//禁用状态
+ Checked = 8,//选中状态
+ Hover = 16,//鼠标悬浮
+ Active = 32//鼠标按住
+ };
+ EZUI_ENUM_OPERATORS(ControlState, int);
+
+ enum class DockStyle {
+ // 摘要:
+ //未设置
+ None,
+ // 摘要:
+ //在父控件中 左右保持
+ Horizontal,
+ // 摘要:
+ //在父控件中 上下保持
+ Vertical,
+ // 摘要:
+ // 铺满整个父控件
+ Fill
+ };
+ enum class MouseButton {
+ // 摘要:
+ // 未曾按下鼠标按钮。
+ None,
+ //
+ // 摘要:
+ // 鼠标左按钮曾按下。
+ Left,
+ //
+ // 摘要:
+ // 鼠标右按钮曾按下。
+ Right,
+ //
+ // 摘要:
+ // 鼠标中按钮曾按下。
+ Middle,
+ //
+ // 摘要:
+ // 第 1 个 XButton 曾按下。
+ XButton1,
+ //
+ // 摘要:
+ // 第 2 个 XButton 曾按下。
+ XButton2
+ };
+ enum class Cursor :ULONG_PTR
+ {
+ None = 0,//未指定
+ APPSTARTING = (ULONG_PTR)IDC_APPSTARTING,// 标准的箭头和小沙漏
+ ARROW = (ULONG_PTR)IDC_ARROW,// 标准的箭头
+ CROSS = (ULONG_PTR)IDC_CROSS,// 十字光标
+ HAND = (ULONG_PTR)IDC_HAND,// Windows 98/Me, Windows 2000/XP: Hand
+ HELP = (ULONG_PTR)IDC_HELP,// 标准的箭头和问号
+ IBEAM = (ULONG_PTR)IDC_IBEAM,// 工字光标
+ ICON = (ULONG_PTR)IDC_ICON,// Obsolete for applications marked version 4.0 or later.
+ NO = (ULONG_PTR)IDC_NO,// 禁止圈
+ SIZE = (ULONG_PTR)IDC_SIZE,// Obsolete for applications marked version 4.0 or later. Use SIZEALL.
+ SIZEALL = (ULONG_PTR)IDC_SIZEALL,// 四向箭头指向东、西、南、北
+ SIZENESW = (ULONG_PTR)IDC_SIZENESW,// 双箭头指向东北和西南
+ SIZENS = (ULONG_PTR)IDC_SIZENS, // 双箭头指向南北
+ SIZENWSE = (ULONG_PTR)IDC_SIZENWSE,// 双箭头指向西北和东南
+ SIZEWE = (ULONG_PTR)IDC_SIZEWE,// 双箭头指向东西
+ UPARROW = (ULONG_PTR)IDC_UPARROW,// 垂直箭头
+ WAIT = (ULONG_PTR)IDC_WAIT// 沙漏,Windows7下会显示为选择的圆圈表示等待
+ };
+
+ //基础事件
+ class UI_EXPORT EventArgs {
+ public:
+ Event EventType = Event::None;
+ EventArgs(Event eventType) {
+ this->EventType = eventType;
+ }
+ virtual ~EventArgs() {};
+ };
+ //为鼠标事件提供基础数据
+ class UI_EXPORT MouseEventArgs :public EventArgs {
+ public:
+ MouseButton Button = MouseButton::None;
+ int ZDelta = 0;//方向
+ Point Location;
+ public:
+ MouseEventArgs(Event eventType, const Point& location = Point(0, 0), MouseButton mouseButton = MouseButton::None, int ZDelta = 0) :EventArgs(eventType) {
+ this->Button = mouseButton;
+ this->Location = location;
+ this->ZDelta = ZDelta;
+ }
+ virtual ~MouseEventArgs() {}
+ };
+ // 摘要:
+ //为键盘事件提供基础数据
+ class UI_EXPORT KeyboardEventArgs :public EventArgs {
+ public:
+ ///
+ /// 一般是指 键盘的ascii值
+ ///
+ WPARAM wParam;
+ LPARAM lParam;
+ KeyboardEventArgs(Event eventType, WPARAM wParam, LPARAM lParam) :EventArgs(eventType) {
+ this->wParam = wParam;
+ this->lParam = lParam;
+ }
+ virtual ~KeyboardEventArgs() {}
+ };
+ //获取焦点
+ class UI_EXPORT FocusEventArgs :public EventArgs {
+ public:
+ Control* Control;
+ FocusEventArgs(ezui::Control* ctl) :EventArgs(Event::OnFocus) {
+ this->Control = ctl;
+ }
+ virtual ~FocusEventArgs() {}
+ };
+ //失去焦点
+ class UI_EXPORT KillFocusEventArgs :public EventArgs {
+ public:
+ Control* Control;
+ KillFocusEventArgs(ezui::Control* ctl) :EventArgs(Event::OnKillFocus) {
+ this->Control = ctl;
+ }
+ virtual ~KillFocusEventArgs() {}
+ };
+ //坐标发生改变
+ class UI_EXPORT MoveEventArgs :public EventArgs {
+ public:
+ const ezui::Point Location;
+ MoveEventArgs(const ezui::Point& location) :EventArgs(Event::OnMove), Location(location) {}
+ virtual ~MoveEventArgs() {}
+ };
+ //大小发生改变
+ class UI_EXPORT SizeEventArgs :public EventArgs {
+ public:
+ const ezui::Size Size;
+ SizeEventArgs(const ezui::Size& size) :EventArgs(Event::OnSize), Size(size) {}
+ virtual ~SizeEventArgs() {}
+ };
+ //dpi发生变化
+ class UI_EXPORT DpiChangeEventArgs :public EventArgs {
+ public:
+ float Scale = 1.0f;
+ DpiChangeEventArgs(float scale) :EventArgs(Event::OnDpiChange), Scale(scale) {}
+ virtual ~DpiChangeEventArgs() {}
+ };
+ // 为 OnPaint 事件提供数据。
+ class UI_EXPORT PaintEventArgs :public EventArgs {
+ private:
+ std::list m_layers;
+ std::list m_offsets;
+ public:
+ PaintEventArgs(const PaintEventArgs&) = delete;
+ PaintEventArgs& operator=(const PaintEventArgs&) = delete;
+ WindowData* PublicData = NULL;
+ ::HWND HWND = NULL;
+ HDC DC = NULL;
+ ezui::DXRender& Graphics;//画家
+ Rect InvalidRectangle;//WM_PAINT里面的无效区域
+ PaintEventArgs(ezui::DXRender& _painter) : EventArgs(Event::OnPaint), Graphics(_painter) {}
+ virtual ~PaintEventArgs() {}
+ //添加裁剪(速度较快)
+ void PushLayer(const Rect& rectBounds);
+ //添加异形裁剪 比较耗性能,但是可以异形抗锯齿裁剪
+ void PushLayer(const Geometry& dxGeometry);
+ //弹出最后一个裁剪
+ void PopLayer();
+ //放入一个偏移
+ void PushOffset(const Point& offset);
+ //弹出最后一个偏移
+ void PopOffset();
+ };
+ // 为控件样式提供数据。
+ class UI_EXPORT ControlStyle {
+ public:
+ //边框信息
+ ezui::Border Border;
+ //整体不透明度
+ //UI_Float Opacity;
+ //背景颜色
+ Color BackColor = 0;
+ //背景图片 如果指定的图片被删除 请必须将此置零
+ Image* BackImage = NULL;
+ //前景图片 如果指定的图片被删除 请必须将此置零
+ Image* ForeImage = NULL;
+ //字体名称 具有继承性
+ std::wstring FontFamily;
+ //字体大小 具有继承性
+ int FontSize = 0;
+ //前景颜色 具有继承性
+ Color ForeColor;
+ //鼠标样式
+ HCURSOR Cursor = NULL;
+ //旋转范围 0~360
+ float Angle = 0;
+ private:
+ void operator=(const ControlStyle& right) {} //禁止直接赋值 因为这样会导致 Color执行拷贝使得Color变得不合法的有效
+ ControlStyle(const ControlStyle& right) {} //禁止拷贝
+ public:
+ ControlStyle() {}
+ virtual ~ControlStyle() {}
+ void Scale(float scale);
+ };
+
+ //指针管理
+ template
+ class PtrManager {
+ private:
+ std::vector m_ptrs;
+ public:
+ PtrManager() {}
+ virtual ~PtrManager() {
+ for (auto& obj : m_ptrs) {
+ delete obj;
+ }
+ }
+ void Add(const T& v) {
+ if (v) {
+ m_ptrs.push_back(v);
+ }
+ }
+ void Remove(const T& v/*, bool bFree = false*/) {
+ auto it = std::find(m_ptrs.begin(), m_ptrs.end(), v);
+ if (it != m_ptrs.end()) {
+ /*if (bFree) {
+ delete(*it);
+ }*/
+ m_ptrs.erase(it);
+ }
+ }
+ void Clear() {
+ for (auto& obj : m_ptrs) {
+ delete obj;
+ }
+ m_ptrs.clear();
+ }
+ };
+
+ //常用对象基类
+ class UI_EXPORT Object {
+ private:
+ //属性集合
+ std::map m_attrs;
+ // 管理子对象的释放
+ PtrManager