导航程序调试1---MFC应用以及数据显示程序
- 问题
error C2664: "BuildCommDCBW": 不能将参数 1 从"char *"转换为"LPCWSTR"经常出现这样的错误?
对于上面的错误,主要是字符编码设置的问题,修改下面的选项即可:
http://bbs.csdn.net/topics/310076558 这篇帖子里面有解决方案.
不能想当然的,就做强制转换,不然可能会出错。下面的做法是错误的。
正确的解决方案:
类似下面这种:
当我们将上面的改为 支持多字符集的时候,我们需要将下面的 OpenEventW (xxxx) 改为:
- MFC当中创建线程
参考文档: http://www.cnblogs.com/mx113/archive/2009/12/03/1616445.html 使用MFC中的AfxBeginThread创建多线程
用户界面线程和工作线程区别:继承主用户界面进程。
error C2248: "CObject::operator =": 无法访问 private 成员(在"CObject"类中声明)
参考资料: http://blog.csdn.net/cxf7394373/article/details/12389507 这种对控件操作的对象最好都声明成指针
多线程中,数据传递:通过消息机制实现。
下面这个解释和android当中控件必须在子线程当中的解释几乎一致。
不要在线程函数体内操作MFC控件,因为每个线程都有自己的线程模块状态映射表,在一个线程中操作另一个线程中创建的MFC对象,会带来意想不到的问题。更不要在线程函数里,直接调用UpdataData()函数更新用户界面,这会导致程序直接crash。而应该通过发送消息给主线程的方式,在主线程的消息响应函数里操作控件。
不过,我们虽然不能对控件进行操作,但是我们还是可以操作主界面的。
我们完全可以通过获取 AfxGetApp() -> m_pMainWnd -> GetDC(); 来与主窗体进行联系。
但是如何联系里面的控件? 目前还没有好的方法。不过,我觉得肯定是有方法的。
- 如何对MFC当中的EDIT控件进行操作。
这里我们需要通过EDIT控件的ID进行操作。通过其ID我们可以得到很多东西。
参考文章:http://blog.csdn.net/jiayanhui2877/article/details/7589756 MFC Edit控件操作
- 字节,字节,字节
一定要控制好,昨天闲来没事,改了一个字节,把 unsigned short 改为 unsigned int .折腾好久才搞定。后来,竟然是我自己程序出错。我也是无语了。
- 写了一个简单的界面显示:
左边是C++版本,真是丑。右边是C#版本。
遇到的问题颇多,下面说说整体结构。
程序在主线程,也就是 下面这个地方进行开辟2个新的线程进行数据处理:
上面的代码涉及到 EDIT控件的设置问题,我们可以联想到android当中eidtview的设置问题,其实还是蛮像的。
当我们在子线程中,想要获取到主线程的东西的话,比较麻烦,可以通过得到其上下文的方式来进行操作。
如上图的代码就是这样一回事。
当然,这里就涉及到数据通讯的问题。以及数据共享的问题。
还有就是主线程一般是用户界面线程,它有消息循环队列,而我们创建的工作线程中没有这种工作机制。
所以,一般我们想要更新主线程当中的控件的时候,我们一般通过消息队列去通知主线程,然后让主线程去绘制窗体。
毕竟,我们执行程序的时候,所有的东西都是"被实例化的"
继续接上面的开了两个线程之后,怎么办?
线程1:
虚拟总线初始化,等待用户输入,输入0K之后,我们进入到数据采集部分。
还有就是m_run 是由主线程提供的。
线程2:处理线程
处理线程,专门处理子线程1当中采集到的数据,这里我们用了循环数组来进行线程间的通讯。采集完之后,我们直接显示即可。
在用画笔绘制图形的过程中,我想强调一点,适当的sleep是必须的,因为绘制需要时间,不然上一个图形还没绘制完,新图形又过来了,
这样会造成界面的卡顿十分严重。
两个主要的程序代码:
Dlg.h
- // DatasShowDlg.h : 头文件
- //
- #pragma once
- #include "afxwin.h"
- #include "VirtualSwitchPlus.h"
- DWORD WINAPI DealThread(LPVOID pParam);
- DWORD WINAPI ReceiverThread(LPVOID pParam);
- extern char szbuffer[10][arrayBytes];
- extern int recvcount;
- extern bool m_run;
- extern CRect* pictureWH;
- extern string msgLable;
- extern string busNum;
- typedef struct Point //点转换为矩阵的x与y坐标。
- {
- unsigned short x;
- unsigned short y;
- unsigned char value;
- unsigned char U;
- } Point;
- typedef struct Matrix //稀疏矩阵数据结构
- {
- int Num;
- Point point[3000];
- } Matrix;
- static const int PointLength = 6; //一个point点的长度
- static const int startoffset = 4; //头字节的长度
- void DrawPoints(Matrix *marix,LPVOID pParam);
- // CDatasShowDlg 对话框
- class CDatasShowDlg : public CDialogEx
- {
- // 构造
- public:
- CDatasShowDlg(CWnd* pParent = NULL); // 标准构造函数
- // 对话框数据
- enum { IDD = IDD_DATASSHOW_DIALOG };
- protected:
- virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
- // 实现
- protected:
- HICON m_hIcon;
- // 生成的消息映射函数
- virtual BOOL OnInitDialog();
- afx_msg void OnPaint();
- afx_msg HCURSOR OnQueryDragIcon();
- DECLARE_MESSAGE_MAP()
- public:
- CButton m_show;
- CEdit m_msgLable;
- CEdit m_busNum;
- afx_msg void OnBnClickedOk();
- CString m_msgLabelNum;
- CString m_busNumValue;
- };
Dlg.cpp
- // DatasShowDlg.cpp : 实现文件
- //
- #include "stdafx.h"
- #include "DatasShow.h"
- #include "DatasShowDlg.h"
- #include "afxdialogex.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #endif
- // CDatasShowDlg 对话框
- char szbuffer[10][arrayBytes];
- int recvcount;
- bool m_run;
- CRect* pictureWH = new CRect();
- string msgLable;
- string busNum;
- CDatasShowDlg::CDatasShowDlg(CWnd* pParent /*=NULL*/)
- : CDialogEx(CDatasShowDlg::IDD, pParent)
- , m_msgLabelNum(_T(""))
- , m_busNumValue(_T(""))
- {
- m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
- }
- void CDatasShowDlg::DoDataExchange(CDataExchange* pDX)
- {
- CDialogEx::DoDataExchange(pDX);
- DDX_Control(pDX, IDOK, m_show);
- DDX_Control(pDX, IDC_EDIT1, m_msgLable);
- DDX_Control(pDX, IDC_EDIT2, m_busNum);
- //DDX_Control(pDX, IDC_PICTURE, m_picture);
- DDX_Text(pDX, IDC_EDIT1, m_msgLabelNum);
- DDX_Text(pDX, IDC_EDIT2, m_busNumValue);
- }
- BEGIN_MESSAGE_MAP(CDatasShowDlg, CDialogEx)
- ON_WM_PAINT()
- ON_WM_QUERYDRAGICON()
- ON_BN_CLICKED(IDOK, &CDatasShowDlg::OnBnClickedOk)
- END_MESSAGE_MAP()
- // CDatasShowDlg 消息处理程序
- BOOL CDatasShowDlg::OnInitDialog()
- {
- CDialogEx::OnInitDialog();
- // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
- // 执行此操作
- SetIcon(m_hIcon, TRUE); // 设置大图标
- SetIcon(m_hIcon, FALSE); // 设置小图标
- // TODO: 在此添加额外的初始化代码
- m_run = false;
- recvcount = 0;
- CRect rect;
- /*m_picture.GetWindowRect(rect);*/
- /*pictureWH = ▭ 下面的参数没什么卵用*/
- AfxBeginThread((AFX_THREADPROC)DealThread,(LPVOID)GetSafeHwnd(),THREAD_BASE_PRIORITY_IDLE);
- AfxBeginThread((AFX_THREADPROC)ReceiverThread,NULL,THREAD_BASE_PRIORITY_IDLE);
- //对edit控件赋值
- /*char label[20] = {0};
- char busnum[20] = {0};*/
- SetDlgItemText(IDC_EDIT1,"Path_GPS");
- SetDlgItemText(IDC_EDIT2,"");
- return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
- }
- // 如果向对话框添加最小化按钮,则需要下面的代码
- // 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
- // 这将由框架自动完成。
- DWORD WINAPI DealThread(LPVOID pParam)
- {
- //CRect* rect = (CRect*)pParam;
- while(1)
- {
- if (m_run)
- {
- unsigned char str1[arrayBytes] = {0}; //获取数据
- //开辟两个无符号类型,这里是加了锁机制处理,string 默认并不是无符号类型
- for (int i = 0; i < arrayBytes; ++i)
- {
- str1[i] = szbuffer[(recvcount-1+10)%10][i];
- }
- Matrix *matrixH = new Matrix(); //记得释放
- memset(matrixH,0,sizeof(Matrix));
- matrixH->Num = str1[3]*16*16*16*16*16*16*16*16 + str1[2]*16*16*16*16 + str1[1]*16*16 + str1[0];
- int obs1 = 0;
- for (int i = 0; i < matrixH->Num; ++i)
- {
- matrixH->point[obs1].x = str1[startoffset + 1 + i*PointLength]*16*16 + str1[startoffset + 0 + i*PointLength];
- matrixH->point[obs1].y = str1[startoffset + 3 + i*PointLength]*16*16 + str1[startoffset + 2 + i*PointLength];
- matrixH->point[obs1].value = str1[startoffset + 4 + i*PointLength];
- //matrixH->point[obs1].value = 50;
- matrixH->point[obs1].U = str1[startoffset + 5 + i*PointLength];
- obs1++; //注意清零
- }
- DrawPoints(matrixH,pParam);
- delete matrixH;
- }//end if
- else
- {
- Sleep(1);
- }
- }
- return 0;
- }
- void DrawPoints(Matrix *marix,LPVOID pParam)
- {
- //HWND hWnd = (HWND)pParam;
- CRect rect;
- AfxGetApp()->m_pMainWnd->GetWindowRect(rect);
- int PicW = rect.Width();
- int PicH = rect.Height() - 145;
- //曲线轮廓显示
- //以下是画在主线程中,我们需要画在picture控件中
- CDC* pDC = AfxGetApp()->m_pMainWnd->GetDC(); //通过GetDc()获取的HDC直接与相关设备沟通, CDC* pDC = picture.GetDC();
- CDC memDC;
- CBitmap bmp; //本函数创建的DC,则是与内存中的一个表,面相关联。
- memDC.CreateCompatibleDC(pDC); //该函数创建一个与指定设备兼容的内存设备上下文环境(DC)。
- bmp.CreateCompatibleBitmap( pDC, PicW, PicH); //该函数创建与指定的设备环境相关的设备兼容的位图
- memDC.SelectObject(bmp); //该函数选择一对象到指定的设备上下文环境中,该新对象替换先前的相同类型的对象
- memDC.SelectStockObject(WHITE_BRUSH);//该语句把终端字体选入设备环境
- memDC.SelectStockObject(WHITE_PEN);
- pDC->SelectStockObject(WHITE_BRUSH);
- pDC->SelectStockObject(WHITE_PEN);
- int yGap = 10;
- memDC.Ellipse( PicW/2-5, PicH-yGap-5, PicW/2+5, PicH-yGap+5); //小圆形,用来标识雷达
- int n = 0;
- int m = 0;
- for (int i = 0; i < marix->Num; ++i)
- {
- n = marix->point[i].x;
- m = marix->point[i].y;
- if ((n > 0 && n < 350) && (m > 0 && m < 100))
- {
- n = n * PicH / 400;
- m = m * PicW / 100;
- memDC.SetPixel(m, n,RGB(255,255,255));
- //memDC.Ellipse( m-5, n-yGap-5, m+5, n-yGap+5); //小圆形,用来标识雷达
- }
- }
- pDC->StretchBlt(0,0,PicH,PicH,&memDC,0,0,PicH,PicH,SRCCOPY); //函数从源矩形中复制一个位图到目标矩形
- bmp.DeleteObject(); //必要时按目标设备设置的模式进行图像的拉伸或压缩
- /*目标区域左上角点的x坐标
- 目标区域左上角点的y坐标
- 目标区域的宽度
- 目标区域的高度
- 源贴图区域DC的指针
- 源贴图区域x坐标
- 源贴图区域y坐标
- 像素直接拷贝模式*/
- memDC.DeleteDC();
- AfxGetApp()->m_pMainWnd->ReleaseDC(pDC);
- Sleep(50);
- }
- DWORD WINAPI ReceiverThread(LPVOID pParam)
- {
- VirtualSwitchPlusRecv *vspR;
- while(1) //等待用户输入
- {
- if (m_run)
- {
- int BUSNUM = busNum[0] - '0';
- vspR = new VirtualSwitchPlusRecv(BUSNUM);
- break;
- }
- else
- {
- Sleep(1);
- }
- }
- while (true)
- {
- vspR->SubMsg(msgLable); //数据必须这样接收,每次判断一次
- for (int i = 0; i < 3000; ++i)
- {
- szbuffer[recvcount][i] = vspR->szbuffer[i];
- }
- int nRet = vspR->nRet;
- if (nRet == SOCKET_ERROR)
- {
- cout << "Path_GPS not receive!" << endl;
- }
- if(nRet > 0) //主程序需要循环检测
- {
- cout << "flag0: "<<recvcount<<endl;
- recvcount = (recvcount + 1) % 10;
- }else{
- recvcount = 0;
- }
- }
- delete vspR;
- }
- void CDatasShowDlg::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
- {
- CDialogEx::OnPaint();
- }
- }
- //当用户拖动最小化窗口时系统调用此函数取得光标
- //显示。
- HCURSOR CDatasShowDlg::OnQueryDragIcon()
- {
- return static_cast<HCURSOR>(m_hIcon);
- }
- void CDatasShowDlg::OnBnClickedOk()
- {
- // TODO: 在此添加控件通知处理程序代码
- if (!m_run){
- m_show.SetWindowText(_T("暂停"));
- m_run = true;
- char label[20] = {0};
- char busnum[20] = {0};
- GetDlgItemText(IDC_EDIT1,label,20);
- GetDlgItemText(IDC_EDIT2,busnum,20);
- busNum = busnum[0];
- for (int i = 0; i < 20; ++i)
- {
- if (label[i] != 0)
- {
- msgLable += label[i];
- }
- }
- }else{
- m_show.SetWindowText(_T("显示"));
- m_run = false;
- }
- }
- MFC 的生存周期
参考资料:
http://blog.csdn.net/lesky/article/details/2470907 MFC应用程序的初始化过程
构造全局对象CWinApp è 调用WINMain中的AfxGetAPP
得到全局对象的pApp,然后调用 initInstance,并在里面完成注册,显示窗体。然后执行消息循环。
关于Mfc的好的帖子,值得一看: http://blog.csdn.net/lesky/article/details/2471039 MFC要点概括
导航程序调试1---MFC应用以及数据显示程序的更多相关文章
- 【matlab】MATLAB程序调试方法和过程
3.8 MATLAB程序的调试和优化 在MATLAB的程序调试过程中,不仅要求程序能够满足设计者的设计需求,而且还要求程序调试能够优化程序的性能,这样使得程序调试有时比程序设计更为复杂.MATLAB ...
- Linux Bash命令关于程序调试详解
转载:http://os.51cto.com/art/201006/207230.htm 参考:<Linux shell 脚本攻略>Page22-23 Linux bash程序在程序员的使 ...
- 零基础学Python--------第9章 异常处理及程序调试
第9章 异常处理及程序调试 9.1 异常概述 在程序运行过程中,经常会遇到各种各样的错误,这些错误统称为“异常”.这些异常有的是由于开发者将关键字敲错导致的,这类错误多数产生的是SyntaxError ...
- MFC单文档程序架构解析
MFC单文档程序架构解析 MFC单文档程序架构解析 这里我以科院杨老师的单文档程序来分析一下MFC单文档的程序架构,纯属个人见解,不当之处烦请指教! 首先我们了解到的是 图(一) theApp 是唯一 ...
- 052 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 14 Eclipse下程序调试——debug2 多断点调试程序
052 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 14 Eclipse下程序调试--debug2 多断点调试程序 本文知识点: Eclipse下程序调 ...
- VS2008/2005 MFC程序调试经验
我的VS2008不知道是有bug还是自己的问题,很多时候变量定义后CTRL+F5运行却没反应,一定要“生成解决方案”下才行? 1.没有可用于当前位置的源代码 将工具->选项->调试-> ...
- [安卓][转]Android eclipse中程序调试
一:断点调试 用eclipse开发android程序的时,跟VS一样是可以断点单步调试的.步骤如下.1 设置断点:在编码窗体的左边框上用鼠标双击,或者右键点击菜单,选择 Toggle Breakpoi ...
- VC++ MFC SDI/MDI Ribbon程序的停靠窗格被关闭后如何再次显示
VC++ 创建基于MFC的SDI应用程序,Visual Studio风格的主界面如下图所示,在该主界面上的视图菜单下包含有队对各个可停靠窗格显示或隐藏的控制菜单项.而基于Ribbon风格的应用程序,所 ...
- 如何优雅的写UI——(1)MFC六大核心机制-程序初始化
很多做软件开发的人都有一种对事情刨根问底的精神,例如我们一直在用的MFC,很方便,不用学太多原理性的知识就可以做出各种窗口程序,但喜欢钻研的朋友肯定想知道,到底微软帮我们做了些什么,让我们在它的框架下 ...
- 【系统篇】从int 3探索Windows应用程序调试原理
探索调试器下断点的原理 在Windows上做开发的程序猿们都知道,x86架构处理器有一条特殊的指令——int 3,也就是机器码0xCC,用于调试所用,当程序执行到int 3的时候会中断到调试器,如果程 ...
随机推荐
- iOS-多线程之NSOperation
前言 这篇文章主要讲NSOperation的使用. What 使用NSOperation和NSOperationQueue进行多线程开发类似于线程池,只要将一个NSOperation(实际开发中需要使 ...
- Objective-C之Protocol
*:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...
- .net串口通信
背景: 前一段时间需要写一个向蓝牙模块发消息的功能. 对蓝牙的机制不太了解,所以一直在查资料, 但始终没找到我需要的东西,还误以为需要配套的一套开发模板和开发包, 偶然间发现只需要简单的串口通信,并且 ...
- Js中获取对象的所有key值
假如现在有一个对象 var obj = { A:2 ,B:"Ray" ,C:true ,D:function(){} } 如果想遍历对象obj中的所有键值,一般是用以下方式 for ...
- MongoDB学习笔记——文档操作之增删改
插入文档 使用db.COLLECTION_NAME.insert() 或 db.COLLECTION_NAME.save() 方法向集合中插入文档 db.users.insert( { user_id ...
- 【mysql】关于innodb_file_format
一.几条mysql命令 通过以下命令看一下mysql中 innodb_file_format的配置 mysql> show engines; +--------------------+---- ...
- java poi read write xlsx
package myjava; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundExce ...
- Virtual Box上安装CentOS7
问题1:安装完没有桌面系统(Gnome或KDE)解答:安装的时候,软件选择为最小安装",更改该选择 问题2:开机提示Initial setup of CentOS Linux 7 (core ...
- Java语法结构
一.顺序结构(从上往下依次执行) 顺序结构语法比较简单,从上往下依次执行即可. 二.选择结构(选择性执行,如果....则.....) 1.if 语句 if语句,作用是根据判断结果为真或假,选择其中一个 ...
- 【问题&解决】解决 Android SDK下载和更新失败“Connection to https://dl-ssl.google.com refused”的问题
缘由: 更新sdk,遇到了更新下载失败问题: Fetching https://dl-ssl.google.com/android/repository/addons_list-2.xmlFetche ...