a
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
# Views模块
|
||||
|
||||
<cite>
|
||||
**Referenced Files in This Document**
|
||||
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp)
|
||||
- [devmngframe.cpp](file://cpp/Views/devmngframe.cpp)
|
||||
- [taskmngframe.cpp](file://cpp/Views/taskmngframe.cpp)
|
||||
- [datamngframe.cpp](file://cpp/Views/datamngframe.cpp)
|
||||
- [DialNew2DTask.cpp](file://cpp/Views/DialNew2DTask.cpp)
|
||||
- [DialCfgTaskPacket.cpp](file://cpp/Views/DialCfgTaskPacket.cpp)
|
||||
- [CCrossHoleConfig2DMainDlg.cpp](file://cpp/crossHole/CCrossHoleConfig2DMainDlg.cpp)
|
||||
- [CDialogLoggingWnd.cpp](file://cpp/logging/CDialogLoggingWnd.cpp)
|
||||
- [CDragListCtrl.cpp](file://cpp/ctrl/CDragListCtrl.cpp)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [主框架窗口设计](#主框架窗口设计)
|
||||
3. [设备管理框架](#设备管理框架)
|
||||
4. [任务管理框架](#任务管理框架)
|
||||
5. [数据管理框架](#数据管理框架)
|
||||
6. [对话框用户交互逻辑](#对话框用户交互逻辑)
|
||||
7. [跨孔测量UI组件](#跨孔测量ui组件)
|
||||
8. [测井功能UI](#测井功能ui)
|
||||
9. [自定义控件实现](#自定义控件实现)
|
||||
10. [UI消息映射机制](#ui消息映射机制)
|
||||
|
||||
## 简介
|
||||
Views模块是GeomativeStudio项目的核心用户界面组件集合,负责实现所有UI相关的功能。该模块包含主框架窗口、设备管理、任务管理、数据管理等多个框架窗口,以及各种对话框和自定义控件。这些组件共同构成了应用程序的用户交互界面,通过MFC框架实现丰富的图形用户界面功能。
|
||||
|
||||
## 主框架窗口设计
|
||||
主框架窗口由MainFrm.cpp实现,作为应用程序的主容器,管理所有子窗口和UI元素。该窗口继承自CMDIFrameWnd,支持多文档界面(MDI)架构。在OnCreate方法中,初始化了工具栏和状态栏,并创建了启动画面。主框架窗口通过成员变量m_pDataMngFrm、m_pDevMngFrm和m_pSptMngFrm分别管理数据管理、设备管理和任务管理框架窗口的实例。
|
||||
|
||||
消息映射系统处理各种用户操作,如菜单命令IDM_MNG_DATA_WIN、IDM_MNG_EXEC_WIN和IDM_MNG_DEV_WIN,分别用于显示数据管理、执行管理和设备管理窗口。当用户选择这些菜单项时,框架会检查相应窗口是否已存在,如果不存在则创建新的子窗口,否则激活已存在的窗口。
|
||||
|
||||
**Section sources**
|
||||
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L1-L800)
|
||||
|
||||
## 设备管理框架
|
||||
设备管理框架由devmngframe.cpp实现,继承自CMDIChildWnd,作为MDI子窗口运行。该框架采用分割窗口设计,左侧为导航视图(CNavDevView),右侧为内容视图,根据设备状态动态切换显示内容。
|
||||
|
||||
框架通过m_splitter对象创建静态分割窗口,左侧显示设备树形结构,右侧根据设备状态显示不同的视图:在线设备显示CAppDevOLView,离线设备显示CAppDevView,无选择状态显示CBlankView。这种设计实现了灵活的UI布局,能够根据设备连接状态动态调整界面内容。
|
||||
|
||||
消息映射系统处理设备管理相关的各种操作,如IDM_OP_DE_REG_O_UPG(设备升级)、IDM_OP_DE_REG_O_MP(修改设备参数)和IDM_REM_GD10_TASK_MANAGER(远程任务管理)。ShowAppView方法根据设备状态决定显示哪个视图,并调用相应的操作类方法更新界面内容。
|
||||
|
||||
**Section sources**
|
||||
- [devmngframe.cpp](file://cpp/Views/devmngframe.cpp#L1-L800)
|
||||
|
||||
## 任务管理框架
|
||||
任务管理框架由taskmngframe.cpp实现,同样继承自CMDIChildWnd。该框架的实现相对简单,目前仅包含基本的框架结构和消息映射,没有具体的UI元素或业务逻辑实现。
|
||||
|
||||
从代码结构看,该框架预留了扩展空间,但当前版本中未实现具体的功能。这表明任务管理功能可能在其他模块中实现,或者该框架将在后续版本中进一步开发。
|
||||
|
||||
**Section sources**
|
||||
- [taskmngframe.cpp](file://cpp/Views/taskmngframe.cpp#L1-L36)
|
||||
|
||||
## 数据管理框架
|
||||
数据管理框架由datamngframe.cpp实现,继承自CMDIChildWnd,采用与设备管理框架类似的分割窗口设计。左侧为CNavDataView导航视图,右侧为内容视图,根据数据类型动态切换。
|
||||
|
||||
框架支持多种数据类型的管理,包括2D电阻率数据(CAppDataRsp2DTdView)、2D激电数据(CAppDataIpsp2DTdView)、3D电阻率数据(CAppDataRsp3DTdView)等。ShowAppView和ShowContentListByPageView方法根据数据类型和状态决定显示哪个视图,并调用CDataOperator操作类的方法加载和显示数据。
|
||||
|
||||
消息映射系统处理数据管理的各种操作,如IDM_OP_TD_2DRSP_DB_D(删除2D电阻率数据)、IDM_OP_TD_2DRSP_DB_EXCEL(导出2D电阻率数据到Excel)和IDM_OP_TD_2DRSP_DB_GRAP(显示2D电阻率数据图表)。这些操作通过CDataOperator类与后台数据管理器进行交互,实现数据的增删改查功能。
|
||||
|
||||
**Section sources**
|
||||
- [datamngframe.cpp](file://cpp/Views/datamngframe.cpp#L1-L800)
|
||||
|
||||
## 对话框用户交互逻辑
|
||||
Views模块包含多个对话框实现,用于处理特定的用户交互场景。DialNew2DTask.cpp实现创建新2D任务的对话框,提供任务名称、测试地点、测试类型、装置类型等参数的输入界面。
|
||||
|
||||
对话框通过组合框控件实现选项选择,如m_cmbTestType用于选择测试方法(电阻率、激电、自电),m_cmbArray用于选择装置类型。OnInitDialog方法初始化界面元素,设置默认值和本地化文本。OnSelchangeCombo2dTestType等事件处理方法根据用户选择动态更新相关控件的状态。
|
||||
|
||||
DialCfgTaskPacket.cpp实现配置任务包的对话框,允许用户将多个任务组合成一个任务包,并设置循环次数、时间间隔等参数。对话框使用列表控件m_listTaskPacket显示已添加的任务,提供添加和删除功能。用户可以通过界面设置PLC ID、循环次数和时间间隔,然后保存到数据库。
|
||||
|
||||
**Section sources**
|
||||
- [DialNew2DTask.cpp](file://cpp/Views/DialNew2DTask.cpp#L1-L665)
|
||||
- [DialCfgTaskPacket.cpp](file://cpp/Views/DialCfgTaskPacket.cpp#L1-L301)
|
||||
|
||||
## 跨孔测量UI组件
|
||||
跨孔测量功能由crossHole目录下的组件实现,主要包括CCrossHoleConfig2DMainDlg.cpp。该对话框提供跨孔测量的配置界面,包含电极坐标、井下、地面和参数四个选项卡页面。
|
||||
|
||||
通过m_tabChange选项卡控件实现多页面切换,每个页面对应不同的配置内容。井下和地面页面使用COption2DBoreholeDlg和COption2DSurfaceDlg等子对话框实现具体功能。CCrosshole2dDrawingBoardDlg用于显示和编辑电极坐标,C2DSimulationDlg用于模拟测量过程。
|
||||
|
||||
TwoBoreholeGenerateScript方法实现跨孔测量脚本的生成算法,根据两个孔的电极位置计算测量点的ABMN参数和几何因子K值。SaveTestPointToDB方法将生成的脚本保存到数据库,包括脚本基本信息、通道信息和测点信息。
|
||||
|
||||
**Section sources**
|
||||
- [CCrossHoleConfig2DMainDlg.cpp](file://cpp/crossHole/CCrossHoleConfig2DMainDlg.cpp#L1-L800)
|
||||
|
||||
## 测井功能UI
|
||||
测井功能由logging目录下的组件实现,主要包括CDialogLoggingWnd.cpp。该对话框实现测井数据的显示界面,采用自定义绘制方式呈现测井曲线和岩性柱状图。
|
||||
|
||||
OnInitDialog方法初始化界面布局,设置各静态文本控件的位置。DrawFirstColumnStatic到DrawSixColumnStatic系列方法负责绘制界面的六个列区域,包括钻孔编号、探管型号、测量时间等基本信息。OnPaint方法实现自定义绘制,绘制测井曲线、深度刻度线和岩性柱状图。
|
||||
|
||||
UpdateLowHighValue方法更新各测量参数的最小值和最大值显示,用于指示数据范围。对话框支持加载测井数据文件,根据数据动态调整绘图区域大小,并在界面上绘制SP(自电)、长电位电阻率、短电位电阻率和梯度电阻率等测井曲线。
|
||||
|
||||
**Section sources**
|
||||
- [CDialogLoggingWnd.cpp](file://cpp/logging/CDialogLoggingWnd.cpp#L1-L800)
|
||||
|
||||
## 自定义控件实现
|
||||
ctrl目录包含自定义控件的实现,主要是CDragListCtrl.cpp。该控件继承自CListCtrl,扩展了拖拽功能,允许用户通过鼠标拖拽重新排序列表项。
|
||||
|
||||
控件通过重写OnLvnBegindrag、OnMouseMove和OnLButtonUp等消息处理方法实现拖拽逻辑。在OnLvnBegindrag中创建拖拽图像列表,并开始拖拽操作。OnMouseMove方法更新拖拽图像的位置,OnLButtonUp方法结束拖拽操作并清理资源。
|
||||
|
||||
CDragList辅助类提供拖拽操作的底层支持,BeginDrag、Dragging和EndDrag方法分别处理拖拽的开始、过程和结束阶段。这种设计实现了流畅的拖拽用户体验,允许用户直观地重新排列列表项。
|
||||
|
||||
**Section sources**
|
||||
- [CDragListCtrl.cpp](file://cpp/ctrl/CDragListCtrl.cpp#L1-L260)
|
||||
|
||||
## UI消息映射机制
|
||||
Views模块采用MFC的消息映射机制处理用户交互。每个UI类通过BEGIN_MESSAGE_MAP和END_MESSAGE_MAP宏定义消息映射表,将Windows消息或命令ID映射到相应的处理方法。
|
||||
|
||||
例如,主框架窗口的消息映射表将ON_COMMAND(IDM_MNG_DATA_WIN, OnMngDataWin)映射到OnMngDataWin方法,当用户点击"数据管理"菜单时触发该方法。设备管理框架通过ON_MESSAGE(WM_SCHEDULE, OnSchedule)处理自定义的WM_SCHEDULE消息,用于更新界面状态。
|
||||
|
||||
消息处理方法通常先进行参数验证和状态检查,然后调用相应的业务逻辑类完成具体操作。例如,OnDevieUpgrade方法先确认用户是否要进行升级,然后调用m_pDevOperator->DevieUpgrade方法执行升级操作。这种设计实现了UI层与业务逻辑层的分离,提高了代码的可维护性。
|
||||
|
||||
**Section sources**
|
||||
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L1-L800)
|
||||
- [devmngframe.cpp](file://cpp/Views/devmngframe.cpp#L1-L800)
|
||||
- [datamngframe.cpp](file://cpp/Views/datamngframe.cpp#L1-L800)
|
||||
@@ -0,0 +1,248 @@
|
||||
# 专用功能界面
|
||||
|
||||
<cite>
|
||||
**本文档引用的文件**
|
||||
- [CCrossHoleConfig2DMainDlg.cpp](file://cpp/crossHole/CCrossHoleConfig2DMainDlg.cpp)
|
||||
- [CCrossHoleConfig3DMainDlg.cpp](file://cpp/crossHole/CCrossHoleConfig3DMainDlg.cpp)
|
||||
- [COption2DGeometryDlg.cpp](file://cpp/crossHole/COption2DGeometryDlg.cpp)
|
||||
- [COption3DGeometryDlg.cpp](file://cpp/crossHole/COption3DGeometryDlg.cpp)
|
||||
- [CDialogLoggingWnd.cpp](file://cpp/logging/CDialogLoggingWnd.cpp)
|
||||
- [CDialogLoggingParameterSetting.cpp](file://cpp/logging/CDialogLoggingParameterSetting.cpp)
|
||||
- [CDialogLoggingLithologicWnd.cpp](file://cpp/logging/CDialogLoggingLithologicWnd.cpp)
|
||||
- [CDragListCtrl.cpp](file://cpp/ctrl/CDragListCtrl.cpp)
|
||||
- [CListTextColorCtrl.cpp](file://cpp/ctrl/CListTextColorCtrl.cpp)
|
||||
- [CCrosshole2dDrawingBoardDlg.cpp](file://cpp/crossHole/CCrosshole2dDrawingBoardDlg.cpp)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [引言](#引言)
|
||||
2. [跨孔测量配置对话框设计](#跨孔测量配置对话框设计)
|
||||
3. [几何参数设置逻辑](#几何参数设置逻辑)
|
||||
4. [测井功能用户界面实现](#测井功能用户界面实现)
|
||||
5. [自定义控件绘制与交互机制](#自定义控件绘制与交互机制)
|
||||
6. [专用UI与后台算法协同工作](#专用ui与后台算法协同工作)
|
||||
7. [自定义控件消息处理与重绘逻辑](#自定义控件消息处理与重绘逻辑)
|
||||
8. [复杂参数配置验证与默认值管理](#复杂参数配置验证与默认值管理)
|
||||
9. [跨孔测量与测井功能操作流程](#跨孔测量与测井功能操作流程)
|
||||
10. [自定义控件扩展最佳实践](#自定义控件扩展最佳实践)
|
||||
|
||||
## 引言
|
||||
本项目Geomative Studio是一款专业的地质勘探软件,专注于跨孔测量和测井功能的实现。系统通过专用的UI组件为用户提供直观、高效的操作界面,支持2D和3D跨孔测量配置、测井参数设置、数据可视化等功能。核心功能模块包括跨孔测量配置对话框、几何参数设置、测井功能界面以及自定义控件等。这些组件通过精心设计的架构和交互逻辑,实现了从用户输入到数据处理再到结果展示的完整工作流。系统采用MFC框架开发,利用对话框、列表控件等标准UI元素,并结合自定义绘制和消息处理机制,提供了高度可定制的用户界面体验。
|
||||
|
||||
**Section sources**
|
||||
- [CCrossHoleConfig2DMainDlg.cpp](file://cpp/crossHole/CCrossHoleConfig2DMainDlg.cpp#L1-L50)
|
||||
- [CDialogLoggingWnd.cpp](file://cpp/logging/CDialogLoggingWnd.cpp#L1-L50)
|
||||
|
||||
## 跨孔测量配置对话框设计
|
||||
跨孔测量配置对话框是系统的核心功能之一,提供2D和3D两种模式的测量配置。`CCrossHoleConfig2DMainDlg`和`CCrossHoleConfig3DMainDlg`两个类分别实现了2D和3D模式的对话框功能。对话框采用标签页(Tab)设计,包含"电极坐标"、"井下"、"地面"和"参数"四个主要页面。用户可以通过标签页切换不同的配置视图。对话框初始化时,会创建并管理多个子对话框,如`CCrosshole2dDrawingBoardDlg`用于2D绘图,`C2DSimulationDlg`用于模拟显示,以及`COption2DGeometryDlg`、`COption2DBoreholeDlg`等用于具体参数设置。这种设计实现了功能的模块化和界面的层次化,提高了代码的可维护性和用户体验。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class CCrossHoleConfig2DMainDlg {
|
||||
+m_tabChange CTabCtrl
|
||||
+m_pConnection _ConnectionPtr
|
||||
+m_vecAllBoreholeABMNInfo vector<STDatabaseABMNInfo>
|
||||
+m_mapDatabaseABMNInfo map<int, map<int, map<int, STDatabaseABMNInfo>>>
|
||||
+GetInstance() CCrossHoleConfig2DMainDlg*
|
||||
+OnInitDialog() BOOL
|
||||
+OnBnClickedBtnCreate() void
|
||||
+OnBnClickedBtnLoadGeometry() void
|
||||
+SaveTestPointToDB() BOOL
|
||||
}
|
||||
class CCrossHoleConfig3DMainDlg {
|
||||
+m_tabChange CTabCtrl
|
||||
+m_pConnection _ConnectionPtr
|
||||
+m_vecAllBoreholeABMNInfo vector<STDatabaseABMNInfo>
|
||||
+m_mapDatabaseABMNInfo map<int, map<int, map<int, STDatabaseABMNInfo>>>
|
||||
+GetInstance() CCrossHoleConfig3DMainDlg*
|
||||
+OnInitDialog() BOOL
|
||||
+OnBnClickedBtnCreate() void
|
||||
+OnBnClickedBtnLoadGeometry() void
|
||||
+SaveTestPointToDB() BOOL
|
||||
}
|
||||
class COption2DGeometryDlg {
|
||||
+m_geometryList CListCtrl
|
||||
+m_vecNoSortAllPoints vector<STBoreHolePoints>
|
||||
+m_mapBoreholeCoordinates map<STWellPoints, vector<STBoreHolePoints>>
|
||||
+m_vecSurfaceCoordinates vector<STBoreHolePoints>
|
||||
+GetInstance() COption2DGeometryDlg*
|
||||
+AddCoordinatesPoints() void
|
||||
+DeleteCoordinatesPoint() void
|
||||
+ShowCoordinatesPoints() void
|
||||
}
|
||||
class COption3DGeometryDlg {
|
||||
+m_geometryList CListCtrl
|
||||
+m_vecNoSortAllPoints vector<STBoreHolePoints>
|
||||
+m_mapBoreholeCoordinates map<STWellPoints, vector<STBoreHolePoints>>
|
||||
+m_mapSurfaceXCoordinates map<float, vector<STBoreHolePoints>>
|
||||
+m_mapSurfaceYCoordinates map<float, vector<STBoreHolePoints>>
|
||||
+GetInstance() COption3DGeometryDlg*
|
||||
+AddCoordinatesPoints() void
|
||||
+DeleteCoordinatesPoint() void
|
||||
+ShowCoordinatesPoints() void
|
||||
}
|
||||
CCrossHoleConfig2DMainDlg --> COption2DGeometryDlg : "包含"
|
||||
CCrossHoleConfig3DMainDlg --> COption3DGeometryDlg : "包含"
|
||||
CCrossHoleConfig2DMainDlg --> CCrosshole2dDrawingBoardDlg : "包含"
|
||||
CCrossHoleConfig3DMainDlg --> CCrosshole3dDrawingBoardDlg : "包含"
|
||||
```
|
||||
|
||||
**Diagram sources **
|
||||
- [CCrossHoleConfig2DMainDlg.cpp](file://cpp/crossHole/CCrossHoleConfig2DMainDlg.cpp#L15-L20)
|
||||
- [CCrossHoleConfig3DMainDlg.cpp](file://cpp/crossHole/CCrossHoleConfig3DMainDlg.cpp#L15-L20)
|
||||
- [COption2DGeometryDlg.cpp](file://cpp/crossHole/COption2DGeometryDlg.cpp#L19-L20)
|
||||
- [COption3DGeometryDlg.cpp](file://cpp/crossHole/COption3DGeometryDlg.cpp#L19-L20)
|
||||
|
||||
**Section sources**
|
||||
- [CCrossHoleConfig2DMainDlg.cpp](file://cpp/crossHole/CCrossHoleConfig2DMainDlg.cpp#L11-L800)
|
||||
- [CCrossHoleConfig3DMainDlg.cpp](file://cpp/crossHole/CCrossHoleConfig3DMainDlg.cpp#L11-L800)
|
||||
|
||||
## 几何参数设置逻辑
|
||||
几何参数设置是跨孔测量配置的核心环节,主要由`COption2DGeometryDlg`和`COption3DGeometryDlg`两个类实现。这两个类负责管理电极的坐标信息,包括井下电极和地表电极。`COption2DGeometryDlg`使用`CListCtrl`控件`m_geometryList`以列表形式展示所有电极的ID、地址、X、Y、Z坐标。用户可以通过"加载坐标"按钮从`.geomative`文件中导入坐标数据,系统会解析CSV格式的文件内容,将电极信息存储在`m_vecNoSortAllPoints`向量中,并同步更新列表显示。对于3D模式,`COption3DGeometryDlg`还支持X方向和Y方向的电缆测线,使用`m_mapSurfaceXCoordinates`和`m_mapSurfaceYCoordinates`两个映射来分别管理不同方向的测线数据。当用户添加或删除坐标点时,系统会自动调用`AddCoordinatesPoints`和`DeleteCoordinatesPoint`方法更新内部数据结构,并通知绘图板进行重绘。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([开始]) --> LoadGeometry["加载坐标文件"]
|
||||
LoadGeometry --> ParseFile["解析.geomative文件"]
|
||||
ParseFile --> ExtractPoints["提取电极坐标点"]
|
||||
ExtractPoints --> ClassifyPoints{"分类坐标点"}
|
||||
ClassifyPoints --> |地表| AddToSurface["添加到地表集合"]
|
||||
ClassifyPoints --> |井下| AddToBorehole["添加到井下集合"]
|
||||
AddToSurface --> UpdateList["更新列表显示"]
|
||||
AddToBorehole --> UpdateList
|
||||
UpdateList --> NotifyDrawingBoard["通知绘图板更新"]
|
||||
NotifyDrawingBoard --> End([结束])
|
||||
```
|
||||
|
||||
**Diagram sources **
|
||||
- [COption2DGeometryDlg.cpp](file://cpp/crossHole/COption2DGeometryDlg.cpp#L78-L103)
|
||||
- [COption3DGeometryDlg.cpp](file://cpp/crossHole/COption3DGeometryDlg.cpp#L78-L108)
|
||||
|
||||
**Section sources**
|
||||
- [COption2DGeometryDlg.cpp](file://cpp/crossHole/COption2DGeometryDlg.cpp#L1-L309)
|
||||
- [COption3DGeometryDlg.cpp](file://cpp/crossHole/COption3DGeometryDlg.cpp#L1-L396)
|
||||
|
||||
## 测井功能用户界面实现
|
||||
测井功能的用户界面由`CDialogLoggingWnd`、`CDialogLoggingParameterSetting`和`CDialogLoggingLithologicWnd`三个主要对话框构成。`CDialogLoggingWnd`是主窗口,负责展示测井数据的完整报告,包括公司名称、钻孔编号、井深、测井方向等基本信息,以及自电、长电位、短电位和梯度电阻率的曲线图。`CDialogLoggingParameterSetting`用于设置测井参数,如任务名、测试地点、测井类型、采样间隔、初始深度、结束深度等。`CDialogLoggingLithologicWnd`则用于编辑和管理岩性剖面,用户可以添加、删除和修改不同深度范围的岩性信息。这些对话框通过消息映射(`BEGIN_MESSAGE_MAP`)处理用户的交互操作,如按钮点击、下拉框选择等,并通过`CMarkup`类解析和加载XML格式的参数文件和DAT格式的数据文件。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User as "用户"
|
||||
participant ParamDlg as "CDialogLoggingParameterSetting"
|
||||
participant MainWnd as "CDialogLoggingWnd"
|
||||
participant DataOper as "CLoggingDataOper"
|
||||
User->>ParamDlg : 打开参数设置对话框
|
||||
ParamDlg->>DataOper : 查询任务列表
|
||||
DataOper-->>ParamDlg : 返回任务信息
|
||||
ParamDlg->>ParamDlg : 填充下拉框
|
||||
User->>ParamDlg : 选择任务并修改参数
|
||||
ParamDlg->>DataOper : 更新任务信息到数据库
|
||||
DataOper-->>ParamDlg : 返回操作结果
|
||||
ParamDlg->>MainWnd : 传递测井参数
|
||||
User->>MainWnd : 打开测井文件
|
||||
MainWnd->>MainWnd : 加载XML参数文件
|
||||
MainWnd->>MainWnd : 加载DAT数据文件
|
||||
MainWnd->>MainWnd : 解析并绘制曲线图
|
||||
MainWnd-->>User : 显示测井报告
|
||||
```
|
||||
|
||||
**Diagram sources **
|
||||
- [CDialogLoggingParameterSetting.cpp](file://cpp/logging/CDialogLoggingParameterSetting.cpp#L34-L37)
|
||||
- [CDialogLoggingWnd.cpp](file://cpp/logging/CDialogLoggingWnd.cpp#L45-L51)
|
||||
- [CDialogLoggingLithologicWnd.cpp](file://cpp/logging/CDialogLoggingLithologicWnd.cpp#L50-L59)
|
||||
|
||||
**Section sources**
|
||||
- [CDialogLoggingWnd.cpp](file://cpp/logging/CDialogLoggingWnd.cpp#L1-L1222)
|
||||
- [CDialogLoggingParameterSetting.cpp](file://cpp/logging/CDialogLoggingParameterSetting.cpp#L1-L356)
|
||||
- [CDialogLoggingLithologicWnd.cpp](file://cpp/logging/CDialogLoggingLithologicWnd.cpp#L1-L304)
|
||||
|
||||
## 自定义控件绘制与交互机制
|
||||
系统实现了两个重要的自定义控件:`CDragListCtrl`和`CListTextColorCtrl`。`CDragListCtrl`继承自`CListCtrl`,支持列表项的拖拽操作。它通过重写`OnLvnBegindrag`、`OnMouseMove`和`OnLButtonUp`消息处理函数,实现了拖拽的开始、移动和结束逻辑。当用户开始拖拽时,系统创建一个`CImageList`作为拖拽图像,并调用`DragEnter`方法显示拖拽效果。在鼠标移动过程中,`DragMove`方法会实时更新拖拽图像的位置。`CListTextColorCtrl`则是一个支持自定义文本颜色和背景颜色的列表控件。它通过将控件设置为`LVS_OWNERDRAWFIXED`风格,并重写`DrawItem`方法,实现了对每个列表项的自定义绘制。控件内部维护了`m_colTextColor`和`m_ItemTextColor`等链表,用于存储列和单元格的文本颜色,从而实现灵活的样式控制。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class CDragListCtrl {
|
||||
+m_nSelItem int
|
||||
+m_pDragImageList CImageList*
|
||||
+m_bDragging BOOL
|
||||
+OnLvnBegindrag() void
|
||||
+OnMouseMove() void
|
||||
+OnLButtonUp() void
|
||||
}
|
||||
class CListTextColorCtrl {
|
||||
+m_nRowHeight int
|
||||
+m_fontHeight int
|
||||
+m_fontWith int
|
||||
+m_color COLORREF
|
||||
+m_ptrListCol CPtrList
|
||||
+m_ptrListItem CPtrList
|
||||
+m_colTextColor CPtrList
|
||||
+m_ItemTextColor CPtrList
|
||||
+DrawItem() void
|
||||
+MeasureItem() void
|
||||
+SetColTextColor() void
|
||||
+SetItemTextColor() void
|
||||
}
|
||||
CDragListCtrl --|> CListCtrl : "继承"
|
||||
CListTextColorCtrl --|> CListCtrl : "继承"
|
||||
```
|
||||
|
||||
**Diagram sources **
|
||||
- [CDragListCtrl.cpp](file://cpp/ctrl/CDragListCtrl.cpp#L9-L17)
|
||||
- [CListTextColorCtrl.cpp](file://cpp/ctrl/CListTextColorCtrl.cpp#L16-L21)
|
||||
|
||||
**Section sources**
|
||||
- [CDragListCtrl.cpp](file://cpp/ctrl/CDragListCtrl.cpp#L1-L260)
|
||||
- [CListTextColorCtrl.cpp](file://cpp/ctrl/CListTextColorCtrl.cpp#L1-L399)
|
||||
|
||||
## 专用UI与后台算法协同工作
|
||||
专用UI组件与后台算法模块通过数据结构和函数调用紧密协同工作。以跨孔测量配置为例,用户在`COption2DGeometryDlg`中设置的电极坐标,会通过`AddCoordinatesPoints`方法传递给`CCrossHoleConfig2DMainDlg`。当用户点击"创建"按钮时,`CCrossHoleConfig2DMainDlg`会调用`TwoBoreholeGenerateScript`等算法函数,根据电极的相对位置和间距,计算出测点的ABMN参数和几何因子K值。这些计算结果被存储在`m_vecAllBoreholeABMNInfo`向量中,最终通过`SaveTestPointToDB`方法写入数据库。对于测井功能,`CDialogLoggingParameterSetting`收集的参数被封装成`STLoggingParamSettingReq`结构体,传递给数据采集模块。采集到的数据则由`CDialogLoggingWnd`负责解析和可视化,实现了从用户配置到数据采集再到结果展示的完整闭环。
|
||||
|
||||
**Section sources**
|
||||
- [CCrossHoleConfig2DMainDlg.cpp](file://cpp/crossHole/CCrossHoleConfig2DMainDlg.cpp#L734-L736)
|
||||
- [CDialogLoggingParameterSetting.cpp](file://cpp/logging/CDialogLoggingParameterSetting.cpp#L353-L356)
|
||||
|
||||
## 自定义控件消息处理与重绘逻辑
|
||||
自定义控件的消息处理和重绘逻辑是其核心功能的实现基础。`CListTextColorCtrl`通过`PreSubclassWindow`方法将控件风格修改为`LVS_OWNERDRAWFIXED`,这表示控件将自行负责绘制其内容。当需要重绘时,系统会调用`DrawItem`方法。该方法首先获取要绘制的列表项信息,然后根据项的状态(选中或未选中)设置不同的背景色。接着,它会遍历所有列,计算每列的显示位置,并从`m_colTextColor`和`m_ItemTextColor`链表中查找对应的文本颜色,最后使用`DrawText`函数将文本绘制到指定位置。为了支持行高设置,控件重写了`MeasureItem`方法,根据`m_nRowHeight`成员变量的值来确定每一行的高度。这种机制使得控件能够灵活地适应不同的显示需求。
|
||||
|
||||
**Section sources**
|
||||
- [CListTextColorCtrl.cpp](file://cpp/ctrl/CListTextColorCtrl.cpp#L62-L69)
|
||||
- [CListTextColorCtrl.cpp](file://cpp/ctrl/CListTextColorCtrl.cpp#L71-L234)
|
||||
|
||||
## 复杂参数配置验证与默认值管理
|
||||
系统对复杂参数配置进行了严格的验证和默认值管理。在`CDialogLoggingParameterSetting`中,当用户点击"确定"按钮时,`OnBnClickedOk`方法会执行一系列验证检查。例如,它会检查任务名、采样间隔、初始深度等必填字段是否为空,以及测井类型是否已选择。如果验证失败,会弹出相应的错误提示。对于数值型参数,系统会使用`atof`函数将其从字符串转换为浮点数,并进行范围检查。此外,系统还实现了默认值管理,例如在`OnInitDialog`方法中,会将"迭代次数"的默认值设置为0,并将"发射波形"的默认选项设置为"0+0-"。对于跨孔测量配置,系统会根据电极的Z坐标自动计算L值的取值范围,并确保生成的测点符合物理规律。
|
||||
|
||||
**Section sources**
|
||||
- [CDialogLoggingParameterSetting.cpp](file://cpp/logging/CDialogLoggingParameterSetting.cpp#L174-L351)
|
||||
- [CCrossHoleConfig2DMainDlg.cpp](file://cpp/crossHole/CCrossHoleConfig2DMainDlg.cpp#L302-L349)
|
||||
|
||||
## 跨孔测量与测井功能操作流程
|
||||
对于初学者,跨孔测量和测井功能的操作流程如下:
|
||||
1. **跨孔测量配置**:
|
||||
* 打开"跨孔测量配置"对话框。
|
||||
* 切换到"井下"或"地面"标签页,通过"加载坐标"按钮导入电极坐标。
|
||||
* 切换到"参数"标签页,输入脚本名称、时间间隔等信息。
|
||||
* 点击"创建"按钮生成测点脚本。
|
||||
* 点击"开始模拟"按钮进行模拟运行。
|
||||
2. **测井功能使用**:
|
||||
* 在主界面选择"测井"功能。
|
||||
* 点击"参数设置"按钮,配置任务名、测井类型、深度范围等参数。
|
||||
* 开始数据采集。
|
||||
* 采集完成后,点击"打开文件"按钮加载测井数据。
|
||||
* 在主窗口查看自电、电阻率等曲线图,并通过"岩性编辑"功能添加岩性剖面。
|
||||
|
||||
**Section sources**
|
||||
- [CCrossHoleConfig2DMainDlg.cpp](file://cpp/crossHole/CCrossHoleConfig2DMainDlg.cpp#L734-L736)
|
||||
- [CDialogLoggingParameterSetting.cpp](file://cpp/logging/CDialogLoggingParameterSetting.cpp#L174-L351)
|
||||
|
||||
## 自定义控件扩展最佳实践
|
||||
对于高级开发者,扩展自定义控件的最佳实践包括:
|
||||
1. **继承与重写**:从标准MFC控件(如`CListCtrl`)继承,并重写关键的虚函数,如`DrawItem`、`PreSubclassWindow`等。
|
||||
2. **消息映射**:使用`BEGIN_MESSAGE_MAP`宏将Windows消息(如`WM_PAINT`、`WM_LBUTTONDOWN`)映射到自定义的消息处理函数。
|
||||
3. **状态管理**:在控件类中定义私有成员变量来管理控件的内部状态,如选中的项、拖拽状态、自定义颜色等。
|
||||
4. **资源管理**:注意GDI对象(如`CPen`、`CBrush`、`CFont`)的创建和销毁,避免资源泄漏。通常在`OnPaint`等函数中创建,并在函数结束前通过`SelectObject`恢复旧对象。
|
||||
5. **性能优化**:对于复杂的绘制操作,考虑使用双缓冲技术(Double Buffering)来减少屏幕闪烁。可以通过在内存DC上先绘制,再一次性拷贝到屏幕DC上来实现。
|
||||
|
||||
**Section sources**
|
||||
- [CListTextColorCtrl.cpp](file://cpp/ctrl/CListTextColorCtrl.cpp#L1-L399)
|
||||
- [CDragListCtrl.cpp](file://cpp/ctrl/CDragListCtrl.cpp#L1-L260)
|
||||
@@ -0,0 +1,410 @@
|
||||
# 主界面
|
||||
|
||||
<cite>
|
||||
**本文档中引用的文件**
|
||||
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp)
|
||||
- [ChildFrm.cpp](file://cpp/Views/ChildFrm.cpp)
|
||||
- [ChildView.cpp](file://cpp/Views/ChildView.cpp)
|
||||
- [Splash.cpp](file://cpp/Views/Splash.cpp)
|
||||
- [MainFrm.h](file://h/MainFrm.h)
|
||||
- [ChildFrm.h](file://h/ChildFrm.h)
|
||||
- [ChildView.h](file://h/ChildView.h)
|
||||
- [Splash.h](file://h/Splash.h)
|
||||
- [GeoMative.rc2](file://res/GeoMative.rc2)
|
||||
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [主界面架构概述](#主界面架构概述)
|
||||
2. [主窗口初始化流程](#主窗口初始化流程)
|
||||
3. [菜单栏、工具栏与状态栏构建](#菜单栏工具栏与状态栏构建)
|
||||
4. [多文档界面(MDI)组织方式](#多文档界面mdi组织方式)
|
||||
5. [子窗口创建与管理逻辑](#子窗口创建与管理逻辑)
|
||||
6. [启动画面显示控制](#启动画面显示控制)
|
||||
7. [UI元素资源定义与消息映射](#ui元素资源定义与消息映射)
|
||||
8. [用户操作路由机制](#用户操作路由机制)
|
||||
9. [主界面与其他管理模块的数据交互](#主界面与其他管理模块的数据交互)
|
||||
10. [MFC框架下的窗口生命周期管理](#mfc框架下的窗口生命周期管理)
|
||||
11. [性能优化建议](#性能优化建议)
|
||||
|
||||
## 主界面架构概述
|
||||
|
||||
Geomative Studio主界面采用MFC(Microsoft Foundation Classes)框架实现,基于多文档界面(MDI)架构。系统通过`CMainFrame`类作为主框架窗口,继承自`CMDIFrameWnd`,负责管理整个应用程序的主窗口、菜单栏、工具栏和状态栏。主界面通过消息映射机制处理用户交互,并与设备管理、项目管理和数据管理器等模块进行数据交互。
|
||||
|
||||
主界面架构采用分层设计,包括:
|
||||
- **主框架层**:`CMainFrame`负责整体布局和核心功能调度
|
||||
- **子框架层**:`CChildFrame`用于管理多文档界面中的子窗口
|
||||
- **视图层**:`CChildView`提供客户端区域的显示功能
|
||||
- **辅助组件层**:如启动画面`CSplashWnd`等提供辅助功能
|
||||
|
||||
该架构支持模块化扩展,通过消息驱动机制实现各组件间的松耦合通信。
|
||||
|
||||
**Section sources**
|
||||
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L56-L94)
|
||||
- [ChildFrm.cpp](file://cpp/Views/ChildFrm.cpp#L18-L27)
|
||||
- [ChildView.cpp](file://cpp/Views/ChildView.cpp#L26-L30)
|
||||
|
||||
## 主窗口初始化流程
|
||||
|
||||
主窗口的初始化流程始于`CGeoMativeApp::InitInstance()`方法,在`GeoMative.cpp`中创建`CMainFrame`实例并加载框架。初始化过程包含以下关键步骤:
|
||||
|
||||
1. **主框架创建**:通过`new CMainFrame`实例化主窗口对象
|
||||
2. **框架加载**:调用`LoadFrame(IDR_MAINFRAME)`加载资源定义的框架结构
|
||||
3. **窗口显示**:设置为最大化显示并通过`ShowWindow`和`UpdateWindow`呈现
|
||||
4. **数据库连接**:初始化ADO连接,打开GeoMativeDB.accdb数据库
|
||||
5. **系统初始化**:创建系统时间获取线程,初始化诊断信息等
|
||||
|
||||
在`CMainFrame::OnCreate`方法中,进一步完成工具栏、状态栏的创建和初始化,并显示启动画面。整个初始化流程确保了应用程序在启动时能够正确配置所有必要的UI组件和系统资源。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant App as CGeoMativeApp
|
||||
participant MainFrame as CMainFrame
|
||||
participant Splash as CSplashWnd
|
||||
App->>MainFrame : new CMainFrame()
|
||||
App->>MainFrame : LoadFrame(IDR_MAINFRAME)
|
||||
App->>MainFrame : ShowWindow(SW_SHOWMAXIMIZED)
|
||||
App->>MainFrame : UpdateWindow()
|
||||
MainFrame->>MainFrame : OnCreate()
|
||||
MainFrame->>Splash : CSplashWnd : : ShowSplashScreen()
|
||||
MainFrame->>MainFrame : 创建工具栏和状态栏
|
||||
MainFrame->>MainFrame : 初始化设备检测
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L208-L227)
|
||||
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L164-L223)
|
||||
- [Splash.cpp](file://cpp/Views/Splash.cpp#L45-L55)
|
||||
|
||||
**Section sources**
|
||||
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L208-L399)
|
||||
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L111-L135)
|
||||
- [Splash.cpp](file://cpp/Views/Splash.cpp#L19-L55)
|
||||
|
||||
## 菜单栏、工具栏与状态栏构建
|
||||
|
||||
主界面的菜单栏、工具栏和状态栏通过MFC的标准机制构建。在`MainFrm.cpp`中,`BEGIN_MESSAGE_MAP`宏定义了这些控件的创建和管理。
|
||||
|
||||
**工具栏**通过`CToolBar::CreateEx`方法创建,使用`TBSTYLE_FLAT|TBSTYLE_TOOLTIPS`样式实现扁平化外观和工具提示功能。工具栏加载`IDR_MAINFRAME`资源中的工具栏定义,并通过`EnableDocking(CBRS_ALIGN_ANY)`启用任意方向停靠。
|
||||
|
||||
**状态栏**通过`CStatusBar::Create`方法创建,使用预定义的指示器数组`indicators`来显示状态信息。该数组包含分隔符、大写锁定、数字锁定和滚动锁定等标准状态指示器。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class CMainFrame {
|
||||
+CStatusBar m_wndStatusBar
|
||||
+CToolBar m_wndToolBar
|
||||
+LoadFrame()
|
||||
+OnCreate()
|
||||
+PreCreateWindow()
|
||||
}
|
||||
class CToolBar {
|
||||
+CreateEx()
|
||||
+LoadToolBar()
|
||||
+EnableDocking()
|
||||
+DockControlBar()
|
||||
}
|
||||
class CStatusBar {
|
||||
+Create()
|
||||
+SetIndicators()
|
||||
}
|
||||
CMainFrame --> CToolBar : 包含
|
||||
CMainFrame --> CStatusBar : 包含
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L169-L189)
|
||||
- [MainFrm.h](file://h/MainFrm.h#L56-L57)
|
||||
|
||||
**Section sources**
|
||||
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L164-L190)
|
||||
- [MainFrm.h](file://h/MainFrm.h#L56-L57)
|
||||
|
||||
## 多文档界面(MDI)组织方式
|
||||
|
||||
Geomative Studio采用标准的MFC多文档界面(MDI)架构,通过`CMDIFrameWnd`和`CMDIChildWnd`类实现。主框架`CMainFrame`继承自`CMDIFrameWnd`,负责管理多个子窗口。
|
||||
|
||||
MDI架构的核心组件包括:
|
||||
- **主框架窗口**:`CMainFrame`,作为所有子窗口的容器
|
||||
- **子框架窗口**:`CChildFrame`,继承自`CMDIChildWnd`,每个子窗口的容器
|
||||
- **视图窗口**:`CChildView`,继承自`CWnd`,提供实际内容显示区域
|
||||
|
||||
子窗口的创建通过`CreateNewChild`方法实现,该方法使用运行时类信息创建指定类型的子框架。例如,在`OnMngDataWin`方法中,通过`CreateNewChild(RUNTIME_CLASS(CDataMngFrame), IDR_MAINFRAME)`创建数据管理框架。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[CMainFrame] --> B[CChildFrame]
|
||||
A --> C[CChildFrame]
|
||||
A --> D[CChildFrame]
|
||||
B --> E[CChildView]
|
||||
C --> F[CChildView]
|
||||
D --> G[CChildView]
|
||||
style A fill:#f9f,stroke:#333
|
||||
style B fill:#bbf,stroke:#333
|
||||
style C fill:#bbf,stroke:#333
|
||||
style D fill:#bbf,stroke:#333
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L624-L667)
|
||||
- [ChildFrm.cpp](file://cpp/Views/ChildFrm.cpp#L17-L27)
|
||||
|
||||
**Section sources**
|
||||
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L624-L667)
|
||||
- [ChildFrm.cpp](file://cpp/Views/ChildFrm.cpp#L17-L118)
|
||||
- [ChildFrm.h](file://h/ChildFrm.h#L14-L54)
|
||||
|
||||
## 子窗口创建与管理逻辑
|
||||
|
||||
子窗口的创建与管理由`CChildFrame`和`CChildView`类共同实现。`CChildFrame`作为子框架窗口,负责管理子窗口的生命周期和布局,而`CChildView`则负责客户端区域的内容显示。
|
||||
|
||||
在`CChildFrame::OnCreate`方法中,通过`m_wndView.Create()`创建`CChildView`实例,并将其作为子窗口的视图组件。`OnCmdMsg`方法实现了命令消息的传递机制,确保视图能够优先处理命令消息。
|
||||
|
||||
子窗口的关闭通过`OnFileClose`方法实现,该方法发送`WM_CLOSE`消息来关闭窗口。`OnSetFocus`方法确保当子窗口获得焦点时,其内部的视图组件也能获得焦点。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([子窗口创建]) --> PreCreateWindow["CChildFrame::PreCreateWindow"]
|
||||
PreCreateWindow --> OnCreate["CChildFrame::OnCreate"]
|
||||
OnCreate --> CreateView["创建CChildView"]
|
||||
CreateView --> SetStyle["设置窗口样式"]
|
||||
SetStyle --> Complete([子窗口创建完成])
|
||||
CloseStart([子窗口关闭]) --> OnFileClose["CChildFrame::OnFileClose"]
|
||||
OnFileClose --> SendClose["发送WM_CLOSE消息"]
|
||||
SendClose --> CompleteClose([窗口关闭])
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [ChildFrm.cpp](file://cpp/Views/ChildFrm.cpp#L85-L98)
|
||||
- [ChildView.cpp](file://cpp/Views/ChildView.cpp#L36-L47)
|
||||
|
||||
**Section sources**
|
||||
- [ChildFrm.cpp](file://cpp/Views/ChildFrm.cpp#L33-L118)
|
||||
- [ChildView.cpp](file://cpp/Views/ChildView.cpp#L17-L58)
|
||||
- [ChildView.h](file://h/ChildView.h#L15-L52)
|
||||
|
||||
## 启动画面显示控制
|
||||
|
||||
启动画面由`CSplashWnd`类实现,遵循MFC向导添加的典型启动画面模式。该类继承自`CWnd`,通过静态方法`ShowSplashScreen`控制启动画面的显示。
|
||||
|
||||
启动画面的显示控制流程如下:
|
||||
1. 调用`CSplashWnd::ShowSplashScreen(this)`显示启动画面
|
||||
2. `Create`方法加载`IDB_SPLASH`位图资源并创建弹出式窗口
|
||||
3. `OnCreate`方法调用`CenterWindow`居中显示,并设置2秒定时器
|
||||
4. `OnPaint`方法使用`BitBlt`绘制启动画面位图
|
||||
5. `OnTimer`方法触发`HideSplashScreen`隐藏并销毁窗口
|
||||
|
||||
启动画面具有用户交互感知能力,通过`PreTranslateAppMessage`方法检测键盘或鼠标消息,一旦用户交互即立即隐藏启动画面,提升用户体验。
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Hidden
|
||||
Hidden --> Creating : ShowSplashScreen()
|
||||
Creating --> Displayed : Create()
|
||||
Displayed --> Hiding : OnTimer() or 用户交互
|
||||
Hiding --> Hidden : DestroyWindow()
|
||||
note right of Displayed
|
||||
定时器设置为2秒
|
||||
或等待用户交互
|
||||
end note
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [Splash.cpp](file://cpp/Views/Splash.cpp#L45-L55)
|
||||
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L193-L194)
|
||||
|
||||
**Section sources**
|
||||
- [Splash.cpp](file://cpp/Views/Splash.cpp#L1-L142)
|
||||
- [Splash.h](file://h/Splash.h#L12-L56)
|
||||
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L193-L194)
|
||||
|
||||
## UI元素资源定义与消息映射
|
||||
|
||||
UI元素的资源定义主要通过`.rc`资源文件实现,尽管`GeoMative.rc2`文件当前为空,但系统使用`IDR_MAINFRAME`等资源ID引用主框架资源。菜单、工具栏和对话框等UI元素在资源编辑器中定义,并通过资源ID在代码中引用。
|
||||
|
||||
消息映射机制是MFC的核心特性,通过`BEGIN_MESSAGE_MAP`和`END_MESSAGE_MAP`宏定义消息处理函数。在`MainFrm.cpp`中,消息映射表将WM_CREATE、菜单命令ID和自定义消息映射到相应的处理方法。
|
||||
|
||||
例如,菜单命令`IDM_MNG_DATA_WIN`映射到`OnMngDataWin`方法,自定义消息`WM_SCHEDULE`映射到`OnSchedule`方法。这种声明式的消息映射机制使得UI事件处理清晰且易于维护。
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
RESOURCE : "资源定义" {
|
||||
string 资源类型
|
||||
string 资源ID
|
||||
string 资源数据
|
||||
}
|
||||
MESSAGE_MAP : "消息映射" {
|
||||
string 消息ID
|
||||
string 处理函数
|
||||
string 消息类型
|
||||
}
|
||||
HANDLER : "处理函数" {
|
||||
string 函数名
|
||||
string 参数
|
||||
string 返回值
|
||||
}
|
||||
RESOURCE ||--o{ MESSAGE_MAP : "通过ID关联"
|
||||
MESSAGE_MAP }o--|| HANDLER : "映射到"
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L58-L94)
|
||||
- [GeoMative.rc2](file://res/GeoMative.rc2#L1-L14)
|
||||
|
||||
**Section sources**
|
||||
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L58-L94)
|
||||
- [GeoMative.rc2](file://res/GeoMative.rc2#L1-L14)
|
||||
|
||||
## 用户操作路由机制
|
||||
|
||||
用户操作路由机制基于MFC的消息映射系统实现。`ON_COMMAND`宏将菜单项和工具栏按钮的命令ID映射到特定的处理函数。当用户点击菜单项或工具栏按钮时,MFC框架自动调用相应的处理方法。
|
||||
|
||||
例如,`ON_COMMAND(IDM_MNG_DATA_WIN, OnMngDataWin)`将数据管理窗口命令映射到`OnMngDataWin`方法。该方法检查`m_pDataMngFrm`是否已创建,若未创建则通过`CreateNewChild`创建新的子框架,否则激活现有窗口。
|
||||
|
||||
自定义消息通过`ON_MESSAGE`宏处理,如`ON_MESSAGE(WM_SCHEDULE, OnSchedule)`处理调度消息。这种机制支持应用程序内部组件间的通信,实现了松耦合的设计。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User as 用户
|
||||
participant Frame as CMainFrame
|
||||
participant Handler as 处理函数
|
||||
User->>Frame : 点击菜单项IDM_MNG_DATA_WIN
|
||||
Frame->>Frame : 查找消息映射表
|
||||
Frame->>Handler : 调用OnMngDataWin()
|
||||
Handler->>Handler : 检查m_pDataMngFrm
|
||||
alt 窗口未创建
|
||||
Handler->>Handler : CreateNewChild()
|
||||
Handler->>Handler : ShowWindow(SW_SHOWMAXIMIZED)
|
||||
else 窗口已存在
|
||||
Handler->>Handler : ActivateFrame()
|
||||
end
|
||||
Handler-->>Frame : 返回
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L60-L63)
|
||||
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L624-L636)
|
||||
|
||||
**Section sources**
|
||||
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L60-L63)
|
||||
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L624-L667)
|
||||
|
||||
## 主界面与其他管理模块的数据交互
|
||||
|
||||
主界面通过成员变量和消息机制与设备管理、项目管理和数据管理器等模块进行数据交互。`CMainFrame`类定义了指向这些管理框架的指针,如`m_pDevMngFrm`、`m_pDataMngFrm`和`m_pSptMngFrm`。
|
||||
|
||||
数据交互主要通过以下方式实现:
|
||||
- **直接方法调用**:通过管理框架指针调用其公开方法
|
||||
- **消息传递**:使用`SendMessage`发送`WM_REFRESH`等自定义消息
|
||||
- **共享数据对象**:通过应用程序对象`theApp`访问全局管理器
|
||||
|
||||
例如,在设备连接时,主框架通过`m_pDevMngFrm->SendMessage(WM_REFRESH_NAV_DEVICE)`通知设备管理框架刷新设备列表。文件导入导出操作通过`theApp.m_pIOManager`执行,并在完成后发送刷新消息。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class CMainFrame {
|
||||
+CDevMngFrame* m_pDevMngFrm
|
||||
+CDataMngFrame* m_pDataMngFrm
|
||||
+CSptMngFrame* m_pSptMngFrm
|
||||
+OnRefresh()
|
||||
+OnFileExp()
|
||||
+OnFileImp()
|
||||
}
|
||||
class CDevMngFrame {
|
||||
+OnRefreshNavDevice()
|
||||
}
|
||||
class CDataMngFrame {
|
||||
+OnRefresh()
|
||||
}
|
||||
class CIOManager {
|
||||
+Export()
|
||||
+Import()
|
||||
}
|
||||
CMainFrame --> CDevMngFrame : 持有引用
|
||||
CMainFrame --> CDataMngFrame : 持有引用
|
||||
CMainFrame --> CIOManager : 通过theApp访问
|
||||
CMainFrame ..> CDevMngFrame : 发送WM_REFRESH_NAV_DEVICE
|
||||
CMainFrame ..> CDataMngFrame : 发送WM_REFRESH
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [MainFrm.h](file://h/MainFrm.h#L40-L42)
|
||||
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L554-L555)
|
||||
|
||||
**Section sources**
|
||||
- [MainFrm.h](file://h/MainFrm.h#L40-L42)
|
||||
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L554-L555)
|
||||
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L69-L72)
|
||||
|
||||
## MFC框架下的窗口生命周期管理
|
||||
|
||||
MFC框架通过一系列虚拟方法和消息处理机制管理窗口生命周期。窗口的创建、销毁和消息处理遵循特定的顺序和模式。
|
||||
|
||||
**创建过程**:
|
||||
1. 构造函数:`CMainFrame()`进行成员变量初始化
|
||||
2. `PreCreateWindow`:修改窗口样式和类属性
|
||||
3. `OnCreate`:创建子控件(工具栏、状态栏)
|
||||
4. `LoadFrame`:加载框架资源并显示窗口
|
||||
|
||||
**销毁过程**:
|
||||
1. `WM_CLOSE`消息:触发窗口关闭
|
||||
2. 析构函数:`~CMainFrame()`清理资源
|
||||
3. `PostNcDestroy`:删除C++对象(在`CSplashWnd`中实现)
|
||||
|
||||
子窗口通过`OnCmdMsg`方法实现命令消息的传递,确保视图能够优先处理命令。这种分层的消息处理机制是MFC框架的核心特性之一。
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph 创建流程
|
||||
A[构造函数] --> B[PreCreateWindow]
|
||||
B --> C[OnCreate]
|
||||
C --> D[LoadFrame]
|
||||
D --> E[ShowWindow]
|
||||
end
|
||||
subgraph 销毁流程
|
||||
F[WM_CLOSE] --> G[析构函数]
|
||||
G --> H[PostNcDestroy]
|
||||
H --> I[对象删除]
|
||||
end
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L111-L127)
|
||||
- [ChildFrm.cpp](file://cpp/Views/ChildFrm.cpp#L33-L43)
|
||||
- [Splash.cpp](file://cpp/Views/Splash.cpp#L100-L104)
|
||||
|
||||
**Section sources**
|
||||
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp#L111-L127)
|
||||
- [ChildFrm.cpp](file://cpp/Views/ChildFrm.cpp#L33-L43)
|
||||
- [Splash.cpp](file://cpp/Views/Splash.cpp#L100-L104)
|
||||
|
||||
## 性能优化建议
|
||||
|
||||
针对Geomative Studio主界面的性能优化,建议从以下几个方面着手:
|
||||
|
||||
**减少重绘开销**:
|
||||
- 使用双缓冲技术减少闪烁
|
||||
- 仅重绘无效区域而非整个窗口
|
||||
- 延迟更新,批量处理UI变更
|
||||
|
||||
**减少消息处理延迟**:
|
||||
- 避免在消息处理函数中执行耗时操作
|
||||
- 将长时间运行的任务移至工作线程
|
||||
- 使用定时器分批处理大量数据更新
|
||||
|
||||
**内存管理优化**:
|
||||
- 及时释放不再使用的子窗口
|
||||
- 使用智能指针管理动态创建的对象
|
||||
- 缓存频繁访问的资源
|
||||
|
||||
**启动性能优化**:
|
||||
- 延迟加载非关键模块
|
||||
- 优化数据库连接和初始化流程
|
||||
- 减少启动时的同步操作
|
||||
|
||||
通过实施这些优化措施,可以显著提升主界面的响应速度和用户体验。
|
||||
|
||||
**Section sources**
|
||||
- [MainFrm.cpp](file://cpp/Views/MainFrm.cpp)
|
||||
- [ChildFrm.cpp](file://cpp/Views/ChildFrm.cpp)
|
||||
- [Splash.cpp](file://cpp/Views/Splash.cpp)
|
||||
@@ -0,0 +1,269 @@
|
||||
# 数据管理界面
|
||||
|
||||
<cite>
|
||||
**本文档引用的文件**
|
||||
- [datamngframe.cpp](file://cpp/Views/datamngframe.cpp)
|
||||
- [DialListMeasuData.cpp](file://cpp/Views/DialListMeasuData.cpp)
|
||||
- [DialListMeasuGR.cpp](file://cpp/Views/DialListMeasuGR.cpp)
|
||||
- [DialListRealTimeMeasuData.cpp](file://cpp/Views/DialListRealTimeMeasuData.cpp)
|
||||
- [DialListRealTimeMeasuGR.cpp](file://cpp/Views/DialListRealTimeMeasuGR.cpp)
|
||||
- [DialMeasureData.cpp](file://cpp/Views/DialMeasureData.cpp)
|
||||
- [DialMeasureDetailInfo.cpp](file://cpp/Views/DialMeasureDetailInfo.cpp)
|
||||
- [DialRealTimeMeasureData.cpp](file://cpp/Views/DialRealTimeMeasureData.cpp)
|
||||
- [TdManager.h](file://h/TdManager.h)
|
||||
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp)
|
||||
- [DataOperator.h](file://h/DataOperator.h)
|
||||
- [TaskDataOper.h](file://h/TaskDataOper.h)
|
||||
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [数据管理框架](#数据管理框架)
|
||||
2. [测量数据列表展示](#测量数据列表展示)
|
||||
3. [实时数据刷新机制](#实时数据刷新机制)
|
||||
4. [测量详情查看功能](#测量详情查看功能)
|
||||
5. [实时监控界面行为](#实时监控界面行为)
|
||||
6. [数据查询、过滤与导出](#数据查询过滤与导出)
|
||||
7. [大数据量列表优化](#大数据量列表优化)
|
||||
8. [操作指南](#操作指南)
|
||||
9. [高级开发者指南](#高级开发者指南)
|
||||
|
||||
## 数据管理框架
|
||||
|
||||
数据管理框架的核心是`CDataMngFrame`类,它负责组织和管理数据管理界面的整体结构。该框架采用MDI(多文档界面)设计,通过分割窗口(Splitter Window)将界面分为左右两个视图:左侧为导航数据视图(`CNavDataView`),右侧为应用数据视图(`CAppDataView`)。
|
||||
|
||||
框架通过消息映射(`BEGIN_MESSAGE_MAP`)处理各种数据管理操作,如创建、删除、导出和刷新数据。当用户在导航树中选择一个数据项时,框架会根据数据类型(如2D电阻率、3D激电等)动态创建相应的应用视图,并加载和显示数据。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class CDataMngFrame {
|
||||
+m_pNavDataView : CView*
|
||||
+m_pAppDataView : CView*
|
||||
+m_pDataOperator : CDataOperator*
|
||||
+OnCreateClient() bool
|
||||
+OnSchedule() LRESULT
|
||||
+ShowAppView() bool
|
||||
+ShowContentListByPageView() bool
|
||||
}
|
||||
class CDataOperator {
|
||||
+ShowRsp2DTdInfo() void
|
||||
+ShowIps2DpTdInfo() void
|
||||
+ShowSP2DTdInfo() void
|
||||
+LoadRsp2dRecordbyPage() void
|
||||
+LoadIpsp2dRecordbyPage() void
|
||||
+LoadSP2dRecordbyPage() void
|
||||
}
|
||||
CDataMngFrame --> CDataOperator : "使用"
|
||||
CDataMngFrame --> CView : "包含 m_pNavDataView"
|
||||
CDataMngFrame --> CView : "包含 m_pAppDataView"
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [datamngframe.cpp](file://cpp/Views/datamngframe.cpp#L49-L602)
|
||||
|
||||
**Section sources**
|
||||
- [datamngframe.cpp](file://cpp/Views/datamngframe.cpp#L1-L800)
|
||||
|
||||
## 测量数据列表展示
|
||||
|
||||
测量数据列表的展示逻辑主要由`CDialListMeasuData`和`CDialListMeasuGR`两个类实现。`CDialListMeasuData`负责显示测量数据,而`CDialListMeasuGR`负责显示接地电阻信息。
|
||||
|
||||
`CDialListMeasuData`在`OnInitDialog`方法中初始化列表控件,设置列标题(如ID、A、B、M、N、Stack、K、V(mV)、I(mA)、R0(Ohm*m)等),并从数据库查询数据填充列表。它支持分页显示,通过“上一页”和“下一页”按钮进行导航。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[初始化对话框] --> B[设置列表控件样式]
|
||||
B --> C[插入列标题]
|
||||
C --> D[查询数据库获取数据]
|
||||
D --> E{数据是否为空?}
|
||||
E --> |否| F[调用OnShowTdData显示数据]
|
||||
E --> |是| G[返回]
|
||||
F --> H[遍历数据向量]
|
||||
H --> I[格式化并插入列表项]
|
||||
I --> J[设置列表项文本]
|
||||
J --> K{是否遍历完成?}
|
||||
K --> |否| H
|
||||
K --> |是| L[结束]
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [DialListMeasuData.cpp](file://cpp/Views/DialListMeasuData.cpp#L52-L120)
|
||||
|
||||
**Section sources**
|
||||
- [DialListMeasuData.cpp](file://cpp/Views/DialListMeasuData.cpp#L1-L333)
|
||||
- [DialListMeasuGR.cpp](file://cpp/Views/DialListMeasuGR.cpp#L1-L113)
|
||||
|
||||
## 实时数据刷新机制
|
||||
|
||||
实时数据的刷新机制由`CDialListRealTimeMeasureData`和`CDialListRealTimeMeasuGR`类实现。与静态数据列表不同,实时数据需要在测量过程中动态更新。
|
||||
|
||||
`CDialListRealTimeMeasureData`提供了三种数据更新方法:
|
||||
1. `OnShowTdData`: 一次性清空并重新填充整个列表。
|
||||
2. `OnShowTdDataAppend`: 在列表末尾追加新数据。
|
||||
3. `OnShowTdDataUpdate`: 智能更新,先查找是否存在该数据,存在则更新,不存在则追加。
|
||||
|
||||
这种设计确保了在高频率数据更新场景下的流畅性和准确性。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Device as "测量设备"
|
||||
participant App as "应用程序"
|
||||
participant List as "实时数据列表"
|
||||
Device->>App : 发送测量数据包
|
||||
App->>App : 解析数据包
|
||||
App->>List : 调用OnShowTdDataUpdate
|
||||
List->>List : 查找ID匹配的列表项
|
||||
alt 找到匹配项
|
||||
List->>List : 更新现有项的数据
|
||||
else 未找到匹配项
|
||||
List->>List : 在末尾追加新项
|
||||
end
|
||||
List->>List : 确保新项可见(EnsureVisible)
|
||||
List->>List : 更新界面
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [DialListRealTimeMeasuData.cpp](file://cpp/Views/DialListRealTimeMeasuData.cpp#L171-L332)
|
||||
- [DialListRealTimeMeasuData.cpp](file://cpp/Views/DialListRealTimeMeasuData.cpp#L251-L332)
|
||||
|
||||
**Section sources**
|
||||
- [DialListRealTimeMeasuData.cpp](file://cpp/Views/DialListRealTimeMeasuData.cpp#L1-L486)
|
||||
- [DialListRealTimeMeasuGR.cpp](file://cpp/Views/DialListRealTimeMeasuGR.cpp#L1-L244)
|
||||
|
||||
## 测量详情查看功能
|
||||
|
||||
测量详情的查看功能由`CDialMeasureDetailInfo`类实现。该类提供了一个包含“数据”和“接地电阻”两个标签页的对话框,允许用户在一个界面中查看任务的详细信息。
|
||||
|
||||
其核心逻辑在`OnInitDialog`方法中:
|
||||
1. 根据传入的任务参数(`STRemTaskArg`),创建并初始化`CDialListMeasuTask`和`CDialListMeasuGR`两个子控件。
|
||||
2. 分别调用`ShowPage(1)`和`GetGRRequest(m_stTaskArg)`从云端获取任务数据和接地电阻信息。
|
||||
3. 通过标签页的切换事件(`OnSelchangeTabChg`)来显示或隐藏相应的子控件。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class CDialMeasureDetailInfo {
|
||||
+m_dialListMeasuTask : CDialListMeasuTask
|
||||
+m_dialListMeasuGR : CDialListMeasuGR
|
||||
+OnInitDialog() bool
|
||||
+OnSelchangeTabChg() void
|
||||
}
|
||||
class CDialListMeasuTask {
|
||||
+ShowPage() void
|
||||
}
|
||||
class CDialListMeasuGR {
|
||||
+GetGRRequest() void
|
||||
}
|
||||
CDialMeasureDetailInfo --> CDialListMeasuTask
|
||||
CDialMeasureDetailInfo --> CDialListMeasuGR
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [DialMeasureDetailInfo.cpp](file://cpp/Views/DialMeasureDetailInfo.cpp#L56-L104)
|
||||
|
||||
**Section sources**
|
||||
- [DialMeasureData.cpp](file://cpp/Views/DialMeasureData.cpp#L1-L2262)
|
||||
- [DialMeasureDetailInfo.cpp](file://cpp/Views/DialMeasureDetailInfo.cpp#L1-L186)
|
||||
|
||||
## 实时监控界面行为
|
||||
|
||||
实时监控界面由`CDialRealTimeMeasureData`类控制。该类不仅管理数据列表,还处理用户与测量过程的交互,如开始测量、暂停测量、单点测量等。
|
||||
|
||||
其行为逻辑如下:
|
||||
- **按钮状态管理**: 通过`SetBtnStatus`方法根据当前测量状态(如`EN_MEASU_BTN_MEASU_ALL`)启用或禁用按钮,防止用户进行无效操作。
|
||||
- **测量命令发送**: 当用户点击“开始测量”时,`OnMeasureAll`方法会构造一个`STTrusteeTaskTable`结构体,并通过`PostNetRequest`发送到设备,启动测量任务。
|
||||
- **数据接收与处理**: 重写`ProcRcvMeasuData`等方法来处理从设备接收的实时数据,并更新UI。
|
||||
|
||||
**Section sources**
|
||||
- [DialRealTimeMeasureData.cpp](file://cpp/Views/DialRealTimeMeasureData.cpp#L1-L1879)
|
||||
|
||||
## 数据查询、过滤与导出
|
||||
|
||||
数据查询、过滤和导出功能主要由`CTdManager`和`CDataOperator`两个核心类实现。
|
||||
|
||||
`CTdManager`作为数据管理器,提供了与数据库交互的底层接口:
|
||||
- **查询**: `ShowTdListByTz`、`ShowTdListByProject`等方法用于从数据库查询任务列表。
|
||||
- **删除**: `DeleteRsp2DTd`、`DeleteIpsp2DTd`等方法用于删除不同类型的数据。
|
||||
- **导入/导出**: `Import2DTdConToDB`、`ExportRsp2DTdToDAT`等方法用于数据的导入和导出。
|
||||
|
||||
`CDataOperator`则作为`CTdManager`的上层封装,为UI提供更便捷的调用接口。例如,`ExportRsp2DTdToExcel`方法会调用`CTdManager`的底层功能,将2D电阻率数据导出为Excel文件。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class CDataOperator {
|
||||
+ExportRsp2DTdToExcel() UINT
|
||||
+ExportRsp2DTdToDAT() UINT
|
||||
+ExportRsp2DTdToCSV() UINT
|
||||
+ShowRsp2DTdInfo() void
|
||||
+LoadRsp2dRecordbyPage() void
|
||||
}
|
||||
class CTdManager {
|
||||
+ShowTdListByTz() bool
|
||||
+DeleteRsp2DTd() void
|
||||
+Import2DTdConToDB() bool
|
||||
+ExportRsp2DTdToDAT() UINT
|
||||
}
|
||||
CDataOperator --> CTdManager : "使用"
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [DataOperator.h](file://h/DataOperator.h#L29-L87)
|
||||
- [TdManager.h](file://h/TdManager.h#L33-L87)
|
||||
|
||||
**Section sources**
|
||||
- [TdManager.h](file://h/TdManager.h#L1-L109)
|
||||
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp#L1-L6839)
|
||||
- [DataOperator.h](file://h/DataOperator.h#L1-L174)
|
||||
|
||||
## 大数据量列表优化
|
||||
|
||||
在处理大数据量时,直接加载所有数据会导致界面卡顿。项目通过以下两种技术进行优化:
|
||||
|
||||
1. **分页加载**: `CDataOperator`类中的`LoadRsp2dRecordbyPage`等方法实现了分页查询。它接收一个起始ID和页大小,只从数据库加载指定范围的数据,显著减少了内存占用和加载时间。
|
||||
2. **虚拟列表**: 虽然代码中未直接体现,但`CListCtrl`控件支持虚拟列表(Virtual List)模式。在这种模式下,控件不会存储所有数据,而是通过`LVN_GETDISPINFO`消息在需要显示某一行时,由程序动态提供该行的数据。这是一种处理海量数据的高效方式。
|
||||
|
||||
**Section sources**
|
||||
- [DataOperator.h](file://h/DataOperator.h#L76-L83)
|
||||
- [TaskDataOper.h](file://h/TaskDataOper.h#L378-L382)
|
||||
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp#L418-L513)
|
||||
|
||||
## 操作指南
|
||||
|
||||
### 初学者:数据查看与导出
|
||||
|
||||
1. **查看数据**:
|
||||
* 打开“数据管理”界面。
|
||||
* 在左侧导航树中选择一个任务。
|
||||
* 右侧会自动显示该任务的测量数据列表。
|
||||
* 使用“上一页”和“下一页”按钮浏览不同页面的数据。
|
||||
2. **导出数据**:
|
||||
* 在导航树中右键点击要导出的任务。
|
||||
* 选择“导出”菜单下的格式,如“导出为Excel”或“导出为DAT文件”。
|
||||
* 在弹出的对话框中选择保存路径,点击“保存”即可。
|
||||
|
||||
## 高级开发者指南
|
||||
|
||||
### 高频率数据更新场景下的UI线程安全处理
|
||||
|
||||
在实时监控等高频率数据更新场景下,数据接收通常在后台线程中进行,而UI更新必须在主线程(UI线程)中完成。为确保线程安全,项目采用了以下方案:
|
||||
|
||||
1. **消息传递机制**: 后台线程不直接操作UI控件,而是通过`PostMessage`或`PostNetRequest`向UI线程发送自定义消息(如`WM_MSG_UPDATE_TASK_LIST`)。
|
||||
2. **UI线程处理**: UI线程的消息循环接收到消息后,调用相应的消息处理函数(如`OnShowTdDataUpdate`)来安全地更新列表控件。
|
||||
|
||||
这种“生产者-消费者”模式有效地隔离了数据处理和UI更新,避免了多线程访问共享资源导致的竞态条件和崩溃。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant WorkerThread as "工作线程"
|
||||
participant UIThread as "UI线程"
|
||||
participant ListCtrl as "列表控件"
|
||||
WorkerThread->>WorkerThread : 接收测量数据
|
||||
WorkerThread->>UIThread : PostMessage(WM_SHOW_TD_DATA_UPDATE, 数据指针)
|
||||
UIThread->>UIThread : 消息循环接收到消息
|
||||
UIThread->>UIThread : 调用OnShowTdDataUpdate
|
||||
UIThread->>ListCtrl : 安全地更新列表项
|
||||
ListCtrl->>UIThread : 更新完成
|
||||
```
|
||||
|
||||
**Section sources**
|
||||
- [DialListRealTimeMeasuData.cpp](file://cpp/Views/DialListRealTimeMeasuData.cpp#L344-L343)
|
||||
- [DialRealTimeMeasureData.cpp](file://cpp/Views/DialRealTimeMeasureData.cpp#L593-L594)
|
||||
@@ -0,0 +1,266 @@
|
||||
# 设备管理界面
|
||||
|
||||
<cite>
|
||||
**本文档引用的文件**
|
||||
- [devmngframe.cpp](file://cpp/Views/devmngframe.cpp)
|
||||
- [DailLogin.cpp](file://cpp/Views/DailLogin.cpp)
|
||||
- [DialFindComShow.cpp](file://cpp/Views/DialFindComShow.cpp)
|
||||
- [DialShowDevParam.cpp](file://cpp/Views/DialShowDevParam.cpp)
|
||||
- [DialPlcStatusShow.cpp](file://cpp/Views/DialPlcStatusShow.cpp)
|
||||
- [DialDevStatusTimerShow.cpp](file://cpp/Views/DialDevStatusTimerShow.cpp)
|
||||
- [DevManager.cpp](file://cpp/Managers/DevManager.cpp)
|
||||
- [DevOperator.cpp](file://cpp/Operator/DevOperator.cpp)
|
||||
- [Device.cpp](file://cpp/ProblemZone/Device.cpp)
|
||||
- [NetRequestDialog.cpp](file://cpp/socket/NetRequestDialog.cpp)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构概述](#架构概述)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖关系分析](#依赖关系分析)
|
||||
7. [性能考虑](#性能考虑)
|
||||
8. [故障排除指南](#故障排除指南)
|
||||
9. [结论](#结论)
|
||||
|
||||
## 简介
|
||||
本文档深入分析GeomativeStudio项目中设备管理相关的UI组件实现。重点介绍devmngframe.cpp中设备管理框架的布局结构与消息响应机制,DailLogin.cpp中的登录验证流程,DialFindComShow.cpp中的串口检测对话框逻辑,DialShowDevParam.cpp中的设备参数展示机制。解释DialPlcStatusShow.cpp和DialDevStatusTimerShow.cpp中PLC状态与定时状态的实时更新策略。结合MFC消息映射机制,说明用户操作如何触发CDevManager的接口调用。为初学者提供UI与设备通信协同工作的概念性解释,为高级开发者提供多线程环境下UI刷新的最佳实践。
|
||||
|
||||
## 项目结构
|
||||
项目采用典型的MFC应用程序结构,设备管理相关的UI组件主要位于cpp/Views目录下。核心的设备管理框架由devmngframe.cpp实现,负责整体布局和消息分发。各个功能模块如登录、串口检测、设备参数展示等通过独立的对话框类实现。业务逻辑与数据管理由cpp/Managers和cpp/Operator目录下的类负责,形成清晰的分层架构。
|
||||
|
||||
**Section sources**
|
||||
- [devmngframe.cpp](file://cpp/Views/devmngframe.cpp)
|
||||
- [DailLogin.cpp](file://cpp/Views/DailLogin.cpp)
|
||||
|
||||
## 核心组件
|
||||
设备管理界面的核心组件包括设备管理框架、登录验证、串口检测、设备参数展示和状态监控等模块。这些组件通过MFC的消息映射机制协同工作,实现用户与设备的交互。CDevManager类作为设备管理的核心,负责设备的生命周期管理和状态维护。
|
||||
|
||||
**Section sources**
|
||||
- [devmngframe.cpp](file://cpp/Views/devmngframe.cpp)
|
||||
- [DevManager.cpp](file://cpp/Managers/DevManager.cpp)
|
||||
- [DevOperator.cpp](file://cpp/Operator/DevOperator.cpp)
|
||||
|
||||
## 架构概述
|
||||
系统采用MFC文档/视图架构,设备管理功能通过CMDIChildWnd派生的CDevMngFrame类实现。该框架使用CSplitterWnd进行界面分割,左侧为导航树视图,右侧为内容显示区域。通过消息映射机制处理用户操作,调用CDevOperator和CDevManager类完成具体业务逻辑。
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "UI层"
|
||||
A[CDevMngFrame] --> B[CNavDevView]
|
||||
A --> C[CAppDevView]
|
||||
A --> D[CAppDevOLView]
|
||||
end
|
||||
subgraph "业务逻辑层"
|
||||
E[CDevOperator] --> F[CDevManager]
|
||||
E --> G[CDevice]
|
||||
end
|
||||
subgraph "数据层"
|
||||
F --> H[数据库]
|
||||
G --> I[串口通信]
|
||||
end
|
||||
A --> E
|
||||
B --> E
|
||||
C --> E
|
||||
D --> E
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [devmngframe.cpp](file://cpp/Views/devmngframe.cpp)
|
||||
- [DevOperator.cpp](file://cpp/Operator/DevOperator.cpp)
|
||||
- [DevManager.cpp](file://cpp/Managers/DevManager.cpp)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### 设备管理框架分析
|
||||
CDevMngFrame类实现了设备管理的主框架,负责界面布局和消息处理。通过CSplitterWnd将界面分为导航区域和内容显示区域,支持动态切换视图以显示不同状态的设备信息。
|
||||
|
||||
#### 布局结构
|
||||
```mermaid
|
||||
classDiagram
|
||||
class CDevMngFrame {
|
||||
+CSplitterWnd m_splitter
|
||||
+CView* m_pAppDevView
|
||||
+CView* m_pNavDevView
|
||||
+OnCreateClient()
|
||||
+ShowAppView()
|
||||
}
|
||||
class CNavDevView {
|
||||
+CTreeCtrl m_devTree
|
||||
}
|
||||
class CAppDevView {
|
||||
+CListCtrl m_devDetailList
|
||||
}
|
||||
class CAppDevOLView {
|
||||
+CListCtrl m_devOLDetailList
|
||||
+CListCtrl m_devOLGRList
|
||||
+CListCtrl m_devOLACList
|
||||
}
|
||||
CDevMngFrame --> CNavDevView : "包含"
|
||||
CDevMngFrame --> CAppDevView : "包含"
|
||||
CDevMngFrame --> CAppDevOLView : "包含"
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [devmngframe.cpp](file://cpp/Views/devmngframe.cpp)
|
||||
- [navdevview.h](file://h/navdevview.h)
|
||||
- [appdevview.h](file://h/appdevview.h)
|
||||
|
||||
#### 消息响应机制
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant 用户
|
||||
participant CDevMngFrame
|
||||
participant CDevOperator
|
||||
participant CDevManager
|
||||
用户->>CDevMngFrame : 点击"修改设备参数"
|
||||
CDevMngFrame->>CDevMngFrame : OnModifyDeviceParameter()
|
||||
CDevMngFrame->>CDevOperator : ModifyDeviceParameter()
|
||||
CDevOperator->>CDevManager : GetDeviceByID()
|
||||
CDevManager-->>CDevOperator : 返回CDevice对象
|
||||
CDevOperator->>CDevice : ModifyParameter()
|
||||
CDevice-->>CDevOperator : 显示参数对话框
|
||||
CDevOperator->>CDevice : ShowOLDetailInfo()
|
||||
CDevice-->>CDevOperator : 更新UI
|
||||
CDevOperator-->>CDevMngFrame : 返回结果
|
||||
CDevMngFrame-->>用户 : 显示更新后的界面
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [devmngframe.cpp](file://cpp/Views/devmngframe.cpp)
|
||||
- [DevOperator.cpp](file://cpp/Operator/DevOperator.cpp)
|
||||
- [Device.cpp](file://cpp/ProblemZone/Device.cpp)
|
||||
|
||||
### 登录验证流程分析
|
||||
DailLogin.cpp实现了系统的登录验证功能,包括用户身份验证、密码保存和自动登录等特性。
|
||||
|
||||
#### 登录验证流程
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([开始]) --> ValidateInput["验证输入参数"]
|
||||
ValidateInput --> InputValid{"输入有效?"}
|
||||
InputValid --> |否| ReturnError["显示错误信息"]
|
||||
InputValid --> |是| CheckUserID["验证用户ID"]
|
||||
CheckUserID --> UserIDValid{"ID正确?"}
|
||||
UserIDValid --> |否| ReturnError
|
||||
UserIDValid --> |是| CheckPassword["验证密码"]
|
||||
CheckPassword --> PasswordValid{"密码正确?"}
|
||||
PasswordValid --> |否| ReturnError
|
||||
PasswordValid --> |是| SaveSettings["保存设置"]
|
||||
SaveSettings --> CheckSave["是否保存密码?"]
|
||||
CheckSave --> |是| SavePassword["写入config.ini"]
|
||||
CheckSave --> |否| SkipSave
|
||||
SkipSave --> CheckAutoLogin["是否自动登录?"]
|
||||
CheckAutoLogin --> |是| SaveAutoLogin["写入config.ini"]
|
||||
CheckAutoLogin --> |否| SkipAutoLogin
|
||||
SkipAutoLogin --> Complete["登录成功"]
|
||||
ReturnError --> End([结束])
|
||||
Complete --> End
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [DailLogin.cpp](file://cpp/Views/DailLogin.cpp)
|
||||
|
||||
### 串口检测对话框逻辑
|
||||
DialFindComShow.cpp实现了串口检测结果的显示功能,用于向用户展示串口连接状态。
|
||||
|
||||
#### 串口检测逻辑
|
||||
```mermaid
|
||||
classDiagram
|
||||
class CDialFindComShow {
|
||||
+CString m_strShowCom
|
||||
+OnInitDialog()
|
||||
}
|
||||
CDialFindComShow --> CDialog : "继承"
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [DialFindComShow.cpp](file://cpp/Views/DialFindComShow.cpp)
|
||||
|
||||
### 设备参数展示机制
|
||||
DialShowDevParam.cpp实现了设备参数的展示和修改功能,支持参数的本地编辑和云端同步。
|
||||
|
||||
#### 参数展示与同步
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant CDevMngFrame
|
||||
participant CDialShowDevParam
|
||||
participant Network
|
||||
CDevMngFrame->>CDialShowDevParam : OnShowDevParam()
|
||||
CDialShowDevParam->>CDialShowDevParam : 显示参数对话框
|
||||
CDialShowDevParam->>CDialShowDevParam : 用户修改参数
|
||||
CDialShowDevParam->>CDialShowDevParam : 验证输入
|
||||
CDialShowDevParam->>Network : 发送修改请求
|
||||
Network-->>CDialShowDevParam : 接收响应
|
||||
CDialShowDevParam-->>CDevMngFrame : 返回结果
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [DialShowDevParam.cpp](file://cpp/Views/DialShowDevParam.cpp)
|
||||
- [devmngframe.cpp](file://cpp/Views/devmngframe.cpp)
|
||||
|
||||
### PLC状态与定时状态实时更新
|
||||
DialPlcStatusShow.cpp和DialDevStatusTimerShow.cpp实现了PLC状态和定时状态的实时监控功能。
|
||||
|
||||
#### 状态更新策略
|
||||
```mermaid
|
||||
classDiagram
|
||||
class CDialPlcStatusShow {
|
||||
+STRemPlcData* m_pRemPlcData
|
||||
+OnInitDialog()
|
||||
}
|
||||
class CDialDevStatusTimerShow {
|
||||
+CListCtrl m_listData
|
||||
+ShowPlcStatusData()
|
||||
}
|
||||
class CTaskDataOper {
|
||||
+QueryPlcStatusData()
|
||||
}
|
||||
CDialDevStatusTimerShow --> CTaskDataOper : "使用"
|
||||
CDialPlcStatusShow --> CDialDevStatusTimerShow : "关联"
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [DialPlcStatusShow.cpp](file://cpp/Views/DialPlcStatusShow.cpp)
|
||||
- [DialDevStatusTimerShow.cpp](file://cpp/Views/DialDevStatusTimerShow.cpp)
|
||||
- [TaskDataOper.h](file://h/TaskDataOper.h)
|
||||
|
||||
**Section sources**
|
||||
- [DialPlcStatusShow.cpp](file://cpp/Views/DialPlcStatusShow.cpp)
|
||||
- [DialDevStatusTimerShow.cpp](file://cpp/Views/DialDevStatusTimerShow.cpp)
|
||||
|
||||
## 依赖关系分析
|
||||
系统各组件之间存在清晰的依赖关系,UI组件依赖于业务逻辑组件,业务逻辑组件又依赖于数据访问组件。这种分层架构有助于代码的维护和扩展。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[devmngframe.cpp] --> B[DevOperator.cpp]
|
||||
B --> C[DevManager.cpp]
|
||||
C --> D[Device.cpp]
|
||||
D --> E[SComPort.cpp]
|
||||
A --> F[DialShowDevParam.cpp]
|
||||
F --> G[NetRequestDialog.cpp]
|
||||
A --> H[DialPlcStatusShow.cpp]
|
||||
H --> I[DialDevStatusTimerShow.cpp]
|
||||
I --> J[TaskDataOper.cpp]
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [devmngframe.cpp](file://cpp/Views/devmngframe.cpp)
|
||||
- [DevOperator.cpp](file://cpp/Operator/DevOperator.cpp)
|
||||
- [DevManager.cpp](file://cpp/Managers/DevManager.cpp)
|
||||
|
||||
## 性能考虑
|
||||
在多线程环境下进行UI刷新时,应避免在主线程中执行耗时操作。建议使用工作线程处理设备通信,通过PostMessage或SendMessage将结果发送回UI线程进行界面更新。对于频繁的状态更新,可以采用定时器机制,避免过度刷新导致的性能问题。
|
||||
|
||||
## 故障排除指南
|
||||
常见问题包括设备连接失败、参数同步异常和界面刷新延迟等。检查网络连接状态、验证设备ID和类型、确认串口配置正确性是解决问题的关键步骤。使用日志文件可以帮助定位具体的问题根源。
|
||||
|
||||
**Section sources**
|
||||
- [devmngframe.cpp](file://cpp/Views/devmngframe.cpp)
|
||||
- [Device.cpp](file://cpp/ProblemZone/Device.cpp)
|
||||
|
||||
## 结论
|
||||
本文档详细分析了GeomativeStudio项目中设备管理相关的UI组件实现。通过MFC框架实现了功能完整的设备管理界面,各组件之间通过清晰的消息传递机制协同工作。系统架构合理,代码组织规范,为类似应用的开发提供了有价值的参考。
|
||||
@@ -0,0 +1,358 @@
|
||||
# 项目管理界面
|
||||
|
||||
<cite>
|
||||
**本文档引用的文件**
|
||||
- [taskmngframe.cpp](file://cpp/Views/taskmngframe.cpp)
|
||||
- [DialNew1DTask.cpp](file://cpp/Views/DialNew1DTask.cpp)
|
||||
- [DialNew2DTask.cpp](file://cpp/Views/DialNew2DTask.cpp)
|
||||
- [DialNew3DTask.cpp](file://cpp/Views/DialNew3DTask.cpp)
|
||||
- [DialCfgTaskPacket.cpp](file://cpp/Views/DialCfgTaskPacket.cpp)
|
||||
- [DialCfgTerrain.cpp](file://cpp/Views/DialCfgTerrain.cpp)
|
||||
- [DialTaskTree.cpp](file://cpp/Views/DialTaskTree.cpp)
|
||||
- [DialTaskManager.cpp](file://cpp/Views/DialTaskManager.cpp)
|
||||
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [任务管理框架与导航逻辑](#任务管理框架与导航逻辑)
|
||||
2. [测量任务创建流程](#测量任务创建流程)
|
||||
3. [任务包配置机制](#任务包配置机制)
|
||||
4. [地形参数设置逻辑](#地形参数设置逻辑)
|
||||
5. [任务树形视图构建与交互](#任务树形视图构建与交互)
|
||||
6. [项目数据持久化与加载](#项目数据持久化与加载)
|
||||
7. [任务参数验证与数据传递](#任务参数验证与数据传递)
|
||||
8. [任务配置工作流](#任务配置工作流)
|
||||
9. [UI响应性能优化建议](#ui响应性能优化建议)
|
||||
|
||||
## 任务管理框架与导航逻辑
|
||||
|
||||
任务管理框架由`taskmngframe.cpp`实现,作为MDI子窗口继承自`CMDIChildWnd`。该框架负责组织和管理所有与任务相关的UI组件,提供统一的导航界面。框架通过消息映射处理窗口激活、关闭等事件,确保在用户切换不同任务管理视图时能够正确更新状态和界面元素。
|
||||
|
||||
**Section sources**
|
||||
- [taskmngframe.cpp](file://cpp/Views/taskmngframe.cpp#L1-L36)
|
||||
|
||||
## 测量任务创建流程
|
||||
|
||||
### 1D测量任务创建
|
||||
|
||||
`DialNew1DTask.cpp`实现了1D测量任务的创建对话框。该对话框初始化时会根据当前UI语言设置控件文本,并从`CTaskDataOper`操作类查询可用的介质类型和脚本信息。用户选择测试类型(电阻率、激电、自电)后,系统会动态更新发射波形和发射周期的选项。在用户点击"创建"按钮后,系统会执行完整的参数验证,包括任务名、测试方式、装置类型、脚本、迭代次数等,确保所有必填项都已正确填写且符合取值范围。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([开始创建1D任务]) --> Init["初始化对话框\n设置语言、加载介质和脚本"]
|
||||
Init --> SelectType["用户选择测试类型\n(电阻率/激电/自电)"]
|
||||
SelectType --> UpdateOptions["更新发射波形和周期选项"]
|
||||
UpdateOptions --> UserInput["用户输入任务参数\n任务名、位置、脚本等"]
|
||||
UserInput --> Validate["点击创建时验证参数"]
|
||||
Validate --> CheckName{"任务名为空?"}
|
||||
CheckName --> |是| ShowError1["显示错误提示"]
|
||||
CheckName --> |否| CheckType{"测试方式未选?"}
|
||||
CheckType --> |是| ShowError2["显示错误提示"]
|
||||
CheckType --> |否| CheckArray{"装置类型未选?"}
|
||||
CheckArray --> |是| ShowError3["显示错误提示"]
|
||||
CheckArray --> |否| CheckScript{"脚本未选?"}
|
||||
CheckScript --> |是| ShowError4["显示错误提示"]
|
||||
CheckScript --> |否| CheckStacking{"迭代次数有效?"}
|
||||
CheckStacking --> |否| ShowError5["显示错误提示"]
|
||||
CheckStacking --> |是| CreateTask["调用CTaskDataOper::Create1DTask\n创建任务"]
|
||||
CreateTask --> Success{"创建成功?"}
|
||||
Success --> |是| CloseDialog["关闭对话框"]
|
||||
Success --> |否| Return["返回等待用户修正"]
|
||||
ShowError1 --> Return
|
||||
ShowError2 --> Return
|
||||
ShowError3 --> Return
|
||||
ShowError4 --> Return
|
||||
ShowError5 --> Return
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [DialNew1DTask.cpp](file://cpp/Views/DialNew1DTask.cpp#L1-L381)
|
||||
|
||||
### 2D测量任务创建
|
||||
|
||||
`DialNew2DTask.cpp`实现了2D测量任务的创建对话框。与1D任务相比,2D任务需要更多的参数配置,包括电缆布线方式、起始/结束电极、电极间距、孔间距(对于交叉孔装置)等。对话框在初始化时会根据装置类型动态显示或隐藏相关控件,例如交叉孔装置会显示孔间距输入框。当用户选择不同的测试类型时,系统会过滤可用的电缆布线方式,确保选择的配置是有效的。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([开始创建2D任务]) --> Init["初始化对话框\n加载介质、脚本、电缆布局"]
|
||||
Init --> SelectType["用户选择测试类型"]
|
||||
SelectType --> FilterLayout["根据测试类型过滤\n电缆布线方式"]
|
||||
FilterLayout --> UserInput["用户输入任务参数\n包括电极间距、起始/结束电极等"]
|
||||
UserInput --> Validate["点击创建时验证参数"]
|
||||
Validate --> CheckCommon["验证通用参数\n(任务名、测试方式等)"]
|
||||
CheckCommon --> CheckSpace{"电极间距为零?"}
|
||||
CheckSpace --> |是| ShowError1["显示错误提示"]
|
||||
CheckSpace --> |否| CheckHole{"交叉孔装置且孔间距为零?"}
|
||||
CheckHole --> |是| ShowError2["显示错误提示"]
|
||||
CheckHole --> |否| CheckRange{"起始/结束电极越界?"}
|
||||
CheckRange --> |是| ShowError3["显示错误提示"]
|
||||
CheckRange --> |否| CreateTask["调用CTaskDataOper::Create2DTask\n创建任务"]
|
||||
CreateTask --> Success{"创建成功?"}
|
||||
Success --> |是| CloseDialog["关闭对话框"]
|
||||
Success --> |否| Return["返回等待用户修正"]
|
||||
ShowError1 --> Return
|
||||
ShowError2 --> Return
|
||||
ShowError3 --> Return
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [DialNew2DTask.cpp](file://cpp/Views/DialNew2DTask.cpp#L1-L665)
|
||||
|
||||
### 3D测量任务创建
|
||||
|
||||
`DialNew3DTask.cpp`实现了3D测量任务的创建对话框。3D任务的配置最为复杂,需要设置网格大小、X/Y方向电极步长和距离等参数。当用户选择脚本时,系统会自动查询并显示网格信息(X和Y方向的点数),帮助用户理解测量范围。对话框还提供了发射周期的"自动"选项,为用户提供更灵活的配置选择。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([开始创建3D任务]) --> Init["初始化对话框\n加载介质、脚本、电缆布局"]
|
||||
Init --> SelectScript["用户选择脚本"]
|
||||
SelectScript --> QueryGrid["查询并显示网格信息\n(X方向点数, Y方向点数)"]
|
||||
QueryGrid --> UserInput["用户输入任务参数\n包括步长、距离等"]
|
||||
UserInput --> Validate["点击创建时验证参数"]
|
||||
Validate --> CheckCommon["验证通用参数\n(任务名、测试方式等)"]
|
||||
CheckCommon --> CheckStep{"步长为空?"}
|
||||
CheckStep --> |是| ShowError["显示错误提示"]
|
||||
CheckStep --> |否| CreateTask["调用CTaskDataOper::Create3DTask\n创建任务"]
|
||||
CreateTask --> Success{"创建成功?"}
|
||||
Success --> |是| CloseDialog["关闭对话框"]
|
||||
Success --> |否| Return["返回等待用户修正"]
|
||||
ShowError --> Return
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [DialNew3DTask.cpp](file://cpp/Views/DialNew3DTask.cpp#L1-L570)
|
||||
|
||||
## 任务包配置机制
|
||||
|
||||
`DialCfgTaskPacket.cpp`实现了任务包的配置对话框,允许用户将多个任务组织成一个任务包进行循环执行。对话框包含一个任务选择下拉框和一个任务列表,用户可以将选中的任务添加到列表中,也可以从列表中删除任务。系统会检查重复添加的任务,避免同一个任务被多次执行。
|
||||
|
||||
在用户点击"保存"时,系统会对输入的参数进行严格验证:
|
||||
- 循环次数必须在1-60000之间
|
||||
- 时间间隔必须在1-60000之间
|
||||
- PLC ID不能为空
|
||||
|
||||
验证通过后,系统会将任务列表和属性信息保存到数据库中,供后续执行使用。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class CDialCfgTaskPacket {
|
||||
+m_cmbTaskName : CComboBox
|
||||
+m_listTaskPacket : CListCtrl
|
||||
+m_cmbTaskName : CComboBox
|
||||
+OnButtonAdd() void
|
||||
+OnButtonDel() void
|
||||
+OnOK() void
|
||||
+IsRepeatTask(int) bool
|
||||
+InitialTaskList() void
|
||||
}
|
||||
class CTaskDataOper {
|
||||
+QueryTdBrowseInfo() void
|
||||
+QueryTaskPacketAttr() bool
|
||||
+InsertTaskPacketInfo() bool
|
||||
}
|
||||
CDialCfgTaskPacket --> CTaskDataOper : "使用"
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [DialCfgTaskPacket.cpp](file://cpp/Views/DialCfgTaskPacket.cpp#L1-L301)
|
||||
|
||||
## 地形参数设置逻辑
|
||||
|
||||
`DialCfgTerrain.cpp`实现了地形参数的配置对话框,允许用户导入DAT文件并编辑地形数据点。对话框提供了添加、修改、删除地形数据点的功能,并支持从文件导入地形数据。用户可以设置地形数据标志(水平距离或垂直距离)和第一个电极对应的地形数据点编号。
|
||||
|
||||
在保存地形数据时,系统会执行严格的验证:
|
||||
- 必须已导入DAT文件
|
||||
- 必须选择地形数据标志
|
||||
- 必须输入至少一个地形数据点
|
||||
- 第一个电极对应的地形数据点编号必须在有效范围内
|
||||
|
||||
验证通过后,系统会将地形数据写入原DAT文件的末尾,遵循特定的文件格式要求。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([开始配置地形]) --> ImportFile["用户导入DAT文件"]
|
||||
ImportFile --> EditData["编辑地形数据点\n添加、修改、删除"]
|
||||
EditData --> SetParams["设置地形参数\n标志、第一个电极编号"]
|
||||
SetParams --> Save["点击保存"]
|
||||
Save --> Validate["验证参数"]
|
||||
Validate --> CheckFile{"已导入文件?"}
|
||||
CheckFile --> |否| ShowError1["显示错误提示"]
|
||||
CheckFile --> |是| CheckFlag{"选择数据标志?"}
|
||||
CheckFlag --> |否| ShowError2["显示错误提示"]
|
||||
CheckFlag --> |是| CheckData{"输入地形数据?"}
|
||||
CheckData --> |否| ShowError3["显示错误提示"]
|
||||
CheckData --> |是| CheckIndex{"第一个电极编号有效?"}
|
||||
CheckIndex --> |否| ShowError4["显示错误提示"]
|
||||
CheckIndex --> |是| WriteFile["将地形数据写入DAT文件"]
|
||||
WriteFile --> Success{"写入成功?"}
|
||||
Success --> |是| ShowSuccess["显示成功提示"]
|
||||
Success --> |否| ShowFail["显示失败提示"]
|
||||
ShowError1 --> Return["返回等待用户修正"]
|
||||
ShowError2 --> Return
|
||||
ShowError3 --> Return
|
||||
ShowError4 --> Return
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [DialCfgTerrain.cpp](file://cpp/Views/DialCfgTerrain.cpp#L1-L843)
|
||||
|
||||
## 任务树形视图构建与交互
|
||||
|
||||
### 任务树形视图构建
|
||||
|
||||
`DialTaskTree.cpp`实现了任务树形视图,使用`CTreeCtrl`控件显示任务列表。视图支持复选框功能,允许用户选择多个任务进行批量操作。视图初始化时会根据任务类型(2D或3D)从服务器获取任务数据,并构建树形结构。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class CDialTaskTree {
|
||||
+m_treeTask : CTreeCtrl
|
||||
+m_iSptType : int
|
||||
+m_pParentWnd : CWnd*
|
||||
+ShowTaskTree(int, time_t, time_t) void
|
||||
+OnClickTreeTaskList() void
|
||||
+OnNMRClickTreeTaskList() void
|
||||
+OnAddNewItemToTaskList() bool
|
||||
+OnClearTaskList() void
|
||||
}
|
||||
class CTaskDataOper {
|
||||
+InitOnLineTaskTreeCtrl() void
|
||||
+SetCurrentTimeRange() void
|
||||
}
|
||||
CDialTaskTree --> CTaskDataOper : "使用"
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [DialTaskTree.cpp](file://cpp/Views/DialTaskTree.cpp#L1-L686)
|
||||
|
||||
### 任务树形视图交互
|
||||
|
||||
任务树形视图支持丰富的交互功能:
|
||||
- 点击复选框:选择或取消选择任务,同时更新父节点的选中计数
|
||||
- 右键点击:显示上下文菜单,提供创建任务、删除任务、取消测试、刷新列表等操作
|
||||
- 点击任务节点:通知父窗口当前选中的任务
|
||||
|
||||
上下文菜单的选项会根据当前UI语言动态调整文本内容,确保用户界面的国际化支持。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User as "用户"
|
||||
participant Tree as "任务树"
|
||||
participant Parent as "父窗口"
|
||||
User->>Tree : 右键点击任务节点
|
||||
Tree->>Tree : 显示上下文菜单
|
||||
User->>Tree : 选择"删除任务"
|
||||
Tree->>Parent : 发送WM_MSG_DELETE_TASK消息
|
||||
Parent->>Parent : 处理删除任务逻辑
|
||||
Parent->>Tree : 刷新任务列表
|
||||
Tree->>User : 显示操作结果
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [DialTaskTree.cpp](file://cpp/Views/DialTaskTree.cpp#L1-L686)
|
||||
|
||||
## 项目数据持久化与加载
|
||||
|
||||
`ProManager.cpp`实现了项目管理器,负责项目数据的持久化与加载。项目管理器通过`CProManager`类与数据库交互,实现项目和测区的创建、查询和同步功能。
|
||||
|
||||
项目创建流程包括:
|
||||
1. 在数据库中创建项目记录
|
||||
2. 在设备上创建项目文件夹和配置文件
|
||||
3. 同步项目数据到设备
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant UI as "用户界面"
|
||||
participant ProMgr as "CProManager"
|
||||
participant DB as "数据库"
|
||||
participant Dev as "设备"
|
||||
UI->>ProMgr : 创建项目
|
||||
ProMgr->>ProMgr : 显示创建对话框
|
||||
ProMgr->>ProMgr : 验证项目名称唯一性
|
||||
ProMgr->>DB : 插入项目记录
|
||||
DB-->>ProMgr : 返回项目ID
|
||||
ProMgr->>Dev : 在设备上创建项目文件夹
|
||||
Dev-->>ProMgr : 文件夹创建成功
|
||||
ProMgr->>Dev : 发送项目配置文件
|
||||
Dev-->>ProMgr : 文件发送成功
|
||||
ProMgr->>DB : 记录同步状态
|
||||
DB-->>ProMgr : 同步记录创建成功
|
||||
ProMgr-->>UI : 显示创建成功
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp#L1-L2054)
|
||||
|
||||
## 任务参数验证与数据传递
|
||||
|
||||
### 任务参数验证
|
||||
|
||||
系统在创建任务时执行严格的参数验证,确保所有输入都符合业务规则:
|
||||
- **必填项验证**:任务名、测试方式、装置类型、脚本等必须填写
|
||||
- **取值范围验证**:迭代次数(1-255)、采样间隔(0-30000)、电极间距(>0)等
|
||||
- **逻辑关系验证**:交叉孔装置的孔间距必须大于电极间距
|
||||
- **唯一性验证**:任务包中不能包含重复任务
|
||||
|
||||
### 跨对话框数据传递
|
||||
|
||||
系统通过多种机制实现跨对话框的数据传递:
|
||||
- **构造函数传递**:在创建对话框时通过构造函数传递必要的操作对象(如`CTaskDataOper`)
|
||||
- **成员变量共享**:父窗口与子窗口通过成员变量共享数据
|
||||
- **消息机制**:使用Windows消息在不同窗口间传递数据和状态
|
||||
|
||||
例如,在`DialTaskManager.cpp`中,创建任务时会根据任务类型显示相应的创建对话框,并将创建好的任务参数传递给上传逻辑:
|
||||
|
||||
```cpp
|
||||
// 伪代码示例
|
||||
if (0 == m_iSelTaskType) {
|
||||
iRet = m_dialNew2DTask.DoModal();
|
||||
if (IDOK == iRet) {
|
||||
// 从对话框获取创建好的任务参数
|
||||
strTaskCN = m_dialNew2DTask.m_strTaskCN;
|
||||
// 构造任务参数结构体
|
||||
strcpy(m_TaskArg.ucTaskID, strTmp);
|
||||
strcpy(m_TaskArg.ucTDName, m_dialNew2DTask.m_strTaskName);
|
||||
// ... 其他参数
|
||||
// 上传任务数据
|
||||
CDownloadDataProgressDlg uploadDlg(&m_TaskArg, &m_taskOper,this);
|
||||
uploadDlg.DoModal();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Section sources**
|
||||
- [DialNew1DTask.cpp](file://cpp/Views/DialNew1DTask.cpp#L1-L381)
|
||||
- [DialNew2DTask.cpp](file://cpp/Views/DialNew2DTask.cpp#L1-L665)
|
||||
- [DialNew3DTask.cpp](file://cpp/Views/DialNew3DTask.cpp#L1-L570)
|
||||
- [DialTaskManager.cpp](file://cpp/Views/DialTaskManager.cpp#L1-L2242)
|
||||
|
||||
## 任务配置工作流
|
||||
|
||||
对于初学者,任务配置的工作流可以概括为以下步骤:
|
||||
|
||||
1. **创建项目**:通过项目管理器创建新的项目,填写项目基本信息
|
||||
2. **创建测区**:在项目中创建测区,定义测量区域
|
||||
3. **创建任务**:
|
||||
- 选择任务类型(1D、2D或3D)
|
||||
- 选择测试方式(电阻率、激电或自电)
|
||||
- 选择装置类型和测量脚本
|
||||
- 设置任务参数(迭代次数、发射周期等)
|
||||
- 点击"创建"完成任务创建
|
||||
4. **配置地形**(可选):为任务配置地形数据,导入或手动输入地形点
|
||||
5. **组织任务包**(可选):将多个任务组织成任务包,设置循环执行参数
|
||||
6. **执行任务**:在任务管理器中选择任务并开始测量
|
||||
|
||||
每个步骤都有相应的对话框引导用户完成配置,系统会在关键操作前进行参数验证,确保配置的正确性。
|
||||
|
||||
## UI响应性能优化建议
|
||||
|
||||
针对大型项目下的UI响应性能,建议采取以下优化措施:
|
||||
|
||||
1. **分页加载任务数据**:避免一次性加载所有任务,采用分页或按时间范围加载的方式,减少内存占用和UI阻塞
|
||||
2. **异步数据加载**:将耗时的数据查询操作放在后台线程执行,避免阻塞UI线程
|
||||
3. **虚拟化列表控件**:对于包含大量任务的列表,使用虚拟化技术,只渲染可见区域的项目
|
||||
4. **缓存常用数据**:将频繁访问的数据(如介质类型、脚本列表)缓存到内存中,减少数据库查询次数
|
||||
5. **优化数据库查询**:为常用查询字段建立索引,优化SQL查询语句,减少查询时间
|
||||
6. **延迟加载**:对于非关键信息,在用户需要时才进行加载,提高初始加载速度
|
||||
7. **批量操作优化**:对于批量删除等操作,使用事务处理,减少数据库交互次数
|
||||
|
||||
这些优化措施可以显著提升大型项目下的UI响应速度,改善用户体验。
|
||||
Reference in New Issue
Block a user