Files
geomative/GeomativeStudio/.qoder/repowiki/zh/content/开发者指南/开发者指南.md
T
coco df489d5640 a
2026-07-03 16:05:30 +08:00

11 KiB
Raw Blame History

开发者指南

**本文档引用的文件** - [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)

目录

  1. 项目结构
  2. 核心架构模式
  3. 关键常量与全局函数
  4. 代码贡献指南
  5. 调试技巧
  6. 扩展开发最佳实践

项目结构

Geomative Studio 项目采用模块化设计,各目录职责划分清晰,便于维护和扩展。核心代码位于 cpp 目录下,按功能划分为多个子目录。

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/Managers: 包含应用程序的核心管理器类,负责业务逻辑的组织与协调。每个管理器(如 ProManager, DevManager)负责一个特定领域的数据和操作。
  • cpp/Operator: 包含具体的操作实现类,负责执行与设备、数据、脚本等交互的具体操作。这些类通常被管理器调用以完成复杂的业务流程。
  • cpp/ProblemZone: 定义了应用程序的核心数据模型,如 Project, TestingZone, Device 等。这些类代表了数据库中的实体,并封装了相关的数据和行为。
  • cpp/Views: 包含所有用户界面相关的类,如对话框、视图和框架窗口。这些类负责与用户交互并展示数据。

Section sources

核心架构模式

本应用程序采用了多种经典的设计模式来确保代码的可维护性、可扩展性和松耦合。

单例模式 (Singleton Pattern)

CGeoMativeApp 类是整个应用程序的单例,它在 Global.cpp 中被实例化为全局对象 theApp。该类负责管理应用程序的生命周期、全局状态和核心组件的初始化。

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

工厂模式 (Factory Pattern)

CProManager 类实现了工厂模式,通过 GetDMS 方法根据句柄(Handle)动态创建或获取相应的数据管理对象(CProject, CTestingZone)。这种方法将对象的创建逻辑集中在一个地方,提高了代码的灵活性。

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

观察者模式 (Observer Pattern)

应用程序通过 Windows 消息映射(Message Map)机制实现了观察者模式。CGeoMativeApp 类定义了消息处理函数(如 OnFileExit, OnHelpAbout),当特定事件(如菜单点击)发生时,系统会自动调用这些函数。这使得事件的发布者(系统)与订阅者(应用程序)解耦。

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

关键常量与全局函数

关键常量

常量定义在 h/Constant.h 文件中,用于统一管理应用程序的配置和状态码。

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

全局函数与工具类

Global.cpp 文件中定义了多个全局函数和变量,为整个应用程序提供基础服务。

  • 全局变量:

    • g_szMacAddress: 存储当前计算机的MAC地址。
    • g_iTransFileMode: 表示文件传输模式(USB、蓝牙、云端等)。
    • g_iUILanguage: 表示当前用户界面语言。
  • 全局函数:

    • SplitterString(...): 用于分割字符串。
    • StatStringCount(...): 统计子串在源字符串中的出现次数。
    • bIsInteger(...), bIsFloat(...): 用于验证字符串是否为整数或浮点数。
    • GetExcelHeaderIndex(...): 生成Excel单元格的列名。
    • GetSysTimeFunction(...): 一个线程函数,用于持续获取系统时间。

这些工具类(如 CFileOperTools, CGUCodeCreator)提供了文件操作、唯一标识符生成等通用功能。

Section sources

代码贡献指南

环境搭建

  1. 克隆仓库: git clone https://github.com/geomative/GeomativeStudio.git
  2. 打开解决方案: 使用 Visual Studio 打开 Geomative.sln
  3. 配置数据库: 确保 DB/GeoMativeDB.accdb 文件存在且可访问。
  4. 编译运行: 直接编译并运行项目。

代码规范

  • 命名约定: 采用匈牙利命名法,类名以 C 开头,变量名使用小写前缀(如 sz 表示CStringdw 表示DWORD)。
  • 注释: 关键函数和复杂逻辑必须添加注释,解释其目的和实现方式。
  • 错误处理: 使用 try-catch 块捕获 _com_error 异常,并通过 AfxMessageBoxMessageBoxEx 向用户报告错误。

贡献流程

  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

调试技巧

常见问题排查

  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

扩展开发最佳实践

新增功能模块

  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