第3版emWin教程第44章 emWin6.x窗口管理器官方实例简单讲解

Posted Simon223

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第3版emWin教程第44章 emWin6.x窗口管理器官方实例简单讲解相关的知识,希望对你有一定的参考价值。

教程不断更新中:第3版emWin教程和ThreadX GUIX教程开工,双管齐下,GUIX更新至第28章,emWin更新至第48章(2021-09-13) - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz!http://www.armbbs.cn/forum.php?mod=viewthread&tid=98429

第44章       emWin6.x窗口管理器官方实例简单讲解

为了帮助大家更好的理解窗口管理器的回调和消息机制,官方也提供了好几个这方面的例子,本章节我们将官方这几个例子也跟大家进行简单讲解,进一步帮助大家更好的学习窗口管理器。

目录

44.1 初学者重要提示

44.2 官方WM_Redraw.c实例讲解

44.3 官方WM_Sample.c实例讲解(含大量窗口API操作)

44.3.1   桌面窗口回调函数自定义消息的使用

44.3.2   Redrawing部分演示

44.3.3   Resize部分演示

44.4 官方WM_LateClipping.c实例讲解

44.5 官方WM_Video.c实例讲解

44.6 总结


44.1 初学者重要提示

1、  通过实例来学习emWin是最佳的学习捷径。

2、  本章节讲解的例子中用到的部分功能还没有讲解到,但是不影响大家学习窗口管理器相关的知识。没有讲解到的知识基本都会在后面章节中跟大家讲解。

3、  窗口管理器这块的API函数应该是emWin手册所有章节中函数最多的,以后需要用到什么功能了,查询就行,或者看官方的实例,哪个函数不理解了也可以查手册。下图是中文版手册里面API函数位置:

 

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

 

44.2 官方WM_Redraw.c实例讲解

这个DEMO在模拟器中的位置:

 

主要功能介绍:

这个例子与第43章43.3小节中的例子相似,分别演示桌面窗口配置了重绘操作和不配置重绘操作下,移动窗口的效果。其实不光在桌面窗口上面移动窗口要重绘,其它创建的窗口上面移动是一样的,也需要设置重绘。如果用户新窗口的窗口回调函数里面没有写重绘消息WM_PAINT,窗口管理器就会按照系统默认的颜色的进行重绘,如果用户写了WM_PAINT消息就会按照用户设置的进行重绘。

下面我们将这个代码分析一下:

#include "GUI.h"
#include "WM.h"

/*********************************************************************
*
*       Defines
*
**********************************************************************
*/
//
// Recommended memory to run the sample with adequate performance
//
#define RECOMMENDED_MEMORY (1024L * 5)

/*******************************************************************
*
*       static code
*
********************************************************************
*/
/*******************************************************************
*
*       _cbBkWindow
*/
static void _cbBkWindow(WM_MESSAGE* pMsg) {      //--------------(1)
  switch (pMsg->MsgId) {
  case WM_PAINT:
    GUI_ClearRect(0, 50, 319, 239); //--------------(2)
  default:
    WM_DefaultProc(pMsg);
  }
}

/*******************************************************************
*
*       _cbWindow
*/
static void _cbWindow(WM_MESSAGE* pMsg) {  //--------------(3)
  GUI_RECT Rect;

  switch (pMsg->MsgId) {
  case WM_PAINT:
    WM_GetInsideRect(&Rect); //--------------(4)
    GUI_SetBkColor(GUI_RED);
    GUI_SetColor(GUI_YELLOW); 
    GUI_ClearRectEx(&Rect); //--------------(5)
    GUI_DrawRectEx(&Rect);
    GUI_SetColor(GUI_BLACK);
    GUI_SetFont(&GUI_Font8x16);
    GUI_DispStringHCenterAt("Foreground window", 75, 40);
    break;
  default:
    WM_DefaultProc(pMsg);
  }
}

/*******************************************************************
*
*       _MoveWindow
*/
static void _MoveWindow(const char* pText) {
  WM_HWIN hWnd;
  int     i;

  //
  // Create foreground window
  //
  hWnd = WM_CreateWindow(10, 50, 150, 100, WM_CF_SHOW, _cbWindow, 0); //--------------(6)
  GUI_Delay(500);
  //
  // Move foreground window
  //
  for (i = 0; i < 40; i++) {
    WM_MoveWindow(hWnd, 2, 2); //--------------(7)
    GUI_Delay(10);
  }
  //
  // Show text before deleting window if we have one
  //
  if (pText) {
    GUI_DispStringAt(pText, 5, 50);
    GUI_Delay(2500);
  }
  //
  // Delete foreground window
  //
  WM_DeleteWindow(hWnd); //--------------(8)
  WM_Invalidate(WM_HBKWIN); //--------------(9)
  GUI_Exec();
}

/*******************************************************************
*
*       _DemoRedraw
*/
static void _DemoRedraw(void) {
  WM_CALLBACK * _cbOldBk;

  GUI_SetBkColor(GUI_BLACK);
  GUI_Clear();
  GUI_SetColor(GUI_WHITE);
  GUI_SetFont(&GUI_Font24_ASCII);
  GUI_DispStringHCenterAt("WM_Redraw - Sample", 160, 5);
  GUI_SetFont(&GUI_Font8x16);
  while(1) {
    //
    // Move a window over background
    //
    _MoveWindow("Background has not been redrawn");  //--------------(10)
    //
    // Clear background
    //
    GUI_ClearRect(0, 50, 319, 239);
    GUI_Delay(1000);
    //
    // Set callback for background window
    //
    _cbOldBk = WM_SetCallback(WM_HBKWIN, _cbBkWindow); //--------------(11)
    //
    // Move a window over background
    //
    _MoveWindow("Background has been redrawn");
    //
    // Delete callback for Background window
    //
    WM_SetCallback(WM_HBKWIN, _cbOldBk); //--------------(12)
  }
}

/*********************************************************************
*
*       Public code
*
**********************************************************************
*/
/*********************************************************************
*
*       MainTask
*/
void MainTask(void) {
  GUI_Init();
  //
  // Check if recommended memory for the sample is available
  //
  if (GUI_ALLOC_GetNumFreeBytes() < RECOMMENDED_MEMORY) {
    GUI_ErrorOut("Not enough memory available."); 
    return;
  }
  _DemoRedraw();
}
  1. 桌面窗口回调函数。
  2. 在桌面窗口回调函数的WM_PAINT消息中刷一块矩形区域。
  3. 另外一个新创建窗口的回调函数。
  4. 函数WM_GetInsideRect返回客户区的坐标,即实际可供用户使用的显示区。
  5. 调用函数GUI_ClearRectEx清屏一块矩形区。
  6. 函数WM_CreateWindow用来创建一个窗口,其中每个参数的含义需要大家详细研究官方手册,这里就不做解释了。
  7. 通过函数WM_MoveWindow()实现窗口位置的移动,注意这里移动的是相对距离。
  8. 删除创建的窗口。
  9. 通过函数WM_Invalidate(WM_HBKWIN)使得桌面窗口无效,然后调用函数GUI_Exec()就会通过窗口管理给桌面窗口回调函数发送WM_PAINT消息,从而执行重绘。
  10. 执行第一种情况:移动窗口,但是不做桌面窗口的重绘。
  11. 给桌面窗口设置专门的回调函数。
  12. 执行第二种情况:移动窗口,并执行桌面窗口的重绘。

这个实例主要演示了两种情况,一种是演示:移动窗口的情况下,但是不做桌面窗口的重绘。另一种是:移动窗口,并执行桌面窗口的重绘。通过这两种情况的演示可以帮助大家对回调函数有一个更好的认识。

第一种情况:没有执行桌面回调函数的显示效果

 

第二种情况:执行桌面回调函数的显示效果

 

44.3 官方WM_Sample.c实例讲解(含大量窗口API操作)

这个DEMO在模拟器中的位置:

 

主要功能介绍:

这个例子最主要的特点是将大部分窗口管理器的API函数都进行了调用,方便用户查看演示效果。如果那个函数不太会使用了,看这个例子也是比较方便。

下面我们将这个代码分析一下,这里捡几个重要的部分跟大家讲解一下:

44.3.1   桌面窗口回调函数自定义消息的使用

#define MSG_CHANGE_TEXT     (WM_USER + 0) //--------------(1)

/*******************************************************************
*
*       _ChangeInfoText
*
* Function description
*   Sends a message to the background window and invalidate it, so
*   the callback of the background window display the new text.
*/
static void _ChangeInfoText(char * pStr) { //--------------(2)
  WM_MESSAGE Message;

  Message.MsgId  = MSG_CHANGE_TEXT;
  Message.Data.p = pStr;
  WM_SendMessage(WM_HBKWIN, &Message);
  WM_InvalidateWindow(WM_HBKWIN);
}

/*******************************************************************
*
*       _DrawInfoText
*
* Function description
*   Drawes the info text directly on the display. This function is for
*   the moments when no callback is set.
*/
static void _DrawInfoText(char * pStr) { //--------------(3)
  GUI_SetColor(GUI_WHITE);
  GUI_SetFont(&GUI_Font24_ASCII);
  GUI_DispStringHCenterAt("WindowManager - Sample", 160, 5);
  GUI_SetFont(&GUI_Font8x16);
  GUI_DispStringAtCEOL(pStr, 5, 40);
}

/*******************************************************************
*
*       _cbBkWindow
*/
static void _cbBkWindow(WM_MESSAGE * pMsg) {
  switch (pMsg->MsgId) {
  case MSG_CHANGE_TEXT: //--------------(4)
    strcpy(_acInfoText, (char const *)pMsg->Data.p); //--------------(5)
  case WM_PAINT:        //--------------(6)
    GUI_SetBkColor(GUI_BLACK);
    GUI_Clear();
    GUI_SetColor(GUI_WHITE);
    GUI_SetFont(&GUI_Font24_ASCII);
    GUI_DispStringHCenterAt("WindowManager - Sample", 160, 5);
    GUI_SetFont(&GUI_Font8x16);
    GUI_DispStringAt(_acInfoText, 5, 40);
    break;
  default:
    WM_DefaultProc(pMsg);
  }
}

这部分代码主要学习消息发送函数WM_SendMessage的使用,43章的43.2小节学习了无参数的消息发送函数WM_SendMessageNoPara,而函数WM_SendMessage是带参数的。

  1. 用户自定义的消息ID,使用的时候一定要以WM_USER作为起始值,防止跟系统其他的数值冲突。如果还要实现其它自定义消息,在这个数值的基础上面定义即可。
  2. 通过用户自定义的消息实现给桌面窗口的回调函数发送数据。调用了函数WM_SendMessage(WM_HBKWIN, &Message)后会给桌面窗口的回调函数发送数据,再调用了函数WM_Invalidate(WM_HBKWIN)使得桌面窗口无效,然后调用函数GUI_Delay()就会通过窗口管理给桌面窗口回调函数发送WM_PAINT消息,从而执行重绘。
  3. 文本显示函数。
  4. 用户自定义消息ID。
  5. 字符串复制,将Data.p中的数据复制到_acInfoText中。
  6. 在WM_PAINT消息中显示文本acInfoText。

44.3.2   Redrawing部分演示

/*******************************************************************
*
*       _LiftUp
*/
static void _LiftUp(int dy) {//--------------(1)
  int i;
  int tm;

  for (i = 0; i < (dy/4); i++) {
    tm = GUI_GetTime();
    WM_MoveWindow(_hWindow1, 0, -4);
    WM_MoveWindow(_hWindow2, 0, -4);
    while ((GUI_GetTime() - tm) < 20) {
      WM_Exec();
    }
  }
}

/*******************************************************************
*
*       _LiftDown
*/
static void _LiftDown(int dy) { //--------------(2)
  int i;
  int tm;

  for (i = 0; i < (dy/4); i++) {
    tm = GUI_GetTime();
    WM_MoveWindow(_hWindow1, 0, 4);
    WM_MoveWindow(_hWindow2, 0, 4);
    while ((GUI_GetTime() - tm) < 20) {
      WM_Exec();
    }
  }
}

/*******************************************************************
*
*       _DemoRedrawing
*
* Function description
*   Demonstrates how useful can be a callback
*/
static void _DemoRedrawing(void) {
  int i;
  int tm;
  int tDiff;

  _ChangeInfoText("Demonstrating redrawing");
  GUI_Delay(SPEED);
  _LiftUp(40);
  GUI_Delay(SPEED/3);
  _ChangeInfoText("Using a callback for redrawing");
  GUI_Delay(SPEED/3);
  for (i = 0; i < 55; i++) {
    tm = GUI_GetTime();
    WM_MoveWindow(_hWindow1,  1,  1);
    WM_MoveWindow(_hWindow2, -1, -1);
    tDiff = 15 - (GUI_GetTime() - tm);
    GUI_Delay(tDiff);
  }
  for (i = 0; i < 55; i++) {
    tm = GUI_GetTime();
    WM_MoveWindow(_hWindow1, -1, -1);
    WM_MoveWindow(_hWindow2,  1,  1);
    tDiff = 15 - (GUI_GetTime() - tm);
    GUI_Delay(tDiff);
  }
  GUI_Delay(SPEED/4);
  _LiftDown(30);
  GUI_Delay(SPEED/2);
  _ChangeInfoText("Without redrawing");
  GUI_Delay(SPEED);
  _LiftUp(30);
  GUI_Delay(SPEED/4);
  WM_SetCallback(WM_HBKWIN, _cbBkWindowOld);
  for (i = 0; i < 55; i++) {
    tm = GUI_GetTime();
    WM_MoveWindow(_hWindow1,  1,  1);
    WM_MoveWindow(_hWindow2, -1, -1);
    tDiff = 15 - (GUI_GetTime() - tm);
    GUI_Delay(tDiff);
  }
  for (i = 0; i < 55; i++) {
    tm = GUI_GetTime();
    WM_MoveWindow(_hWindow1, -1, -1);
    WM_MoveWindow(_hWindow2,  1,  1);
    tDiff = 15 - (GUI_GetTime() - tm);
    GUI_Delay(tDiff);
  }
  GUI_Delay(SPEED/3);
  WM_SetCallback(WM_HBKWIN, _cbBkWindow);
  _LiftDown(40);
  GUI_Delay(SPEED);
}

这部分代码实现了两个窗口在具有重绘和不具有重绘功能时的演示,还有一个重点是学习窗口移动函数WM_MoveWindow的使用,这个函数是实现相对移动,相对于窗口当前所在的位置。另外还一个窗口移动函数WM_MoveTo是绝对位置移动,设置移动到那个坐标点就移动到那个坐标点。

  1. 实现两个窗口向上移动。
  2. 实现两个窗口向下移动。

显示效果如下:

 

44.3.3   Resize部分演示

/*******************************************************************
*
*       _DemoResizeWindow
*
* Function description
*   Demonstrates the use of WM_ResizeWindow
*/
static void _DemoResizeWindow(void) {
  int i;
  int tm;
  int tDiff;

  _ChangeInfoText("WM_ResizeWindow()");
  GUI_Delay(SPEED);
  _LiftUp(30);
  for (i = 0; i < 20; i++) {
    tm = GUI_GetTime();
    WM_ResizeWindow(_hWindow1,  1,  1);
    WM_ResizeWindow(_hWindow2, -1, -1);
    tDiff = 15 - (GUI_GetTime() - tm);
    GUI_Delay(tDiff);
  }
  for (i = 0; i < 40; i++) {
    tm = GUI_GetTime();
    WM_ResizeWindow(_hWindow1, -1, -1);
    WM_ResizeWindow(_hWindow2,  1,  1);
    tDiff = 15 - (GUI_GetTime() - tm);
    GUI_Delay(tDiff);
  }
  for (i = 0; i < 20; i++) {
    tm = GUI_GetTime();
    WM_ResizeWindow(_hWindow1,  1,  1);
    WM_ResizeWindow(_hWindow2, -1, -1);
    tDiff = 15 - (GUI_GetTime() - tm);
    GUI_Delay(tDiff);
  }
  _LiftDown(30);
  GUI_Delay(SPEED);
}

这部分演示主要看窗口加大和减小函数WM_ResizeWindow()的使用,注意这个函数是对窗口的显示大小进行加大和减小,并不是进行放缩,显示效果如下:

 

44.4 官方WM_LateClipping.c实例讲解

这个DEMO在模拟器中的位置:

 

主要功能介绍:

这个例子依然主要演示回调函数的重绘机制,作为重绘机制方面的学习,比较有参考价值。

下面我们将这个代码分析一下:

#include "GUI.h"
#include "WM.h"
#include "FRAMEWIN.h"
#include "BUTTON.h"

/*********************************************************************
*
*       Defines
*
**********************************************************************
*/
//
// Recommended memory to run the sample with adequate performance
//
#define RECOMMENDED_MEMORY (1024L * 5)

/*********************************************************************
*
*       Static data
*
**********************************************************************
*/
static WM_HWIN _hWin1;
static WM_HWIN _hWin2;
static WM_HWIN _hBut1;
static WM_HWIN _hBut2;
static int     _PaintCount1;
static int     _PaintCount2;

static GUI_COLOR _aColors[] = {
  0x0000FF, 0x00FF00, 0xFF0000, 0x00FFFF, 0xA000A0, 0xFFFF00
};

/*********************************************************************
*
*       Static code
*
**********************************************************************
*/
/*********************************************************************
*
*       _cbBkWin
*/
static void _cbBkWin(WM_MESSAGE* pMsg) { //--------------(1)
  switch(pMsg->MsgId) {
  case WM_PAINT:     //--------------(2)
    GUI_SetBkColor(GUI_BLACK);
    GUI_Clear();
    GUI_SetColor(0x0060FF);
    GUI_DispStringAt("PaintCount (Early):", 0, 0);
    GUI_DispDecAt(_PaintCount1, 120, 0, 5);
    GUI_SetColor(0x00FFC0);
    GUI_DispStringAt("PaintCount (Late):", 0, 12);
    GUI_DispDecAt(_PaintCount2, 120, 12, 5);
    break;
  case WM_NOTIFY_PARENT:
    if (pMsg->Data.v == WM_NOTIFICATION_RELEASED) {
      if (pMsg->hWinSrc == _hBut1) { //--------------(3)
        WM_InvalidateWindow(_hWin1);
        WM_InvalidateWindow(_hWin2);
      } else if (pMsg->hWinSrc == _hBut2) { //--------------(4)
        _PaintCount1 = 0;
        _PaintCount2 = 0;
        WM_InvalidateWindow(pMsg->hWin);
      }
    }
    break;
  default:
    WM_DefaultProc(pMsg);
  }
}

/*********************************************************************
*
*       _cbTop
*/
static void _cbTop(WM_MESSAGE* pMsg) { //--------------(5)
  switch(pMsg->MsgId) {
  case WM_PAINT:
    GUI_SetBkColor(GUI_MAGENTA);
    GUI_Clear();
    break;
  default:
    WM_DefaultProc(pMsg);
  }
}

/*********************************************************************
*
*       _cbFrameWin1
*/
static void _cbFrameWin1(WM_MESSAGE* pMsg) { //--------------(6)
  switch(pMsg->MsgId) {
  case WM_PAINT:
    GUI_SetBkColor(_aColors[_PaintCount1 % 6]);
    GUI_Clear();
    GUI_SetColor(0x0060FF);
    GUI_FillCircle(25, 25, 15);
    GUI_SetColor(GUI_BLACK);
    GUI_DrawCircle(25, 25, 15);
    _PaintCount1++;
    WM_InvalidateWindow(WM_HBKWIN);
    break;
  default:
    WM_DefaultProc(pMsg);
  }
}

/*********************************************************************
*
*       _cbFrameWin2
*/
static void _cbFrameWin2(WM_MESSAGE* pMsg) { //--------------(7)
  switch(pMsg->MsgId) {
  case WM_PAINT:
    GUI_SetBkColor(_aColors[_PaintCount2 % 6]);
    GUI_Clear();
    GUI_SetColor(0x00FFC0);
    GUI_FillCircle(25, 25, 15);
    GUI_SetColor(GUI_BLACK);
    GUI_DrawCircle(25, 25, 15);
    _PaintCount2++;
    WM_InvalidateWindow(WM_HBKWIN);
    break;
  default:
    WM_DefaultProc(pMsg);
  }
}

/*********************************************************************
*
*       _ShowDemo
*/
static void _ShowDemo(void) {
  WM_HWIN hWin0;
  WM_HWIN hWin1;
  WM_HWIN hWin2;
  WM_HWIN hFrame1;
  WM_HWIN hFrame2;
  WM_HWIN hClient1;
  WM_HWIN hClient2;

  WM_SetCallback(WM_HBKWIN, _cbBkWin); //--------------(8)
  hFrame1  = FRAMEWIN_CreateEx( 10, 30, 140, 140, 0, WM_CF_SHOW, FRAMEWIN_CF_MOVEABLE, 0, "Early Clipping", _cbFrameWin1);
  hFrame2  = FRAMEWIN_CreateEx(170, 30, 140, 140, 0, WM_CF_SHOW, FRAMEWIN_CF_MOVEABLE, 0, "Late Clipping",
 _cbFrameWin2);
  hClient1 = WM_GetClientWindow(hFrame1);
  hClient2 = WM_GetClientWindow(hFrame2);
  _hWin1  = WM_CreateWindowAsChild(0, 0, WM_GetWindowSizeX(hClient1), WM_GetWindowSizeY(hClient1), hClient1,
 WM_CF_SHOW, _cbFrameWin1, 0);
  _hWin2  = WM_CreateWindowAsChild(0, 0, WM_GetWindowSizeX(hClient2), WM_GetWindowSizeY(hClient2), hClient2,
 WM_CF_SHOW | WM_CF_LATE_CLIP, _cbFrameWin2, 0);
  _hBut1  = BUTTON_CreateEx(10, 210, 140, 20, 0, WM_CF_SHOW, 0, 1);
  _hBut2  = BUTTON_CreateEx(170, 210, 140, 20, 0, WM_CF_SHOW, 0, 2);
  hWin0 = FRAMEWIN_CreateEx(60,  80, 40, 40, 0, WM_CF_SHOW | WM_CF_STAYONTOP, FRAMEWIN_CF_MOVEABLE, 0, "Top 0",
 _cbTop);
  hWin1 = FRAMEWIN_CreateEx(220, 80, 40, 40, 0, WM_CF_SHOW | WM_CF_STAYONTOP, FRAMEWIN_CF_MOVEABLE, 0, "Top 1",
 _cbTop);
  hWin2 = FRAMEWIN_CreateEx(140,170, 40, 40, 0, WM_CF_SHOW | WM_CF_STAYONTOP, FRAMEWIN_CF_MOVEABLE, 0, "Top 2",
 _cbTop);
  FRAMEWIN_SetResizeable(hWin0, 1);
  FRAMEWIN_SetResizeable(hWin1, 1);
  FRAMEWIN_SetResizeable(hWin2, 1);
  BUTTON_SetText(_hBut1, "Invalidate");
  BUTTON_SetText(_hBut2, "Reset counters");
  while(1) {
    GUI_Delay(50);
  }
}

/*********************************************************************
*
*       Public code
*
**********************************************************************
*/
/*********************************************************************
*
*       MainTask
*/
void MainTask(void) {
  GUI_Init();
  //
  // Check if recommended memory for the sample is available
  //
  if (GUI_ALLOC_GetNumFreeBytes() < RECOMMENDED_MEMORY) {
    GUI_ErrorOut("Not enough memory available."); 
    return;
  }
  while(1) {
    _ShowDemo();
  }
}

1、桌面窗口回调函数。

2、桌面窗口回调函数中重绘消息WM_PAINT。

3、由于两个按钮是创建在桌面窗口上面的,所以按钮的WM_NOTIFICATION_RELEASED(通知代码消息类型)是在桌面窗口的回调函数中。这个按钮按下后将窗口_hWin1和窗口_hWin2无效,从而会执行这两个窗口的背景重绘功能。

4、同上,只不过这里实现的功能是将两个计数值清零,并使桌面窗口无效,从而执行桌面窗口的重绘消息。

5、此函数同时是hWin0,hWin1,hWin2三个框架窗口的回调函数。

6、此函数是框架窗口hFrame1的回调函数,回调函数中主要实现了重绘消息,重绘消息中记录了重绘的次数,并根据重绘次数修改背景颜色。

7、此函数是框架窗口hFrame2的回调函数,回调函数中主要实现了重绘消息,重绘消息中记录了重绘的次数,并根据重绘次数修改背景颜色。

8、(1) 先创建两个框架窗口hFrame1和hFrame2。

(2) 分别在这两个框架窗口中创建两个子窗口_hWin1和_hWin2。

(3) 创建两个按钮_hBut1和_hBut2。

(4) 创建三个框架窗口hWin0,hWin1和hWin2。

这个例子对于研究回调函数函数还是非常好的,大家可以在这个例子的基础上做一些修改,实现一些功能,显示效果如下:

 

44.5 官方WM_Video.c实例讲解

这个DEMO在模拟器中的位置:

 

主要功能介绍:

 这个例子主要演示框架窗口的创建,删除,隐藏和显示,关于框架窗口暂时还没有讲到,后面章节会专门讲解,跟普通窗口差不多,只是多了一个标题栏,所以将其放在本章节进行讲解也是可以的,用来学习窗口相关的API函数操作。

下面我们将这个代码分析一下:

#include <stddef.h>
#include <stdio.h>

#include "WM.h"
#include "GUI.h"
#include "FRAMEWIN.h"
#include "BUTTON.h"
#include "TEXT.h"

static void _cbFrameWinTest(WM_MESSAGE * pMsg);

/*********************************************************************
*
*       Defines
*
**********************************************************************
*/
#define MAX_WINDOWS   50

//
// Recommended memory to run the sample with adequate performance
//
#define RECOMMENDED_MEMORY (1024L * 5)

/*********************************************************************
*
*       Static data
*
**********************************************************************
*/

static WM_HWIN _ahWin[MAX_WINDOWS];
static char    _IsCompletelyVis;

/*********************************************************************
*
*       Static code
*
**********************************************************************
*/
/*********************************************************************
*
*       _CreateWindow
*/
static void _CreateWindow(void) {  //--------------(1)
  unsigned i;
  WM_HWIN  hWin;
  char     ac[32];
  int      j;

  for (i = 0; i < MAX_WINDOWS; i++) {
    if (_ahWin[i] == 0) {
      j = i + 1;
      sprintf(ac, "Test window %d", j);
      hWin = FRAMEWIN_CreateEx(5 + 10 * i, 135 + 10 * i, 120, 60, 0, WM_CF_SHOW, FRAMEWIN_CF_MOVEABLE, 0, ac,
 _cbFrameWinTest);
      FRAMEWIN_SetClientColor(hWin, GUI_INVALID_COLOR);
      _ahWin[i] = hWin;
      break;
    }
  }
}

/*********************************************************************
*
*       _DeleteWindow
*/
static void _DeleteWindow(void) {  //--------------(2)
  unsigned i;

  for (i = 0; i < MAX_WINDOWS; i++) {
    if (WM_IsVisible(_ahWin[i])) {
      WM_DeleteWindow(_ahWin[i]);
      _ahWin[i] = 0;
      break;
    }
  }
}

/*********************************************************************
*
*       _ShowWindow
*/
static void _ShowWindow(void) {  //--------------(3)
  unsigned i;

  for (i = 0; i < MAX_WINDOWS; i++) {
    if (_ahWin[i] != 0) {
      if (WM_IsVisible(_ahWin[i]) == 0) {
        WM_ShowWindow(_ahWin[i]);
        break;
      }
    }
  }
}

/*********************************************************************
*
*       _HideWindow
*/
static void _HideWindow(void) {  //--------------(4)
  unsigned i;

  for (i = 0; i < MAX_WINDOWS; i++) {
    if (WM_IsVisible(_ahWin[i])) {
      WM_HideWindow(_ahWin[i]);
      break;
    }
  }
}

/*********************************************************************
*
*       Static code, callbacks
*
**********************************************************************
*/
/*********************************************************************
*
*       _cbBkWin
*/
static void _cbBkWin(WM_MESSAGE* pMsg) {  //--------------(5)
  int Id;

  switch (pMsg->MsgId) {
  case WM_PAINT:
    GUI_SetBkColor(GUI_BLACK);
    GUI_Clear();
    break;
  case WM_NOTIFY_PARENT:
    if (pMsg->Data.v == WM_NOTIFICATION_RELEASED) {
      Id = WM_GetId(pMsg->hWinSrc);
      switch (Id) {
      case GUI_ID_BUTTON0:
        _CreateWindow();
        break;
      case GUI_ID_BUTTON1:
        _DeleteWindow();
        break;
      case GUI_ID_BUTTON2:
        _ShowWindow();
        break;
      case GUI_ID_BUTTON3:
        _HideWindow();
        break;
      }
    }
    break;
  default:
    WM_DefaultProc(pMsg);
  }
}

/*********************************************************************
*
*       _cbFrameWinVideo
*/
static void _cbFrameWinVideo(WM_MESSAGE* pMsg) {  //--------------(6)
  WM_HWIN hWin;
  WM_HWIN hText;
  int     IsCompletelyVis;
  int     IsCompletelyCovered;

  switch (pMsg->MsgId) {
  case WM_PAINT:
    if (_IsCompletelyVis) {
      GUI_SetBkColor(GUI_DARKGREEN);
      GUI_Clear();
      GUI_SetColor(GUI_WHITE);
      GUI_DispStringAt("Completely visible", 5, 5);
    } else {
      GUI_SetBkColor(GUI_GRAY);
      GUI_Clear();
      GUI_SetColor(GUI_WHITE);
      GUI_DispStringAt("Not completely visible", 5, 5);
    }
    break;
  case WM_NOTIFY_VIS_CHANGED:
    hText = WM_GetDialogItem(WM_HBKWIN, GUI_ID_TEXT1);
    hWin  = WM_GetClientWindow(pMsg->hWin);
    IsCompletelyVis     = WM_IsCompletelyVisible(hWin);
    IsCompletelyCovered = WM_IsCompletelyCovered(hWin);
    if (IsCompletelyCovered) {
      TEXT_SetText(hText, "completely\\ncovered");
    } else {
      TEXT_SetText(hText, "not completely\\ncovered");
    }
    if (_IsCompletelyVis != IsCompletelyVis) {
      _IsCompletelyVis = IsCompletelyVis;
      WM_InvalidateWindow(hWin);    /* Only required if content changes if partially hidden */
    }
    break;
  default:
    WM_DefaultProc(pMsg);
  }
}

/*********************************************************************
*
*       _cbFrameWinTest
*/
static void _cbFrameWinTest(WM_MESSAGE* pMsg) {  //--------------(7)
  switch (pMsg->MsgId) {
  case WM_PAINT:
    GUI_SetBkColor(GUI_DARKRED);
    GUI_Clear();
    break;
  default:
    WM_DefaultProc(pMsg);
  }
}

/*********************************************************************
*
*       Public code
*
**********************************************************************
*/
/*********************************************************************
*
*       MainTask
*/
void MainTask(void) {
  FRAMEWIN_Handle hWinVideo;
  BUTTON_Handle   hBut;
  WM_HWIN         hText;

  GUI_Init();
  //
  // Check if recommended memory for the sample is available
  //
  if (GUI_ALLOC_GetNumFreeBytes() < RECOMMENDED_MEMORY) {
    GUI_ErrorOut("Not enough memory available."); 
    return;
  }
  WM_SetCallback(WM_HBKWIN, _cbBkWin); 
  //--------------(8)
  hText = TEXT_CreateEx(240,  85, 80, 26, WM_HBKWIN, WM_CF_SHOW, 0, GUI_ID_TEXT0, "The client\\nwindow is");
  TEXT_SetTextColor(hText, GUI_WHITE);
  hText = TEXT_CreateEx(240, 111, 80, 26, WM_HBKWIN, WM_CF_SHOW, 0, GUI_ID_TEXT1, NULL);
  TEXT_SetTextColor(hText, GUI_WHITE);
  //
  // Create buttons
  //
  hBut = BUTTON_CreateEx(240,  5, 75, 18, WM_HBKWIN, WM_CF_SHOW, 0, GUI_ID_BUTTON0);
  BUTTON_SetText(hBut, "Create win");
  hBut = BUTTON_CreateEx(240, 25, 75, 18, WM_HBKWIN, WM_CF_SHOW, 0, GUI_ID_BUTTON1);
  BUTTON_SetText(hBut, "Delete win");
  hBut = BUTTON_CreateEx(240, 45, 75, 18, WM_HBKWIN, WM_CF_SHOW, 0, GUI_ID_BUTTON2);
  BUTTON_SetText(hBut, "Show win");
  hBut = BUTTON_CreateEx(240, 65, 75, 18, WM_HBKWIN, WM_CF_SHOW, 0, GUI_ID_BUTTON3);
  BUTTON_SetText(hBut, "Hide win");
  //
  // Create framewin video
  //  
  hWinVideo = FRAMEWIN_CreateEx(5, 5, 170, 120, 0, WM_CF_SHOW, FRAMEWIN_CF_MOVEABLE, 0, "Video window", 
_cbFrameWinVideo);
  FRAMEWIN_SetClientColor(hWinVideo, GUI_INVALID_COLOR);
  //
  // Create test windows
  //
  _CreateWindow();
  _CreateWindow();
  _CreateWindow();
  while (1) {
    GUI_Delay(1000);
  }
}

1、创建FrameWin。

2、删除FrameWin,主要是函数WM_DeleteWindow的使用。

3、显示FrameWin,主要是函数WM_IsVisible和WM_ShowWindow的使用。

4、隐藏FrameWin,主要是函数WM_HideWindow的使用。

5、桌面窗口回调函数,主要看WM_NOTIFY_PARENT消息,进入后再分为4个button的消息,分别实现框架窗口的创建,删除,显示和隐藏。

6、框架窗口FrameVideo的回调函数。

7、函数_CreateWindow里面所创建框架窗口的回调函数。

8、(1)创建两个文本控件。

(2)创建四个按钮,分别实现创建,删除,显示和隐藏窗口。

(3)创建框架窗口hWinVideo。

这个例子相对要简单很多,下面是这个例子的实际显示效果:

 

44.6 总结

本期教程就跟大家讲这么多,官方提供的这几个例子还是比较有参考价值的,希望初学者把这几个例子研究下,并在模拟器或者开发板上面多做这方面的练习。

以上是关于第3版emWin教程第44章 emWin6.x窗口管理器官方实例简单讲解的主要内容,如果未能解决你的问题,请参考以下文章

第3版emWin教程第46章 emWin6.x窗口管理器之ToolTip的使用

第3版emWin教程第43章 emWin6.x窗口管理器实例(含自定义消息)

第3版emWin教程第42章 emWin6.x窗口管理器之回调消息类型

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

第3版emWin教程第36章 emWin6.x光标

第3版emWin教程第37章 emWin6.x抗锯齿