zoukankan      html  css  js  c++  java
  • 导航程序调试1---MFC应用以及数据显示程序

    1. 问题

      error C2664: "BuildCommDCBW": 不能将参数 1 从"char *"转换为"LPCWSTR"经常出现这样的错误?

      对于上面的错误,主要是字符编码设置的问题,修改下面的选项即可:

      http://bbs.csdn.net/topics/310076558 这篇帖子里面有解决方案.

      不能想当然的,就做强制转换,不然可能会出错。下面的做法是错误的。

      正确的解决方案:

      类似下面这种:

      当我们将上面的改为 支持多字符集的时候,我们需要将下面的 OpenEventW (xxxx) 改为:

    2. 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(); 来与主窗体进行联系。

    但是如何联系里面的控件? 目前还没有好的方法。不过,我觉得肯定是有方法的。

    1. 如何对MFC当中的EDIT控件进行操作。

      这里我们需要通过EDIT控件的ID进行操作。通过其ID我们可以得到很多东西。

      参考文章:http://blog.csdn.net/jiayanhui2877/article/details/7589756 MFC Edit控件操作

    2. 字节,字节,字节

      一定要控制好,昨天闲来没事,改了一个字节,把 unsigned short 改为 unsigned int .折腾好久才搞定。后来,竟然是我自己程序出错。我也是无语了。

    3. 写了一个简单的界面显示:

      左边是C++版本,真是丑。右边是C#版本。

      遇到的问题颇多,下面说说整体结构。

      程序在主线程,也就是 下面这个地方进行开辟2个新的线程进行数据处理:

      上面的代码涉及到 EDIT控件的设置问题,我们可以联想到android当中eidtview的设置问题,其实还是蛮像的。

      当我们在子线程中,想要获取到主线程的东西的话,比较麻烦,可以通过得到其上下文的方式来进行操作。

      如上图的代码就是这样一回事。

      当然,这里就涉及到数据通讯的问题。以及数据共享的问题。

      还有就是主线程一般是用户界面线程,它有消息循环队列,而我们创建的工作线程中没有这种工作机制。

      所以,一般我们想要更新主线程当中的控件的时候,我们一般通过消息队列去通知主线程,然后让主线程去绘制窗体。

      毕竟,我们执行程序的时候,所有的东西都是"被实例化的"

      继续接上面的开了两个线程之后,怎么办?

      线程1:

      虚拟总线初始化,等待用户输入,输入0K之后,我们进入到数据采集部分。

      还有就是m_run 是由主线程提供的。

      线程2:处理线程

      处理线程,专门处理子线程1当中采集到的数据,这里我们用了循环数组来进行线程间的通讯。采集完之后,我们直接显示即可。

      在用画笔绘制图形的过程中,我想强调一点,适当的sleep是必须的,因为绘制需要时间,不然上一个图形还没绘制完,新图形又过来了,

      这样会造成界面的卡顿十分严重。

      两个主要的程序代码:

      Dlg.h

      1. // DatasShowDlg.h : 头文件
      2. //
      3.  
      4. #pragma once
      5. #include "afxwin.h"
      6. #include "VirtualSwitchPlus.h"
      7.  
      8. DWORD WINAPI DealThread(LPVOID pParam);
      9. DWORD WINAPI ReceiverThread(LPVOID pParam);
      10.  
      11. extern char szbuffer[10][arrayBytes];
      12. extern int recvcount;
      13. extern bool m_run;
      14. extern CRect* pictureWH;
      15.  
      16. extern string msgLable;
      17. extern string busNum;
      18.  
      19. typedef struct Point //点转换为矩阵的x与y坐标。
      20. {
      21.    unsigned short x;
      22.    unsigned short y;
      23.    unsigned char value;
      24.    unsigned char U;
      25. } Point;
      26. typedef struct Matrix //稀疏矩阵数据结构
      27. {
      28.    int Num;
      29.    Point point[3000];
      30.  
      31. } Matrix;
      32.  
      33. static const int PointLength = 6; //一个point点的长度
      34. static const int startoffset = 4; //头字节的长度
      35. void DrawPoints(Matrix *marix,LPVOID pParam);
      36.  
      37. // CDatasShowDlg 对话框
      38. class CDatasShowDlg : public CDialogEx
      39. {
      40. // 构造
      41. public:
      42.    CDatasShowDlg(CWnd* pParent = NULL); // 标准构造函数
      43.  
      44. // 对话框数据
      45.    enum { IDD = IDD_DATASSHOW_DIALOG };
      46.  
      47.    protected:
      48.    virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
      49.  
      50.  
      51. // 实现
      52. protected:
      53.    HICON m_hIcon;
      54.  
      55.    // 生成的消息映射函数
      56.    virtual BOOL OnInitDialog();
      57.    afx_msg void OnPaint();
      58.    afx_msg HCURSOR OnQueryDragIcon();
      59.    DECLARE_MESSAGE_MAP()
      60. public:
      61.    CButton m_show;
      62.    CEdit m_msgLable;
      63.    CEdit m_busNum;
      64.  
      65.    afx_msg void OnBnClickedOk();
      66.  
      67.  
      68.    CString m_msgLabelNum;
      69.    CString m_busNumValue;
      70. };

      Dlg.cpp

      1. // DatasShowDlg.cpp : 实现文件
      2. //
      3.  
      4. #include "stdafx.h"
      5. #include "DatasShow.h"
      6. #include "DatasShowDlg.h"
      7. #include "afxdialogex.h"
      8.  
      9.  
      10. #ifdef _DEBUG
      11. #define new DEBUG_NEW
      12. #endif
      13.  
      14.  
      15. // CDatasShowDlg 对话框
      16. char szbuffer[10][arrayBytes];
      17. int recvcount;
      18. bool m_run;
      19. CRect* pictureWH = new CRect();
      20. string msgLable;
      21. string busNum;
      22.  
      23. CDatasShowDlg::CDatasShowDlg(CWnd* pParent /*=NULL*/)
      24.    : CDialogEx(CDatasShowDlg::IDD, pParent)
      25.    , m_msgLabelNum(_T(""))
      26.    , m_busNumValue(_T(""))
      27. {
      28.    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
      29. }
      30.  
      31. void CDatasShowDlg::DoDataExchange(CDataExchange* pDX)
      32. {
      33.    CDialogEx::DoDataExchange(pDX);
      34.    DDX_Control(pDX, IDOK, m_show);
      35.    DDX_Control(pDX, IDC_EDIT1, m_msgLable);
      36.    DDX_Control(pDX, IDC_EDIT2, m_busNum);
      37.    //DDX_Control(pDX, IDC_PICTURE, m_picture);
      38.    DDX_Text(pDX, IDC_EDIT1, m_msgLabelNum);
      39.    DDX_Text(pDX, IDC_EDIT2, m_busNumValue);
      40. }
      41.  
      42. BEGIN_MESSAGE_MAP(CDatasShowDlg, CDialogEx)
      43.    ON_WM_PAINT()
      44.    ON_WM_QUERYDRAGICON()
      45.    ON_BN_CLICKED(IDOK, &CDatasShowDlg::OnBnClickedOk)
      46. END_MESSAGE_MAP()
      47.  
      48.  
      49. // CDatasShowDlg 消息处理程序
      50.  
      51. BOOL CDatasShowDlg::OnInitDialog()
      52. {
      53.    CDialogEx::OnInitDialog();
      54.  
      55.    // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
      56.    // 执行此操作
      57.    SetIcon(m_hIcon, TRUE); // 设置大图标
      58.    SetIcon(m_hIcon, FALSE); // 设置小图标
      59.  
      60.    // TODO: 在此添加额外的初始化代码
      61.    m_run = false;
      62.    recvcount = 0;
      63.    CRect rect;
      64.    /*m_picture.GetWindowRect(rect);*/
      65.  
      66.    /*pictureWH = ▭ 下面的参数没什么卵用*/
      67.    AfxBeginThread((AFX_THREADPROC)DealThread,(LPVOID)GetSafeHwnd(),THREAD_BASE_PRIORITY_IDLE);
      68.    AfxBeginThread((AFX_THREADPROC)ReceiverThread,NULL,THREAD_BASE_PRIORITY_IDLE);
      69.    //对edit控件赋值
      70.    /*char label[20] = {0};
      71.    char busnum[20] = {0};*/
      72.    SetDlgItemText(IDC_EDIT1,"Path_GPS");
      73.    SetDlgItemText(IDC_EDIT2,"1");
      74.  
      75.    return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
      76. }
      77.  
      78. // 如果向对话框添加最小化按钮,则需要下面的代码
      79. // 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
      80. // 这将由框架自动完成。
      81.  
      82.  
      83. DWORD WINAPI DealThread(LPVOID pParam)
      84. {
      85.  
      86.    //CRect* rect = (CRect*)pParam;
      87.    while(1)
      88.    {
      89.       if (m_run)
      90.     {
      91.       unsigned char str1[arrayBytes] = {0}; //获取数据
      92.       //开辟两个无符号类型,这里是加了锁机制处理,string 默认并不是无符号类型
      93.  
      94.       for (int i = 0; i < arrayBytes; ++i)
      95.       {
      96.          str1[i] = szbuffer[(recvcount-1+10)%10][i];
      97.       }
      98.       Matrix *matrixH = new Matrix(); //记得释放
      99.       memset(matrixH,0,sizeof(Matrix));
      100.       matrixH->Num = str1[3]*16*16*16*16*16*16*16*16 + str1[2]*16*16*16*16 + str1[1]*16*16 + str1[0];
      101.       int obs1 = 0;
      102.       for (int i = 0; i < matrixH->Num; ++i)
      103.       {
      104.          matrixH->point[obs1].x = str1[startoffset + 1 + i*PointLength]*16*16 + str1[startoffset + 0 + i*PointLength];
      105.          matrixH->point[obs1].y = str1[startoffset + 3 + i*PointLength]*16*16 + str1[startoffset + 2 + i*PointLength];
      106.          matrixH->point[obs1].value = str1[startoffset + 4 + i*PointLength];
      107.          //matrixH->point[obs1].value = 50;
      108.          matrixH->point[obs1].U = str1[startoffset + 5 + i*PointLength];
      109.          obs1++; //注意清零
      110.       }
      111.       DrawPoints(matrixH,pParam);
      112.  
      113.  
      114.       delete matrixH;
      115.       }//end if
      116.       else
      117.       {
      118.          Sleep(1);
      119.       }
      120.    }
      121.  
      122.  
      123.    return 0;
      124. }
      125.  
      126. void DrawPoints(Matrix *marix,LPVOID pParam)
      127. {
      128.    //HWND hWnd = (HWND)pParam;
      129.    CRect rect;
      130.     AfxGetApp()->m_pMainWnd->GetWindowRect(rect);
      131.    int PicW = rect.Width();
      132.    int PicH = rect.Height() - 145;
      133.    //曲线轮廓显示
      134.    //以下是画在主线程中,我们需要画在picture控件中
      135.    CDC* pDC = AfxGetApp()->m_pMainWnd->GetDC(); //通过GetDc()获取的HDC直接与相关设备沟通, CDC* pDC = picture.GetDC();
      136.  
      137.    CDC memDC;
      138.    CBitmap bmp; //本函数创建的DC,则是与内存中的一个表,面相关联。
      139.    memDC.CreateCompatibleDC(pDC); //该函数创建一个与指定设备兼容的内存设备上下文环境(DC)。
      140.    bmp.CreateCompatibleBitmap( pDC, PicW, PicH); //该函数创建与指定的设备环境相关的设备兼容的位图
      141.    memDC.SelectObject(bmp); //该函数选择一对象到指定的设备上下文环境中,该新对象替换先前的相同类型的对象
      142.  
      143.    memDC.SelectStockObject(WHITE_BRUSH);//该语句把终端字体选入设备环境
      144.    memDC.SelectStockObject(WHITE_PEN);
      145.  
      146.    pDC->SelectStockObject(WHITE_BRUSH);
      147.    pDC->SelectStockObject(WHITE_PEN);
      148.  
      149.    int yGap = 10;
      150.    memDC.Ellipse( PicW/2-5, PicH-yGap-5, PicW/2+5, PicH-yGap+5); //小圆形,用来标识雷达
      151.  
      152.    int n = 0;
      153.    int m = 0;
      154.    for (int i = 0; i < marix->Num; ++i)
      155.    {
      156.       n = marix->point[i].x;
      157.       m = marix->point[i].y;
      158.       if ((n > 0 && n < 350) && (m > 0 && m < 100))
      159.       {
      160.          n = n * PicH / 400;
      161.          m = m * PicW / 100;
      162.          memDC.SetPixel(m, n,RGB(255,255,255));
      163.          //memDC.Ellipse( m-5, n-yGap-5, m+5, n-yGap+5); //小圆形,用来标识雷达
      164.       }
      165.    }
      166.  
      167.    pDC->StretchBlt(0,0,PicH,PicH,&memDC,0,0,PicH,PicH,SRCCOPY); //函数从源矩形中复制一个位图到目标矩形
      168.    bmp.DeleteObject(); //必要时按目标设备设置的模式进行图像的拉伸或压缩
      169.  
      170.    /*目标区域左上角点的x坐标
      171.     目标区域左上角点的y坐标
      172.    目标区域的宽度
      173.    目标区域的高度
      174.    源贴图区域DC的指针
      175.    源贴图区域x坐标
      176.    源贴图区域y坐标
      177.    像素直接拷贝模式*/
      178.    memDC.DeleteDC();
      179.    AfxGetApp()->m_pMainWnd->ReleaseDC(pDC);
      180.    Sleep(50);
      181. }
      182.  
      183. DWORD WINAPI ReceiverThread(LPVOID pParam)
      184. {
      185.    VirtualSwitchPlusRecv *vspR;
      186.    while(1) //等待用户输入
      187.     {
      188.       if (m_run)
      189.      {
      190.        int BUSNUM = busNum[0] - '0';
      191.         vspR = new VirtualSwitchPlusRecv(BUSNUM);
      192.        break;
      193.       }
      194.       else
      195.       {
      196.          Sleep(1);
      197.         }
      198.      }
      199.  
      200.  
      201.    while (true)
      202.    {
      203.        vspR->SubMsg(msgLable); //数据必须这样接收,每次判断一次
      204.       for (int i = 0; i < 3000; ++i)
      205.       {
      206.          szbuffer[recvcount][i] = vspR->szbuffer[i];
      207.       }
      208.       int nRet = vspR->nRet;
      209.  
      210.       if (nRet == SOCKET_ERROR)
      211.       {
      212.          cout << "Path_GPS not receive!" << endl;
      213.       }
      214.       if(nRet > 0) //主程序需要循环检测
      215.       {
      216.          cout << "flag0: "<<recvcount<<endl;
      217.          recvcount = (recvcount + 1) % 10;
      218.       }else{
      219.          recvcount = 0;
      220.       }
      221.    }
      222.    delete vspR;
      223. }
      224.  
      225. void CDatasShowDlg::OnPaint()
      226. {
      227.    if (IsIconic())
      228.    {
      229.       CPaintDC dc(this); // 用于绘制的设备上下文
      230.  
      231.       SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
      232.  
      233.       // 使图标在工作区矩形中居中
      234.       int cxIcon = GetSystemMetrics(SM_CXICON);
      235.       int cyIcon = GetSystemMetrics(SM_CYICON);
      236.       CRect rect;
      237.       GetClientRect(&rect);
      238.       int x = (rect.Width() - cxIcon + 1) / 2;
      239.       int y = (rect.Height() - cyIcon + 1) / 2;
      240.  
      241.       // 绘制图标
      242.       dc.DrawIcon(x, y, m_hIcon);
      243.    }
      244.    else
      245.    {
      246.       CDialogEx::OnPaint();
      247.    }
      248. }
      249.  
      250. //当用户拖动最小化窗口时系统调用此函数取得光标
      251. //显示。
      252. HCURSOR CDatasShowDlg::OnQueryDragIcon()
      253. {
      254.    return static_cast<HCURSOR>(m_hIcon);
      255. }
      256.  
      257.  
      258.  
      259. void CDatasShowDlg::OnBnClickedOk()
      260. {
      261.    // TODO: 在此添加控件通知处理程序代码
      262.    if (!m_run){
      263.       m_show.SetWindowText(_T("暂停"));
      264.       m_run = true;
      265.       char label[20] = {0};
      266.       char busnum[20] = {0};
      267.       GetDlgItemText(IDC_EDIT1,label,20);
      268.       GetDlgItemText(IDC_EDIT2,busnum,20);
      269.  
      270.       busNum = busnum[0];
      271.       for (int i = 0; i < 20; ++i)
      272.       {
      273.          if (label[i] != 0)
      274.          {
      275.             msgLable += label[i];
      276.          }
      277.       }
      278.    }else{
      279.       m_show.SetWindowText(_T("显示"));
      280.       m_run = false;
      281.    }
      282.  
      283. }
    4. 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要点概括

     

     

     

  • 相关阅读:
    网站、博客、文章推荐
    hdu 4000 Fruit Ninja
    2011年 北京区域赛A题 Qin Shi Huang's National Road System // hdu 4081 Qin Shi Huang's National Road System 最优比率生成树
    2008 北京区域赛 Minimal Ratio Tree
    uva 10608 Friends 并查集
    2011 北京区域赛 Hou Yi's secret // hdu 4082
    C/C++中有关字长与平台无关的整数类型(转)
    C/C++中有关字长与平台无关的整数类型(转)
    C# Windows Media Player 控件使用实例 方法(转)
    c# 系统时间
  • 原文地址:https://www.cnblogs.com/zhuxuekui/p/4700875.html
Copyright © 2011-2022 走看看