• 【第3版emWin教程】第45章 emWin6.x窗口管理器之定时器使用


    教程不断更新中:http://www.armbbs.cn/forum.php?mod=viewthread&tid=98429

    第45章       emWin6.x窗口管理器之定时器使用

    本期教程为大家讲解窗口管理器之定时器使用方法,这个定时器使用起来比较简单,而且很实用,以后的项目工程中很多时候要用到,不过使用时有些小问题要特别注意,如果不注意的话,定时器将无法正确启动。

    45.1  初学者重要提示

    45.2 定时器功能介绍

    45.3 桌面窗口上使用定时器实例

    45.4 对话框上使用定时器实例

    45.5 实验例程说明(RTOS)

    45.6 实验例程说明(裸机)

    45.7 总结

    45.1 初学者重要提示

    1、  特别注意定时器使用时的注意事项,在本章45.2小节详细讲解了,要不定时器无法正确启动。然后再结合本章教程给出的实例进行学习。

    2、  窗口管理器这块的API函数应该是emWin手册所有章节中函数最多的,定时器的API函数也属于这部分。下图是中文版手册里面API函数位置:

     

     

    下图是英文版手册里面API函数的位置:

     

     

    45.2 定时器功能介绍

    emWin中有四个定时器相关的API函数供用户调用。

     

    这四个函数都是简单易用,不过使用时有些问题还是要注意下,要不无法正确启动,初学者也是经常在这几个点犯错误,导致配置了定时器,却没有效果。

    •   WM_HTIMER WM_CreateTimer(WM_HWIN hWin, int UserId, int Period, int Mode)

    此函数用于创建定时器,注意,这个函数创建的定时器是单次的,也是说定时器时间到后定时器就不再工作了,如果还想继续使用,务必要在窗口回调函数的定时器消息WM_TIMER里面调用函数WM_RestartTimer重启此定时器。

    第1个参数 hWin填写窗口的句柄,即给那个窗口创建定时器。这个参数比较关键,很多初学者经常在这个参数上犯错误。如果是给对话框创建定时器,且对话框的主体是框架窗口FrameWin或者直接给框架窗口FrameWin创建定时器,此参数必须要使用函数WM_GetClientWindow获得框架窗口的客户区,这一点非常重要。如果对话框的主体是Windows或者直接给Windows窗口创建定时器,无需使用函数WM_GetClientWindow了,直接填句柄就可以了。

    第2个参数UserId填写此定时器的ID,设置ID的目的是方便同一个窗口创建了多个定时器的话,可以用来区分是哪个定时器。

    第3个参数Period是定时器周期,确切的说是溢出时间更贴切,因为此定时器不是自动重启的,仅执行一次,时间到后会给定时器所在窗口的回调函数发送WM_TIMER消息,如果要重新启动需要在此消息里面调用函数WM_RestartTimer重新启动。

    第4个参数暂时保留,未被使用。

    •   void WM_DeleteTimer(WM_HTIMER hTimer)

    此函数用于定时器删除,参数是定时器句柄(即调用函数WM_CreateTimer的返回值)。

    •   int WM_GetTimerId(WM_HTIMER hTimer);

    此函数用于获得定时器ID,参数是定时器句柄(即调用函数WM_CreateTimer的返回值)。

    •   void WM_RestartTimer(WM_HTIMER hTimer, int Period)

    此函数用于重启定时器。

    第1个参数是定时器句柄,即调用函数WM_CreateTimer的返回值。

    第2个参数是重新配置定时器的溢出时间。

    -----------------

    讲解完这些,也许初学者还有些模糊,没有关系,且看下面举的几个例子,看完后基本就都理解了。

    45.3 桌面窗口上使用定时器实例

    这个Demo主要是实现每隔1000ms改变一次桌面窗口的颜色,源代码如下(可以将其直接的复制到开发板或者模拟器上面运行)。

    #include "DIALOG.h"
    
    /*
    *********************************************************************************************************
    *                                       变量
    *********************************************************************************************************
    */
    GUI_COLOR _acColor[3] = {GUI_BLUE,GUI_RED,GUI_YELLOW};  //--------------(1)
    static  char ucBackColor;
    
    
    /*
    *********************************************************************************************************
    *    函 数 名: _cbBkWindow
    *    功能说明: 桌面窗口回调函数        
    *    形    参: 无
    *    返 回 值: 返回对话框句柄
    *********************************************************************************************************
    */
    static void _cbBkWindow(WM_MESSAGE * pMsg) 
    {
        WM_HWIN hWin = pMsg->hWin;
    
        switch (pMsg->MsgId) 
        {
            /* 重绘消息 */
            case WM_PAINT:  //--------------(2)
                ucBackColor++;
                if (ucBackColor == 3)
                {
                    ucBackColor = 0;
                }
                GUI_SetBkColor(_acColor[ucBackColor]);
                GUI_Clear();
                break;
    
            /* 定时器消息 */
            case WM_TIMER: //--------------(3)
                WM_InvalidateWindow(hWin);
                WM_RestartTimer(pMsg->Data.v, 1000);
                break;
                
            default:
                WM_DefaultProc(pMsg);
        }
    }
    
    /*
    *********************************************************************************************************
    *    函 数 名: MainTask
    *    功能说明: GUI主函数
    *    形    参: 无
    *    返 回 值: 无
    *********************************************************************************************************
    */
    void MainTask(void) 
    {
        WM_HTIMER hTimer;
    
        /* 初始emWin */
        GUI_Init();
    
        /* 设置桌面窗口回调函数 */
        WM_SetCallback(WM_HBKWIN, _cbBkWindow); //--------------(4)
    
        /* 为桌面窗口创建定时器,定时器溢出时间1000ms */
        hTimer = WM_CreateTimer(WM_HBKWIN, 0, 1000, 0); //--------------(5)
    
        while (1)
        {
            GUI_Delay(10);
        }
    }
    1. 定义一个数组,里面有三种颜色,再定义一个变量,用于三种颜色的切换。
    2. 桌面窗口回调函数的重绘消息,每执行一次更新一次背景色。
    3. 定时器消息,这里要特别注意,如果想要定时器周期性执行,而不是只执行一次,必须得调用重启定时器函数WM_RestartTimer()。在这个消息里面将桌面窗口无效,从而会触发窗口管理器去执行WM_PAINT消息,这样就实现了定时修改桌面窗口背景色。
    4. 设置桌面窗口的回调函数。
    5. 创建定时器函数,溢出时间是1000ms。

    这个Demo的实际显示效果如下:

     

     

    45.4 对话框上使用定时器实例

    这个Demo的主要功能是在对话框上面实现一个计数功能,每100ms更新一次,下面是源码(可以将其直接的复制到开发板或者模拟器上面运行)

    #include "DIALOG.h"
    #include "stdio.h"
    
    
    
    /*
    *********************************************************************************************************
    *                                        变量
    *********************************************************************************************************
    */
    static int Count = 0;
    
    
    /*
    *********************************************************************************************************
    *                           GUI_WIDGET_CREATE_INFO类型数组
    *********************************************************************************************************
    */
    static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = {
        { FRAMEWIN_CreateIndirect,  "armfly",   0,               0,  0,  320,240,0,0},
        { TEXT_CreateIndirect,      "0000",     GUI_ID_TEXT0,    30,30,300,48, 0,0}
    };
    
    
    /*
    *********************************************************************************************************
    *    函 数 名: _cbCallback
    *    功能说明: 对话框回调函数        
    *    形    参: pMsg  回调参数 
    *    返 回 值: 无
    *********************************************************************************************************
    */
    static void _cbCallback(WM_MESSAGE * pMsg) 
    {
        int NCode, Id;
        char buf[10];
        WM_HWIN hWin = pMsg->hWin;
    
        switch (pMsg->MsgId) 
        {
            case WM_INIT_DIALOG:
    
                //
                //初始化框架窗口
                //
                FRAMEWIN_SetFont(hWin,&GUI_Font24B_ASCII);
                FRAMEWIN_SetTextAlign(hWin,GUI_TA_VCENTER|GUI_TA_CENTER);
                FRAMEWIN_SetTitleHeight(hWin,30);
    
                //
                //初始化文本控件
                //
                TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT0), &GUI_FontD36x48);
                break;
    
            /* 定时器消息 */
            case WM_TIMER:   //--------------(1)
                 Count++;
                sprintf(buf, "%04d", Count);
                TEXT_SetText(WM_GetDialogItem(hWin,GUI_ID_TEXT0), (const char *)buf);
                WM_RestartTimer(pMsg->Data.v, 100);
                  break;
                
            case WM_KEY:
                switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key) 
                {
                    case GUI_KEY_ESCAPE:
                        GUI_EndDialog(hWin, 1);
                        break;
                    case GUI_KEY_ENTER:
                        GUI_EndDialog(hWin, 0);
                        break;
                }
                break;
                
            case WM_NOTIFY_PARENT:
                Id = WM_GetId(pMsg->hWinSrc); 
                NCode = pMsg->Data.v;        
                switch (Id) 
                {
                    case GUI_ID_OK:
                        if(NCode==WM_NOTIFICATION_RELEASED)
                            GUI_EndDialog(hWin, 0);
                        break;
                    case GUI_ID_CANCEL:
                        if(NCode==WM_NOTIFICATION_RELEASED)
                            GUI_EndDialog(hWin, 0);
                        break;
                }
                break;
                
            default:
                WM_DefaultProc(pMsg);
        }
    }
    
    /*
    *********************************************************************************************************
    *    函 数 名: MainTask
    *    功能说明: GUI主函数
    *    形    参: 无
    *    返 回 值: 无
    *********************************************************************************************************
    */
    void MainTask(void) 
    {
        WM_HWIN hDlg;
        WM_HTIMER hTimer;
        
    
        /* 初始emWin */
        GUI_Init();
        
        /* 窗口使能使用内存设备,防止闪烁 */
        WM_SetCreateFlags(WM_CF_MEMDEV);  
    
       /* 创建一个对话框 */
        hDlg = GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), &_cbCallback, 0, 0, 0);
    
        /* 给对话框hDlg创建定时器,溢出时间是100ms */
        hTimer = WM_CreateTimer(WM_GetClientWindow(hDlg), 0, 100, 0); //--------------(2)
    
        while (1)
        {
            GUI_Delay(10);
        }
    }
    1. 定时器消息,在定时器消息中实现文件控件计数值的更新,每次计数值加1。
    2. 给对话框创建一个定时器,特别注意,这里需要获取对话框中客户区窗口的句柄才可以使用。

    这个例子的实际显示效果如下:

     

     

    45.5 实验例程说明(RTOS)

    配套例子:

    V7-558_emWin6.x实验_窗口管理器之定时器使用(RTOS)

    实验目的:

    1. 本实验主要学习窗口管理器之定时器使用方法。
    2. emWin功能的实现在MainTask.c文件里面。

    实验内容:

    1、K1按键按下,串口或者RTT打印任务执行情况(串口波特率115200,数据位8,奇偶校验位无,停止位1)。

    2、(1) 凡是用到printf函数的全部通过函数App_Printf实现。

    (2) App_Printf函数做了信号量的互斥操作,解决资源共享问题。

    3、默认上电是通过串口打印信息,如果使用RTT打印信息:

    MDK AC5,MDK AC6或IAR通过使能bsp.h文件中的宏定义为1即可

    #define Enable_RTTViewer  1

    4、各个任务实现的功能如下:

    App Task Start   任务 :启动任务,这里用作BSP驱动包处理。

    App Task MspPro任务 :消息处理,这里用作LED闪烁。

    App Task UserIF  任务 :按键消息处理。

    App Task COM   任务 :暂未使用。

    App Task GUI    任务 :GUI任务。

    μCOS-III任务调试信息(按K1按键,串口打印):

     

     

    RTT 打印信息方式:

     

     

    程序设计:

    任务栈大小分配:

    μCOS-III任务栈大小在app_cfg.h文件中配置:

    #define  APP_CFG_TASK_START_STK_SIZE                      512u

    #define  APP_CFG_TASK_MsgPro_STK_SIZE                     2048u

    #define  APP_CFG_TASK_COM_STK_SIZE                        512u

    #define  APP_CFG_TASK_USER_IF_STK_SIZE                    512u

    #define  APP_CFG_TASK_GUI_STK_SIZE                        2048u

    任务栈大小的单位是4字节,那么每个任务的栈大小如下:

    App Task Start   任务 :2048字节。

    App Task MspPro任务 :8192字节。

    App Task UserIF  任务 :2048字节。

    App Task COM   任务 :2048字节。

    App Task GUI    任务 :8192字节。

    系统栈大小分配:

    μCOS-III的系统栈大小在os_cfg_app.h文件中配置:

    #define  OS_CFG_ISR_STK_SIZE                      512u     

    系统栈大小的单位是4字节,那么这里就是配置系统栈大小为2KB

    emWin动态内存配置:

    GUIConf.c文件中的配置如下:

    #define EX_SRAM   1/*1 used extern sram, 0 used internal sram */
    
    #if EX_SRAM
    #define GUI_NUMBYTES  (1024*1024*24)
    #else
    #define GUI_NUMBYTES  (100*1024)
    #endif

    通过宏定义来配置使用内部SRAM还是外部的SDRAM做为emWin的动态内存,当配置:

    #define  EX_SRAM     1 表示使用外部SDRAM作为emWin动态内存,大小24MB。

    #define  EX_SRAM     0 表示使用内部SRAM作为emWin动态内存,大小100KB。

    默认情况下,本教程配套的所有emWin例子都是用外部SDRAM作为emWin动态内存。

    emWin界面显示效果:

    800*480分辨率界面效果。

     

     

    45.6 实验例程说明(裸机)

    配套例子:

    V7-557_emWin6.x实验_窗口管理器之定时器使用(裸机)

    实验目的:

    1. 本实验主要学习窗口管理器之定时器使用方法。
    2. emWin功能的实现在MainTask.c文件里面。

    emWin界面显示效果:

    800*480分辨率界面效果。

     

     

    emWin动态内存配置:

    GUIConf.c文件中的配置如下:

    #define EX_SRAM   1/*1 used extern sram, 0 used internal sram */
    
    #if EX_SRAM
    #define GUI_NUMBYTES  (1024*1024*24)
    #else
    #define GUI_NUMBYTES  (100*1024)
    #endif

    通过宏定义来配置使用内部SRAM还是外部的SDRAM做为emWin的动态内存,当配置:

    #define  EX_SRAM     1 表示使用外部SDRAM作为emWin动态内存,大小24MB。

    #define  EX_SRAM     0 表示使用内部SRAM作为emWin动态内存,大小100KB。

    默认情况下,本教程配套的所有emWin例子都是用外部SDRAM作为emWin动态内存。

    45.7 总结

    本章节就为大家讲解这么多,窗口定时器简单实用,望初学者务必掌握,以后用到的地方还是很多的。

    微信公众号:armfly_com 安富莱论坛:www.armbbs.cn 安富莱淘宝:https://armfly.taobao.com
  • 相关阅读:
    [WPF VTK]三维图形开发基础(一)
    WP开发(一)
    [WPF VTK]三维图形开发基础(四)

    WIN8 下IE突然无法打开(管理员权限可打开)
    [WPF VTK]三维图形开发基础(三)
    堆排序、快排的坑
    双向链表之插入
    [WPF VTK]三维图形开发基础(二)
    [转载]Android界面设计学习日志(一)
  • 原文地址:https://www.cnblogs.com/armfly/p/15347790.html
Copyright © 2020-2023  润新知