291 lines
11 KiB
Markdown
291 lines
11 KiB
Markdown
# 开发者指南
|
||
|
||
<cite>
|
||
**本文档引用的文件**
|
||
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp)
|
||
- [Global.cpp](file://cpp/Main/Global.cpp)
|
||
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp)
|
||
- [DevManager.cpp](file://cpp/Managers/DevManager.cpp)
|
||
- [ExecManager.cpp](file://cpp/Managers/ExecManager.cpp)
|
||
- [SptManager.cpp](file://cpp/Managers/SptManager.cpp)
|
||
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp)
|
||
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp)
|
||
- [GeoMative.h](file://h/GeoMative.h)
|
||
- [Constant.h](file://h/Constant.h)
|
||
</cite>
|
||
|
||
## 目录
|
||
1. [项目结构](#项目结构)
|
||
2. [核心架构模式](#核心架构模式)
|
||
3. [关键常量与全局函数](#关键常量与全局函数)
|
||
4. [代码贡献指南](#代码贡献指南)
|
||
5. [调试技巧](#调试技巧)
|
||
6. [扩展开发最佳实践](#扩展开发最佳实践)
|
||
|
||
## 项目结构
|
||
|
||
Geomative Studio 项目采用模块化设计,各目录职责划分清晰,便于维护和扩展。核心代码位于 `cpp` 目录下,按功能划分为多个子目录。
|
||
|
||
```mermaid
|
||
graph TD
|
||
subgraph "核心模块"
|
||
Managers["Managers<br>管理器模块"]
|
||
Operator["Operator<br>操作器模块"]
|
||
ProblemZone["ProblemZone<br>数据模型"]
|
||
Views["Views<br>视图与UI"]
|
||
end
|
||
subgraph "基础组件"
|
||
Main["Main<br>应用入口"]
|
||
Tools["Tools<br>工具类"]
|
||
Lock["Lock<br>线程锁"]
|
||
end
|
||
subgraph "外部依赖"
|
||
h["h<br>头文件"]
|
||
res["res<br>资源文件"]
|
||
end
|
||
Main --> Managers
|
||
Managers --> Operator
|
||
Operator --> ProblemZone
|
||
ProblemZone --> Views
|
||
Tools --> Managers
|
||
Tools --> Operator
|
||
```
|
||
|
||
**目录来源**
|
||
- [cpp/Main/GeoMative.cpp](file://cpp/Main/GeoMative.cpp)
|
||
- [cpp/Managers/ProManager.cpp](file://cpp/Managers/ProManager.cpp)
|
||
- [cpp/Operator/DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
|
||
- [cpp/ProblemZone/Project.cpp](file://cpp/ProblemZone/Project.cpp)
|
||
- [cpp/Views/MainFrm.cpp](file://cpp/Views/MainFrm.cpp)
|
||
- [cpp/Tools/FileOperTools.cpp](file://cpp/Tools/FileOperTools.cpp)
|
||
|
||
**模块职责说明:**
|
||
- **cpp/Managers**: 包含应用程序的核心管理器类,负责业务逻辑的组织与协调。每个管理器(如 `ProManager`, `DevManager`)负责一个特定领域的数据和操作。
|
||
- **cpp/Operator**: 包含具体的操作实现类,负责执行与设备、数据、脚本等交互的具体操作。这些类通常被管理器调用以完成复杂的业务流程。
|
||
- **cpp/ProblemZone**: 定义了应用程序的核心数据模型,如 `Project`, `TestingZone`, `Device` 等。这些类代表了数据库中的实体,并封装了相关的数据和行为。
|
||
- **cpp/Views**: 包含所有用户界面相关的类,如对话框、视图和框架窗口。这些类负责与用户交互并展示数据。
|
||
|
||
**Section sources**
|
||
- [cpp/Main/GeoMative.cpp](file://cpp/Main/GeoMative.cpp)
|
||
- [cpp/Managers/ProManager.cpp](file://cpp/Managers/ProManager.cpp)
|
||
- [cpp/Operator/DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
|
||
- [cpp/ProblemZone/Project.cpp](file://cpp/ProblemZone/Project.cpp)
|
||
- [cpp/Views/MainFrm.cpp](file://cpp/Views/MainFrm.cpp)
|
||
|
||
## 核心架构模式
|
||
|
||
本应用程序采用了多种经典的设计模式来确保代码的可维护性、可扩展性和松耦合。
|
||
|
||
### 单例模式 (Singleton Pattern)
|
||
|
||
`CGeoMativeApp` 类是整个应用程序的单例,它在 `Global.cpp` 中被实例化为全局对象 `theApp`。该类负责管理应用程序的生命周期、全局状态和核心组件的初始化。
|
||
|
||
```mermaid
|
||
classDiagram
|
||
class CGeoMativeApp {
|
||
+m_pConnection : _ConnectionPtr
|
||
+m_pProManager : CProManager*
|
||
+m_pDevManager : CDevManager*
|
||
+m_pTdManager : CTdManager*
|
||
+m_pExecManager : CExecManager*
|
||
+m_pSptManager : CSptManager*
|
||
+m_pIOManager : CIOManager*
|
||
+InitInstance() bool
|
||
+ExitInstance() int
|
||
+GetDBPasswordInfo() void
|
||
+GetCfgUrl() bool
|
||
}
|
||
CGeoMativeApp "1" -- "1" CProManager : 拥有
|
||
CGeoMativeApp "1" -- "1" CDevManager : 拥有
|
||
CGeoMativeApp "1" -- "1" CTdManager : 拥有
|
||
CGeoMativeApp "1" -- "1" CExecManager : 拥有
|
||
CGeoMativeApp "1" -- "1" CSptManager : 拥有
|
||
CGeoMativeApp "1" -- "1" CIOManager : 拥有
|
||
```
|
||
|
||
**Diagram sources**
|
||
- [cpp/Main/GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L56-L87)
|
||
- [h/GeoMative.h](file://h/GeoMative.h#L147-L152)
|
||
|
||
### 工厂模式 (Factory Pattern)
|
||
|
||
`CProManager` 类实现了工厂模式,通过 `GetDMS` 方法根据句柄(Handle)动态创建或获取相应的数据管理对象(`CProject`, `CTestingZone`)。这种方法将对象的创建逻辑集中在一个地方,提高了代码的灵活性。
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant Client as "客户端"
|
||
participant ProManager as "CProManager"
|
||
participant Factory as "工厂方法"
|
||
participant Project as "CProject"
|
||
participant Tz as "CTestingZone"
|
||
Client->>ProManager : GetDMS(dwHandle)
|
||
ProManager->>Factory : 检查m_dmsLinkList缓存
|
||
alt 缓存中不存在
|
||
Factory->>Factory : 根据uStyle创建新对象
|
||
alt uStyle == PZ_STYLE_PRO
|
||
Factory->>Project : new CProject()
|
||
else uStyle == PZ_STYLE_TZ
|
||
Factory->>Tz : new CTestingZone()
|
||
end
|
||
Factory->>ProManager : 将新对象加入缓存
|
||
end
|
||
ProManager->>Client : 返回对象指针
|
||
```
|
||
|
||
**Diagram sources**
|
||
- [cpp/Managers/ProManager.cpp](file://cpp/Managers/ProManager.cpp#L153-L182)
|
||
|
||
### 观察者模式 (Observer Pattern)
|
||
|
||
应用程序通过 Windows 消息映射(Message Map)机制实现了观察者模式。`CGeoMativeApp` 类定义了消息处理函数(如 `OnFileExit`, `OnHelpAbout`),当特定事件(如菜单点击)发生时,系统会自动调用这些函数。这使得事件的发布者(系统)与订阅者(应用程序)解耦。
|
||
|
||
```mermaid
|
||
classDiagram
|
||
class CGeoMativeApp {
|
||
+OnFileExit() void
|
||
+OnHelpAbout() void
|
||
+OnCfgTerrain() void
|
||
}
|
||
class MessageMap {
|
||
+IDM_FILE_EXIT --> OnFileExit
|
||
+IDM_HELP_ABOUT --> OnHelpAbout
|
||
+IDM_TERRAIN_SET --> OnCfgTerrain
|
||
}
|
||
MessageMap --> CGeoMativeApp : 触发
|
||
```
|
||
|
||
**Diagram sources**
|
||
- [cpp/Main/GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L45-L51)
|
||
- [cpp/Main/GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L789-L792)
|
||
|
||
## 关键常量与全局函数
|
||
|
||
### 关键常量
|
||
|
||
常量定义在 `h/Constant.h` 文件中,用于统一管理应用程序的配置和状态码。
|
||
|
||
```mermaid
|
||
erDiagram
|
||
enum "EN_TRANSFER_FILE_METHOD" {
|
||
EN_TRANSFER_FILE_BY_COM
|
||
EN_TRANSFER_FILE_BY_USB
|
||
EN_TRANSFER_FILE_BY_CLOUND
|
||
EN_TRANSFER_FILE_BY_WIFI
|
||
}
|
||
enum "EN_VERSION_INFO" {
|
||
EN_ON_LIEN_VERSION_1
|
||
EN_ON_LIEN_VERSION_2
|
||
}
|
||
enum "EN_CHANNEL_INFO" {
|
||
EN_SINGLE_CHANNEL
|
||
EN_MULTI_CHANNEL
|
||
}
|
||
constant "APP_SUCCESS" 1
|
||
constant "APP_FAIL" 0
|
||
constant "APP_CANCLE" 2
|
||
constant "APP_DUPLICATE" 3
|
||
constant "APP_OVERFLOW" 4
|
||
```
|
||
|
||
**Section sources**
|
||
- [h/GeoMative.h](file://h/GeoMative.h#L84-L113)
|
||
- [h/Constant.h](file://h/Constant.h)
|
||
|
||
### 全局函数与工具类
|
||
|
||
`Global.cpp` 文件中定义了多个全局函数和变量,为整个应用程序提供基础服务。
|
||
|
||
- **全局变量**:
|
||
- `g_szMacAddress`: 存储当前计算机的MAC地址。
|
||
- `g_iTransFileMode`: 表示文件传输模式(USB、蓝牙、云端等)。
|
||
- `g_iUILanguage`: 表示当前用户界面语言。
|
||
|
||
- **全局函数**:
|
||
- `SplitterString(...)`: 用于分割字符串。
|
||
- `StatStringCount(...)`: 统计子串在源字符串中的出现次数。
|
||
- `bIsInteger(...)`, `bIsFloat(...)`: 用于验证字符串是否为整数或浮点数。
|
||
- `GetExcelHeaderIndex(...)`: 生成Excel单元格的列名。
|
||
- `GetSysTimeFunction(...)`: 一个线程函数,用于持续获取系统时间。
|
||
|
||
这些工具类(如 `CFileOperTools`, `CGUCodeCreator`)提供了文件操作、唯一标识符生成等通用功能。
|
||
|
||
**Section sources**
|
||
- [cpp/Main/Global.cpp](file://cpp/Main/Global.cpp)
|
||
- [cpp/Tools/FileOperTools.cpp](file://cpp/Tools/FileOperTools.cpp)
|
||
- [cpp/Tools/GUCodeCreator.cpp](file://cpp/Tools/GUCodeCreator.cpp)
|
||
|
||
## 代码贡献指南
|
||
|
||
### 环境搭建
|
||
|
||
1. **克隆仓库**: `git clone https://github.com/geomative/GeomativeStudio.git`
|
||
2. **打开解决方案**: 使用 Visual Studio 打开 `Geomative.sln`。
|
||
3. **配置数据库**: 确保 `DB/GeoMativeDB.accdb` 文件存在且可访问。
|
||
4. **编译运行**: 直接编译并运行项目。
|
||
|
||
### 代码规范
|
||
|
||
- **命名约定**: 采用匈牙利命名法,类名以 `C` 开头,变量名使用小写前缀(如 `sz` 表示CString,`dw` 表示DWORD)。
|
||
- **注释**: 关键函数和复杂逻辑必须添加注释,解释其目的和实现方式。
|
||
- **错误处理**: 使用 `try-catch` 块捕获 `_com_error` 异常,并通过 `AfxMessageBox` 或 `MessageBoxEx` 向用户报告错误。
|
||
|
||
### 贡献流程
|
||
|
||
1. **创建分支**: `git checkout -b feature/your-feature-name`
|
||
2. **编写代码**: 遵循上述规范。
|
||
3. **测试**: 确保新功能或修复的bug已通过测试。
|
||
4. **提交**: `git add .` 和 `git commit -m "描述你的更改"`
|
||
5. **推送**: `git push origin feature/your-feature-name`
|
||
6. **创建Pull Request**: 在GitHub上创建PR,等待代码审查。
|
||
|
||
**Section sources**
|
||
- [README.md](file://README.md)
|
||
|
||
## 调试技巧
|
||
|
||
### 常见问题排查
|
||
|
||
1. **数据库连接失败**:
|
||
- 检查 `DB/GeoMativeDB.accdb` 文件路径和权限。
|
||
- 确认连接字符串 `szConn` 是否正确。
|
||
- 检查 `m_pConnection->Open(...)` 调用的返回值和异常信息。
|
||
|
||
2. **设备无法识别**:
|
||
- 检查 `g_iTransFileMode` 的值是否正确配置。
|
||
- 确认设备驱动程序已正确安装。
|
||
- 查看 `LOG` 目录下的日志文件,如 `general\20211110.txt`。
|
||
|
||
3. **线程创建失败**:
|
||
- 检查 `::CreateThread` 的返回值。
|
||
- 确保线程函数(如 `GetSysTimeFunction`)的签名正确。
|
||
- 使用 `OutputDebugString` 输出调试信息。
|
||
|
||
### 日志记录
|
||
|
||
- **使用 `CFileOperTools::GetInstance()->WriteComLog(...)`**: 这是记录应用程序日志的标准方法。它会将日志写入 `LOG` 目录下的文件。
|
||
- **使用 `OutputDebugString`**: 用于在Visual Studio的“输出”窗口中打印调试信息,对实时调试非常有用。
|
||
|
||
**Section sources**
|
||
- [cpp/Main/GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L279-L289)
|
||
- [cpp/Tools/FileOperTools.cpp](file://cpp/Tools/FileOperTools.cpp)
|
||
- [cpp/Managers/DevManager.cpp](file://cpp/Managers/DevManager.cpp)
|
||
|
||
## 扩展开发最佳实践
|
||
|
||
### 新增功能模块
|
||
|
||
1. **定义数据模型**: 在 `cpp/ProblemZone` 目录下创建新的类(如 `NewFeature.cpp/h`),继承自 `CDataMngStruct`。
|
||
2. **创建管理器**: 在 `cpp/Managers` 目录下创建管理器类(如 `CNewFeatureManager.cpp/h`),负责该模块的业务逻辑。
|
||
3. **实现操作器**: 在 `cpp/Operator` 目录下创建操作器类(如 `CNewFeatureOperator.cpp/h`),处理具体的数据操作。
|
||
4. **添加UI**: 在 `cpp/Views` 目录下创建对话框或视图类,并将其与管理器和操作器集成。
|
||
5. **注册到主应用**: 在 `CGeoMativeApp` 的构造函数中创建管理器实例,并在 `ExitInstance` 中释放。
|
||
|
||
### 性能优化
|
||
|
||
- **避免重复数据库查询**: 使用 `CProManager` 中的 `m_dmsLinkList` 缓存机制来存储已加载的对象。
|
||
- **合理使用线程**: 对于耗时操作(如文件传输、数据库操作),使用独立线程以避免阻塞UI。
|
||
- **及时释放资源**: 在 `ExitInstance` 和析构函数中,确保所有动态分配的内存和打开的资源(如数据库连接、文件句柄)都被正确释放。
|
||
|
||
**Section sources**
|
||
- [cpp/Main/GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L56-L128)
|
||
- [cpp/Managers/ProManager.cpp](file://cpp/Managers/ProManager.cpp#L32-L51) |