[原创] 【STM32F7英雄联盟大赛】demo模块及及界面理解

247153481   2015-12-17 15:19 楼主
拿到stm32F746开发板,运行官方提供的demo,觉得很惊艳。

而且在项目中应该也可以使用这种方法,毕竟好的东西都可以学习和使用

初看代码,便看到k_ModuleAdd(),显得非常简洁独立,试着删除掉,屏幕上立马就少了一个图标,而其他的并没有受到影响,而且还可以自动调整

点击图标打开程序竟然还有翻转效果,对实现原理很是好奇,与今日便花了点时间看了看代码,学习一下是如何实现的。
模块模块的添加
先列出主页的一些必要代码
  
extern  K_ModuleItem_Typedef   video_player_board;
  
k_ModuleInit();
  
k_ModuleAdd(&audio_player_board);  
  


这样就算完成了一个模块的添加。

类型 K_ModuleItem_Typedef
定义在k_module.h

  
typedef  struct
  
{
  
uint8_t      id;
  
const char   *name;
  
GUI_CONST_STORAGE GUI_BITMAP  ** open_icon;
  
GUI_CONST_STORAGE GUI_BITMAP  ** close_icon;
  
void         (*startup) (WM_HWIN , uint16_t, uint16_t );
  
void         (*DirectOpen) (char * );
  
}
  
K_ModuleItem_Typedef;  
  

ID 模块的id
Name 显示在图标下的名字

Open_icon 一个二级指针,里面固定存放5张图片,知道图标翻转效果怎么来的吗?对就是在这里

Close_icon类似喽
Startup 一个函数指针,这个最重要了 ,点击图片你希望有什么样的反应。
DirectOpen 好像没怎么用到 设置为NULL即可

来一个具体例子
  
K_ModuleItem_Typedef  audio_recorder_board =
  
{
  
  7,
  
  "audio recorder   ",
  
  open_recorder,
  
  0,
  
  Startup,
  
  NULL,
  
}
  

类型 K_ModulePropertyTypedef
  
typedef  struct
  
{
  
  const K_ModuleItem_Typedef   *module;   
  
  uint8_t   in_use;  
  
  uint8_t   win_state;   
  
}
  
K_ModulePropertyTypedef;
  

模块属性
包含一个模块指针,指向上面定义的模块
win_state 表示当前模块是否在后台运行,如果在后台运行,那么再次打开的时候只需要显示就可以了,而不需要新建。
in_use 当前模块是否在运行
类型 K_ModuleOpenTypedef

  
typedef  struct
  
{
  
  char    ext[4];
  
  const K_ModuleItem_Typedef   *module;
  
}
  
K_ModuleOpenTypedef;
  

好像没怎么用到


在画一个总体关系图

QQ截图20151217151806.jpg
几个重要函数
k_ModuleInit
  
void  k_ModuleInit(void)
  
{
  
  module_num = 0;
  
  openlink_num = 0;
  
  memset(module_prop, 0,  sizeof(module_prop));
  
  memset(open_link, 0,  sizeof(module_prop));  
  
}
  

module_num和openlink_num为全局变量,记录模块总数和打开总数。
  
K_ModulePropertyTypedef    module_prop [MAX_MODULES_NUM];
  
K_ModuleOpenTypedef        open_link   [MAX_MODULES_NUM]
  
;定义的全局数组,存储所加载的模块参数

  
uint8_t  k_ModuleAdd(K_ModuleItem_Typedef *module)
  
{
  
  module_prop[module_num].in_use = 0;
  
  module_prop[module_num].win_state = 0;
  
  module_prop[module_num].module = module;
  
  module_num++;
  
  return 0;
  
}
  
添加一个模块,状态置0;

重点就在下面了,图标菜单是如何实现的
文件k_menu.c
在介绍这个之前不得不先说一下st的另外一个库
STM32746G_Discovery_STemWin_Addons_Keil.lib
St对默认皮肤和图标界面进行了封装。展现出来的效果就是demo那样了。

建立菜单界面的关键函数
  
void  k_InitMenu(void)
  
{
  
  uint8_t i = 0;
  
  WM_HWIN    hItem;
  
  
  
  
  WM_SetCallback(WM_GetDesktopWindowEx(0),  _cbBk);
  
  
  
  hIcon = ST_AnimatedIconView_CreateEx(0,
  
                                       0,
  
                                        LCD_GetXSize() - 80,
  
                                        LCD_GetYSize() - 0,
  
                                        WM_GetDesktopWindowEx(0),
  
                                        WM_CF_SHOW | WM_CF_HASTRANS ,
  
                                       0,
  
                                        ID_ICONVIEW_MENU,
  
                                       100,
  
                                       120,  40, 5);
  
  
  
  ST_AnimatedIconView_SetDualFont(hIcon,  &GUI_FontLubalGraph16, &GUI_FontLubalGraph16);
  
  
  
  ST_AnimatedIconView_SetSpace(hIcon,  GUI_COORD_Y, 0);
  
  ST_AnimatedIconView_SetSpace(hIcon,  GUI_COORD_X, 0);
  
  ST_AnimatedIconView_SetFrame(hIcon,  GUI_COORD_Y, 0);
  
  ST_AnimatedIconView_SetFrame(hIcon,  GUI_COORD_X, 0);
  
  
  
  ST_AnimatedIconView_SetTextColor(hIcon,  ICONVIEW_CI_UNSEL, GUI_STCOLOR_LIGHTBLUE);
  
  ST_AnimatedIconView_SetBkColor(hIcon,  ICONVIEW_CI_UNSEL, GUI_WHITE);
  
  ST_AnimatedIconView_SetBkColor(hIcon,  ICONVIEW_CI_SEL, GUI_WHITE);
  
  ST_AnimatedIconView_SetSel(hIcon, -1);
  
  ST_AnimatedIconView_SetDualTextColor(hIcon,  ICONVIEW_CI_SEL, GUI_STCOLOR_LIGHTBLUE, GUI_STCOLOR_DARKBLUE    );   
  
  
  
  for (i = 0; i < k_ModuleGetNumber();  i++)
  
  {   
  
    ST_AnimatedIconView_AddIcon(hIcon,  module_prop.module->open_icon, module_prop.module->close_icon,  (char *)module_prop.module->name);
  
  }
  
  
  
  hItem = TEXT_CreateEx(407, 152, 260, 20,  WM_GetDesktopWindowEx(0), WM_CF_SHOW, TEXT_CF_LEFT, ID_FEATURES_FPU,  "FPU : ON");
  
  TEXT_SetFont(hItem, GUI_FONT_8_1);
  
  TEXT_SetTextColor(hItem, GUI_WHITE);
  
  
  
  hItem = TEXT_CreateEx(407, 167, 260, 20,  WM_GetDesktopWindowEx(0), WM_CF_SHOW, TEXT_CF_LEFT, ID_FEATURES_IC,  "I-Cache : ON");
  
  TEXT_SetFont(hItem, GUI_FONT_8_1);
  
  TEXT_SetTextColor(hItem, GUI_WHITE);     
  
  
  
  hItem = TEXT_CreateEx(407, 182, 260, 20, WM_GetDesktopWindowEx(0),  WM_CF_SHOW, TEXT_CF_LEFT, ID_FEATURES_DC, "D-Cache : ON");
  
  TEXT_SetFont(hItem, GUI_FONT_8_1);
  
  TEXT_SetTextColor(hItem, GUI_WHITE);  
  
  
  
  hCPULoad = TEXT_CreateEx(407, 198, 260, 20,  WM_GetDesktopWindowEx(0), WM_CF_SHOW, TEXT_CF_LEFT, ID_FEATURES_CPU,  "MCU Load : --%");
  
  TEXT_SetFont(hCPULoad, GUI_FONT_8_1);
  
  TEXT_SetTextColor(hCPULoad,  GUI_WHITE);  
  
  
  
  hItem = TEXT_CreateEx(407, 212, 260, 20,  WM_GetDesktopWindowEx(0), WM_CF_SHOW, TEXT_CF_LEFT, ID_FEATURES_FREQ,  "Clk : 200 MHz");
  
  TEXT_SetFont(hItem, GUI_FONT_8_1);
  
  TEXT_SetTextColor(hItem, GUI_WHITE);   
  
  
  
  hRefreshTimer =  WM_CreateTimer(WM_GetDesktopWindowEx(0), 0, 500, 0);   
  
}
  

意思跟据函数名称就可以看得出来。
对界面的响应在回调函数中
  
static  void _cbBk(WM_MESSAGE * pMsg) {
  
  
  
  uint32_t NCode, Id;
  
  static uint8_t sel;
  
  WM_HWIN    hItem;
  
  char tmp[16];
  
  
  
  switch (pMsg->MsgId)
  
  {
  
  case WM_PAINT:
  
    GUI_SetBkColor(GUI_WHITE);
  
    GUI_Clear();
  
  
    /*H/W Information */
  
    GUI_SetColor(0x007C18CC);
  
    GUI_AA_FillRoundedRect(400, 31, 780, 238,  15);
  
    GUI_DrawBitmap(&bmF7Logo, 400, 47);
  
    break;
  
      
  
   
  
  case WM_TIMER:
  
   
  
    hItem = WM_GetDialogItem(pMsg->hWin,  ID_FEATURES_CPU);
  
   
  
    sprintf((char *)tmp , "MCU Load :  %d%%",  osGetCPUUsage());
  
    TEXT_SetText(hItem, tmp);
  
   
  
    WM_InvalidateWindow(hItem);
  
    WM_Update(hItem);
  
    WM_RestartTimer(pMsg->Data.v, 1000);
  
    break;
  
  
  
  
  
  case WM_NOTIFY_PARENT:
  
    Id     = WM_GetId(pMsg->hWinSrc);      
  
     NCode = pMsg->Data.v;  
  
   
  
//这里开始处理图标响应
  
    switch (NCode)
  
    {  
  
      
  
    case WM_NOTIFICATION_RELEASED:
  
      if (Id == ID_ICONVIEW_MENU)//点击的是菜单
  
      {
  
        sel =  ST_AnimatedIconView_GetSel(pMsg->hWinSrc);//得到点击图标的idex
  
        
  
        if(sel < k_ModuleGetNumber())
  
        {
  
           ST_AnimatedIconView_SetSel(pMsg->hWinSrc, -1);
  
          if(module_prop[sel].in_use == 0)
  
          {
  
             module_prop[sel].module->startup(pMsg->hWin, 0, 0);//进入此功能app
  
            module_prop[sel].in_use = 1;//注明正在运行
  
          }
  
         
  
          else if(module_prop[sel].win_state == 1)//如果是后台运行
  
          {
  
             module_prop[sel].module->startup(pMsg->hWin, 0, 0);
  
          }         
  
        }
  
        else
  
        {
  
          WM_InvalidateWindow  (pMsg->hWinSrc);
  
        }
  
      }
  
      break;
  
  
     case WM_NOTIFICATION_CHILD_DELETED://退出功能
  
        module_prop[sel].in_use = 0;
  
        module_prop[sel].win_state = 0;
  
        break;
  
      
  
    default:
  
      break;
  
    }
  
    break;
  
  default:
  
    WM_DefaultProc(pMsg);
  
  }
  
}
  

到这里就应该比较明白了,当然还存在很多细节和技巧,需要更进一步研究

如果想要加入一个模块或删除一个模块,给对应的数据结构填充数据。

菜单初始化则会对所有的菜单进行自动调整显示,如果多余8个,应该会自动到第二页。

当用户点击图标项,iconview会发送消息给父窗口,然后根据所点击的图标索引调用相应的入口函数





回复评论 (2)

DEMO的代码真不是一时半会儿能学会的。
看了一天只是看了个皮毛,结构弄清楚了点。
确实是高手写的啊。
点赞  2015-12-22 10:42
引用: arthasarthas 发表于 2015-12-22 10:42
DEMO的代码真不是一时半会儿能学会的。
看了一天只是看了个皮毛,结构弄清楚了点。
确实是高手写的啊。

是的,写的非常好,结构很清晰,可以用在自己的项目里面
点赞  2015-12-22 13:25
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复