MFC中保存数据为TXT的方法
1.首先:创建MFC工程,工程名XX,基于对话框的文件,最后完成。
2.在对话框中添加控件两个Edit Box、。 用ClassWizard向导,设置Edit Box的ID为XXXXX。添加Button消息响应为void XXXXX::OnSave()
3.void XXXXX::OnSave()中添加如下代码:
  CString strText(_T(""));
    GetDlgItemText(IDC_EDIT, strText); //获取edit box中的数据
    try
    {
        CStdioFile file;
    file.Open(_T("D:\\"), CFile::modeCreate | CFile::modeWrite | CFile::typeText);
//打开D盘的txt文件
        file.WriteString(strText);  //写入edit box中的数据
        file.Close();
    }
    catch (CFileException* e)
    {
        e->ReportError();
        e->Delete();
    }
CString path = "d:\\";
        CString temp;
        CFile file;
        float a = 12.2, b = 123.3, c = 1234.4;
        file.Open(path, CFile::modeCreate | CFile::modeReadWrite);
        temp = "通道1  通道2  通道3\r\n";
        file.Write(temp, temp.GetLength());
        CString m_str;
        for(int i = 0; i < 1; i++)
        {
            temp.Empty();
            m_str.Format("%.1f    ", a);
            temp += m_str;
            m_str.Format("%.1f    ", b);
            temp += m_str;
            m_str.Format("%.1f    ", c);
            temp += m_str;
cstring转为int            temp += "\r\n";
            file.Write(temp, temp.GetLength());
        }
        file.Close();
MFC绘制动态曲线,用双缓冲绘图技术防闪烁 
2011-07-14 10:34:54|  分类: 学习笔记 |  标签:双缓冲绘图技术  mfc  动态曲线  |举报|字号 订阅
先上效果图
随着时间的推移,曲线向右平移,同时X轴的时间坐标跟着更新。
一、如何绘制动态曲线。
所谓动画,都是一帧一帧的图像连续呈现在用户面前形成的。所以如果你掌握了如何绘制静态曲线,那么学会绘制动态曲线也不远啦,只需要创建一个定时器(比如调用MFC中的SetTimmer函数),每隔一定时间(比如1ms),调用OnPaint或者OnDraw函数,绘制当前帧图像即可
这里需要注意的是,绘制图像的代码需要写在OnPaint或者OnDraw函数中,因为当窗口失效(比如最小化)恢复后,会重新绘制当前窗口,窗口之前的自绘图像会丢失。而把绘图代码写在OnPaint或者OnDraw中就是为了让窗口每次重绘时也能重绘你自己画的图像,避免出现窗口最小化再恢复后,自己画的图像丢失的尴尬情况。
另外绘制当前帧图像之前,记得用InvalidateRect函数清除上一帧图像,不然各帧图像会背景的堆叠。
比如我想清除窗口中(0,0)和(100,100)这两点确定的矩形中的图像,代码如下:
    CRect Rect;
    p = 0;
    Rect.left = 0;
    Rect.bottom = 100;
    Rect.right = 100;
    InvalidateRect(Rect);
根据上面的思路,我们每隔一定时间绘制一幅图像,可是如果每次绘制的图像都是完全相同的,那么图像看起来也是静态的。如何让曲线动起来呢?我们需要为自己绘图的代码设计一个输入,即在当前时刻曲线上各个点的坐标信息。随着时间的推移,令曲线上各个点的坐标随之变化,这样每次绘图都是基于当前时刻的曲线坐标绘制的,控制好曲线坐标的变化,也就能让你绘制的曲线乖乖的动起来。
上面提到了曲线上各个点的坐标信息,这个信息可以用多种数据结构储存,不过笔者推荐使用STL中的deque数据结构储存。为什么呢?需求决定选择。让我们先想想在绘制图像的过程中需要对这个数据进行哪些操作。
1、需要遍历这个数据,获取各个点的坐标以便绘图,所以选择的数据结构必须有较高的遍历效率。
2、当曲线上的点横向上充满了横坐标轴提供的显示范围,需要将曲线最右边的点的坐标移除,然后在曲线最左边添加下一个新点的坐标,以实现曲线向右平移的效果。所以选择的数据结构需要支持前端和后端元素的添加删除操作,大家很自然会想到队列。
STL中的list容器也能很轻松的实现队列功能,但是list还支持任意位置元素的添加和删除操作,功能上的冗余决定了list需要花费更多的时间来实现我们的需求,事实上遍历一个deque常常比遍历一个list快几十倍,原因在这里就不赘述啦。
于是,笔者构建了这样的数据结构deque<pair<TIME, VALUE>> m_dqDisplayData;队列中的每个元素是一个pair,pair中存放坐标。维护这个数据结构的核心代码如下:
    //如果队列长度超过了X轴方向上可绘的所有点的数量
    if (m_dqDisplayData.size() >= XPointNum)
    {
        //将队列前端的坐标移除
        m_dqDisplayData.pop_front();
      //在队列后端添加新的坐标
        m_dqDisplayData.push_back(make_pair(time, value));
    }
    else
    {
        m_dqDisplayData.push_back(make_pair(tiem, value));
    }
前面介绍了如何让静态的曲线动起来,下面具体介绍绘制静态图像的主要技能。
1、画图首先需要一位画家,MFC是这样获取一位画家的。
CDC *pDC = GetDC();
记得这位画家画完本帧图像之后,打发他走人,闲人咱们养不起。
即必须用ReleaseDC(pDC);释放资源,否则会造成内存泄漏,因为GetDC();函数中分配了一些资源,这些资源关联在pDC指向的内存中,如果不调用ReleaseDC,当pDC出作用域后,
只是pDC这个32位的指针变量(也可以说它是一个整数变量)的内存释放了,pDC指向的内存没有机会得到释放。这里也反映出MFC的一个原则,Get之后需要Release,这两个函数往往是成对定义好的。
另外,GetDC和ReleaseDC都是CWnd的成员函数,我们需要在哪个窗口上画图,就在那个窗口类的OnPaint或者OnDraw函数中创建一位会在该窗口上画画的画家,其实GetDC中隐含的操作是,创建一位画家,将自己所在的窗口的绘图区作为画纸交给这位画家,然后再把画家返回给用户。当我们直接建立CDC对象时(比如:CDC  MemDC;),就需要用其他方法(比如:SelectObject函数)为其选择画纸了。
2、画家画图之前,首先要准备好画图工具。
MFC提供了很多画图工具,比如画刷(CBrush),画笔(CPen)等。(呵呵,其实笔者也没用过几种)
    //下面就实例化了一个画实线,宽度为1,颜为RGB(0, 128, 64)的画笔
    CPen PenForDrawAxis(PS_SOLID, 1, RGB(0, 128, 64));
    //画家使用SelectObject技能,将画笔握入手中
    pDC->SelectObject(PenForDrawAxis);
另外说明一点:关于画笔不再使用后,是否需要调用PenForDrawAxis.DeleteObject();释放资源的问题,网上说法不一。各大书籍上,作者们都常常下意识的显式地调用了DeleteObject函数,以体现释放资源的动作。
如果需要及时释放内存资源,为后面的程序运行扫清障碍,那显式的调用DeleteObject函数我觉得没有问题。但是如果说不调用DeleteObject函数,CPen对象分配的资源就无法释放,就会造成内存泄漏,这点我深表怀疑。
因为CPen对象的资源在构造函数中分配,自然在其析构函数中应该有对应的释放函数,因为作为MFC用户来说, 在使用CPen时,根本不知道是否分配了需要显式释放的资源。对象应该对自己负责,不应该将冗余责任移交给用户,这是设计C++类的基本原则。通俗的说就是,自己干了哪些好事自己心理清楚,走人的时候自己要收拾干净。微软在代码上不会耍流氓吧(虽然其他地方经常流氓)。
MSDN上的原话是:When an application no longer requires a given pen, it should call the CGdiObject::DeleteObject member function or destroy the CPen object so the resource is no longer in use. An application should not delete a pen when the pen is selected in a device context.

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。