zoukankan      html  css  js  c++  java
  • 【安富莱二代示波器教程】第7章 示波器设计—波形滑动浏览

    第7章        示波器设计—波形滑动浏览

    类似手机的滑动功能用在示波器上还是比较实用的,可以用来调节波形位置和滑动浏览波形的存储记录。

    7.1   滑动基础知识

    7.2   滑动基础知识总结

    7.3   滑动功能在窗口上的实现

    7.4    总结

    7.1  滑动基础知识

    滑动的实现是基于emWin提供的Motion功能。在emWin的官方手册中对这部分功能讲解的比较少,但是仍然需要大家去读一下,有一个大概的了解。

     

    7.2   滑动基础知识总结

    望大家务必看了emWin官方手册中Motion章节的内容,这里将这些知识点做个汇总,方便大家后面使用。

    WM_MOTION_Enable()            使能motion

    WM_MOTION_SetMoveable()      使能窗口X方向或者Y方向的Motion

    WM_MOTION_SetMovement()     设置窗口以指定的速度移动一段距离。

    =================

    WM_MOTION_SetDeceleration()    设置窗口减速度

    WM_MOTION_SetSpeed()          设置窗口的移动速度。

    WM_MOTION_SetMotion()         设置初始速度和加速度。等同于上面两个函数之和

    =======================

    WM_MOTION_SetDefaultPeriod() 

    设置指针输入设备(触摸,鼠标,键盘等)等释放后,减速度默认持续的时间。

    1、如果窗口在移动中,将减速,直到停止运行。

    2、如果窗口没有移动,但是使能了snap功能,那么窗口会在设置的时间内移动到下一个栅格内。

    3、如果窗口在移动,且使能了snap功能,那么窗口会减速运动直到停止在最近的一个栅格上。

     

    上面的这些函数都是独立的操作Motion功能,而二代示波器中使用Motion功能是基于窗口的,其实就是把上面这些函数的功能在窗口上实现。下面我们就讲解二代示波器的Motion功能实现。

    7.3   滑动功能在窗口上的实现

    我们这里以二代示波器的滑动功能实现过程为例,给大家做个说明。

    第1步:使能滑动,设置周期。

    WM_MOTION_Enable(1);              /* 使能滑动 */
    
    WM_MOTION_SetDefaultPeriod(100);  /* 设置滑动周期 */

    第2步:创建一个透明的窗口,正好覆盖600*400的波形显示区。

    hMotion = WM_CreateWindowAsChild(40,
    
                                     40,
    
                                      600,
    
                                      400,
    
                                      WM_HBKWIN, 
    
                                      WM_CF_MOTION_Y | WM_CF_SHOW | WM_CF_HASTRANS,
    
                                      _cbMotion,
    
                                      sizeof(pPara));
    
                                          
    
    WM_SetUserData(hMotion, &pPara, sizeof(pPara));

    函数里面的标志WM_CF_MOTION_Y | WM_CF_SHOW | WM_CF_HASTRANS比较重要,滑动标志既可以在这里设置,也可以在窗口回调函数的WM_MOTION消息里面设置。

    WM_CF_MOTION_Y:表示窗口支持垂直滑动。

    WM_CF_MOTION_X:表示窗口支持水平滑动(在窗口回调里面进行了设置)。

    WM_CF_HASTRANS:表示窗口透明,这个标志不要忘记设置,这样使用滑动功能的时候对示波器显示区没有任何影响。

    第3步:也是最后一步,滑动窗口的回调函数。

    源代码是如下这样的:

    /*
    
    *********************************************************************************************************
    
    *    函 数 名: _cbMotion
    
    *    功能说明: Motion窗口的回调函数,主要是桌面图标的滑动处理
    
    *    形    参: pMsg  WM_MESSAGE类型指针变量  
    
    *    返 回 值: 无
    
    *********************************************************************************************************
    
    */
    
    static void _cbMotion(WM_MESSAGE * pMsg)
    
    {
    
         WM_MOTION_INFO * pInfo;
    
         WM_HWIN          hWin = pMsg->hWin;
    
         PARA           * pPara;
    
     
    
         switch (pMsg->MsgId)
    
         {
    
             case WM_MOTION:
    
                  WM_GetUserData(hWin, &pPara, sizeof(pPara));
    
                  pInfo = (WM_MOTION_INFO *)pMsg->Data.p;
    
                  switch (pInfo->Cmd)
    
                  {
    
                       /* Motion功能初始化,设置X方向和Y方向都支持滑动 */
    
                       case WM_MOTION_INIT:
    
                           pInfo->Flags =  WM_CF_MOTION_X | WM_CF_MOTION_Y | WM_MOTION_MANAGE_BY_WINDOW;
    
                           pInfo->SnapY = 1;
    
                           pInfo->SnapX = 1;
    
                           break;
    
     
    
                       case WM_MOTION_MOVE:
    
                           pPara->FinalMove = pInfo->FinalMove;
    
                            /* Y轴方向,上下滑动 */
    
                           if(g_Flag->ucMotionXY == 0)
    
                           {
    
                                if((pInfo->pState->Pressed == 1)&&(pInfo->pState->x <= 340))
    
                                {
    
                                     pPara->iCH1Pos += pInfo->dy;
    
                                     if(pPara->iCH1Pos >= 440)
    
                                     {
    
                                         pPara->iCH1Pos = 440;
    
                                     }
    
                                     if(pPara->iCH1Pos <= 40)
    
                                     {
    
                                         pPara->iCH1Pos = 40;
    
                                     }
    
     
    
                                     g_DSO1->usRefPos = pPara->iCH1Pos;
    
                                }
    
                                else if((pInfo->pState->Pressed == 1)&&(pInfo->pState->x > 340))
    
                                {                          
    
                                     pPara->iCH2Pos += pInfo->dy;
    
                                     if(pPara->iCH2Pos >= 440)
    
                                     {
    
                                         pPara->iCH2Pos = 440;
    
                                     }
    
                                     if(pPara->iCH2Pos <= 40)
    
                                     {
    
                                         pPara->iCH2Pos = 40;
    
                                     }
    
     
    
                                     g_DSO2->usRefPos = pPara->iCH2Pos;
    
                                }
    
     
    
                                WM_InvalidateArea(&rRefPos);
    
                           }
    
                           /* X轴方向,左右滑动 */
    
                           else
    
                           {
    
                                if(pInfo->pState->Pressed == 1)
    
                                {
    
                                     g_DSO1->sCurTriStep -= pInfo->dx;
    
                                }
    
     
    
                                if(TriggerFlag == 0)
    
                                {
    
     
    
                                }
    
                                else
    
                                {
    
                                     if(g_DSO1->sCurTriStep <= -724)
    
                                     {
    
                                         g_DSO1->sCurTriStep = -724;
    
                                     }
    
     
    
                                     if(g_DSO1->sCurTriStep >= 724)
    
                                     {
    
                                         g_DSO1->sCurTriStep = 724;
    
                                     }
    
     
    
                                     TriggerFlag = 2;
    
                                }
    
     
    
                                WM_InvalidateArea(&rTrigPos);
    
                           }
    
     
    
                           /* 更新当前的数据位置的箭头 */
    
                           g_Flag->ucWaveRefresh = 1;
    
                           break;
    
     
    
                       case WM_MOTION_GETPOS:
    
                           pInfo->yPos = pPara->iCH1Pos;
    
                           //pInfo->xPos = pPara->iCH1Pos;
    
                           break;
    
                  }
    
                  break;
    
         }
    
    }

    为了方便看这个函数实现的功能,这里将其进一步简化成如下这样:

    static void _cbMotion(WM_MESSAGE * pMsg)
    
    {
    
         WM_MOTION_INFO * pInfo;
    
         WM_HWIN          hWin = pMsg->hWin;
    
         PARA           * pPara;
    
     
    
         switch (pMsg->MsgId)
    
         {
    
             case WM_MOTION:
    
                  WM_GetUserData(hWin, &pPara, sizeof(pPara));
    
                  pInfo = (WM_MOTION_INFO *)pMsg->Data.p;
    
                  switch (pInfo->Cmd)
    
                  {
    
                       /* Motion功能初始化,设置X方向和Y方向都支持滑动 */
    
                       case WM_MOTION_INIT:      //-----------(1)
    
                           pInfo->Flags =  WM_CF_MOTION_X | WM_CF_MOTION_Y | WM_MOTION_MANAGE_BY_WINDOW;
    
                           pInfo->SnapY = 1;
    
                           pInfo->SnapX = 1;
    
                           break;
    
     
    
                       case WM_MOTION_MOVE:  //-----------(2)
    
                           pPara->FinalMove = pInfo->FinalMove;
    
                            /* Y轴方向,上下滑动 */
    
                           if(g_Flag->ucMotionXY == 0)
    
                           {
    
                                if(pInfo->pState->Pressed == 1)
    
                                {
    
                                    
    
                                }
    
                           }
    
                           /* X轴方向,左右滑动 */
    
                           else
    
                           {
    
                                if(pInfo->pState->Pressed == 1)
    
                                {
    
                                }
    
                           }
    
     
    
                           /* 更新当前的数据位置的箭头 */
    
                           g_Flag->ucWaveRefresh = 1;
    
                           break;
    
     
    
                       case WM_MOTION_GETPOS:   //-----------(3)
    
                           pInfo->yPos = pPara->iCH1Pos;
    
                           //pInfo->xPos = pPara->iCH1Pos;
    
                           break;
    
                  }
    
                  break;
    
         }
    
    }

    滑动功能实现的关键就在这个WM_MOTION消息里面。

    1、WM_MOTION_INIT消息

    在初始化消息里面设置pInfo->Flags来使能水平滑动和垂直滑动,并且通过标志WM_MOTION_MANAGE_BY_WINDOW使能窗口管理器来管理Motion功能。标志pInfo->SnapY和pInfo->SnapX是用来设置滑动停止后的栅格区域,详情看7.2小节中函数WM_MOTION_SetDefaultPeriod的作用说明。

    2、WM_MOTION_MOVE消息

    这个消息在二代示波器中的使用比较简单,主要是判断是否按下,然后根据按下的位置设置波形的水平或者上下移动即可。当前按下的位置在参数pInfo->pState->x和pInfo->pState->y里面。实际的波形更新是通过设置标志g_Flag->ucWaveRefresh = 1实现的。

    3、WM_MOTION_GETPOS消息

    这个消息未用到,用于获取按下的位置。

    7.4  总结

    关于滑动的实现,关键的知识点就这么多,需要大家实际操作下,有个深入的认识。

  • 相关阅读:
    CentOS7局域网下安装离线Ambari
    虚拟机怎么发送ctrl+alt+delete组合键
    RedHat6.5创建本地yum源
    RedHat7安装vmware虚拟机启动报错
    Spark基本术语表+基本架构+基本提交运行模式
    Spark官网资料学习网址
    大数据开源组件图谱
    HADOOP1.X中HDFS工作原理
    大数据时代——为什么用HADOOP?
    Linux Shell脚本中获取本机ip地址方法
  • 原文地址:https://www.cnblogs.com/armfly/p/9243838.html
Copyright © 2011-2022 走看看