CSingleLevelingDlg 消息处理程序
- 格式:doc
- 大小:42.50 KB
- 文档页数:9
MFC应⽤程序编写实例—完整版(原创)前段时间,将近花了⼀周⾄两周上班和上班后的闲余时间,做了⼀个⽤于调试和测试⼯作项⽬的应⽤软件,下⾯将实现软件的重要步骤及主要功能讲解⼀遍,⽅便⽇后查阅。
程序开始后,提⽰登录框,输⼊⽤户名,密码后,登录进去主窗体,效果图如下:下⾯将主要实现的功能函数要点进⾏描述,具体实现如下:⼀、设置主窗体⼤⼩1、进⼊⼯程窗体初始化函数,OnInitDialog()中,在CDialog::OnInitDialog() 下⾯添加函数语句如下:SetWindowPos(NULL,0,0,600,400,SWP_NOMOVE); ////设置主窗体⼤⼩,长为600,⾼为400⼆、为主窗体添加背景图⽚:1、⾸先,在⼯程头⽂件中,声明画刷变量如:CBrush m_brBk;2、在⼯程OnInitDialog()中,添加如下代码:CBitmap bmp1;bmp1.LoadBitmap(IDB_BITMAP1);m_brBk.CreatePatternBrush(&bmp1);3、添加消息函数OnCtlColor,代码如下所⽰:HBRUSH CDebugDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor){HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);// if (pWnd == this)//// {//// return m_brBk;//// }return(HBRUSH) m_brBk;}三、调⽤模态对话框和⾮模态对话框(以菜单⼊⼝为例)如菜单所属的主窗体类名为CDebugDlg,调⽤对话框的类名为CPing实现调⽤⾮模态对话框⽅法:选择调⽤菜单⼊⼝后,点击添加消息处理函数,在函数体内添中如下代码:CPing *dlg = new CPing();dlg->Create(IDD_DIALOG_PING); //创建⼀个⾮模态对话框dlg->ShowWindow(SW_SHOW); //显⽰⾮模态对话框 实现调⽤模态对话框⽅法:Cping dlg;dlg.DoModal();四、调⽤外部应⽤程序⽅法:1、调⽤外部应⽤程序可采⽤WinExec函数例如,调⽤⼀个Tcpview.exe外部程序,可在消息处理函数中添加如下代码:WinExec(".\\dll\\TCPview\\Tcpview.exe",SW_SHOW); // 其中.代表当前路径,此时需要⽤到\\来区分路径。
mfc 消息处理过程嘿,朋友!咱今天来聊聊 MFC 消息处理过程这事儿。
你知道不,MFC 的消息处理就像是一场精彩的舞蹈表演。
每个舞步都有它的节奏和规律,一旦乱了套,那整个表演可就砸啦!想象一下,当你在操作一个 MFC 程序时,比如点击一个按钮,这就像是给舞台上的舞者发了一个信号。
那这个信号是怎么被接收和处理的呢?首先,消息会像个小信使一样,跑到程序的消息队列里等着。
这队列就像是个邮箱,各种消息都在这儿排队等着被处理。
然后呢,程序会时不时地去查看这个邮箱,把新到的消息拿出来。
这就好像你每天去查看自己的信箱,看看有没有新的信件。
拿到消息后,程序就开始判断这是个啥类型的消息。
是点击消息?还是鼠标移动消息?这就好比你收到一封信,得先看看是情书还是账单。
判断完类型,程序就会去找对应的处理函数。
这处理函数就像是专门处理各种信件的工作人员。
比如点击按钮的消息,就会找到专门处理点击按钮的函数。
找到处理函数后,程序就会让这个函数开始工作。
这个函数就会根据消息做各种事情,比如修改界面显示,或者进行一些计算。
你说这过程是不是挺有意思?就像一个有条不紊的工厂生产线一样。
再打个比方,这消息处理过程就像是一场接力赛。
消息是接力棒,不同的处理函数就是不同的运动员,大家依次传递,完成整个任务。
可别小看这消息处理过程,要是其中一个环节出了问题,那程序可能就会变得不听话,要么没反应,要么乱反应。
比如说,如果消息在队列里被卡住了,就像信件被卡在邮箱里出不来,那后面的处理都没法进行啦。
又或者,如果找不到对应的处理函数,那这消息就没人管啦,就像你寄出去的信没人接收一样。
所以啊,搞清楚 MFC 消息处理过程,对于开发出稳定、好用的程序,那可是至关重要的!只有把这个过程摸透了,咱们才能编写出像舞蹈表演一样精彩流畅的程序来,让用户用得开心、满意!。
C#Message消息处理⼀、消息概述Windows下应⽤程序的执⾏是通过消息驱动的。
消息是整个应⽤程序的⼯作引擎,我们需要理解掌握我们使⽤的编程语⾔是如何封装消息的原理。
C#⾃定义消息通信往往采⽤事件驱动的⽅式实现,但有时候我们不得不采⽤操作系统的消息通信机制,例如在和底层语⾔开发的DLL交互时,是⽐较⽅便的。
下⾯列举了⼀些实现⽅式,供⼤家参考.1 什么是消息(Message)消息就是通知和命令。
在.NET框架类库中的System.Windows.Forms命名空间中微软采⽤⾯对对象的⽅式重新定义了Message。
新的消息(Message)结构的公共部分属性基本与早期的⼀样,不过它是⾯对对象的。
公共属性:HWnd 获取或设定消息的处理函数Msg 获取或设定消息的ID号Lparam 指定消息的LParam字段Wparam 指定消息的WParam字段Result 指定为响应消息处理函数⽽向OS系统返回的值2 消息驱动的过程所有的外部事件,如键盘输⼊、⿏标移动、按动⿏标都由OS系统转换成相应的消息发送到应⽤程序的消息队列。
每个应⽤程序都有⼀段相应的程序代码来检索、分发这些消息到对应的窗体,然后由窗体的处理函数来处理。
⼆、C#中的消息的封装C#对消息重新进⾏了⾯对对象的封装,在C#中消息被封装成了事件。
System.Windows.Forms.Application类具有⽤于启动和停⽌应⽤程序和线程以及处理Windows消息的⽅法。
调⽤Run以启动当前线程上的应⽤程序消息循环,并可以选择使其窗体可见。
调⽤Exit或ExitThread来停⽌消息循环。
C#中⽤Application类来处理消息的接收和发送的。
消息的循环是由它负责的。
从本质上来讲,每个窗体⼀般都对应⼀个窗体过程处理函数。
那么,C#的⼀个Form实例(相当于⼀个窗体)收到消息后是如何处理消息的?其实,这个问题的分析也就是展⽰了C#的消息封装原理。
dlmain使用技巧在进行编程开发时,我们经常会遇到需要使用main函数的情况。
main函数是每个C/C++程序的入口函数,它是程序开始执行的地方。
下面是一些使用main函数的技巧。
1. 程序的执行逻辑:在编写程序时,我们需要考虑程序的执行逻辑。
我们可以使用多个函数实现不同的功能,然后在main函数中按照顺序调用这些函数。
这样可以使程序结构清晰,易于阅读和维护。
2. 命令行参数:main函数可以接受命令行参数。
通过命令行参数,我们可以在程序运行时向程序传递一些参数。
在main函数的参数列表中,argc表示命令行参数的个数,而argv是一个字符串数组,其中存储了这些参数的值。
利用这些参数,我们可以实现程序的不同功能和配置。
3. 程序的返回值:main函数可以有返回值,它可以用来告诉操作系统程序的执行结果。
一般来说,返回0表示程序正常退出,而非零值表示程序出现了错误或异常情况。
通过返回值,可以方便地在脚本或其他编程语言中调用和处理C/C++程序。
4. 调试技巧:在调试程序时,我们经常会使用断点来暂停程序的执行,然后逐步跟踪代码的执行过程。
在main函数中设置断点,可以方便地查看程序执行到哪个位置,变量的值是多少,以及函数的调用顺序等。
这样可以快速定位和解决程序的问题。
5. 程序的异常处理:在程序出现异常情况时,我们可以使用try-catch语句来捕获和处理异常。
将主要的程序逻辑放在try块中,当程序抛出异常时,可以在catch块中进行处理。
这样可以保证程序的健壮性和可靠性,避免程序崩溃或产生不确定的行为。
6. 程序的多线程处理:在程序需要处理大量数据或并行计算时,我们可以使用多线程来提高程序的性能和效率。
在main函数中创建多个线程,每个线程负责一部分任务,然后通过线程间的通信来实现数据共享和同步。
这样可以有效地利用计算资源,加速程序的运行。
7. 程序的模块化设计:在大型项目中,我们通常会使用模块化设计来组织代码。
[转]VC中如何让⼦对话框响应最⼤化、最⼩化、关闭等系统消息我们知道实现捕获最⼤化、最⼩化、关闭、⼤⼩变化等系统消息主要有如下两种⽅法:1、重写PreTranslateMessage函数BOOL CSuperSpeedDlg::PreTranslateMessage(MSG* pMsg){// TODO: Add your specialized code here and/or call the base classif ( pMsg->message == WM_SYSCOMMAND ){if ( ( pMsg->wParam & 0xFFF0) == SC_MINIMIZE ){AfxMessageBox(_T("捕获到窗⼝最⼩化消息"));}else if ( ( pMsg->wParam & 0xFFF0) == SC_MAXIMIZE ){AfxMessageBox(_T("捕获到窗⼝最⼤化消息"));}else if ( ( pMsg->wParam & 0xFFF0) == SC_CLOSE ){AfxMessageBox(_T("捕获到窗⼝关闭消息"));}}return CDialog::PreTranslateMessage(pMsg);}注:此⽅法⽆法捕获对话框程序程序中的系统按钮消息2、响应WM_SIZE消息(OnSize函数)void CSuperSpeedDlg::OnSize(UINT nType, int cx, int cy){CDialogEx::OnSize(nType, cx, cy);switch( nType){case SIZE_RESTORED:AfxMessageBox( L"捕获到窗⼝还原消息" );break;case SIZE_MINIMIZED:AfxMessageBox( L"捕获到窗⼝最⼩化消息" );break;case SIZE_MAXIMIZED:AfxMessageBox( L"捕获到窗⼝最⼤化消息" );break;}}注:此⽅法不但可以捕获对话框程序程序中的系统按钮消息,同时还可以获取客户区⾼度与宽度。
航管一次监视雷达信号处理基本流程下载温馨提示:该文档是我店铺精心编制而成,希望大家下载以后,能够帮助大家解决实际的问题。
文档下载后可定制随意修改,请根据实际需要进行相应的调整和使用,谢谢!并且,本店铺为大家提供各种各样类型的实用资料,如教育随笔、日记赏析、句子摘抄、古诗大全、经典美文、话题作文、工作总结、词语解析、文案摘录、其他资料等等,如想了解不同资料格式和写法,敬请关注!Download tips: This document is carefully compiled by theeditor.I hope that after you download them,they can help yousolve practical problems. The document can be customized andmodified after downloading,please adjust and use it according toactual needs, thank you!In addition, our shop provides you with various types ofpractical materials,such as educational essays, diaryappreciation,sentence excerpts,ancient poems,classic articles,topic composition,work summary,word parsing,copy excerpts,other materials and so on,want to know different data formats andwriting methods,please pay attention!航管一次监视雷达信号处理的基本流程航管一次监视雷达,作为航空交通管理的重要工具,其主要任务是实时监测和追踪空中飞行器的位置、速度和方向。
何谓消息、消息处理函数、消息映射?消息简单的说就是指通过输入设备向程序发出指令要执行某个操作。
具体的某个操作是你的一系列代码。
称为消息处理函数。
在SDK中消息其实非常容易理解,当窗口建立后便会有一个函数(窗口处理函数)开始执行一个消息循环,我们还可以清楚的看到消息处理的脉络。
一个switch case语句就可以搞定,消息循环直到遇到WM_QUIT消息才会结束,其余的消息均被拦截后调用相应的处理函数。
但在封装了API的MFC中,消息似乎变的有些复杂了,我们看不到熟悉的switch case语句了,取而代之的是一个叫消息映射的东西。
为什么MFC 要引入消息映射机制,你可以想象一下,在现在的程序开发活动中,你的一个程序是否拥有多个窗体,主窗口就算只有一个,那菜单、工具条、控件这些都是子窗口,那我们需要写多少个switch case,并且还要为每个消息分配一个消息处理函数,这样做是多么的复杂呀。
因此MFC采用了一种新的机制。
利用一个数组,将窗口消息和相对应的消息处理函数进行映射,你可以理解成这是一个表。
这种机制就是消息映射。
这张表在窗口基类CWnd定义,派生类的消息映射表如果你没有动作它是空的,也就是说如果你不手工的增加消息处理函数,则当派生窗口接受一个消息时会执行父类的消息处理函数。
这样做显然是高效的。
MFC提供的消息结构同时MFC定义了下面的两个主要结构:AFX_MSGMAP_ENTRYstruct AFX_MSGMAP_ENTRY{UINT nMessage; // Windows消息的ID号UINT nCode; // 控制消息的通知UINT nID; // Windows控制消息的IDUINT nLastID; //表示是一个指定范围的消息被映射的范围UINT nSig; //表示消息的动作标识AFX_PMSG pfn; // 指向消息处理函数的指针};AFX_MSGMAPstruct AFX_MSGMAP{#ifdef _AFXDLLconst AFX_MSGMAP* (PASCAL* pfnGetBaseMap)();#elseconst AFX_MSGMAP* pBaseMap;#endifconst AFX_MSGMAP_ENTRY* lpEntries;};///AFX_MSGMAP可以得到基类的消息映射入口地址和得到本身的消息映射入口地址。
消息映射的实现Windows消息概述Windows应用程序的输入由Windows系统以消息的形式发送给应用程序的窗口。
这些窗口通过窗口过程来接收和处理消息,然后把控制返还给Windows。
消息的分类队列消息和非队列消息从消息的发送途径上看,消息分两种:队列消息和非队列消息。
队列消息送到系统消息队列,然后到线程消息队列;非队列消息直接送给目的窗口过程。
这里,对消息队列阐述如下:Windows维护一个系统消息队列(System message queue),每个GUI线程有一个线程消息队列(Thread message queue)。
鼠标、键盘事件由鼠标或键盘驱动程序转换成输入消息并把消息放进系统消息队列,例如WM_MOUSEMOVE、WM_LBUTTONUP、WM_KEYDOWN、WM_CHAR等等。
Windows 每次从系统消息队列移走一个消息,确定它是送给哪个窗口的和这个窗口是由哪个线程创建的,然后,把它放进窗口创建线程的线程消息队列。
线程消息队列接收送给该线程所创建窗口的消息。
线程从消息队列取出消息,通过Windows把它送给适当的窗口过程来处理。
除了键盘、鼠标消息以外,队列消息还有WM_PAINT、WM_TIMER和WM_QUIT。
这些队列消息以外的绝大多数消息是非队列消息。
系统消息和应用程序消息从消息的来源来看,可以分为:系统定义的消息和应用程序定义的消息。
系统消息ID的范围是从0到WM_USER-1,或0X80000到0XBFFFF;应用程序消息从WM_USER(0X0400)到0X7FFF,或0XC000到0XFFFF;WM_USER到0X7FFF范围的消息由应用程序自己使用;0XC000到0XFFFF范围的消息用来和其他应用程序通信,为了ID的唯一性,使用::RegisterWindowMessage来得到该范围的消息ID。
消息结构和消息处理消息的结构为了从消息队列获取消息信息,需要使用MSG结构。
VC通用对话框类CFileDlgCFileDialog类封装了Windows常用的文件对话框。
常用的文件对话框提供了一种简单的与Windows标准相一致的文件打开和文件存盘对话框功能。
可以用构造函数提供的方式使用CFileDialog,也可以从CFileDialog派生出自己的对话类并编写一个构造函数来适应你的需要。
每种情况下,对话框都与标准MFC对话框一样工作。
因为它们都是CCommonDialog类的派生类。
要使用CFileDialog,先用CFileDialog构造函数构造一个对象,当创建了一个对话框后,可以设置或修改m_ofn结构中的任何值,以初始化对话框控件的值或状态。
m_ofn结构是OPENFILENAME类型的。
要了解更多信息,可参阅联机文档“Win32 SDK”中的OPENFILENAME结构。
初始化对话框控件后,调用DoModal成员函数显示对话框并使用户输入路径和文件。
DoModal返回不论是用户选择了OK(IDOK)还是取消(IDCANCEL)按钮。
当DoModal返回IDOK,可以使用某一个CFileDIalog的公共成员函数获取用户输入的信息。
CFileDIalog包含许多保护成员,使你可以处理常用的共享冲突、文件名合法性检查、列表框改变通知。
这些保护成员对许多应用来说用处不大,因为缺省处理是自动的。
对这些函数来说,消息映射入口是不必要的,因为它们是标准虚函数。
可以使用Windows CommDlgExtendError函数判断在初始化对话框时是否是发生了错误,并获取关于错误的更多信息。
析构一个CFileDialog对象是自动,无须调用CDialog::EndDialog。
要使用户选用多个文件,可在调用DoModal之前设置OFN_ALLOWMULTISELECT标志。
你应提供文件名缓冲区来放置返回的多个文件名的列表,这通过用一个分配了的缓冲区指针替换m_ofn.lpstrFile来实现,要在创建了CFileDialog之后调用DoModal 之前进行此操作。
// CSingleLevelingDlg 消息处理程序BOOL CSingleLevelingDlg::OnInitDialog(){CDialog::OnInitDialog();// 将“关于...”菜单项添加到系统菜单中。
// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){CString strAboutMenu;strAboutMenu.LoadString(IDS_ABOUTBOX);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// 设置此对话框的图标。
当应用程序主窗口不是对话框时,框架将自动// 执行此操作SetIcon(m_hIcon, TRUE); // 设置大图标SetIcon(m_hIcon, FALSE); // 设置小图标// TODO: 在此添加额外的初始化代码//数据格式://第一行:单水准类型,1=附合,0=闭合//第二行:起点高程,"点号,高程"//第三行:终点高程,"点号,高程"(附合水准才有,闭合水准则开始观测数据)//第四行:观测数据,"序号,高差观测值m,水准路线长度km"//......//Edit control的MultiLine和WantReturn属性都设置成TRUEstrObsData.Format(_T("%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n%s"),_T("1"),_T("A, 45.286") ,_T("B, 49.579") ,_T("1,2.331,1.6"),_T("2,2.813,2.1"),_T("3,-2.244,1.7"),_T("4,1.430,2.0"));UpdateData(FALSE);return TRUE; // 除非将焦点设置到控件,否则返回TRUE}void CSingleLevelingDlg::OnSysCommand(UINT nID, LPARAM lParam) {if ((nID & 0xFFF0) == IDM_ABOUTBOX){CAboutDlg dlgAbout;dlgAbout.DoModal();}else{CDialog::OnSysCommand(nID, lParam);}}// 如果向对话框添加最小化按钮,则需要下面的代码// 来绘制该图标。
对于使用文档/视图模型的MFC 应用程序,// 这将由框架自动完成。
void CSingleLevelingDlg::OnPaint(){if (IsIconic()){CPaintDC dc(this); // 用于绘制的设备上下文SendMessage(WM_ICONERASEBKGND,reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);// 使图标在工作区矩形中居中int cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// 绘制图标dc.DrawIcon(x, y, m_hIcon);}else{CDialog::OnPaint();}}//当用户拖动最小化窗口时系统调用此函数取得光标//显示。
HCURSOR CSingleLevelingDlg::OnQueryDragIcon(){return static_cast<HCURSOR>(m_hIcon);}void CSingleLevelingDlg::OnBnClickedBtncompute() //分割字符串获得字符数组{// TODO: 在此添加控件通知处理程序代码UpdateData(TRUE);int iLine;//分行并存入字符串数组CString *pstrLine=SplitString(strObsData,13,iLine);if(iLine<4) //改动{MessageBox(_T("输入的数据不完整!"));return;}int iObsCount=iLine-3;//观测值个数short nLevelType;//单一水准类型,1=附合,0=闭合double Ha,Hb;//已知点高程double *hObs=new double[iObsCount];//高差观测值double *dObs=new double[iObsCount];//水准路线长度CString *strTmp=NULL;int n;nLevelType = _ttoi(pstrLine[0]); //第一行为单一水准类型strTmp = SplitString(pstrLine[1], ',',n);//分割第二行Ha = _tstof((strTmp[1])); //获取起始点高程if(strTmp!=NULL)//释放内存{delete[] strTmp;strTmp=NULL;}strTmp = SplitString(pstrLine[2], ',',n);//分割第三行Hb = _tstof((strTmp[1])); //获取终点高程if(strTmp!=NULL)//释放内存{delete[] strTmp;strTmp=NULL;}//逐行用Split函数分离,获取观测数据for(int i=0;i<iObsCount;i++){strTmp = SplitString(pstrLine[i+3], ',',n);//分割第三行hObs[i] = _tstof(strTmp[1]);dObs[i] = _tstof(strTmp[2]);if(strTmp!=NULL)//释放内存{delete[] strTmp;strTmp=NULL;}}if(pstrLine!=NULL)//释放内存{delete[] pstrLine;pstrLine=NULL;}double dFh=0;//高差闭合差double dSumD=0;//路线总长度for(int i=0;i<iObsCount;i++){dFh = dFh + hObs[i]; //计算高差观测值之和dSumD = dSumD + dObs[i];//计算水准路线总长度}dFh = dFh - (Hb - Ha); //计算高差闭合差for(int i=0;i<iObsCount;i++)//按路线长度分配闭合差{hObs[i] = hObs[i] - dFh * dObs[i] / dSumD;}double *dH=new double[iObsCount-1];//未知点个数为nObsCount-1个//推算未知点高程dH[0] = Ha + hObs[0];for(int i=0;i<iObsCount-2;i++){dH[i + 1] = dH[i] + hObs[i + 1];}//输出结果strResult.Format(_T("%s%.1fmm\r\n%s%.1fkm\r\n%s%.1fmm\r\n%s%s\r\n"), _T("闭合差:"),dFh * 1000,_T("水准路线总长度:"), dSumD,_T("每公里高差改正数:"),dFh / dSumD * 1000,_T("序号"),_T("调整后H (m) "));//输出调整后未知点的高程CString strOutput;for(int i=0;i<iObsCount-1;i++){strOutput.Format(_T("%d %.4f\r\n"),i+1,dH[i]);strResult=strResult+strOutput;}UpdateData(FALSE);//释放内存if(dObs!=NULL){delete[] dObs;dObs=NULL;}if(hObs!=NULL){delete[] hObs;hObs=NULL;}if(dH!=NULL){delete[] dH;dH=NULL;}}// 分割字符串,得到字符串数组(CString* )CString * CSingleLevelingDlg::SplitString(CString str, char split, int& iSubStrs) {int iPos = 0; //分割符位置int iNums = 0; //分割符的总数CString strTemp = str;CString strRight;//先计算子字符串的数量while (iPos != -1){iPos = strTemp.Find(split);if (iPos == -1){break;}strRight = strTemp.Mid(iPos + 1, str.GetLength());strTemp = strRight;iNums++;}if (iNums == 0) //没有找到分割符{//子字符串数就是字符串本身iSubStrs = 1;return NULL;}//子字符串数组iSubStrs = iNums + 1; //子串的数量= 分割符数量+ 1CString* pStrSplit;pStrSplit = new CString[iSubStrs];strTemp = str;CString strLeft;for (int i = 0; i < iNums; i++){iPos = strTemp.Find(split);//左子串strLeft = strTemp.Left(iPos);//右子串strRight = strTemp.Mid(iPos + 1, strTemp.GetLength());strTemp = strRight;pStrSplit[i] = strLeft;}pStrSplit[iNums] = strTemp;return pStrSplit;}// 分割字符串,得到字符串数组(CStringArray )int CSingleLevelingDlg::SplitStringArray(CString str, char split, CStringArray& aStr) {int startIdx = 0;int idx = str.Find(split, startIdx);aStr.RemoveAll();//先清空while (-1 != idx){CString sTmp = str.Mid(startIdx, idx - startIdx);aStr.Add(sTmp);startIdx = idx + 1;idx = str.Find(split, startIdx);}CString sTmp = str.Right(str.GetLength() - startIdx);if (! sTmp.IsEmpty())aStr.Add(sTmp);return aStr.GetSize();}void CSingleLevelingDlg::OnBnClickedBtntest(){// TODO: 在此添加控件通知处理程序代码UpdateData(TRUE);int iLine;//分行并存入字符串数组CStringArray aStrLine;iLine=SplitStringArray(strObsData,13,aStrLine);if(iLine<4){MessageBox(_T("输入的数据不完整!"));return;}int iObsCount=iLine-3;//观测值个数short nLevelType;//单一水准类型,1=附合,0=闭合double Ha,Hb;//已知点高程double *hObs=new double[iObsCount];//高差观测值double *dObs=new double[iObsCount];//水准路线长度CStringArray aStrTmp;int n;nLevelType = _ttoi(aStrLine[0]); //第一行为单一水准类型n = SplitStringArray(aStrLine[1], ',',aStrTmp);//分割第二行Ha = _tstof(aStrTmp[1]); //获取起始点高程n = SplitStringArray(aStrLine[2], ',',aStrTmp);//分割第三行Hb = _tstof((aStrTmp[1])); //获取终点高程//逐行用Split函数分离,获取观测数据for(int i=0;i<iObsCount;i++){n= SplitStringArray(aStrLine[i+3], ',',aStrTmp);//分割第三行hObs[i] = _tstof(aStrTmp[1]);dObs[i] = _tstof(aStrTmp[2]);}double dFh=0;//高差闭合差double dSumD=0;//路线总长度for(int i=0;i<iObsCount;i++){dFh = dFh + hObs[i]; //计算高差观测值之和dSumD = dSumD + dObs[i];//计算水准路线总长度}dFh = dFh - (Hb - Ha); //计算高差闭合差for(int i=0;i<iObsCount;i++)//按路线长度分配闭合差{hObs[i] = hObs[i] - dFh * dObs[i] / dSumD;}double *dH=new double[iObsCount-1];//未知点个数为nObsCount-1个//推算未知点高程dH[0] = Ha + hObs[0];for(int i=0;i<iObsCount-2;i++){dH[i + 1] = dH[i] + hObs[i + 1];}//输出结果strResult.Format(_T("%s%.1fmm\r\n%s%.1fkm\r\n%s%.1fmm\r\n%s%s\r\n"), _T("闭合差:"),dFh * 1000,_T("水准路线总长度:"), dSumD,_T("每公里高差改正数:"),dFh / dSumD * 1000,_T("序号"),_T("调整后H (m) "));//输出调整后未知点的高程CString strOutput;for(int i=0;i<iObsCount-1;i++){strOutput.Format(_T("%d %.4f\r\n"),i+1,dH[i]);strResult=strResult+strOutput;}UpdateData(FALSE);//释放内存if(dObs!=NULL){delete[] dObs;dObs=NULL;}if(hObs!=NULL){delete[] hObs;hObs=NULL;}if(dH!=NULL){delete[] dH;dH=NULL;}}。