initial commit
This commit is contained in:
77
.gitignore
vendored
Normal file
77
.gitignore
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
# 编译生成文件
|
||||
*.exe
|
||||
*.ilk
|
||||
*.obj
|
||||
*.pdb
|
||||
*.o
|
||||
*.a
|
||||
*.lib
|
||||
*.dll
|
||||
*.exp
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# 构建目录
|
||||
build/
|
||||
bin/
|
||||
obj/
|
||||
Debug/
|
||||
Release/
|
||||
x64/
|
||||
x86/
|
||||
Win32/
|
||||
|
||||
# Visual Studio 文件
|
||||
.vs/
|
||||
*.sln
|
||||
*.vcxproj
|
||||
*.vcxproj.filters
|
||||
*.vcxproj.user
|
||||
*.suo
|
||||
*.ncb
|
||||
*.user
|
||||
*.sdf
|
||||
ipch/
|
||||
*.aps
|
||||
*.res
|
||||
*.tlog
|
||||
*.lastbuildstate
|
||||
*.idb
|
||||
*.pch
|
||||
|
||||
# CMake 生成文件
|
||||
CMakeFiles/
|
||||
CMakeCache.txt
|
||||
cmake_install.cmake
|
||||
Makefile
|
||||
*.cmake
|
||||
*.cmake.*
|
||||
CTestTestfile.cmake
|
||||
Testing/
|
||||
_deps/
|
||||
|
||||
# 文档生成
|
||||
docs/html/
|
||||
docs/latex/
|
||||
docs/man/
|
||||
docs/rtf/
|
||||
docs/xml/
|
||||
|
||||
# 临时文件
|
||||
*.tmp
|
||||
*.temp
|
||||
*.log
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# EasyX 临时文件
|
||||
*.jpg
|
||||
*.bmp
|
||||
*.png
|
||||
*.tga
|
||||
|
||||
# 其他
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
28
CHANGELOG.md
Normal file
28
CHANGELOG.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# 更新日志
|
||||
|
||||
StellarX 项目所有显著的变化都将被记录在这个文件中。
|
||||
|
||||
格式基于 [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
并且本项目遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
|
||||
|
||||
## [1.0.0] - 2025-09-06
|
||||
|
||||
### 新增
|
||||
- StellarX 框架的第一个稳定版本
|
||||
- 完整的控件库:按钮、标签、文本框、画布、表格和窗口
|
||||
- 基于 CMake 的构建系统
|
||||
- 详细的文档和示例代码
|
||||
- **明确声明:本框架专为 Windows 平台设计**
|
||||
|
||||
### 核心特性
|
||||
- 模块化设计,遵循 SOLID 原则
|
||||
- 统一的控件接口(draw() 和 handleEvent())
|
||||
- 支持多种控件形状和样式
|
||||
- 自定义事件处理回调
|
||||
- 轻量级设计,无外部依赖
|
||||
|
||||
## [0.1.0] - 2025-08-15
|
||||
### 新增
|
||||
- 初始项目结构和核心架构
|
||||
- Control 基类和基本事件处理系统
|
||||
- 基础示例和文档设置
|
||||
130
CMakeLists.txt
Normal file
130
CMakeLists.txt
Normal file
@@ -0,0 +1,130 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
project(StellarX VERSION 1.0.0 LANGUAGES CXX)
|
||||
|
||||
# 设置C++标准
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
# Windows特定设置
|
||||
if(WIN32)
|
||||
add_definitions(-DWIN32 -D_WINDOWS)
|
||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
||||
|
||||
# 设置Windows子系统
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS")
|
||||
endif()
|
||||
|
||||
# 设置输出目录
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||
|
||||
# 包含目录
|
||||
include_directories(include)
|
||||
|
||||
# Windows API库
|
||||
if(WIN32)
|
||||
find_library(GDI32_LIBRARY gdi32)
|
||||
find_library(USER32_LIBRARY user32)
|
||||
find_library(KERNEL32_LIBRARY kernel32)
|
||||
set(WIN32_LIBS ${GDI32_LIBRARY} ${USER32_LIBRARY} ${KERNEL32_LIBRARY})
|
||||
endif()
|
||||
|
||||
# 创建库
|
||||
file(GLOB_RECURSE SOURCES "src/*.cpp")
|
||||
add_library(StellarX STATIC ${SOURCES})
|
||||
|
||||
# 链接Windows库
|
||||
if(WIN32)
|
||||
target_link_libraries(StellarX ${WIN32_LIBS})
|
||||
endif()
|
||||
|
||||
# 设置库属性
|
||||
set_target_properties(StellarX PROPERTIES
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION 1
|
||||
PUBLIC_HEADER "include/StellarX/StellarX.h"
|
||||
OUTPUT_NAME "StellarX"
|
||||
)
|
||||
|
||||
# 安装规则
|
||||
install(DIRECTORY include/StellarX DESTINATION include)
|
||||
install(TARGETS StellarX
|
||||
ARCHIVE DESTINATION lib
|
||||
LIBRARY DESTINATION lib
|
||||
RUNTIME DESTINATION bin
|
||||
PUBLIC_HEADER DESTINATION include/StellarX
|
||||
)
|
||||
|
||||
# 示例程序
|
||||
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/examples)
|
||||
file(GLOB EXAMPLE_SOURCES "examples/*.cpp")
|
||||
foreach(example_source ${EXAMPLE_SOURCES})
|
||||
get_filename_component(example_name ${example_source} NAME_WE)
|
||||
add_executable(${example_name} ${example_source})
|
||||
target_link_libraries(${example_name} StellarX ${WIN32_LIBS})
|
||||
|
||||
# 设置Windows子系统
|
||||
if(WIN32)
|
||||
set_target_properties(${example_name} PROPERTIES
|
||||
LINK_FLAGS "/SUBSYSTEM:WINDOWS"
|
||||
)
|
||||
endif()
|
||||
|
||||
# 安装示例
|
||||
install(TARGETS ${example_name} DESTINATION bin)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# 文档生成选项
|
||||
option(BUILD_DOCS "Build documentation" OFF)
|
||||
if(BUILD_DOCS)
|
||||
find_package(Doxygen)
|
||||
if(Doxygen_FOUND)
|
||||
set(DOXYGEN_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/docs)
|
||||
set(DOXYGEN_USE_MDFILE_AS_MAINPAGE ${CMAKE_CURRENT_SOURCE_DIR}/README.md)
|
||||
set(DOXYGEN_PROJECT_NAME "StellarX GUI Framework")
|
||||
set(DOXYGEN_PROJECT_NUMBER ${PROJECT_VERSION})
|
||||
set(DOXYGEN_PROJECT_BRIEF "A lightweight, modular C++ GUI framework for Windows")
|
||||
set(DOXYGEN_INPUT ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
set(DOXYGEN_RECURSIVE YES)
|
||||
set(DOXYGEN_EXTRACT_ALL YES)
|
||||
set(DOXYGEN_EXTRACT_PRIVATE YES)
|
||||
set(DOXYGEN_EXTRACT_STATIC YES)
|
||||
set(DOXYGEN_SOURCE_BROWSER YES)
|
||||
set(DOXYGEN_GENERATE_TREEVIEW YES)
|
||||
set(DOXYGEN_HAVE_DOT YES)
|
||||
set(DOXYGEN_CALL_GRAPH YES)
|
||||
set(DOXYGEN_CALLER_GRAPH YES)
|
||||
|
||||
doxygen_add_docs(
|
||||
docs
|
||||
${DOXYGEN_INPUT}
|
||||
COMMENT "Generate HTML documentation"
|
||||
)
|
||||
|
||||
install(DIRECTORY ${DOXYGEN_OUTPUT_DIRECTORY}/html DESTINATION docs)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# 打包配置
|
||||
include(InstallRequiredSystemLibraries)
|
||||
set(CPACK_PACKAGE_NAME ${PROJECT_NAME})
|
||||
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
|
||||
set(CPACK_PACKAGE_DESCRIPTION "A lightweight, modular C++ GUI framework for Windows")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "星垣 (StellarX) - A lightweight Windows GUI framework")
|
||||
set(CPACK_PACKAGE_VENDOR "StellarX Development Team")
|
||||
set(CPACK_PACKAGE_CONTACT "contact@stellarx.dev")
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
|
||||
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "StellarX")
|
||||
set(CPACK_NSIS_MODIFY_PATH ON)
|
||||
|
||||
if(WIN32)
|
||||
set(CPACK_GENERATOR "ZIP;NSIS")
|
||||
else()
|
||||
set(CPACK_GENERATOR "ZIP")
|
||||
endif()
|
||||
|
||||
include(CPack)
|
||||
93
CONTRIBUTING.md
Normal file
93
CONTRIBUTING.md
Normal file
@@ -0,0 +1,93 @@
|
||||
# 为 StellarX 做贡献
|
||||
|
||||
感谢您有兴趣为 StellarX 做出贡献!本文档提供了贡献的指南和步骤。
|
||||
|
||||
StellarX 是一个为 **Windows 平台**打造的 C++ GUI 框架,基于 EasyX 图形库。
|
||||
|
||||
## 开发环境设置
|
||||
|
||||
1. 安装 Visual Studio 2019 或更高版本
|
||||
2. 安装对应版本的 EasyX 图形库
|
||||
3. 安装 CMake 3.12 或更高版本
|
||||
4. 克隆项目仓库
|
||||
5. 使用 CMake 生成解决方案并编译
|
||||
|
||||
## 如何贡献
|
||||
|
||||
### 报告错误
|
||||
1. 检查 [Issues](../../issues) 看看这个错误是否已经被报告过。
|
||||
2. 如果没有,请创建一个新的 Issue。
|
||||
3. 使用 "Bug 报告" 模板。
|
||||
4. 提供**清晰的标题和描述**。
|
||||
5. 包括相关的代码片段、截图或重现问题的步骤。
|
||||
|
||||
### 建议功能增强
|
||||
1. 检查现有的 Issue 中是否有你的想法。
|
||||
2. 使用 "功能请求" 模板创建一个新的 Issue。
|
||||
3. 清晰地描述新功能,并解释它为何有用。
|
||||
|
||||
### 提交代码更改 (拉取请求 Pull Requests)
|
||||
1. **Fork** GitHub 上的仓库。
|
||||
2. **Clone** 你 fork 的仓库到本地机器。
|
||||
3. 为你的功能或错误修复创建一个**新分支** (`git checkout -b my-feature-branch`)。
|
||||
4. **进行你的更改**。确保你的代码遵循项目的风格(见下文)。
|
||||
5. **提交你的更改**,并附上清晰描述性的提交信息。
|
||||
6. **Push** 你的分支到你 fork 的 GitHub 仓库 (`git push origin my-feature-branch`)。
|
||||
7. 针对原始 StellarX 仓库的 `main` 分支发起一个**拉取请求 (Pull Request)**。
|
||||
|
||||
## 代码风格指南
|
||||
|
||||
* 遵循项目中现有的代码格式和命名约定。
|
||||
* 为变量、函数和类使用有意义的名称。
|
||||
* 在必要时注释你的代码,特别是复杂的逻辑。
|
||||
* 确保你的代码编译时没有警告。
|
||||
* 彻底测试你的更改。
|
||||
* 使用 **4个空格** 进行缩进(不要使用制表符)
|
||||
- 类名使用 **PascalCase**(如 `ClassName`)
|
||||
- 函数和变量使用 **camelCase**(如 `functionName`, `variableName`)
|
||||
- 常量使用 **UPPER_CASE**(如 `CONSTANT_VALUE`)
|
||||
- 成员变量以 **m_** 前缀(如 `m_memberVariable`)
|
||||
- 控件属性使用有意义的名称,避免缩写
|
||||
- 为所有公共接口添加详细的注释
|
||||
- 遵循 RAII 原则管理资源
|
||||
|
||||
## 示例代码风格
|
||||
|
||||
```c++
|
||||
|
||||
// 好的示例
|
||||
class MyControl : public Control {
|
||||
public:
|
||||
MyControl(int x, int y, int width, int height)
|
||||
: Control(x, y, width, height), m_isActive(false) {}
|
||||
|
||||
void draw() override {
|
||||
// 绘制逻辑
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_isActive;
|
||||
};
|
||||
|
||||
// 不好的示例
|
||||
class my_control: public Control{
|
||||
public:
|
||||
my_control(int x,int y,int w,int h):Control(x,y,w,h),active(false){}
|
||||
void Draw() override{
|
||||
// 绘制逻辑
|
||||
}
|
||||
private:
|
||||
bool active;
|
||||
};
|
||||
```
|
||||
|
||||
## 项目结构
|
||||
|
||||
请遵循项目的目录结构:
|
||||
- 头文件放在 `include/StellarX/` 目录
|
||||
- 实现文件放在 `src/` 目录
|
||||
- 示例代码放在 `examples/` 目录
|
||||
|
||||
## 问题?
|
||||
|
||||
如果你有任何问题,可以随时开一个 Issue 或联系维护者。
|
||||
219
Doxyfile
Normal file
219
Doxyfile
Normal file
@@ -0,0 +1,219 @@
|
||||
# Doxyfile 1.9.1
|
||||
|
||||
# 项目相关配置
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = "星垣 (StellarX) GUI Framework"
|
||||
PROJECT_NUMBER = 1.0.0
|
||||
PROJECT_BRIEF = "A lightweight, modular C++ GUI framework for Windows"
|
||||
PROJECT_LOGO =
|
||||
OUTPUT_DIRECTORY = docs
|
||||
CREATE_SUBDIRS = NO
|
||||
ALLOW_UNICODE_NAMES = YES
|
||||
OUTPUT_LANGUAGE = English
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ABBREVIATE_BRIEF =
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
INLINE_INHERITED_MEMB = NO
|
||||
FULL_PATH_NAMES = YES
|
||||
STRIP_FROM_PATH =
|
||||
STRIP_FROM_INC_PATH =
|
||||
SHORT_NAMES = NO
|
||||
JAVADOC_AUTOBRIEF = YES
|
||||
JAVADOC_BANNER = NO
|
||||
QT_AUTOBRIEF = NO
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
INHERIT_DOCS = YES
|
||||
SEPARATE_MEMBER_PAGES = NO
|
||||
TAB_SIZE = 4
|
||||
ALIASES =
|
||||
OPTIMIZE_OUTPUT_FOR_C = NO
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
OPTIMIZE_FOR_FORTRAN = NO
|
||||
OPTIMIZE_OUTPUT_VHDL = NO
|
||||
EXTENSION_MAPPING =
|
||||
MARKDOWN_SUPPORT = YES
|
||||
|
||||
# 构建类型
|
||||
EXTRACT_ALL = YES
|
||||
EXTRACT_PRIVATE = YES
|
||||
EXTRACT_PACKAGE = YES
|
||||
EXTRACT_STATIC = YES
|
||||
EXTRACT_LOCAL_CLASSES = YES
|
||||
EXTRACT_LOCAL_METHODS = NO
|
||||
EXTRACT_ANON_NSPACES = NO
|
||||
HIDE_UNDOC_MEMBERS = NO
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
HIDE_FRIEND_COMPOUNDS = NO
|
||||
HIDE_IN_BODY_DOCS = NO
|
||||
INTERNAL_DOCS = NO
|
||||
CASE_SENSE_NAMES = NO
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
HIDE_COMPOUND_REFERENCE= NO
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
SHOW_GROUPED_MEMB_INC = NO
|
||||
FORCE_LOCAL_INCLUDES = NO
|
||||
INLINE_INFO = YES
|
||||
SORT_MEMBER_DOCS = YES
|
||||
SORT_BRIEF_DOCS = NO
|
||||
SORT_MEMBERS_CTOR_1ST = NO
|
||||
SORT_GROUP_NAMES = YES
|
||||
SORT_BY_SCOPE_NAME = YES
|
||||
STRICT_PROTO_MATCHING = NO
|
||||
GENERATE_TODOLIST = YES
|
||||
GENERATE_TESTLIST = YES
|
||||
GENERATE_BUGLIST = YES
|
||||
GENERATE_DEPRECATEDLIST= YES
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
SHOW_USED_FILES = YES
|
||||
SHOW_FILES = YES
|
||||
SHOW_NAMESPACES = YES
|
||||
FILE_VERSION_FILTER =
|
||||
LAYOUT_FILE =
|
||||
CITE_BIB_FILES =
|
||||
|
||||
# 输入配置
|
||||
INPUT = include src README.md
|
||||
INPUT_ENCODING = UTF-8
|
||||
FILE_PATTERNS = *.h *.hpp *.cpp *.c *.cc *.cxx *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.idl *.ddl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py *.f90 *.f *.for *.vhd *.vhdl *.md
|
||||
RECURSIVE = YES
|
||||
EXCLUDE =
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
EXCLUDE_PATTERNS =
|
||||
EXCLUDE_SYMBOLS =
|
||||
EXAMPLE_PATH = examples
|
||||
EXAMPLE_PATTERNS = *
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
IMAGE_PATH =
|
||||
INPUT_FILTER =
|
||||
FILTER_PATTERNS =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
FILTER_SOURCE_PATTERNS =
|
||||
USE_MDFILE_AS_MAINPAGE = README.md
|
||||
|
||||
# 源代码浏览配置
|
||||
SOURCE_BROWSER = YES
|
||||
INLINE_SOURCES = NO
|
||||
STRIP_CODE_COMMENTS = YES
|
||||
REFERENCED_BY_RELATION = YES
|
||||
REFERENCES_RELATION = YES
|
||||
REFERENCES_LINK_SOURCE = YES
|
||||
SOURCE_TOOLTIPS = YES
|
||||
USE_HTAGS = NO
|
||||
VERBATIM_HEADERS = YES
|
||||
|
||||
# HTML输出配置
|
||||
GENERATE_HTML = YES
|
||||
HTML_OUTPUT = html
|
||||
HTML_FILE_EXTENSION = .html
|
||||
HTML_HEADER =
|
||||
HTML_FOOTER =
|
||||
HTML_STYLESHEET =
|
||||
HTML_EXTRA_STYLESHEET =
|
||||
HTML_EXTRA_FILES =
|
||||
HTML_COLORSTYLE_HUE = 220
|
||||
HTML_COLORSTYLE_SAT = 100
|
||||
HTML_COLORSTYLE_GAMMA = 80
|
||||
HTML_TIMESTAMP = YES
|
||||
HTML_DYNAMIC_SECTIONS = NO
|
||||
HTML_INDEX_NUM_ENTRIES = 100
|
||||
GENERATE_DOCSET = NO
|
||||
DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||
DOCSET_BUNDLE_ID = org.doxygen.Project
|
||||
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
|
||||
DOCSET_PUBLISHER_NAME = Publisher
|
||||
GENERATE_HTMLHELP = NO
|
||||
GENERATE_CHI = NO
|
||||
GENERATE_QHP = NO
|
||||
GENERATE_ECLIPSEHELP = NO
|
||||
DISABLE_INDEX = NO
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
GENERATE_TREEVIEW = YES
|
||||
TREEVIEW_WIDTH = 250
|
||||
EXT_LINKS_IN_WINDOW = NO
|
||||
FORMULA_FONTSIZE = 10
|
||||
FORMULA_TRANSPARENT = YES
|
||||
USE_MATHJAX = NO
|
||||
MATHJAX_FORMAT = HTML-CSS
|
||||
MATHJAX_RELPATH =
|
||||
MATHJAX_EXTENSIONS =
|
||||
MATHJAX_CODEFILE =
|
||||
SEARCHENGINE = YES
|
||||
SERVER_BASED_SEARCH = NO
|
||||
EXTERNAL_SEARCH = NO
|
||||
SEARCHDATA_FILE = searchdata.xml
|
||||
EXTERNAL_SEARCH_ID =
|
||||
EXTRA_SEARCH_MAPPINGS =
|
||||
|
||||
# LaTeX输出配置
|
||||
GENERATE_LATEX = NO
|
||||
|
||||
# RTF输出配置
|
||||
GENERATE_RTF = NO
|
||||
|
||||
# Man page输出配置
|
||||
GENERATE_MAN = NO
|
||||
|
||||
# XML输出配置
|
||||
GENERATE_XML = NO
|
||||
|
||||
# DOCBOOK输出配置
|
||||
GENERATE_DOCBOOK = NO
|
||||
|
||||
# 自动生成配置
|
||||
GENERATE_AUTOGEN_DEF = NO
|
||||
|
||||
# 配置生成器
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = YES
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
SEARCH_INCLUDES = YES
|
||||
INCLUDE_PATH =
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
PREDEFINED = WIN32=1 \
|
||||
_WINDOWS=1 \
|
||||
UNICODE=1 \
|
||||
_UNICODE=1
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
|
||||
# 外部引用
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE =
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
EXTERNAL_PAGES = YES
|
||||
|
||||
# 图表生成
|
||||
CLASS_DIAGRAMS = YES
|
||||
MSCGEN_PATH =
|
||||
DIA_PATH =
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
HAVE_DOT = YES
|
||||
DOT_NUM_THREADS = 0
|
||||
DOT_FONTNAME = Helvetica
|
||||
DOT_FONTSIZE = 10
|
||||
DOT_FONTPATH =
|
||||
CLASS_GRAPH = YES
|
||||
COLLABORATION_GRAPH = YES
|
||||
GROUP_GRAPHS = YES
|
||||
UML_LOOK = NO
|
||||
UML_LIMIT_NUM_FIELDS = 10
|
||||
TEMPLATE_RELATIONS = YES
|
||||
INCLUDE_GRAPH = YES
|
||||
INCLUDED_BY_GRAPH = YES
|
||||
CALL_GRAPH = YES
|
||||
CALLER_GRAPH = YES
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
DIRECTORY_GRAPH = YES
|
||||
DOT_IMAGE_FORMAT = png
|
||||
INTERACTIVE_SVG = NO
|
||||
DOT_PATH =
|
||||
DOTFILE_DIRS =
|
||||
MSCFILE_DIRS =
|
||||
DOT_GRAPH_MAX_NODES = 50
|
||||
MAX_DOT_GRAPH_DEPTH = 0
|
||||
DOT_TRANSPARENT = YES
|
||||
DOT_MULTI_TARGETS = NO
|
||||
GENERATE_LEGEND = YES
|
||||
DOT_CLEANUP = YES
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 我在人间做废物
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
337
README.md
Normal file
337
README.md
Normal file
@@ -0,0 +1,337 @@
|
||||
# 星垣 (StellarX) GUI Framework
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
> **「繁星为界,轻若尘埃」** —— 一个为Windows平台打造的、极致轻量级、高度模块化的C++原生GUI框架。
|
||||
|
||||
`星垣 (StellarX)` 诞生于对现代GUI框架"过度臃肿"的反抗。它拒绝动辄数百MB的依赖、漫长的编译时间和复杂的学习曲线,选择回归本质:用最精简的代码、最清晰的架构和最高的效率,解决桌面应用开发的核心需求。
|
||||
|
||||
它是一个**纯粹的教学级、工具级框架**,旨在让开发者深入理解GUI原理,并快速构建轻量级Windows工具。
|
||||
|
||||
---
|
||||
|
||||
## 📦 项目结构与设计哲学
|
||||
|
||||
星垣框架采用经典的**面向对象**和**模块化**设计,项目结构清晰规范:
|
||||
|
||||
```
|
||||
StellarX/
|
||||
├── include/ # 头文件目录
|
||||
│ └── StellarX/ # 框架头文件
|
||||
│ ├── StellarX.h # 主包含头文件 - 一键引入整个框架
|
||||
│ ├── CoreTypes.h # ★ 核心 ★ - 所有枚举、结构体的唯一定义源
|
||||
│ ├── Control.h # 抽象基类 - 定义所有控件的统一接口
|
||||
│ ├── Button.h # 按钮控件
|
||||
│ ├── Window.h # 窗口管理
|
||||
│ ├── Label.h # 标签控件
|
||||
│ ├── TextBox.h # 文本框控件
|
||||
│ ├── Canvas.h # 画布容器
|
||||
│ └── Table.h # 表格控件
|
||||
├── src/ # 源文件目录
|
||||
│ ├── Control.cpp
|
||||
│ ├── Button.cpp
|
||||
│ ├── Window.cpp
|
||||
│ ├── Label.cpp
|
||||
│ ├── TextBox.cpp
|
||||
│ ├── Canvas.cpp
|
||||
│ └── Table.cpp
|
||||
├── examples/ # 示例代码目录
|
||||
│ └── demo.cpp # 基础演示
|
||||
├── docs/ # 文档目录
|
||||
│ └── CODE_OF_CONDUCT.md # 行为准则
|
||||
├── CMakeLists.txt # CMake 构建配置
|
||||
├── CONTRIBUTING.md # 贡献指南
|
||||
├── CHANGELOG.md # 更新日志
|
||||
├── Doxyfile # Doxygen 配置
|
||||
├── LICENSE # MIT 许可证
|
||||
└── README.md # 项目说明
|
||||
```
|
||||
|
||||
**设计理念:**
|
||||
1. **单一职责原则 (SRP)**: 每个类/文件只负责一件事。
|
||||
2. **依赖倒置原则 (DIP)**: 高层模块(如`Window`)不依赖低层模块(如`Button`),二者都依赖其抽象(`Control`)。
|
||||
3. **开闭原则 (OCP)**: 通过继承`Control`基类,可以轻松扩展新的控件,而无需修改现有代码。
|
||||
4. **一致性**: 所有控件共享统一的`draw()`和`handleEvent()`接口。
|
||||
|
||||
## 🚀 核心特性
|
||||
|
||||
- **极致的轻量级**: 核心库编译后仅 ~1.2MB,无任何外部依赖。生成的应用程序小巧玲珑。
|
||||
- **清晰的模块化架构**: 使用`CoreTypes.h`统一管理所有类型,消除重复定义,极大提升可维护性。
|
||||
- **原生C++性能**: 直接基于EasyX和Win32 API,提供接近原生的执行效率,内存占用极低(通常<10MB)。
|
||||
- **丰富的控件库**: 提供按钮、标签、文本框、表格、画布等常用控件,满足基本桌面应用需求。
|
||||
- **高度可定制化**: 从控件颜色、形状(矩形、圆角、圆形、椭圆)到填充模式、字体样式,均有详尽枚举支持,可轻松定制。
|
||||
- **简洁直观的API**: 采用经典的面向对象设计,代码即文档,学习成本极低。
|
||||
- **标准项目结构**: 采用标准的include/src分离结构,支持CMake构建,易于集成和使用。
|
||||
|
||||
## ⚡ 快速开始(5分钟上手)
|
||||
|
||||
### 环境要求
|
||||
|
||||
- **操作系统**: Windows 10 或更高版本
|
||||
- **编译器**: 支持C++17的编译器 (如: **Visual Studio 2019+**)
|
||||
- **图形库**: [EasyX](https://easyx.cn/) (2022版本或更高,安装时请选择与您编译器匹配的版本)
|
||||
- **构建工具**: CMake 3.12+ (可选,推荐使用)
|
||||
|
||||
### 安装 EasyX
|
||||
1. 访问 [EasyX 官网](https://easyx.cn/) 下载最新版本
|
||||
2. 运行安装程序,选择与您的 Visual Studio 版本匹配的版本
|
||||
3. 安装完成后,无需额外配置,星垣框架会自动链接 EasyX
|
||||
|
||||
### 方法一:使用CMake构建(推荐)
|
||||
|
||||
1. **克隆项目**:
|
||||
```bash
|
||||
git clone https://github.com/Ysm-04/StellarX
|
||||
cd StellarX
|
||||
```
|
||||
|
||||
2. **生成构建系统**:
|
||||
```bash
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
```
|
||||
|
||||
3. **编译项目**:
|
||||
```bash
|
||||
cmake --build .
|
||||
```
|
||||
|
||||
4. **运行示例**:
|
||||
```bash
|
||||
./examples/Demo
|
||||
```
|
||||
|
||||
### 方法二:手动集成到现有项目
|
||||
|
||||
1. **将include和src目录复制**到您的项目中
|
||||
2. **配置包含路径**,确保编译器可以找到`include/StellarX/`目录
|
||||
3. **将所有.cpp文件**添加到您的项目中编译
|
||||
|
||||
### 创建你的第一个星垣应用
|
||||
|
||||
```cpp
|
||||
// 只需包含这一个头文件即可使用所有功能
|
||||
#include "StellarX/StellarX.h"
|
||||
|
||||
// 程序入口点(请使用WinMain以获得更好的兼容性)
|
||||
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd) {
|
||||
|
||||
// 1. 创建一个640x480的窗口,背景为白色,标题为"我的应用"
|
||||
StellarX::Window mainWindow(640, 480, 0, RGB(255, 255, 255), "我的第一个星垣应用");
|
||||
|
||||
// 2. 创建一个按钮 (使用智能指针管理)
|
||||
auto myButton = std::make_unique<StellarX::Button>(
|
||||
250, 200, 140, 40, // x, y, 宽度, 高度
|
||||
"点击我", // 按钮文本
|
||||
StellarX::ButtonMode::NORMAL,
|
||||
StellarX::ControlShape::ROUND_RECTANGLE
|
||||
);
|
||||
|
||||
// 3. 为按钮设置点击事件(使用Lambda表达式)
|
||||
myButton->setOnClickListener([]() {
|
||||
MessageBox(nullptr, L"Hello, 星垣!", L"问候", MB_OK | MB_ICONINFORMATION);
|
||||
});
|
||||
|
||||
// 4. (可选)设置按钮样式
|
||||
myButton->textStyle.nHeight = 20;
|
||||
myButton->textStyle.color = RGB(0, 0, 128); // 深蓝色文字
|
||||
myButton->setButtonBorder(RGB(0, 128, 255)); // 蓝色边框
|
||||
|
||||
// 5. 将按钮添加到窗口
|
||||
mainWindow.addControl(std::move(myButton));
|
||||
|
||||
// 6. 绘制窗口
|
||||
mainWindow.draw();
|
||||
|
||||
// 7. 进入消息循环,等待用户交互
|
||||
mainWindow.runEventLoop();
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
5. **编译并运行!** 您将看到一个带有蓝色圆角按钮的窗口,点击它将会弹出消息框。
|
||||
|
||||
## 📚 核心类型详解 (`CoreTypes.h`)
|
||||
|
||||
星垣框架的所有视觉和行为属性都通过`CoreTypes.h`中定义的精美枚举和结构体来控制。
|
||||
|
||||
### 枚举类型 (Enums)
|
||||
|
||||
| 枚举类型 | 描述 | 常用值 |
|
||||
| :----------------- | :----------- | :----------------------------------------------------------- |
|
||||
| **`ControlShape`** | 控件几何形状 | `RECTANGLE`, `B_RECTANGLE`, `ROUND_RECTANGLE`, `CIRCLE`, `ELLIPSE`等 |
|
||||
| **`ButtonMode`** | 按钮行为模式 | `NORMAL`(普通), `TOGGLE`(切换), `DISABLED`(禁用) |
|
||||
| **`TextBoxMode`** | 文本框模式 | `INPUT_MODE`(输入), `READONLY_MODE`(只读) |
|
||||
| **`FillMode`** | 图形填充模式 | `SOLID`(实心), `NULL`(空心), `HATCHED`(图案)等 |
|
||||
| **`FillStyle`** | 图案填充样式 | `HORIZONTAL`(水平线), `CROSS`(十字线)等 |
|
||||
| **`LineStyle`** | 边框线型 | `SOLID`(实线), `DASH`(虚线), `DOT`(点线)等 |
|
||||
|
||||
### 结构体 (Structs)
|
||||
|
||||
| 结构体 | 描述 |
|
||||
| :---------------- | :----------------------------------------------------------- |
|
||||
| **`ControlText`** | 封装了所有文本样式属性,包括字体、大小、颜色、粗体、斜体、下划线、删除线等。 |
|
||||
|
||||
**使用示例:**
|
||||
```cpp
|
||||
// 创建一个复杂的文本样式
|
||||
StellarX::ControlText myStyle;
|
||||
myStyle.nHeight = 25; // 字体高度
|
||||
myStyle.lpszFace = _T("微软雅黑"); // 字体
|
||||
myStyle.color = RGB(255, 0, 0); // 红色
|
||||
myStyle.nWeight = FW_BOLD; // 粗体
|
||||
myStyle.bUnderline = true; // 下划线
|
||||
|
||||
// 应用于控件
|
||||
myLabel->textStyle = myStyle;
|
||||
myButton->textStyle = myStyle;
|
||||
```
|
||||
|
||||
## 🧩 控件库大全
|
||||
|
||||
### 1. 基础控件
|
||||
|
||||
| 控件 | 头文件 | 描述 | 关键特性 |
|
||||
| :---------- | :---------- | :------------ | :------------------------------------------------------ |
|
||||
| **Button** | `Button.h` | 多功能按钮 | 支持多种模式/形状/状态,可设置悬停/点击颜色,自定义回调 |
|
||||
| **Label** | `Label.h` | 文本标签 | 支持背景透明/不透明,自定义字体样式 |
|
||||
| **TextBox** | `TextBox.h` | 输入框/显示框 | 支持输入和只读模式,集成EasyX的`InputBox` |
|
||||
|
||||
### 2. 容器控件
|
||||
|
||||
| 控件 | 头文件 | 描述 |
|
||||
| :--------- | :--------- | :------------------------------------------------------- |
|
||||
| **Canvas** | `Canvas.h` | 容器控件,可作为其他控件的父容器,支持自定义边框和背景。 |
|
||||
| **Window** | `Window.h` | 顶级窗口,所有控件的最终容器,负责消息循环和调度。 |
|
||||
|
||||
### 3. 高级控件
|
||||
|
||||
| 控件 | 头文件 | 描述 | 关键特性 |
|
||||
| :-------- | :-------- | :------- | :----------------------------------------------------------- |
|
||||
| **Table** | `Table.h` | 数据表格 | **框架功能亮点**,支持分页显示、自定义表头和数据、自动计算列宽、翻页按钮。 |
|
||||
|
||||
**表格控件示例:**
|
||||
```cpp
|
||||
// 创建一个表格
|
||||
auto myTable = std::make_unique<StellarX::Table>(50, 50);
|
||||
|
||||
// 设置表头
|
||||
myTable->setHeaders({ "ID", "姓名", "年龄", "职业" });
|
||||
|
||||
// 添加数据行
|
||||
myTable->addDataRow({ "1", "张三", "25", "工程师" });
|
||||
myTable->addDataRow({ "2", "李四", "30", "设计师" });
|
||||
myTable->addDataRow({ "3", "王五", "28", "产品经理" });
|
||||
|
||||
// 设置每页显示2行
|
||||
myTable->setRowsPerPage(2);
|
||||
|
||||
// 设置表格样式
|
||||
myTable->textStyle.nHeight = 16;
|
||||
myTable->setTableBorder(RGB(50, 50, 50));
|
||||
myTable->setTableBackground(RGB(240, 240, 240));
|
||||
|
||||
// 添加到窗口
|
||||
mainWindow.addControl(std::move(myTable));
|
||||
```
|
||||
|
||||
## 🔧 高级主题与最佳实践
|
||||
|
||||
### 1. 自定义控件
|
||||
您可以通过继承`Control`基类来创建自定义控件。只需实现`draw()`和`handleEvent()`两个纯虚函数即可。
|
||||
|
||||
```cpp
|
||||
class MyCustomControl : public StellarX::Control {
|
||||
public:
|
||||
MyCustomControl(int x, int y) : Control(x, y, 100, 100) {}
|
||||
void draw() override {
|
||||
// 您的自定义绘制逻辑
|
||||
setfillcolor(RGB(255, 100, 100));
|
||||
fillrectangle(x, y, x + width, y + height);
|
||||
}
|
||||
void handleEvent(const ExMessage& msg) override {
|
||||
// 您的自定义事件处理逻辑
|
||||
if (msg.message == WM_LBUTTONDOWN && isInControl(msg.x, msg.y)) {
|
||||
// 处理点击
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### 2. 布局管理
|
||||
当前版本星垣主要采用**绝对定位**。对于简单布局,您可以通过计算坐标来实现。对于复杂布局,可以考虑:
|
||||
- 在`Canvas`中嵌套控件,实现相对定位。
|
||||
- 自行实现简单的流式布局或网格布局管理器。
|
||||
|
||||
### 3. 性能优化
|
||||
- **脏矩形渲染**: 框架内部已实现,控件状态改变时`dirty=true`,仅在需要时重绘。
|
||||
- **图像资源**: 使用`IMAGE`对象加载图片后,可重复使用,避免多次加载。
|
||||
- **减少循环内操作**: 在`draw()`和`handleEvent()`中避免进行重型计算。
|
||||
|
||||
## ⚠️ 重要限制与适用场景
|
||||
|
||||
**星垣框架的设计目标是轻便、清晰和教学价值,因此它明确** **不适用于** **以下场景:**
|
||||
|
||||
- **高性能游戏或复杂动画**: 渲染基于EasyX的CPU软件渲染,性能有限。
|
||||
- **需要高DPI缩放的应用**: 对高DPI显示器的支持有限,界面可能显示不正确。
|
||||
- **需要无障碍功能的应用**: 未提供对屏幕阅读器等辅助技术的支持。
|
||||
- **跨平台应用**: 深度依赖Windows API和EasyX,无法直接在Linux/macOS上运行。
|
||||
- **复杂的商业软件前端**: 缺乏高级控件(如树形图、富文本框、选项卡、高级列表等)和成熟的自动布局管理器。
|
||||
|
||||
**如果您需要开发上述类型的应用,请考虑使用以下成熟方案:**
|
||||
- **Qt**: 功能极其强大,跨平台,适合大型商业应用。
|
||||
- **wxWidgets**: 原生外观,跨平台。
|
||||
- **Dear ImGui**: 即时模式GUI,非常适合工具和调试界面。
|
||||
- **Web技术栈 (Electron/CEF)**: 适合需要Web技术的场景。
|
||||
|
||||
## 📜 许可证 (License)
|
||||
|
||||
本项目采用 **MIT 许可证**。
|
||||
|
||||
您可以自由地:
|
||||
- 使用、复制、修改、合并、出版发行、散布、再授权及销售本框架的副本。
|
||||
- 将其用于私人或商业项目。
|
||||
|
||||
唯一要求是:
|
||||
- 请在您的项目中保留原始的版权声明。
|
||||
|
||||
详见项目根目录的 [LICENSE](LICENSE) 文件。
|
||||
|
||||
## 👥 贡献指南 (Contributing)
|
||||
|
||||
我们欢迎任何形式的贡献!如果您想为星垣框架添砖加瓦,请阅读以下指南:
|
||||
|
||||
1. **代码风格**: 请遵循现有的Google C++规范风格(使用空格缩进,大括号换行等)。
|
||||
2. **新增功能**: 必须提供**示例代码**,并更新本README文档的相关部分。
|
||||
3. **提交PR**: 请确保您的代码在提交前已经过测试,并描述清楚您的更改内容和动机。
|
||||
4. **问题反馈**: 如果您发现了Bug或有新的想法,欢迎在GitHub提交Issue。
|
||||
|
||||
详细贡献指南请参阅 [CONTRIBUTING.md](CONTRIBUTING.md)。
|
||||
|
||||
## 🙏 致谢 (Acknowledgements)
|
||||
|
||||
- 感谢 [EasyX Graphics Library](https://easyx.cn/) 为这个项目提供了简单易用的图形基础,使得用C++教学GUI编程成为可能。
|
||||
- 感谢所有追求**简洁、高效、清晰**编码理念的开发者,你们是"星垣"诞生的灵感源泉。
|
||||
|
||||
---
|
||||
|
||||
**星辰大海,代码为舟。**
|
||||
|
||||
愿 `星垣 (StellarX)` 能成为您探索GUI世界的一颗可靠基石,无论是用于学习、教学还是创造实用的工具。
|
||||
|
||||
## 📞 支持与反馈
|
||||
|
||||
如果您在使用过程中遇到问题或有任何建议:
|
||||
1. 查看 [示例代码](examples/) 获取使用参考
|
||||
2. 查阅 [更新日志](CHANGELOG.md) 了解最新变化
|
||||
3. 在GitHub仓库提交Issue反馈问题
|
||||
|
||||
---
|
||||
*星垣框架 - 轻若尘埃,繁星为界*
|
||||
25
docs/CODE_OF_CONDUCT.md
Normal file
25
docs/CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# 贡献者公约行为准则
|
||||
|
||||
## 我们的承诺
|
||||
|
||||
为了营造一个开放和受欢迎的环境,我们作为贡献者和维护者承诺:无论年龄、体型、身体健全与否、民族、性征、性别认同与表达、经验水平、教育程度、社会地位、国籍、个人外貌、种族、宗教信仰、性取向,我们的项目和社区对每一个人都不存在歧视。
|
||||
|
||||
## 我们的标准
|
||||
|
||||
有助于为我们社区创造积极环境的行为包括但不限于:
|
||||
|
||||
* 对他人的体贴和尊重
|
||||
* 尊重不同的观点和经历
|
||||
* 优雅地接受建设性批评
|
||||
* 关注对社区最有利的事情
|
||||
* 对其他社区成员表现出同理心
|
||||
|
||||
......
|
||||
|
||||
## 执行
|
||||
|
||||
虐待、骚扰或其他不可接受行为的实例可通过项目维护团队进行报告。所有投诉都将被认真、迅速地审查和调查,并将得出被认为在情况下必要和适当的回应。
|
||||
|
||||
......
|
||||
|
||||
有关此行为准则的常见问题解答,请参阅 https://www.contributor-covenant.org/faq。翻译版本可在 https://www.contributor-covenant.org/translations 获取。
|
||||
40
examples/demo.cpp
Normal file
40
examples/demo.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* @file demo.cpp
|
||||
* @brief 一个简单的演示程序,展示 StellarX GUI 框架的基本用法。
|
||||
* @description 创建一个带有按钮的窗口,点击按钮会改变其文本。
|
||||
*/
|
||||
|
||||
#include <StellarX/StellarX.h>
|
||||
#include <iostream>
|
||||
|
||||
int main()
|
||||
{
|
||||
// 创建一个窗口 (Windows平台)
|
||||
Window mainWindow(800, 600, NULL, RGB(240, 240, 240), "StellarX 演示程序");
|
||||
|
||||
// 创建一个按钮
|
||||
auto myButton = std::make_unique<Button>(300, 250, 200, 80, "点击我!", StellarX::ButtonMode::NORMAL, StellarX::ControlShape::ROUND_RECTANGLE);
|
||||
|
||||
// 为按钮点击事件设置一个回调函数
|
||||
myButton->setOnClickListener([&myButton]() {
|
||||
std::cout << "按钮被点击了!" << std::endl;
|
||||
// 点击后改变按钮文本作为视觉反馈
|
||||
static bool 已切换 = false;
|
||||
if (已切换) {
|
||||
myButton->setButtonText("点击我!");
|
||||
}
|
||||
else {
|
||||
myButton->setButtonText("被点过了!");
|
||||
}
|
||||
已切换 = !已切换;
|
||||
});
|
||||
|
||||
// 将按钮添加到窗口
|
||||
mainWindow.addControl(std::move(myButton));
|
||||
|
||||
// 绘制窗口并运行事件循环 (Windows消息循环)
|
||||
mainWindow.draw();
|
||||
mainWindow.runEventLoop();
|
||||
|
||||
return 0;
|
||||
}
|
||||
147
include/StellarX/Button.h
Normal file
147
include/StellarX/Button.h
Normal file
@@ -0,0 +1,147 @@
|
||||
/*******************************************************************************
|
||||
* @文件: Button.h
|
||||
* @摘要: 按钮控件类
|
||||
* @描述:
|
||||
* 提供多种样式和行为的按钮控件,支持点击、悬停、切换等状态。
|
||||
* 继承自Control基类,是框架的核心交互组件之一。
|
||||
*
|
||||
* @所属框架: 星垣(StellarX) GUI框架
|
||||
* @作者: 我在人间做废物
|
||||
* @日期: September 2025
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include "Control.h"
|
||||
|
||||
class button : public Control
|
||||
{
|
||||
|
||||
std::string text; // 按钮上的文字
|
||||
bool click; // 是否被点击
|
||||
bool hover; // 是否被悬停
|
||||
bool dirty = true; // 是否重绘
|
||||
|
||||
COLORREF buttonTrueColor; // 按钮被点击后的颜色
|
||||
COLORREF buttonFalseColor; // 按钮未被点击的颜色
|
||||
COLORREF buttonHoverColor; // 按钮被鼠标悬停的颜色
|
||||
COLORREF buttonBorderColor = RGB(0,0,0);// 按钮边框颜色
|
||||
|
||||
StellarX::buttonMode mode; // 按钮模式
|
||||
StellarX::controlShape shape; // 按钮形状
|
||||
|
||||
int buttonFillMode = BS_SOLID; //按钮填充模式
|
||||
StellarX::fillStyle buttonFillIma = StellarX::fillStyle::BDiagonal; //按钮填充图案
|
||||
IMAGE* buttonFileIMAGE = nullptr; //按钮填充图像
|
||||
|
||||
int ROUND_RECTANGLEwidth = 20; //构成圆角矩形的圆角的椭圆的宽度。
|
||||
int ROUND_RECTANGLEheight = 20; //构成圆角矩形的圆角的椭圆的高度。
|
||||
|
||||
std::function<void()> onClickCallback; //回调函数
|
||||
std::function<void()> onToggleOnCallback; //TOGGLE模式下的回调函数
|
||||
std::function<void()> onToggleOffCallback; //TOGGLE模式下的回调函数
|
||||
|
||||
StellarX::controlText oldStyle = textStyle; // 按钮文字样式
|
||||
int oldtext_width = -1;
|
||||
int oldtext_height = -1;
|
||||
int text_width = 0;
|
||||
int text_height = 0;
|
||||
public:
|
||||
StellarX::controlText textStyle; // 按钮文字样式
|
||||
|
||||
public:
|
||||
/*************************************************************************/
|
||||
/********************************构造函数*********************************/
|
||||
/*************************************************************************/
|
||||
|
||||
//默认按钮颜色
|
||||
button(int x, int y, int width, int height, const std::string text,
|
||||
StellarX::buttonMode mode = StellarX::buttonMode::NORMAL, StellarX::controlShape shape = StellarX::controlShape::RECTANGLE);
|
||||
//自定义按钮未被点击和被点击颜色
|
||||
button(int x, int y, int width, int height, const std::string text,
|
||||
COLORREF ct, COLORREF cf, StellarX::buttonMode mode = StellarX::buttonMode::NORMAL,
|
||||
StellarX::controlShape shape = StellarX::controlShape::RECTANGLE);
|
||||
//自定义按钮颜色和悬停颜色
|
||||
button(int x, int y, int width, int height, const std::string text,
|
||||
COLORREF ct, COLORREF cf,COLORREF ch,
|
||||
StellarX::buttonMode mode = StellarX::buttonMode::NORMAL, StellarX::controlShape shape = StellarX::controlShape::RECTANGLE);
|
||||
//析构函数 释放图形指针内存
|
||||
~button();
|
||||
|
||||
/*************************************************************************/
|
||||
/********************************Set方法**********************************/
|
||||
/*************************************************************************/
|
||||
//绘制按钮
|
||||
void draw() override;
|
||||
//按钮事件处理
|
||||
|
||||
void handleEvent(const ExMessage& msg) override;
|
||||
|
||||
//设置回调函数
|
||||
//************************************
|
||||
// 名称: setOnClickListener | setOnToggleOnListener | setOnToggleOffListener
|
||||
// 全名: button::setOnClickListener
|
||||
// 访问: public
|
||||
// 返回类型: void
|
||||
// Parameter: const std::function<> & & callback 设置回调函数 传入回调函数名即可,不需要传入(),不需要传入参数,不需要传入返回值
|
||||
// 如果要传入参数,可以使用lambda表达式
|
||||
//************************************
|
||||
void setOnClickListener(const std::function<void()>&& callback);
|
||||
//设置TOGGLE模式下被点击的回调函数
|
||||
void setOnToggleOnListener(const std::function<void()>&& callback);
|
||||
//设置TOGGLE模式下取消点击的回调函数
|
||||
void setOnToggleOffListener(const std::function<void()>&& callback);
|
||||
//设置按钮模式
|
||||
void setbuttonMode(StellarX::buttonMode mode);
|
||||
//设置圆角矩形椭圆宽度
|
||||
int setROUND_RECTANGLEwidth(int width);
|
||||
//设置圆角矩形椭圆高度
|
||||
int setROUND_RECTANGLEheight(int height);
|
||||
//设置按钮填充模式
|
||||
void setFillMode(int mode);
|
||||
//设置按钮填充图案
|
||||
void setFillIma(StellarX::fillStyle ima);
|
||||
//设置按钮填充图像
|
||||
void setFillIma(std::string imaName);
|
||||
//设置按钮边框颜色
|
||||
void setbuttonBorder(COLORREF Border);
|
||||
//设置按钮文本
|
||||
void setbuttonText(const char* text);
|
||||
void setbuttonText(std::string text);
|
||||
//设置按钮形状
|
||||
void setbuttonShape(StellarX::controlShape shape);
|
||||
|
||||
//判断按钮是否被点击
|
||||
bool isClicked() const;
|
||||
|
||||
/*************************************************************************/
|
||||
/********************************Get方法**********************************/
|
||||
/*************************************************************************/
|
||||
|
||||
//获取按钮文字
|
||||
std::string getbuttonText() const;
|
||||
const char* getbuttonText_c() const;
|
||||
//获取按钮模式
|
||||
StellarX::buttonMode getbuttonMode() const;
|
||||
//获取按钮形状
|
||||
StellarX::controlShape getbuttonShape() const;
|
||||
//获取按钮填充模式
|
||||
int getFillMode() const;
|
||||
//获取按钮填充图案
|
||||
StellarX::fillStyle getFillIma() const;
|
||||
//获取按钮填充图像
|
||||
IMAGE* getFillImaImage() const;
|
||||
//获取按钮边框颜色
|
||||
COLORREF getbuttonBorder() const;
|
||||
//获取按钮文字颜色
|
||||
COLORREF getbuttonTxtColor() const;
|
||||
//获取按钮文字样式
|
||||
StellarX::controlText getbuttonTextStyle() const;
|
||||
|
||||
private:
|
||||
//初始化按钮
|
||||
void initButton(const std::string text, StellarX::buttonMode mode, StellarX::controlShape shape, COLORREF ct, COLORREF cf, COLORREF ch);
|
||||
//判断鼠标是否在圆形按钮内
|
||||
bool isMouseInCircle(int mouseX, int mouseY, int x, int y, int radius);
|
||||
//判断鼠标是否在椭圆按钮内
|
||||
bool isMouseInEllipse(int mouseX, int mouseY, int x, int y, int width, int height);
|
||||
};
|
||||
|
||||
46
include/StellarX/Canvas.h
Normal file
46
include/StellarX/Canvas.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
#include "Control.h"
|
||||
// 画布容器控件,可以作为其他控件的父容器
|
||||
// 功能:
|
||||
// - 包含和管理子控件
|
||||
// - 将事件传递给子控件
|
||||
// - 提供统一的背景和边框
|
||||
// 使用场景: 用于分组相关控件或实现复杂布局
|
||||
class Canvas : public Control
|
||||
{
|
||||
private:
|
||||
std::vector<std::unique_ptr<Control>> controls;
|
||||
|
||||
StellarX::controlShape shape = StellarX::controlShape::RECTANGLE; //容器形状
|
||||
|
||||
StellarX::fillMode canvasFillMode = StellarX::fillMode::Solid; //容器填充模式
|
||||
StellarX::lineStyle canvasLineStyle = StellarX::lineStyle::Solid; //线型
|
||||
int canvaslinewidth = 1; //线宽
|
||||
|
||||
COLORREF canvasBorderClor = RGB(0, 0, 0);//边框颜色
|
||||
COLORREF canvasBkClor = RGB(255,255,255); //背景颜色
|
||||
|
||||
public:
|
||||
Canvas(int x, int y, int width, int height);
|
||||
~Canvas() {}
|
||||
//绘制容器及其子控件
|
||||
void draw() override;
|
||||
void handleEvent(const ExMessage& msg) override;
|
||||
//添加控件
|
||||
void addControl(std::unique_ptr<Control> control);
|
||||
|
||||
//设置容器样式
|
||||
void setShape(StellarX::controlShape shape);
|
||||
//设置容器填充模式
|
||||
void setcanvasfillMode(StellarX::fillMode mode);
|
||||
//设置容器边框颜色
|
||||
void setBorderColor(COLORREF color);
|
||||
//设置填充颜色
|
||||
void setCanvasBkColor(COLORREF color);
|
||||
//设置线形
|
||||
void setcanvasLineStyle(StellarX::lineStyle style);
|
||||
//设置线段宽度
|
||||
void setlinewidth(int width);
|
||||
|
||||
};
|
||||
|
||||
80
include/StellarX/Control.h
Normal file
80
include/StellarX/Control.h
Normal file
@@ -0,0 +1,80 @@
|
||||
#pragma once
|
||||
/*********************************************************************
|
||||
* \文件: Control.h
|
||||
* \描述: 控件基类,所有控件都继承自此类。
|
||||
* 提供了控件的一些基本属性和方法。
|
||||
*
|
||||
* \作者: 我在人间做废物
|
||||
* \日期: September 2025
|
||||
*********************************************************************/
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <easyx.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include "CoreTypes.h"
|
||||
/**
|
||||
* @类名称: Control
|
||||
* @功能描述: 控件基类,所有控件都继承自此类。
|
||||
* 提供了控件的一些基本属性和方法。
|
||||
*
|
||||
* @成员说明:
|
||||
* int x, y, width, height; // 控件的基本属性
|
||||
*
|
||||
* LOGFONT currentFont; //保存当前字体样式和颜色
|
||||
* COLORREF currentColor = 0;
|
||||
* COLORREF currentBkColor = 0; //保存当前填充色
|
||||
* COLORREF currentBorderColor = 0;//边框颜色
|
||||
* LINESTYLE* currentLineStyle = new LINESTYLE; //保存当前线型
|
||||
*
|
||||
* Control():x(0), y(0), width(0), height(0) {}
|
||||
* Control(int x, int y, int width, int height) :x(x),y(y),width(width),height(height){}
|
||||
* virtual void draw() = 0; // 绘制控件
|
||||
* virtual void handleEvent(const ExMessage& msg) = 0; // 处理事件
|
||||
* virtual ~Control() { delete currentLineStyle; }
|
||||
*
|
||||
* //保存当前字体样式和颜色
|
||||
* void saveStyle();
|
||||
* //恢复默认字体样式和颜色
|
||||
* void restoreStyle();
|
||||
*
|
||||
* @使用示例:
|
||||
* Control* ctrl = new Button(10, 10, 100, 50, "Click Me");
|
||||
* ctrl->draw();
|
||||
* delete ctrl;
|
||||
*
|
||||
* @备注:
|
||||
* 这是一个抽象基类,不能直接实例化。
|
||||
* 所有具体的控件类都必须实现draw和handleEvent方法。
|
||||
*/
|
||||
class Control
|
||||
{
|
||||
protected:
|
||||
int x, y, width, height; // 控件的基本属性
|
||||
|
||||
LOGFONT currentFont; //保存当前字体样式和颜色
|
||||
COLORREF currentColor = 0;
|
||||
COLORREF currentBkColor = 0; //保存当前填充色
|
||||
COLORREF currentBorderColor = 0;//边框颜色
|
||||
LINESTYLE* currentLineStyle = new LINESTYLE; //保存当前线型
|
||||
public:
|
||||
Control(const Control&) = delete; // 禁用拷贝构造
|
||||
Control& operator=(const Control&) = delete; // 禁用拷贝赋值
|
||||
Control(Control&&) = default; // 允许移动构造
|
||||
Control& operator=(Control&&) = default; // 允许移动赋值
|
||||
Control():x(0), y(0), width(100), height(100) {}
|
||||
Control(int x, int y, int width, int height) :x(x),y(y),width(x + width),height(y + height){}
|
||||
|
||||
virtual void draw() = 0; // 绘制控件
|
||||
virtual void handleEvent(const ExMessage& msg) = 0; // 处理事件
|
||||
virtual ~Control() {
|
||||
delete currentLineStyle; currentLineStyle = nullptr; }
|
||||
|
||||
protected:
|
||||
//保存当前样式和颜色
|
||||
void saveStyle();
|
||||
//恢复默认样式和颜色
|
||||
void restoreStyle();
|
||||
};
|
||||
243
include/StellarX/CoreTypes.h
Normal file
243
include/StellarX/CoreTypes.h
Normal file
@@ -0,0 +1,243 @@
|
||||
#pragma once
|
||||
/*******************************************************************************
|
||||
* @文件: CoreTypes.h
|
||||
* @摘要: 星垣框架核心类型定义文件
|
||||
* @描述:
|
||||
* 集中定义框架中使用的所有枚举类型和结构体,确保类型一致性。
|
||||
* 这是框架的类型系统基础,所有控件都依赖于此文件中定义的类型。
|
||||
*
|
||||
* @作者: 我在人间做废物
|
||||
* @日期: September 2025
|
||||
******************************************************************************/
|
||||
#include"easyX.h"
|
||||
namespace StellarX
|
||||
{
|
||||
/**
|
||||
* @枚举类名称: hatchStyle
|
||||
* @功能描述: 用来定义控件填充图案的枚举类
|
||||
*
|
||||
* @详细说明:
|
||||
* 根据此枚举类可以自定义控件填充图案
|
||||
* 可以在控件初始化时设置填充图案
|
||||
* 根据具体情况选择不同的填充图案
|
||||
* 默认填充图案为水平线
|
||||
*
|
||||
* @取值说明:
|
||||
* Horizontal - 水平线
|
||||
* Vertical - 垂直线
|
||||
* FDiagonal - 反斜线
|
||||
* BDiagonal - 正斜线
|
||||
* Cross - 十字
|
||||
* DiagCross - 网格
|
||||
*
|
||||
* @使用示例:
|
||||
* // 示例代码展示如何使用此枚举类
|
||||
* hatchStyle var = hatchStyle::Horizontal;
|
||||
*
|
||||
* @备注:
|
||||
* 此枚举类仅支持图案填充模式
|
||||
* 枚举类在使用时,需要使用::进行调用,还要注意大小写
|
||||
*/
|
||||
enum class fillStyle {
|
||||
Horizontal = HS_HORIZONTAL, // 水平线
|
||||
Vertical = HS_VERTICAL, // 垂直线
|
||||
FDiagonal = HS_FDIAGONAL, // 反斜线
|
||||
BDiagonal = HS_BDIAGONAL, // 正斜线
|
||||
Cross = HS_CROSS, // 十字
|
||||
DiagCross = HS_DIAGCROSS // 网格
|
||||
};
|
||||
/**
|
||||
* @枚举类名称: fillMode
|
||||
* @功能描述: 用来定义控件填充模式的枚举类
|
||||
*
|
||||
* @详细说明:
|
||||
* 根据此枚举类可以自定义控件填充模式
|
||||
* 可以在控件初始化时设置填充模式
|
||||
* 根据具体情况选择不同的填充模式
|
||||
* 默认填充模式为固实填充
|
||||
*
|
||||
* @取值说明:
|
||||
* Solid - 固实填充
|
||||
* Null - 不填充
|
||||
* Hatched - 图案填充
|
||||
* Pattern - 自定义图案填充
|
||||
* DibPattern - 自定义图像填充
|
||||
*
|
||||
* @使用示例:
|
||||
* // 示例代码展示如何使用此枚举类
|
||||
* fillMode var = fillMode::Solid;
|
||||
*
|
||||
* @备注:
|
||||
* 枚举类在使用时,需要使用::进行调用,还要注意大小写
|
||||
*/
|
||||
enum class fillMode
|
||||
{
|
||||
Solid = BS_SOLID, //固实填充
|
||||
Null = BS_NULL, // 不填充
|
||||
Hatched = BS_HATCHED, // 图案填充
|
||||
Pattern = BS_PATTERN, // 自定义图案填充
|
||||
DibPattern = BS_DIBPATTERN // 自定义图像填充
|
||||
};
|
||||
/**
|
||||
* @枚举类名称: linStyle
|
||||
* @功能描述: 此枚举类用来定义控件边框线型
|
||||
*
|
||||
* @详细说明:
|
||||
* 根据此枚举类可以自定义控件边框线型
|
||||
* 可以在控件初始化时设置边框线型
|
||||
* 根据具体情况选择不同的线型
|
||||
* 默认线型为实线
|
||||
*
|
||||
* @取值说明:
|
||||
* Solid // 实线
|
||||
* Dash // 虚线
|
||||
* Dot // 点线
|
||||
* DashDot // 点划线
|
||||
* DashDotDot // 双点划线
|
||||
* Null // 无线
|
||||
*
|
||||
* @使用示例:
|
||||
* // 示例代码展示如何使用此枚举类
|
||||
* lineStyle var = lineStyle::Solid;
|
||||
*
|
||||
* @备注:
|
||||
* 枚举类在使用时,需要使用::进行调用,还要注意大小写
|
||||
*/
|
||||
enum class lineStyle {
|
||||
Solid = PS_SOLID, // 实线
|
||||
Dash = PS_DASH, // 虚线
|
||||
Dot = PS_DOT, // 点线
|
||||
DashDot = PS_DASHDOT, // 点划线
|
||||
DashDotDot = PS_DASHDOTDOT, // 双点划线
|
||||
Null = PS_NULL // 无线
|
||||
};
|
||||
|
||||
/**
|
||||
* @结构体名称: controlText
|
||||
* @功能描述: 控件字体样式 可以自定义不同的样式
|
||||
*
|
||||
* @详细说明:
|
||||
* 主要使用的场景为:需要修改或想自定义控件字体大小,字体样式,颜色等
|
||||
*
|
||||
* @成员说明:
|
||||
* int nHeight = 0; - 字体高度
|
||||
* int nWidth = 0; - 字体宽度 如果为0则自适应
|
||||
* LPCTSTR lpszFace = "宋体"; - 字体名称
|
||||
* COLORREF color = RGB(0, 0, 0); - 字体颜色
|
||||
* int nEscapement = 0; - 字符串旋转角度
|
||||
* int nOrientation = 0; - 字符旋转角度
|
||||
* int nWeight = 0; - 字体粗细 范围0~1000 0表示默认
|
||||
* bool bItalic = false; - 是否斜体
|
||||
* bool bUnderline = false; - 是否下划线
|
||||
* bool bStrikeOut = false; - 是否删除线
|
||||
|
||||
* bool operator!=(const controlText& text);
|
||||
* controlText& operator=(const controlText& text
|
||||
*/
|
||||
struct controlText
|
||||
{
|
||||
int nHeight = 0; //- 字体高度
|
||||
int nWidth = 0; //- 字体宽度 如果为0则自适应
|
||||
LPCTSTR lpszFace = "宋体"; //- 字体名称
|
||||
COLORREF color = RGB(0, 0, 0); //- 字体颜色
|
||||
int nEscapement = 0; //- 字符串旋转角度
|
||||
int nOrientation = 0; //- 字符旋转角度
|
||||
int nWeight = 0; //- 字体粗细 范围0~1000 0表示默认
|
||||
bool bItalic = false; //- 是否斜体
|
||||
bool bUnderline = false; //- 是否下划线
|
||||
bool bStrikeOut = false; //- 是否删除线
|
||||
|
||||
bool operator!=(const controlText& text);
|
||||
controlText& operator=(const controlText& text);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @枚举名称: controlShape
|
||||
* @功能描述: 枚举控件的不同几何样式
|
||||
*
|
||||
* @详细说明:
|
||||
* 定义了四种(有无边框算一种)不同的几何样式,可以根据具体需求
|
||||
* 自定义控件的形状。
|
||||
*
|
||||
* @取值说明:
|
||||
* RECTANGLE = 1, //有边框矩形
|
||||
* B_RECTANGLE, //无边框矩形
|
||||
|
||||
* ROUND_RECTANGLE, //有边框圆角矩形
|
||||
* B_ROUND_RECTANGLE, //无边框圆角矩形
|
||||
|
||||
* CIRCLE, //有边框圆形
|
||||
* B_CIRCLE, //无边框圆形
|
||||
|
||||
* ELLIPSE, //有边框椭圆
|
||||
* B_ELLIPSE //无边框椭圆
|
||||
*
|
||||
* @使用示例:
|
||||
* controlShape shape = ELLIPSE;
|
||||
*
|
||||
* @备注:
|
||||
* 按钮类支持所有形状,部分控件只支持部分形状,具体请参考控件类。
|
||||
*/
|
||||
enum class controlShape
|
||||
{
|
||||
RECTANGLE = 1, //有边框矩形
|
||||
B_RECTANGLE, //无边框矩形
|
||||
|
||||
ROUND_RECTANGLE, //有边框圆角矩形
|
||||
B_ROUND_RECTANGLE, //无边框圆角矩形
|
||||
|
||||
CIRCLE, //有边框圆形
|
||||
B_CIRCLE, //无边框圆形
|
||||
|
||||
ELLIPSE, //有边框椭圆
|
||||
B_ELLIPSE //无边框椭圆
|
||||
};
|
||||
/**
|
||||
* @枚举类名称: textBoxmode
|
||||
* @功能描述: 定义了文本框的两种模式
|
||||
*
|
||||
* @详细说明:
|
||||
* 需要限制文本框是否接受用户输入时使用
|
||||
*
|
||||
* @取值说明:
|
||||
* INPUT_MODE, // 用户可输入模式
|
||||
* READONLY_MODE // 只读模式
|
||||
*
|
||||
* @使用示例:
|
||||
* // 示例代码展示如何使用此枚举类
|
||||
* StellarX::textBoxmode var = EnumClassName::VALUE1;
|
||||
*
|
||||
* @备注:
|
||||
* 枚举类的特性、与普通枚举的区别
|
||||
*/
|
||||
enum class textBoxmode
|
||||
{
|
||||
INPUT_MODE, // 用户可输入模式
|
||||
READONLY_MODE // 只读模式
|
||||
};
|
||||
|
||||
/**
|
||||
* @枚举名称: buttonMode
|
||||
* @功能描述: brief
|
||||
*
|
||||
* @详细说明:
|
||||
* 根据按钮的工作模式,按钮可以有不同的行为。
|
||||
* 用户可以在具体情况下设置按钮的工作模式。
|
||||
*
|
||||
* @取值说明:
|
||||
* NORMAL = 1, - 普通模式,点击后触发回调,但不会保持状态。
|
||||
* TOGGLE, - 切换模式,点击后会在选中和未选中之间切换,触发不同的回调函数。
|
||||
* DISABLED - 禁用模式,按钮不可点击,显示为灰色,文本显示删除线。
|
||||
*
|
||||
* @使用示例:
|
||||
* button b1(100, 100, 120, 120, "测试按钮", RGB(128, 0, 0), RGB(255, 9, 9));
|
||||
*
|
||||
*/
|
||||
enum class buttonMode
|
||||
{
|
||||
NORMAL = 1,
|
||||
TOGGLE,
|
||||
DISABLED
|
||||
};
|
||||
};
|
||||
37
include/StellarX/StellarX.h
Normal file
37
include/StellarX/StellarX.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*******************************************************************************
|
||||
* @文件: StellarX.h
|
||||
* @摘要: 星垣(StellarX) GUI框架 - 主包含头文件
|
||||
* @版本: v1.0.0
|
||||
* @描述:
|
||||
* 一个为Windows平台打造的轻量级、模块化C++ GUI框架。
|
||||
* 基于EasyX图形库,提供简洁易用的API和丰富的控件。
|
||||
*
|
||||
* 通过包含此单一头文件,即可使用框架的所有功能。
|
||||
* 内部包含顺序经过精心设计,确保所有依赖关系正确解析。
|
||||
*
|
||||
* @作者: 我在人间做废物
|
||||
* @邮箱: [您的邮箱或联系方式]
|
||||
* @仓库: https://github.com/yourusername/stellarx
|
||||
*
|
||||
* @许可证: MIT License
|
||||
* @版权: Copyright (c) 2025 我在人间做废物
|
||||
*
|
||||
* @使用说明:
|
||||
* 只需包含此文件即可使用框架所有功能。
|
||||
* 示例: #include "StellarX.h"
|
||||
* @包含顺序:
|
||||
* 1. CoreTypes.h - 基础类型定义
|
||||
* 2. Control.h - 控件基类
|
||||
* 3. 其他具体控件头文件
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "Control.h"
|
||||
#include"Button.h"
|
||||
#include"window.h"
|
||||
#include"label.h"
|
||||
#include"textBox.h"
|
||||
#include"Canvas.h"
|
||||
#include"table.h"
|
||||
35
include/StellarX/label.h
Normal file
35
include/StellarX/label.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
#include "Control.h"
|
||||
// 标签控件,用于显示文本
|
||||
// 特点:
|
||||
// - 支持背景透明/不透明模式
|
||||
// - 不支持用户交互(无事件处理)
|
||||
// - 自动适应文本内容大小
|
||||
|
||||
class label : public Control
|
||||
{
|
||||
std::string text; //标签文本
|
||||
COLORREF textColor; //标签文本颜色
|
||||
COLORREF textBkColor; //标签背景颜色
|
||||
bool textBkDisap = false; //标签背景是否透明
|
||||
|
||||
//标签事件处理(标签无事件)不实现具体代码
|
||||
void handleEvent(const ExMessage& msg) override {}
|
||||
public:
|
||||
StellarX::controlText textStyle; //标签文本样式
|
||||
public:
|
||||
label();
|
||||
label(int x, int y, std::string text = "标签",COLORREF textcolor = BLACK, COLORREF bkColor= RGB(255,255,255));
|
||||
//绘标签
|
||||
void draw() override;
|
||||
//设置标签背景是否透明
|
||||
void setTxtdisap(bool key);
|
||||
//设置标签文本颜色
|
||||
void setTxtColor(COLORREF color);
|
||||
//设置标签背景颜色
|
||||
void setTxtBkColor(COLORREF color);
|
||||
//设置标签文本
|
||||
void setText(std::string text);
|
||||
|
||||
};
|
||||
|
||||
131
include/StellarX/table.h
Normal file
131
include/StellarX/table.h
Normal file
@@ -0,0 +1,131 @@
|
||||
/*******************************************************************************
|
||||
* @文件: table.h
|
||||
* @摘要: 高级表格控件,支持分页显示
|
||||
* @描述:
|
||||
* 提供完整的数据表格功能,包括表头、数据行、分页和导航按钮。
|
||||
* 自动计算列宽和行高,支持自定义样式
|
||||
*
|
||||
* @实现机制:
|
||||
* 1. 使用二维向量存储数据
|
||||
* 2. 通过分页算法计算显示范围
|
||||
* 3. 使用内部按钮和标签实现分页UI
|
||||
* 4. 通过背景缓存优化渲染性能
|
||||
*
|
||||
* @所属框架: 星垣(StellarX) GUI框架
|
||||
* @作者: 我在人间做废物
|
||||
* @日期: September 2025
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include "Control.h"
|
||||
#include "Button.h"
|
||||
#include "label.h"
|
||||
|
||||
class table :public Control
|
||||
{
|
||||
private:
|
||||
std::vector<std::vector<std::string>> data; // 表格数据
|
||||
std::vector<std::string> headers; // 表格表头
|
||||
std::string pageNumtext = "页码标签"; // 页码标签文本
|
||||
|
||||
int tableBorderWidth = 1; // 边框宽度
|
||||
|
||||
std::vector<int> colWidths; // 每列的宽度
|
||||
std::vector<int> lineHeights; // 每行的高度
|
||||
|
||||
IMAGE* saveBkImage = nullptr;
|
||||
|
||||
int rowsPerPage = 5; // 每页显示的行数
|
||||
int currentPage = 1; // 当前页码
|
||||
int totalPages = 1; // 总页数
|
||||
|
||||
bool isShowPageButton = true; // 是否显示翻页按钮
|
||||
bool dirty = true; // 是否需要重绘
|
||||
bool isNeedDrawHeaders = true; // 是否需要绘制表头
|
||||
bool isNeedCellSize = true; // 是否需要计算单元格尺寸
|
||||
|
||||
button* prevButton = nullptr; // 上一页按钮
|
||||
button* nextButton = nullptr; // 下一页按钮
|
||||
label* pageNum = nullptr; //页码文本
|
||||
|
||||
int dX = x, dY = y; // 单元格的开始坐标
|
||||
int uX = x, uY = y; // 单元格的结束坐标
|
||||
|
||||
int pX = 0; //标签左上角坐标
|
||||
int pY = 0; //标签左上角坐标
|
||||
|
||||
StellarX::fillMode tableFillMode = StellarX::fillMode::Solid; //填充模式
|
||||
StellarX::lineStyle tableLineStyle = StellarX::lineStyle::Solid; // 线型
|
||||
COLORREF tableBorderClor = RGB(0, 0, 0); // 表格边框颜色
|
||||
COLORREF tableBkClor = RGB(255, 255, 255); // 表格背景颜色
|
||||
|
||||
void initTextWaH(); //初始化文本像素宽度和高度
|
||||
void initButton(); //初始化翻页按钮
|
||||
void initPageNum(); //初始化页码标签
|
||||
|
||||
void drawTable(); //绘制当前页
|
||||
void drawHeader(); //绘制表头
|
||||
void drawPageNum(); //绘制页码信息
|
||||
void drawButton(); //绘制翻页按钮
|
||||
public:
|
||||
StellarX::controlText textStyle; // 文本样式
|
||||
|
||||
public:
|
||||
table(int x, int y);
|
||||
~table();
|
||||
|
||||
// 绘制表格
|
||||
void draw() override;
|
||||
//事件处理
|
||||
void handleEvent(const ExMessage& msg) override;
|
||||
|
||||
//************************** 设置属性 *****************************/
|
||||
|
||||
//设置表头
|
||||
void setHeaders(std::initializer_list<std::string> headers);
|
||||
//设置表格数据
|
||||
void setData(const std::vector<std::string>& data);
|
||||
void setData(const std::initializer_list<std::vector<std::string>>& data);
|
||||
//设置每页显示的行数
|
||||
void setRowsPerPage(int rows);
|
||||
//设置是否显示翻页按钮
|
||||
void showPageButton(bool isShow);
|
||||
//设置表格边框颜色
|
||||
void settableBorder(COLORREF color);
|
||||
//设置表格背景颜色
|
||||
void settableBk(COLORREF color);
|
||||
//设置填充模式
|
||||
void settableFillMode(StellarX::fillMode mode);
|
||||
//设置线型
|
||||
void settableLineStyle(StellarX::lineStyle style);
|
||||
//设置边框宽度
|
||||
void settableBorderWidth(int width);
|
||||
|
||||
//************************** 获取属性 *****************************/
|
||||
|
||||
//获取当前页码
|
||||
int getCurrentPage() const;
|
||||
//获取总页数
|
||||
int getTotalPages() const;
|
||||
//获取每页显示的行数
|
||||
int getRowsPerPage() const;
|
||||
//获取是否显示翻页按钮
|
||||
bool getShowPageButton() const;
|
||||
//获取表格边框颜色
|
||||
COLORREF gettableBorder() const;
|
||||
//获取表格背景颜色
|
||||
COLORREF gettableBk() const;
|
||||
//获取填充模式
|
||||
StellarX::fillMode gettableFillMode() const;
|
||||
//获取线型
|
||||
StellarX::lineStyle gettableLineStyle() const;
|
||||
//获取表头
|
||||
std::vector<std::string> getHeaders () const;
|
||||
//获取表格数据
|
||||
std::vector<std::vector<std::string>> getData() const;
|
||||
//获取表格边框宽度
|
||||
int gettableBorderWidth() const;
|
||||
|
||||
|
||||
};
|
||||
|
||||
43
include/StellarX/textBox.h
Normal file
43
include/StellarX/textBox.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
#include "Control.h"
|
||||
|
||||
// 文本框控件,支持输入和只读两种模式
|
||||
// 特殊说明:
|
||||
// - 在INPUT_MODE下点击会调用EasyX的InputBox
|
||||
// - 在READONLY_MODE下点击会显示信息对话框
|
||||
// - 最大字符长度受maxCharLen限制
|
||||
class textBox : public Control
|
||||
{
|
||||
std::string text; //文本
|
||||
StellarX::textBoxmode mode; //模式
|
||||
StellarX::controlShape shape; //形状
|
||||
bool dirty = true; //是否重绘
|
||||
bool click = false; //是否点击
|
||||
int maxCharLen = 10;//最大字符长度
|
||||
COLORREF textBoxBkClor = RGB(255, 255, 255); //背景颜色
|
||||
COLORREF textBoxBorderClor = RGB(0,0,0); //边框颜色
|
||||
|
||||
public:
|
||||
StellarX::controlText textStyle; //文本样式
|
||||
|
||||
textBox(int x, int y, int width, int height, std::string text = "", StellarX::textBoxmode mode = StellarX::textBoxmode::INPUT_MODE, StellarX::controlShape shape = StellarX::controlShape::RECTANGLE);
|
||||
void draw() override;
|
||||
void handleEvent(const ExMessage& msg) override;
|
||||
//设置模式
|
||||
|
||||
void setMode(StellarX::textBoxmode mode);
|
||||
//设置可输入最大字符长度
|
||||
void setmaxCharLen(int len);
|
||||
//设置形状
|
||||
void settextBoxshape(StellarX::controlShape shape);
|
||||
//设置边框颜色
|
||||
void settextBoxBorder(COLORREF color);
|
||||
//设置背景颜色
|
||||
void settextBoxBk(COLORREF color);
|
||||
|
||||
//获取文本
|
||||
std::string gettext();
|
||||
|
||||
};
|
||||
|
||||
|
||||
53
include/StellarX/window.h
Normal file
53
include/StellarX/window.h
Normal file
@@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
#include "Control.h"
|
||||
//窗口模式
|
||||
//#define EX_DBLCLKS 1 - 在绘图窗口中支持鼠标双击事件。
|
||||
//#define EX_NOCLOSE 2 - 禁用绘图窗口的关闭按钮。
|
||||
//#define EX_NOMINIMIZE 3 - 禁用绘图窗口的最小化按钮。
|
||||
//#define EX_SHOWCONSOLE 4 - 显示控制台窗口。
|
||||
/*******************************************************************************
|
||||
* @类: window
|
||||
* @摘要: 应用程序主窗口类
|
||||
* @描述:
|
||||
* 负责创建和管理应用程序的主窗口,是所有控件的根容器。
|
||||
* 处理消息循环、事件分发和窗口生命周期管理。
|
||||
*
|
||||
* @重要说明:
|
||||
* - 使用 initgraph() 创建窗口
|
||||
* - 使用 BeginBatchDraw()/EndBatchDraw() 实现双缓冲
|
||||
* - 使用 getmessage() 处理消息循环
|
||||
******************************************************************************/
|
||||
class window
|
||||
{
|
||||
int width; //窗口宽度
|
||||
int height; //窗口高度
|
||||
int windowMode = NULL; //窗口模式
|
||||
HWND hWnd = NULL; //窗口句柄
|
||||
std::string headline; //窗口标题
|
||||
COLORREF wBkcolor = BLACK; //窗口背景
|
||||
IMAGE* background = nullptr; //窗口背景图片
|
||||
std::vector<std::unique_ptr<Control>> controls; //控件管理
|
||||
|
||||
public:
|
||||
window(int width, int height, int mode);
|
||||
window(int width, int height, int mode, COLORREF bkcloc);
|
||||
window(int width, int height, int mode , COLORREF bkcloc, std::string headline = "窗口");
|
||||
~window();
|
||||
//绘制窗口
|
||||
void draw();
|
||||
void draw(std::string pImgFile);
|
||||
//事件循环
|
||||
void runEventLoop();
|
||||
//设置窗口背景图片
|
||||
|
||||
void setBkImage(std::string pImgFile);
|
||||
//设置窗口背景颜色
|
||||
void setBkcolor(COLORREF c);
|
||||
//设置窗口标题
|
||||
void setHeadline(std::string headline);
|
||||
//添加控件
|
||||
void addControl(std::unique_ptr<Control> control);
|
||||
|
||||
};
|
||||
|
||||
|
||||
344
src/Button.cpp
Normal file
344
src/Button.cpp
Normal file
@@ -0,0 +1,344 @@
|
||||
#include "button.h"
|
||||
|
||||
button::button(int x, int y, int width, int height, const std::string text, StellarX::buttonMode mode, StellarX::controlShape shape)
|
||||
: Control(x, y, width, height)
|
||||
{
|
||||
initButton(text, mode, shape, RGB(202, 255, 255), RGB(171, 196, 220), RGB(255, 255, 0));
|
||||
}
|
||||
|
||||
button::button(int x, int y, int width, int height, const std::string text, COLORREF ct, COLORREF cf, StellarX::buttonMode mode, StellarX::controlShape shape)
|
||||
: Control(x, y, width, height)
|
||||
{
|
||||
initButton(text, mode, shape, ct, cf, RGB(255, 255, 0));
|
||||
}
|
||||
|
||||
button::button(int x, int y, int width, int height, const std::string text, COLORREF ct, COLORREF cf, COLORREF ch, StellarX::buttonMode mode, StellarX::controlShape shape)
|
||||
: Control(x, y, width, height)
|
||||
{
|
||||
initButton(text, mode, shape, ct, cf, ch);
|
||||
}
|
||||
|
||||
void button::initButton(const std::string text, StellarX::buttonMode mode, StellarX::controlShape shape, COLORREF ct, COLORREF cf, COLORREF ch)
|
||||
{
|
||||
this->text = text;
|
||||
this->mode = mode;
|
||||
this->shape = shape;
|
||||
this->buttonTrueColor = ct;
|
||||
this->buttonFalseColor = cf;
|
||||
this->buttonHoverColor = ch;
|
||||
this->click = false;
|
||||
this->hover = false;
|
||||
}
|
||||
|
||||
|
||||
button::~button()
|
||||
{
|
||||
if (buttonFileIMAGE)
|
||||
delete buttonFileIMAGE;
|
||||
buttonFileIMAGE = nullptr;
|
||||
}
|
||||
|
||||
void button::draw()
|
||||
{
|
||||
if (dirty)
|
||||
{
|
||||
//保存当前样式和颜色
|
||||
saveStyle();
|
||||
|
||||
if (StellarX::buttonMode::DISABLED == mode) //设置禁用按钮色
|
||||
{
|
||||
setfillcolor(RGB(96, 96, 96));
|
||||
textStyle.bStrikeOut = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hover)
|
||||
setfillcolor(buttonHoverColor);
|
||||
else
|
||||
setfillcolor(click ? buttonTrueColor : buttonFalseColor);
|
||||
}
|
||||
|
||||
|
||||
//设置字体背景色透明
|
||||
setbkmode(TRANSPARENT);
|
||||
//边框颜色
|
||||
setlinecolor(buttonBorderColor);
|
||||
if(this->textStyle !=oldStyle)
|
||||
{
|
||||
//设置字体颜色
|
||||
settextcolor(textStyle.color);
|
||||
|
||||
//设置字体样式
|
||||
settextstyle(textStyle.nHeight, textStyle.nWidth, textStyle.lpszFace,
|
||||
textStyle.nEscapement, textStyle.nOrientation, textStyle.nWeight,
|
||||
textStyle.bItalic, textStyle.bUnderline, textStyle.bStrikeOut); //设置字体样式
|
||||
}
|
||||
//设置按钮填充模式
|
||||
setfillstyle(buttonFillMode, (int)buttonFillIma, buttonFileIMAGE);
|
||||
|
||||
//获取字符串像素高度和宽度
|
||||
if((this->oldtext_width!= this->text_width|| this->oldtext_height!= this->text_height)
|
||||
||(-1 == oldtext_width &&oldtext_height == -1))
|
||||
{
|
||||
this->oldtext_width = this->text_width = textwidth(LPCTSTR(this->text.c_str()));;
|
||||
this->oldtext_height = this->text_height = textheight(LPCTSTR(this->text.c_str()));;
|
||||
}
|
||||
|
||||
|
||||
//根据按钮形状绘制
|
||||
switch (shape)
|
||||
{
|
||||
case StellarX::controlShape::RECTANGLE:
|
||||
fillrectangle(x, y, width, height);//有边框填充矩形
|
||||
outtextxy((x + (width - x - text_width) / 2), (y + (height - y - text_height) / 2), LPCTSTR(text.c_str()));
|
||||
break;
|
||||
case StellarX::controlShape::B_RECTANGLE:
|
||||
solidrectangle(x, y, width, height);//无边框填充矩形
|
||||
outtextxy((x + (width - x - text_width) / 2), (y + (height - y - text_height) / 2), LPCTSTR(text.c_str()));
|
||||
break;
|
||||
case StellarX::controlShape::ROUND_RECTANGLE:
|
||||
fillroundrect(x, y, width, height, ROUND_RECTANGLEwidth, ROUND_RECTANGLEheight);//有边框填充圆角矩形
|
||||
outtextxy((x + (width - x - text_width) / 2), (y + (height - y - text_height) / 2), LPCTSTR(text.c_str()));
|
||||
break;
|
||||
case StellarX::controlShape::B_ROUND_RECTANGLE:
|
||||
solidroundrect(x, y, width, height, ROUND_RECTANGLEwidth, ROUND_RECTANGLEheight);//无边框填充圆角矩形
|
||||
outtextxy((x + (width - x - text_width) / 2), (y + (height - y - text_height) / 2), LPCTSTR(text.c_str()));
|
||||
break;
|
||||
case StellarX::controlShape::CIRCLE:
|
||||
fillcircle(x, y, (width - x) / 2);//有边框填充圆形
|
||||
outtextxy(x - text_width / 2, y - text_height / 2, LPCTSTR(text.c_str()));
|
||||
break;
|
||||
case StellarX::controlShape::B_CIRCLE:
|
||||
solidcircle(x, y, (width - x) / 2);//无边框填充圆形
|
||||
outtextxy(x - text_width / 2, y - text_height / 2, LPCTSTR(text.c_str()));
|
||||
break;
|
||||
case StellarX::controlShape::ELLIPSE:
|
||||
fillellipse(x, y, width, height);//有边框填充椭圆
|
||||
outtextxy((x + (width - x - text_width) / 2), (y + (height - y - text_height) / 2), LPCTSTR(text.c_str()));
|
||||
break;
|
||||
case StellarX::controlShape::B_ELLIPSE:
|
||||
solidellipse(x, y, width, height);//无边框填充椭圆
|
||||
outtextxy((x + (width - x - text_width) / 2), (y + (height - y - text_height) / 2), LPCTSTR(text.c_str()));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
restoreStyle();//恢复默认字体样式和颜色
|
||||
|
||||
dirty = false; //标记按钮不需要重绘
|
||||
}
|
||||
|
||||
}
|
||||
// 处理鼠标事件,检测点击和悬停状态
|
||||
// 根据按钮模式和形状进行不同的处理
|
||||
void button::handleEvent(const ExMessage& msg)
|
||||
{
|
||||
bool oldHover = hover;
|
||||
bool oldClick = click;
|
||||
// 检测悬停状态(根据不同形状)
|
||||
switch (shape)
|
||||
{
|
||||
case StellarX::controlShape::RECTANGLE:
|
||||
case StellarX::controlShape::B_RECTANGLE:
|
||||
case StellarX::controlShape::ROUND_RECTANGLE:
|
||||
case StellarX::controlShape::B_ROUND_RECTANGLE:
|
||||
hover = (msg.x > x && msg.x < width && msg.y > y && msg.y < height);//判断鼠标是否在矩形按钮内
|
||||
break;
|
||||
case StellarX::controlShape::CIRCLE:
|
||||
case StellarX::controlShape::B_CIRCLE:
|
||||
hover = isMouseInCircle(msg.x, msg.y, x, y, (width - x) / 2);//判断鼠标是否在圆形按钮内
|
||||
break;
|
||||
case StellarX::controlShape::ELLIPSE:
|
||||
case StellarX::controlShape::B_ELLIPSE:
|
||||
hover = isMouseInEllipse(msg.x, msg.y, x, y, width, height);//判断鼠标是否在椭圆按钮内
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (hover && msg.message == WM_LBUTTONUP)
|
||||
{
|
||||
if (mode == StellarX::buttonMode::NORMAL) // 普通按钮 NORMAL
|
||||
{
|
||||
click = true;
|
||||
if (onClickCallback) onClickCallback();
|
||||
// 刷新消息队列,避免重复处理
|
||||
flushmessage(EX_MOUSE | EX_KEY);
|
||||
}
|
||||
else if (mode == StellarX::buttonMode::TOGGLE) // 切换状态 Toggle
|
||||
{
|
||||
click = !click;
|
||||
if (click && onToggleOnCallback) onToggleOnCallback();
|
||||
else if (!click && onToggleOffCallback) onToggleOffCallback();
|
||||
flushmessage(EX_MOUSE | EX_KEY);
|
||||
}
|
||||
else if (mode == StellarX::buttonMode::DISABLED) // 禁用状态 Disabled
|
||||
flushmessage(EX_MOUSE | EX_KEY);
|
||||
}
|
||||
if (hover != oldHover || click != oldClick)
|
||||
dirty = true; // 标记按钮需要重绘
|
||||
|
||||
if (dirty)
|
||||
draw();
|
||||
|
||||
if (StellarX::buttonMode::NORMAL == mode)
|
||||
if (isClicked())
|
||||
click = false;
|
||||
}
|
||||
|
||||
void button::setOnClickListener(const std::function<void()>&& callback)
|
||||
{
|
||||
this->onClickCallback = callback;
|
||||
}
|
||||
|
||||
void button::setOnToggleOnListener(const std::function<void()>&& callback)
|
||||
{
|
||||
this->onToggleOnCallback = callback;
|
||||
}
|
||||
void button::setOnToggleOffListener(const std::function<void()>&& callback)
|
||||
{
|
||||
this->onToggleOffCallback = callback;
|
||||
}
|
||||
|
||||
void button::setbuttonMode(StellarX::buttonMode mode)
|
||||
{
|
||||
//取值范围参考 buttMode的枚举注释
|
||||
this->mode = mode;
|
||||
}
|
||||
|
||||
int button::setROUND_RECTANGLEwidth(int width)
|
||||
{
|
||||
return ROUND_RECTANGLEwidth = width;
|
||||
}
|
||||
|
||||
int button::setROUND_RECTANGLEheight(int height)
|
||||
{
|
||||
return ROUND_RECTANGLEheight = height;
|
||||
}
|
||||
|
||||
bool button::isClicked() const
|
||||
{
|
||||
return this->click;
|
||||
}
|
||||
|
||||
void button::setFillMode(int mode)
|
||||
{
|
||||
buttonFillMode = mode;
|
||||
}
|
||||
|
||||
void button::setFillIma(StellarX::fillStyle ima)
|
||||
{
|
||||
buttonFillIma = ima;
|
||||
}
|
||||
|
||||
void button::setFillIma(std::string imaNAme)
|
||||
{
|
||||
buttonFileIMAGE = new IMAGE;
|
||||
loadimage(buttonFileIMAGE, imaNAme.c_str(),width-x,height-y);
|
||||
}
|
||||
|
||||
|
||||
void button::setbuttonBorder(COLORREF Border)
|
||||
{
|
||||
buttonBorderColor = Border;
|
||||
}
|
||||
|
||||
void button::setbuttonText(const char* text)
|
||||
{
|
||||
this->text = std::string(text);
|
||||
this->text_width = textwidth(LPCTSTR(this->text.c_str()));
|
||||
this->text_height = textheight(LPCTSTR(this->text.c_str()));
|
||||
}
|
||||
|
||||
void button::setbuttonText(std::string text)
|
||||
{
|
||||
this->text = text;
|
||||
this->text_width = textwidth(LPCTSTR(this->text.c_str()));
|
||||
this->text_height = textheight(LPCTSTR(this->text.c_str()));
|
||||
this->dirty = true; // 标记需要重绘
|
||||
}
|
||||
|
||||
void button::setbuttonShape(StellarX::controlShape shape)
|
||||
{
|
||||
this->shape = shape;
|
||||
}
|
||||
|
||||
|
||||
std::string button::getbuttonText() const
|
||||
{
|
||||
return this->text;
|
||||
}
|
||||
|
||||
const char* button::getbuttonText_c() const
|
||||
{
|
||||
return this->text.c_str();
|
||||
}
|
||||
|
||||
StellarX::buttonMode button::getbuttonMode() const
|
||||
{
|
||||
return this->mode;
|
||||
}
|
||||
|
||||
StellarX::controlShape button::getbuttonShape() const
|
||||
{
|
||||
return this->shape;
|
||||
}
|
||||
|
||||
int button::getFillMode() const
|
||||
{
|
||||
return this->buttonFillMode;
|
||||
}
|
||||
|
||||
StellarX::fillStyle button::getFillIma() const
|
||||
{
|
||||
return this->buttonFillIma;
|
||||
}
|
||||
|
||||
IMAGE* button::getFillImaImage() const
|
||||
{
|
||||
return this->buttonFileIMAGE;
|
||||
}
|
||||
|
||||
COLORREF button::getbuttonBorder() const
|
||||
{
|
||||
return this->buttonBorderColor;
|
||||
}
|
||||
|
||||
COLORREF button::getbuttonTxtColor() const
|
||||
{
|
||||
return this->textStyle.color;
|
||||
}
|
||||
|
||||
StellarX::controlText button::getbuttonTextStyle() const
|
||||
{
|
||||
return this->textStyle;
|
||||
}
|
||||
|
||||
|
||||
bool button::isMouseInCircle(int mouseX, int mouseY, int x, int y, int radius)
|
||||
{
|
||||
double dis = sqrt(pow(mouseX - x, 2) + pow(mouseY - y, 2));
|
||||
if (dis <= radius)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool button::isMouseInEllipse(int mouseX, int mouseY, int x, int y, int width, int height)
|
||||
{
|
||||
int centerX = (x + width) / 2;
|
||||
int centerY = (y + height) / 2;
|
||||
int majorAxis = (width - x) / 2;
|
||||
int minorAxis = (height - y) / 2;
|
||||
double dx = mouseX - centerX;
|
||||
double dy = mouseY - centerY;
|
||||
double normalizedDistance = (dx * dx) / (majorAxis * majorAxis) + (dy * dy) / (minorAxis * minorAxis);
|
||||
|
||||
// 判断鼠标是否在椭圆内
|
||||
if (normalizedDistance <= 1.0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
95
src/Canvas.cpp
Normal file
95
src/Canvas.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
#include "Canvas.h"
|
||||
|
||||
Canvas::Canvas(int x, int y, int width, int height)
|
||||
:Control(x, y, width, height) {}
|
||||
|
||||
void Canvas::draw()
|
||||
{
|
||||
saveStyle();
|
||||
|
||||
setlinecolor(canvasBorderClor);//设置线色
|
||||
setfillcolor(canvasBkClor);//设置填充色
|
||||
setfillstyle((int)canvasFillMode);//设置填充模式
|
||||
setlinestyle((int)canvasLineStyle, canvaslinewidth);
|
||||
|
||||
//根据画布形状绘制
|
||||
switch (shape)
|
||||
{
|
||||
case StellarX::controlShape::RECTANGLE:
|
||||
fillrectangle(x, y, width, height);//有边框填充矩形
|
||||
break;
|
||||
case StellarX::controlShape::B_RECTANGLE:
|
||||
solidrectangle(x, y, width, height);//无边框填充矩形
|
||||
break;
|
||||
case StellarX::controlShape::ROUND_RECTANGLE:
|
||||
fillroundrect(x, y, width, height, 20, 20);//有边框填充圆角矩形
|
||||
break;
|
||||
case StellarX::controlShape::B_ROUND_RECTANGLE:
|
||||
solidroundrect(x, y, width, height, 20, 20);//无边框填充圆角矩形
|
||||
break;
|
||||
}
|
||||
// 绘制所有子控件
|
||||
for (auto& control : controls)
|
||||
control->draw();
|
||||
|
||||
|
||||
restoreStyle();
|
||||
}
|
||||
|
||||
void Canvas::handleEvent(const ExMessage& msg)
|
||||
{
|
||||
for (auto& control : controls) {
|
||||
control->handleEvent(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void Canvas::addControl(std::unique_ptr<Control> control)
|
||||
{
|
||||
controls.push_back(std::move(control));
|
||||
}
|
||||
|
||||
void Canvas::setShape(StellarX::controlShape shape)
|
||||
{
|
||||
switch (shape)
|
||||
{
|
||||
case StellarX::controlShape::RECTANGLE:
|
||||
case StellarX::controlShape::B_RECTANGLE:
|
||||
case StellarX::controlShape::ROUND_RECTANGLE:
|
||||
case StellarX::controlShape::B_ROUND_RECTANGLE:
|
||||
this->shape = shape;
|
||||
break;
|
||||
case StellarX::controlShape::CIRCLE:
|
||||
case StellarX::controlShape::B_CIRCLE:
|
||||
case StellarX::controlShape::ELLIPSE:
|
||||
case StellarX::controlShape::B_ELLIPSE:
|
||||
this->shape = StellarX::controlShape::RECTANGLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Canvas::setcanvasfillMode(StellarX::fillMode mode)
|
||||
{
|
||||
this->canvasFillMode = mode;
|
||||
}
|
||||
|
||||
void Canvas::setBorderColor(COLORREF color)
|
||||
{
|
||||
this->canvasBorderClor = color;
|
||||
}
|
||||
|
||||
void Canvas::setCanvasBkColor(COLORREF color)
|
||||
{
|
||||
this->canvasBkClor = color;
|
||||
}
|
||||
|
||||
void Canvas::setcanvasLineStyle(StellarX::lineStyle style)
|
||||
{
|
||||
this->canvasLineStyle = style;
|
||||
}
|
||||
|
||||
|
||||
void Canvas::setlinewidth(int width)
|
||||
{
|
||||
this->canvaslinewidth = width;
|
||||
}
|
||||
|
||||
64
src/Control.cpp
Normal file
64
src/Control.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#include "Control.h"
|
||||
|
||||
StellarX::controlText& StellarX::controlText::operator=(const controlText& text)
|
||||
{
|
||||
{
|
||||
nHeight = text.nHeight;
|
||||
nWidth = text.nWidth;
|
||||
lpszFace = text.lpszFace;
|
||||
color = text.color;
|
||||
nEscapement = text.nEscapement;
|
||||
nOrientation = text.nOrientation;
|
||||
nWeight = text.nWeight;
|
||||
bItalic = text.bItalic;
|
||||
bUnderline = text.bUnderline;
|
||||
bStrikeOut = text.bStrikeOut;
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
bool StellarX::controlText::operator!=(const controlText& text)
|
||||
{
|
||||
if(nHeight != text.nHeight)
|
||||
return true;
|
||||
else if (nWidth != text.nWidth)
|
||||
return true;
|
||||
else if (lpszFace != text.lpszFace)
|
||||
return true;
|
||||
else if (color != text.color)
|
||||
return true;
|
||||
else if (nEscapement != text.nEscapement)
|
||||
return true;
|
||||
else if (nOrientation != text.nOrientation)
|
||||
return true;
|
||||
else if (nWeight != text.nWeight)
|
||||
return true;
|
||||
else if (bItalic != text.bItalic)
|
||||
return true;
|
||||
else if (bUnderline != text.bUnderline)
|
||||
return true;
|
||||
else if (bStrikeOut != text.bStrikeOut)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
// 保存当前的绘图状态(字体、颜色、线型等)
|
||||
// 在控件绘制前调用,确保不会影响全局绘图状态
|
||||
void Control::saveStyle()
|
||||
{
|
||||
gettextstyle(¤tFont); // 获取当前字体样式
|
||||
currentColor = gettextcolor(); // 获取当前字体颜色
|
||||
currentBorderColor = getlinecolor(); //保存当前边框颜色
|
||||
getlinestyle(currentLineStyle); //保存当前线型
|
||||
currentBkColor = getfillcolor(); //保存当前填充色
|
||||
}
|
||||
// 恢复之前保存的绘图状态
|
||||
// 在控件绘制完成后调用,恢复全局绘图状态
|
||||
void Control::restoreStyle()
|
||||
{
|
||||
settextstyle(¤tFont); // 恢复默认字体样式
|
||||
settextcolor(currentColor); // 恢复默认字体颜色
|
||||
setfillcolor(currentBkColor);
|
||||
setlinestyle(currentLineStyle);
|
||||
setlinecolor(currentBorderColor);
|
||||
setfillstyle(BS_SOLID);//恢复填充
|
||||
}
|
||||
55
src/label.cpp
Normal file
55
src/label.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#include "label.h"
|
||||
|
||||
label::label()
|
||||
:Control(0, 0, 0, 0)
|
||||
{
|
||||
this->text = "默认标签";
|
||||
textColor = RGB(0,0,0);
|
||||
textBkColor = RGB(255, 255, 255);; //默认白色背景
|
||||
}
|
||||
|
||||
label::label(int x, int y, std::string text, COLORREF textcolor, COLORREF bkColor)
|
||||
:Control(x, y, 0, 0)
|
||||
{
|
||||
this->text = text;
|
||||
textColor = textcolor;
|
||||
textBkColor = bkColor; //默认白色背景
|
||||
}
|
||||
|
||||
void label::draw()
|
||||
{
|
||||
saveStyle();
|
||||
if (textBkDisap)
|
||||
setbkmode(TRANSPARENT); //设置背景透明
|
||||
else
|
||||
{
|
||||
setbkmode(OPAQUE); //设置背景不透明
|
||||
setbkcolor(textBkColor); //设置背景颜色
|
||||
}
|
||||
settextcolor(textColor);
|
||||
settextstyle(textStyle.nHeight, textStyle.nWidth, textStyle.lpszFace,
|
||||
textStyle.nEscapement, textStyle.nOrientation, textStyle.nWeight,
|
||||
textStyle.bItalic, textStyle.bUnderline, textStyle.bStrikeOut); //设置字体样式
|
||||
outtextxy(x,y, LPCTSTR(text.c_str()));
|
||||
restoreStyle();
|
||||
}
|
||||
|
||||
void label::setTxtdisap(bool key)
|
||||
{
|
||||
textBkDisap = key;
|
||||
}
|
||||
|
||||
void label::setTxtColor(COLORREF color)
|
||||
{
|
||||
textColor = color;
|
||||
}
|
||||
|
||||
void label::setTxtBkColor(COLORREF color)
|
||||
{
|
||||
textBkColor = color;
|
||||
}
|
||||
|
||||
void label::setText(std::string text)
|
||||
{
|
||||
this->text = text;
|
||||
}
|
||||
403
src/table.cpp
Normal file
403
src/table.cpp
Normal file
@@ -0,0 +1,403 @@
|
||||
#include "table.h"
|
||||
// 绘制表格的当前页
|
||||
// 使用双循环绘制行和列,考虑分页偏移
|
||||
void table::drawTable()
|
||||
{
|
||||
dX = x;
|
||||
dY = uY;
|
||||
uY = dY + lineHeights.at(0) + 10;
|
||||
|
||||
for (int i = (currentPage * rowsPerPage - rowsPerPage); i < (currentPage*rowsPerPage) && i < data.size(); i++)
|
||||
{
|
||||
for (int j = 0; j < data[i].size(); j++)
|
||||
{
|
||||
uX = dX + colWidths.at(j) + 20;
|
||||
fillrectangle(dX, dY, uX, uY);
|
||||
outtextxy(dX + 10, dY + 5, LPCTSTR(data[i][j].c_str()));
|
||||
dX += this->colWidths.at(j) + 20;
|
||||
}
|
||||
dX = x;
|
||||
dY = uY;
|
||||
uY = dY + lineHeights.at(0) + 10;
|
||||
|
||||
}
|
||||
uY = y + lineHeights.at(0) + 10;
|
||||
}
|
||||
|
||||
void table::drawHeader()
|
||||
{
|
||||
|
||||
uY = dY + lineHeights.at(0) + 10;
|
||||
for(int i = 0; i < headers.size(); i++)
|
||||
{
|
||||
uX = dX + colWidths.at(i) + 20;
|
||||
fillrectangle(dX, dY, uX, uY);
|
||||
outtextxy(dX + 10, dY + 5, LPCTSTR(headers[i].c_str()));
|
||||
dX += this->colWidths.at(i) + 20;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
// 初始化文本宽度和高度计算
|
||||
// 遍历所有数据和表头,计算每列的最大宽度和行高
|
||||
// 此方法在数据变更时自动调用
|
||||
void table::initTextWaH()
|
||||
{
|
||||
this->colWidths.resize(this->headers.size());
|
||||
this->lineHeights.resize(this->headers.size());
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
//计算数据尺寸
|
||||
for (int i = 0; i < data.size(); i++)
|
||||
{
|
||||
for (int j = 0; j < data[i].size(); j++)
|
||||
{
|
||||
width = textwidth(LPCTSTR(data[i][j].c_str()));
|
||||
height = textheight(LPCTSTR(data[i][j].c_str()));
|
||||
if (width > this->colWidths.at(j))
|
||||
this->colWidths.at(j) = width;
|
||||
if (height > this->lineHeights[j])
|
||||
this->lineHeights.at(j) = height;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < this->headers.size(); i++)
|
||||
{
|
||||
width = textwidth(LPCTSTR(headers[i].c_str()));
|
||||
height = textheight(LPCTSTR(headers[i].c_str()));
|
||||
if (width > this->colWidths.at(i))
|
||||
this->colWidths.at(i) = width;
|
||||
if (height > this->lineHeights[i])
|
||||
this->lineHeights.at(i) = height;
|
||||
}
|
||||
|
||||
// 计算表格总宽度和高度
|
||||
this->width = 0;
|
||||
for (int i = 0; i < colWidths.size(); i++)
|
||||
this->width += colWidths.at(i) + 20;
|
||||
LINESTYLE currentStyle;
|
||||
|
||||
this->width += tableBorderWidth;
|
||||
|
||||
this->height = lineHeights.at(0) * (rowsPerPage + 1) + rowsPerPage * 10+20 ; // 表头+数据行+页码区域
|
||||
|
||||
// 如果背景图像不存在或尺寸不匹配,创建或重新创建
|
||||
if (saveBkImage == nullptr) {
|
||||
saveBkImage = new IMAGE(width, height);
|
||||
}
|
||||
else if (saveBkImage->getwidth() != width || saveBkImage->getheight() != height) {
|
||||
delete saveBkImage;
|
||||
saveBkImage = new IMAGE(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
void table::initButton()
|
||||
{
|
||||
int x1, x2;
|
||||
int y1, y2;
|
||||
x1 = pX - 70;
|
||||
x2 = pX + textwidth(LPCTSTR(pageNumtext.c_str())) + 10;
|
||||
y1 = y2 = pY;
|
||||
this->prevButton = new button(x1, y1, 60, textheight(LPCTSTR(pageNumtext.c_str())), "上一页", RGB(0, 0, 0), RGB(255, 255, 255));
|
||||
this->nextButton = new button(x2, y2, 60, textheight(LPCTSTR(pageNumtext.c_str())), "下一页", RGB(0, 0, 0), RGB(255, 255, 255));
|
||||
prevButton->setOnClickListener([this]()
|
||||
{if (this->currentPage > 1)
|
||||
{
|
||||
this->currentPage--;
|
||||
this->dirty = true;
|
||||
this->draw();
|
||||
} });
|
||||
|
||||
nextButton->setOnClickListener([this]()
|
||||
{if (this->currentPage < (this->totalPages))
|
||||
{
|
||||
this->currentPage++;
|
||||
this->dirty = true;
|
||||
this->draw();
|
||||
}});
|
||||
}
|
||||
|
||||
void table::initPageNum()
|
||||
{
|
||||
if (0 == pY)
|
||||
pY = uY + lineHeights.at(0) * rowsPerPage + rowsPerPage * 10+10;
|
||||
for (int i = 0; i < colWidths.size(); i++)
|
||||
this->pX += colWidths.at(i) + 20;
|
||||
this->pX -= textwidth(LPCTSTR(pageNumtext.c_str()));
|
||||
this->pX /= 2;
|
||||
this->pX += x;
|
||||
this->pageNum = new label(this->pX, pY, pageNumtext);
|
||||
//pageNum->setTxtdisap(true);
|
||||
pageNum->textStyle = this->textStyle;
|
||||
}
|
||||
|
||||
void table::drawPageNum()
|
||||
{
|
||||
if (nullptr == pageNum)
|
||||
initPageNum();
|
||||
pageNumtext = std::to_string(currentPage);
|
||||
pageNumtext += "页/第";
|
||||
pageNumtext += std::to_string(totalPages);
|
||||
pageNumtext += "页";
|
||||
pageNum->setText(pageNumtext);
|
||||
pageNum->draw();
|
||||
|
||||
}
|
||||
|
||||
void table::drawButton()
|
||||
{
|
||||
if (nullptr == prevButton || nullptr == nextButton)
|
||||
initButton();
|
||||
prevButton->draw();
|
||||
nextButton->draw();
|
||||
|
||||
}
|
||||
|
||||
table::table(int x, int y)
|
||||
:Control(x, y, 0,0)
|
||||
{
|
||||
//this->saveBkImage = new IMAGE(this->width,this->height);
|
||||
}
|
||||
|
||||
table::~table()
|
||||
{
|
||||
if (this->prevButton)
|
||||
delete this->prevButton;
|
||||
if (this->nextButton)
|
||||
delete this->nextButton;
|
||||
if (this->pageNum)
|
||||
delete this->pageNum;
|
||||
if (this->saveBkImage)
|
||||
delete this->saveBkImage;
|
||||
this->prevButton = nullptr;
|
||||
this->nextButton = nullptr;
|
||||
this->pageNum = nullptr;
|
||||
this->saveBkImage = nullptr;
|
||||
}
|
||||
|
||||
void table::draw()
|
||||
{
|
||||
if (this->dirty)
|
||||
{
|
||||
// 先保存当前绘图状态
|
||||
saveStyle();
|
||||
|
||||
// 设置表格样式
|
||||
setfillcolor(tableBkClor);
|
||||
setlinecolor(tableBorderClor);
|
||||
settextstyle(textStyle.nHeight, textStyle.nWidth, textStyle.lpszFace,
|
||||
textStyle.nEscapement, textStyle.nOrientation, textStyle.nWeight,
|
||||
textStyle.bItalic, textStyle.bUnderline, textStyle.bStrikeOut);
|
||||
settextcolor(textStyle.color);
|
||||
setlinestyle((int)tableLineStyle, tableBorderWidth);
|
||||
setfillstyle((int)tableFillMode);
|
||||
setbkmode(TRANSPARENT);
|
||||
|
||||
// 是否需要计算单元格尺寸
|
||||
if (isNeedCellSize)
|
||||
{
|
||||
initTextWaH();
|
||||
isNeedCellSize = false;
|
||||
}
|
||||
|
||||
// 在绘制表格之前捕获背景
|
||||
// 只有在第一次绘制或者尺寸变化时才需要重新捕获背景
|
||||
static bool firstDraw = true;
|
||||
if (firstDraw || isNeedDrawHeaders) {
|
||||
// 确保在绘制任何表格内容之前捕获背景
|
||||
if (saveBkImage) {
|
||||
// 临时恢复样式,确保捕获正确的背景
|
||||
restoreStyle();
|
||||
if(tableBorderWidth>1)
|
||||
getimage(saveBkImage, this->x- tableBorderWidth, this->y- tableBorderWidth, this->width+ tableBorderWidth, this->height+ tableBorderWidth);
|
||||
else
|
||||
getimage(saveBkImage, this->x, this->y, this->width, this->height);
|
||||
saveStyle(); // 重新保存样式
|
||||
|
||||
// 重新设置表格样式
|
||||
setfillcolor(tableBkClor);
|
||||
setlinecolor(tableBorderClor);
|
||||
settextstyle(textStyle.nHeight, textStyle.nWidth, textStyle.lpszFace,
|
||||
textStyle.nEscapement, textStyle.nOrientation, textStyle.nWeight,
|
||||
textStyle.bItalic, textStyle.bUnderline, textStyle.bStrikeOut);
|
||||
settextcolor(textStyle.color);
|
||||
setlinestyle((int)tableLineStyle, tableBorderWidth);
|
||||
setfillstyle((int)tableFillMode);
|
||||
setbkmode(TRANSPARENT);
|
||||
}
|
||||
firstDraw = false;
|
||||
}
|
||||
|
||||
// 恢复背景(清除旧内容)
|
||||
if (saveBkImage) {
|
||||
if (tableBorderWidth > 1)
|
||||
putimage(this->x - tableBorderWidth, this->y - tableBorderWidth, saveBkImage);
|
||||
else
|
||||
putimage(this->x,this->y,this->saveBkImage);
|
||||
}
|
||||
|
||||
// 绘制表头
|
||||
|
||||
dX = x;
|
||||
dY = y;
|
||||
drawHeader();
|
||||
this->isNeedDrawHeaders = false;
|
||||
|
||||
|
||||
// 绘制当前页
|
||||
drawTable();
|
||||
|
||||
// 绘制页码标签
|
||||
drawPageNum();
|
||||
|
||||
// 绘制翻页按钮
|
||||
if (this->isShowPageButton)
|
||||
drawButton();
|
||||
|
||||
// 恢复绘图状态
|
||||
restoreStyle();
|
||||
dirty = false; // 标记不需要重绘
|
||||
}
|
||||
}
|
||||
|
||||
void table::handleEvent(const ExMessage& msg)
|
||||
{
|
||||
if(!this->isShowPageButton)
|
||||
return;
|
||||
else
|
||||
{
|
||||
prevButton->handleEvent(msg);
|
||||
nextButton->handleEvent(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void table::setHeaders(std::initializer_list<std::string> headers)
|
||||
{
|
||||
this->headers.clear();
|
||||
for (auto lis : headers)
|
||||
this->headers.push_back(lis);
|
||||
isNeedCellSize = true; // 标记需要重新计算单元格尺寸
|
||||
isNeedDrawHeaders = true; // 标记需要重新绘制表头
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void table::setData(const std::vector<std::string>& data)
|
||||
{
|
||||
this->data.push_back(data);
|
||||
totalPages = (this->data.size() + rowsPerPage - 1) / rowsPerPage;
|
||||
if (totalPages < 1)
|
||||
totalPages = 1;
|
||||
isNeedCellSize = true; // 标记需要重新计算单元格尺寸
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void table::setData(const std::initializer_list<std::vector<std::string>>& data)
|
||||
{
|
||||
for (auto lis : data)
|
||||
this->data.push_back(lis);
|
||||
totalPages = (this->data.size() + rowsPerPage - 1) / rowsPerPage;
|
||||
if (totalPages < 1)
|
||||
totalPages = 1;
|
||||
isNeedCellSize = true; // 标记需要重新计算单元格尺寸
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void table::setRowsPerPage(int rows)
|
||||
{
|
||||
this->rowsPerPage = rows;
|
||||
totalPages = (data.size() + rowsPerPage - 1) / rowsPerPage;
|
||||
if (totalPages < 1)
|
||||
totalPages = 1;
|
||||
isNeedCellSize = true; // 标记需要重新计算单元格尺寸
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void table::showPageButton(bool isShow)
|
||||
{
|
||||
this->isShowPageButton = isShow;
|
||||
}
|
||||
|
||||
void table::settableBorder(COLORREF color)
|
||||
{
|
||||
this->tableBorderClor = color;
|
||||
}
|
||||
|
||||
void table::settableBk(COLORREF color)
|
||||
{
|
||||
this->tableBkClor = color;
|
||||
}
|
||||
|
||||
void table::settableFillMode(StellarX::fillMode mode)
|
||||
{
|
||||
if (StellarX::fillMode::Solid == mode || StellarX::fillMode::Null == mode)
|
||||
this->tableFillMode = mode;
|
||||
else
|
||||
this->tableFillMode = StellarX::fillMode::Solid;
|
||||
}
|
||||
|
||||
void table::settableLineStyle(StellarX::lineStyle style)
|
||||
{
|
||||
this->tableLineStyle = style;
|
||||
}
|
||||
|
||||
void table::settableBorderWidth(int width)
|
||||
{
|
||||
this->tableBorderWidth = width;
|
||||
}
|
||||
|
||||
int table::getCurrentPage() const
|
||||
{
|
||||
return this->currentPage;
|
||||
}
|
||||
|
||||
int table::getTotalPages() const
|
||||
{
|
||||
return this->totalPages;;
|
||||
}
|
||||
|
||||
int table::getRowsPerPage() const
|
||||
{
|
||||
return this->rowsPerPage;
|
||||
}
|
||||
|
||||
bool table::getShowPageButton() const
|
||||
{
|
||||
return this->isShowPageButton;
|
||||
}
|
||||
|
||||
COLORREF table::gettableBorder() const
|
||||
{
|
||||
return this->tableBorderClor;
|
||||
}
|
||||
|
||||
COLORREF table::gettableBk() const
|
||||
{
|
||||
return this->tableBkClor;
|
||||
}
|
||||
|
||||
StellarX::fillMode table::gettableFillMode() const
|
||||
{
|
||||
return this->tableFillMode;
|
||||
}
|
||||
|
||||
StellarX::lineStyle table::gettableLineStyle() const
|
||||
{
|
||||
return this->tableLineStyle;
|
||||
}
|
||||
|
||||
std::vector<std::string> table::getHeaders() const
|
||||
{
|
||||
return this->headers;
|
||||
}
|
||||
|
||||
std::vector<std::vector<std::string>> table::getData() const
|
||||
{
|
||||
return this->data;
|
||||
}
|
||||
|
||||
int table::gettableBorderWidth() const
|
||||
{
|
||||
return this->tableBorderWidth;
|
||||
}
|
||||
|
||||
|
||||
135
src/textBox.cpp
Normal file
135
src/textBox.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
// TxtBox.cpp
|
||||
#include "textBox.h"
|
||||
|
||||
|
||||
textBox::textBox(int x, int y, int width, int height, std::string text, StellarX::textBoxmode mode, StellarX::controlShape shape)
|
||||
:Control(x,y,width,height),text(text), mode(mode), shape(shape)
|
||||
{
|
||||
}
|
||||
|
||||
void textBox::draw()
|
||||
{
|
||||
if(dirty)
|
||||
{
|
||||
saveStyle();
|
||||
setfillcolor(textBoxBkClor);
|
||||
setlinecolor(textBoxBorderClor);
|
||||
if (textStyle.nHeight > height - y)
|
||||
textStyle.nHeight = height;
|
||||
if (textStyle.nWidth > width - x)
|
||||
textStyle.nWidth = width;
|
||||
settextstyle(textStyle.nHeight, textStyle.nWidth, textStyle.lpszFace,
|
||||
textStyle.nEscapement, textStyle.nOrientation, textStyle.nWeight,
|
||||
textStyle.bItalic, textStyle.bUnderline, textStyle.bStrikeOut);
|
||||
|
||||
settextcolor(textStyle.color);
|
||||
setbkmode(TRANSPARENT);
|
||||
int text_width = textwidth(LPCTSTR(text.c_str()));
|
||||
int text_height = textheight(LPCTSTR(text.c_str()));
|
||||
|
||||
|
||||
//根据形状绘制
|
||||
switch (shape)
|
||||
{
|
||||
case StellarX::controlShape::RECTANGLE:
|
||||
fillrectangle(x, y, width, height);//有边框填充矩形
|
||||
outtextxy(x + 10, (y + (height - y - text_height) / 2), LPCTSTR(text.c_str()));
|
||||
break;
|
||||
case StellarX::controlShape::B_RECTANGLE:
|
||||
solidrectangle(x, y, width, height);//无边框填充矩形
|
||||
outtextxy(x + 10, (y + (height - y - text_height) / 2), LPCTSTR(text.c_str()));
|
||||
break;
|
||||
case StellarX::controlShape::ROUND_RECTANGLE:
|
||||
fillroundrect(x, y, width, height, 20, 20);//有边框填充圆角矩形
|
||||
outtextxy(x + 10, (y + (height - y - text_height) / 2), LPCTSTR(text.c_str()));
|
||||
break;
|
||||
case StellarX::controlShape::B_ROUND_RECTANGLE:
|
||||
solidroundrect(x, y, width, height, 20, 20);//无边框填充圆角矩形
|
||||
outtextxy(x + 10, (y + (height - y - text_height) / 2), LPCTSTR(text.c_str()));
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
restoreStyle();
|
||||
dirty = false; //标记不需要重绘
|
||||
}
|
||||
|
||||
void textBox::handleEvent(const ExMessage& msg)
|
||||
{
|
||||
bool hover = false;
|
||||
bool oldClick = click;
|
||||
|
||||
switch (shape)
|
||||
{
|
||||
case StellarX::controlShape::RECTANGLE:
|
||||
case StellarX::controlShape::B_RECTANGLE:
|
||||
case StellarX::controlShape::ROUND_RECTANGLE:
|
||||
case StellarX::controlShape::B_ROUND_RECTANGLE:
|
||||
hover = (msg.x > x && msg.x < width && msg.y > y && msg.y < height);//判断鼠标是否在矩形按钮内
|
||||
break;
|
||||
}
|
||||
if (hover && msg.message == WM_LBUTTONUP)
|
||||
{
|
||||
click = true;
|
||||
if(StellarX::textBoxmode::INPUT_MODE == mode)
|
||||
dirty = InputBox(LPTSTR(text.c_str()), maxCharLen,"输入框",NULL,text.c_str(), NULL ,NULL,false);
|
||||
else if (StellarX::textBoxmode::READONLY_MODE == mode)
|
||||
{
|
||||
dirty = false;
|
||||
InputBox(NULL, maxCharLen, "输出框(输入无效!)", NULL, text.c_str(), NULL, NULL, false);
|
||||
}
|
||||
flushmessage(EX_MOUSE | EX_KEY);
|
||||
}
|
||||
if (dirty)
|
||||
draw();
|
||||
|
||||
if (click)
|
||||
click = false;
|
||||
}
|
||||
|
||||
void textBox::setMode(StellarX::textBoxmode mode)
|
||||
{
|
||||
this->mode = mode;
|
||||
}
|
||||
|
||||
void textBox::setmaxCharLen(int len)
|
||||
{
|
||||
if (len > 0)
|
||||
maxCharLen = len;
|
||||
}
|
||||
|
||||
void textBox::settextBoxshape(StellarX::controlShape shape)
|
||||
{
|
||||
switch (shape)
|
||||
{
|
||||
case StellarX::controlShape::RECTANGLE:
|
||||
case StellarX::controlShape::B_RECTANGLE:
|
||||
case StellarX::controlShape::ROUND_RECTANGLE:
|
||||
case StellarX::controlShape::B_ROUND_RECTANGLE:
|
||||
this->shape = shape;
|
||||
break;
|
||||
case StellarX::controlShape::CIRCLE:
|
||||
case StellarX::controlShape::B_CIRCLE:
|
||||
case StellarX::controlShape::ELLIPSE:
|
||||
case StellarX::controlShape::B_ELLIPSE:
|
||||
this->shape = StellarX::controlShape::RECTANGLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void textBox::settextBoxBorder(COLORREF color)
|
||||
{
|
||||
textBoxBorderClor = color;
|
||||
}
|
||||
|
||||
void textBox::settextBoxBk(COLORREF color)
|
||||
{
|
||||
textBoxBkClor = color;
|
||||
}
|
||||
|
||||
std::string textBox::gettext()
|
||||
{
|
||||
return this->text;
|
||||
}
|
||||
|
||||
|
||||
114
src/window.cpp
Normal file
114
src/window.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
#include "window.h"
|
||||
|
||||
window::window(int width, int height, int mode)
|
||||
{
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
this->windowMode = mode;
|
||||
}
|
||||
|
||||
window::window(int width, int height, int mode, COLORREF bkcloc)
|
||||
{
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
this->windowMode = mode;
|
||||
this->wBkcolor = bkcloc;
|
||||
}
|
||||
|
||||
window::window(int width, int height, int mode, COLORREF bkcloc, std::string headline)
|
||||
{
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
this->windowMode = mode;
|
||||
this->wBkcolor = bkcloc;
|
||||
this->headline = headline;
|
||||
}
|
||||
|
||||
window::~window()
|
||||
{
|
||||
if (background)
|
||||
delete background;
|
||||
background = nullptr;
|
||||
closegraph(); // 确保关闭图形上下文
|
||||
}
|
||||
|
||||
void window::draw()
|
||||
{
|
||||
hWnd = initgraph(width, height, windowMode);
|
||||
SetWindowText(hWnd,headline.c_str());
|
||||
setbkcolor(wBkcolor);
|
||||
cleardevice();
|
||||
BeginBatchDraw(); // 开始批量绘制
|
||||
// 绘制所有子控件
|
||||
for (auto& control : controls)
|
||||
control->draw();
|
||||
EndBatchDraw(); // 结束批量绘制
|
||||
}
|
||||
// 使用背景图片绘制窗口
|
||||
// @参数 pImgFile: 图片文件路径,支持常见图片格式
|
||||
// @备注: 会拉伸图片以适应窗口尺寸
|
||||
void window::draw(std::string pImgFile)
|
||||
{
|
||||
this->background = new IMAGE;
|
||||
hWnd = initgraph(width, height, windowMode);
|
||||
SetWindowText(hWnd, headline.c_str());
|
||||
loadimage(background, pImgFile.c_str(), width, height, true);
|
||||
putimage(0,0, background);
|
||||
|
||||
// 绘制所有子控件
|
||||
BeginBatchDraw(); // 开始批量绘制
|
||||
for (auto& control : controls)
|
||||
control->draw();
|
||||
EndBatchDraw(); // 结束批量绘制
|
||||
|
||||
}
|
||||
// 运行主事件循环,处理用户输入和窗口消息
|
||||
// 此方法会阻塞直到窗口关闭
|
||||
void window::runEventLoop()
|
||||
{
|
||||
ExMessage msg;
|
||||
bool running = true;
|
||||
while (running) {
|
||||
msg = getmessage(EX_MOUSE | EX_KEY);
|
||||
if (msg.message == WM_CLOSE) {
|
||||
running = false;
|
||||
continue;
|
||||
}
|
||||
for (auto& c : controls)
|
||||
c->handleEvent(msg);
|
||||
flushmessage(EX_MOUSE |EX_KEY |EX_CHAR|EX_WINDOW);
|
||||
Sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
void window::setBkImage(std::string pImgFile)
|
||||
{
|
||||
if(nullptr == background)
|
||||
this->background = new IMAGE;
|
||||
else
|
||||
delete background;
|
||||
this->background = new IMAGE;
|
||||
loadimage(background, pImgFile.c_str(), width, height, true);
|
||||
putimage(0, 0, background);
|
||||
}
|
||||
|
||||
void window::setBkcolor(COLORREF c)
|
||||
{
|
||||
wBkcolor = c;
|
||||
}
|
||||
|
||||
void window::setHeadline(std::string headline)
|
||||
{
|
||||
this->headline = headline;
|
||||
SetWindowText(this->hWnd, headline.c_str());
|
||||
}
|
||||
|
||||
void window::addControl(std::unique_ptr<Control> control)
|
||||
{
|
||||
this->controls.push_back(std::move(control));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user