第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  总结

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

 

版权声明:本文为armfly原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/armfly/p/9243838.html