本站动态:

MainMenuWidget简介

之前开发了一个MainMenuWidget,主要用于主菜单的12宫格。它具有以下功能:

1、宫格数可以由用户确定,最大宫格数由宏由MW_ITEM_ROW_MAX_NUM和MW_ITEM_COL_MAX_NUM控制。工程中使用的MainMenuWidget支持n * m宫格(n <= MW_ITEM_ROW_MAX_NUM && m <= MW_ITEM_COL_MAX_NUM)的任意组合。

2、任意一个宫格都可以设置是否支持可选中状态。

3、可以有动画移动效果,也可以关闭动画移动效果。

4、每个选中的宫格都支持animation动画,也可以关闭该功能。各个宫格的动画帧数可以不一致,也可以设置animation动画的播放次数(0次到无限)

5、可以设置移动选中Item到达边界后移向哪里(不再移动/回到同行另一端/移动到上一行/移动到下一行)

6、用户可以通过IWIDGET_SetFocusIndex()和IWIDGET_SelectIndex()设置focus的item或快速进入某个item。

7、Widget通过用户注册的函数通知用户focus发生了移动或某个Item被用户选中了(一般情况下用户只关心选中事件):

  1. typedef enum {
  2.     EVT_Select = 0x00,
  3.     EVT_MOVE_FROM_LEFT = 0x01,
  4.     EVT_MOVE_FROM_RIGHT = 0x02,
  5.     EVT_MOVE_FROM_UP = 0x04,
  6.     EVT_MOVE_FROM_DOWN = 0x08,
  7.     //EVT_MOVE will be sent when the event is not generated by key pressing,
  8.     //eg. Set property of PROP_FOCUSINDEX or PROP_SelectINDEX, or by touching screen if supported
  9.     EVT_MOVE = 0x0F //You can use it to check whether it is a move event via (evt & EVT_MOVE)
  10. } mmwEvent;
  11. typedef void (*PFNMMWSelectHANDLER)(void* pCtx, mmwEvent evt, mmwItemPos* pos)

8、在设计之初MainMenuWidget是不支持触摸屏的,不过后来加了二三十行代码让它支持了。这里使用的方法是将触摸屏事件转化为对PROP_SelectINDEX和PROP_FOCUSINDEX进行设置的EVT_WDG_SETPROPERTY事件。当初在设计的时候考虑了多种方案,最后想到了该方案,个人非常喜欢这样的设计,代码如下:

  1. #ifdef FEATURE_TOUCH_PANEL
  2. //if it is an touch event, we translate it to non-touch event in order to let it support touch events
  3. //we will calculate the point position and translate it to mmwItemPos which will be saved to *pIp,
  4. //and let dwParam point to pIp
  5. static void MainMenuWidget_TranslateTouchEvt(MainMenuWidget* me, AEEEvent* evt,
  6.                                              uint16* wParam, uint32* dwParam, mmwItemPos* pIp)
  7. {
  8.     if (TRUE == me->bNapping)
  9.         return;
  10.     switch (*evt)
  11.     {
  12.     case EVT_POINTER_MOVE: //set focus index
  13.     case EVT_POINTER_DOWN: //set focus index
  14.     case EVT_POINTER_UP: //set selected index
  15.         //set mmwItemPos values
  16.         pIp->indexCol = (*dwParam >> 16) / me->mdt->itemWidth;
  17.         pIp->indexRow = (*dwParam & 0xFFFF) / me->mdt->itemHeight;
  18.  
  19.         //point to mmwItemPos
  20.         *dwParam = (uint32)pIp;
  21.  
  22.         //change wParam value, MUST be BEFORE changing event code
  23.         if (EVT_POINTER_UP == *evt)
  24.             *wParam = (uint16)PROP_SelectINDEX;
  25.         else
  26.             *wParam = (uint16)PROP_FOCUSINDEX;
  27.  
  28.         //change event code
  29.         *evt = EVT_WDG_SETPROPERTY;
  30.         break;
  31.     default:
  32.         break;
  33.     }
  34. }
  35. #endif
  36.  
  37. static boolean MainMenuWidget_HandleEvent(IWidget *po, AEEEvent evt,
  38.                                          uint16 wParam, uint32 dwParam)
  39. {
  40.     MainMenuWidget* me = IWIDGET_TO_MW_WIDGET(po);
  41.     ……
  42. #ifdef FEATURE_TOUCH_PANEL
  43.     mmwItemPos ip = {0};
  44.     MainMenuWidget_TranslateTouchEvt(me, &evt, &wParam, &dwParam, &ip);
  45. #endif
  46.     ……
  47.     else if (EVT_WDG_SETPROPERTY == evt)
  48.     {
  49.         switch (wParam)
  50.         {
  51.         case PROP_FOCUSINDEX: //use the same code with PROP_SelectINDEX
  52.         case PROP_SelectINDEX: //user wanna select the item
  53.             {
  54.                 mmwItemPos *ps = (mmwItemPos*)dwParam;
  55.                 me->eMovingStep = MOVING_STEP_NONE;
  56.                 me->eMovingDirect = MOVING_NONE;
  57.  
  58.                 //if it is napping, we do not take any action
  59.                 if (TRUE == me->bNapping)
  60.                     break;
  61.  
  62.                 //check whether is right pos
  63.                 if (ps->indexCol >= me->mdt->itemColNum)
  64.                     ps->indexCol = me->mdt->itemColNum - 1;
  65.                 if (ps->indexRow >= me->mdt->itemRowNum)
  66.                     ps->indexRow = me->mdt->itemRowNum - 1;
  67.  
  68.                 if (FALSE == MW_CAN_ITEM_TAKE_FOCUS(*ps))
  69.                 {
  70.                 #if 0
  71.                     int i, j;
  72.  
  73.                     for (i = 0; i < me->mdt->itemRowNum ; i++)
  74.                     {
  75.                         for(j = 0; j < me->mdt->itemColNum ; j++)
  76.                         {
  77.                             if (TRUE == me->mdt->arrActiveItemData[i][j].bCanTakeFocus)
  78.                             {
  79.                                 ps->indexCol = j;
  80.                                 ps->indexRow = i;
  81.                                 break;
  82.                             }
  83.                         }
  84.                     }
  85.                 #else
  86.                     //couldn't set focus to the item, just ignore it, so we break it.
  87.                     break//break switch (wParam)
  88.                 #endif
  89.                 }
  90.  
  91.                 if (me->newFocusItemPos.indexCol != ps->indexCol
  92.                     || me->newFocusItemPos.indexRow != ps->indexRow)
  93.                     MW_SEND_EVENT(EVT_MOVE, &me->newFocusItemPos);
  94.  
  95.                 me->newFocusItemPos = *ps;
  96.                 me->oldFocusItemPos = me->newFocusItemPos;
  97.  
  98.                 SET_RECT_BY_POS(me->newFocusItemRect, me->newFocusItemPos);
  99.                 me->oldFocusItemRect = me->newFocusItemRect;
  100.                 MW_SET_ANIMATION_POS(me->newFocusItemPos);
  101.  
  102. #if defined MW_PRELOAD_IMAGES && defined MW_PRELOAD_ANIMATION
  103.                 MW_MOVE_ANI_LIST(me->oldAnimateList, me->newAnimateList);
  104.                 MW_LOAD_ANI_LIST_DEFAULT(me->animatingItemPos);
  105.                 me->bDrawImageFromNewList = TRUE;
  106. #endif
  107.                 //draw new active item immediately
  108.                 //WidgetBase_Invalidate(CAST(IWidget*, me), ICIF_REDRAW);
  109.                 //start its animation
  110.                 ISHELL_Resume(me->piShell, &me->cbkItemAnimation);
  111.  
  112.                 //defer to call user's callback function
  113.                 if (PROP_SelectINDEX == wParam)
  114.                 {
  115.                     me->userSelectedPos = me->newFocusItemPos;
  116.                     me->bNapping = TRUE;
  117.                     ISHELL_SetTimer(me->piShell, 100, MainMenuWidget_SelectItem, (void*)me);
  118.                 }
  119.             }
  120.             break;
  121.             ……
  122.         }
  123.     }
  124.     ……
  125. }    

 以上为触摸屏添加的代码都用宏FEATURE_TOUCH_PANEL控制起来了。

正因为MainMenuWidget的灵活性,所以各个工程中各个使用到它的地方,可以很方便的(用宏)控制或切换效果。

注:网站后台程序会自动将Select转化为Select,代码中的PFNMMWSelectHANDLER、EVT_Select和PROP_SelectINDEX应为全部大写。



[本日志由 shosh 于 2010-04-24 00:08 AM 编辑]
文章来自: Shosh原创
引用通告: 查看所有引用 | 我要引用此文章
Tags:
相关日志:
评论: 0 | 引用: 0 | 查看次数: 255
发表评论
昵 称:
密 码: 游客发言不需要密码.
内 容:
验证码: 验证码
选 项:
虽然发表评论不用注册,但是为了保护您的发言权,建议您注册帐号.
字数限制 1000 字 | UBB代码 开启 | [img]标签 关闭