第35章 窗口管理器实例(二)
为了帮助大家更好的理解窗口管理器的回调和消息机制,本期教程专门做了三个相关的例子,这三个例子全部来自官方。
35. 1 官方WM_Sample.c实例
35. 2 官方WM_LateClipping.c实例
35. 3 官方WM_Video实例
35. 4 总结
35.1 官方WM_Sample.c实例
这个实例基本演示了大部分WM的API函数,这个DEMO的所在位置是:
这个代码的内容比较多,这里捡几个重要的部分跟大家讲解一下。
35.1.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);
- }
- }
1. 用户自定义的消息ID。
2. 通过用户自定义的消息实现给桌面窗口的回调函数发数据。调用了函数WM_SendMessage(WM_HBKWIN, &Message)后会给桌面窗口的回调函数发数据,再调用了WM_InvalidateWindow(WM_HBKWIN)后会执行桌面窗口回调函数中的WM_PAINT。
3. 文本显示函数。
4. 用户自定义消息ID。
5. 字符串复制。将Data.p中的数据复制到_acInfoText中。
6. 在WM_PAINT中显示文本acInfoText。
35.1.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);
- }
这部分代码实现了两个窗口在具有重绘和不具有重绘功能时的演示。
1. 实现两个窗口向上移动。
2. 实现两个窗口向下移动。
显示效果如下:
35.1.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(),注意这个函数里面的参数是相对值。显示效果如下:
35.2 官方WM_LateClipping.c实例
这个Demo中涉及到了BOTTON和FrameWin的创建及其使用,如果初学的同学不理解这部分内容没有关系,后面的教程中会跟大家详细的讲解这部分知识。这里大家重点是看回调函数。Demo所在位置:
源代码如下:
- #include "GUI.h"
- #include "WM.h"
- #include "FRAMEWIN.h"
- #include "BUTTON.h"
-
- /*********************************************************************
- *
- * 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();
- while(1) {
- _ShowDemo();
- }
- }
1. 桌面窗口回调函数。
2. 回调函数中重绘部分的代码。
3. 由于两个按钮是创建在桌面窗口上面的,所以按钮的WM_NOTIFICATION_RELEASED(通知代码消息类型)是在桌面窗口的回调函数中。这个按钮按下后将_hWin1和_hWin2无效。从而会执行这两个窗口的背景重绘功能。
4. 同上,只不过这里实现的功能是将两个计数值清零,并使桌面窗口无效,从而执行桌面窗口的重绘消息。
5. 这个是hWin0,hWin1,hWin2的回调函数。
6. 这个是hFrame1的回调函数。回调函数中主要实现了重绘消息。重绘消息中记录了重绘的次数,并根据重绘次数修改背景颜色。
7. 这个是hFrame2的回调函数。回调函数中主要实现了重绘消息。重绘消息中记录了重绘的次数,并根据重绘次数修改背景颜色。
8. (1) 先创建两个FrameWin
(2) 分别在这两个FrameWin中创建两个子窗口。
(3) 创建两个按钮。
(4) 创建三个FrameWin。
9. 这个Demo还有一个控件剪切问题,后面会专门抽一期教程专门跟大家讲解这个。
这个例子对于研究回调函数函数还是非常好的,大家可以在这个例子的基础上做一些修改,实现一些功能,这个Demo的显示效果如下:
35.3 官方WM_Video.c实例
这个例子所在位置:
源代码如下:
- #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
-
- /*********************************************************************
- *
- * 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();(8)
- WM_SetCallback(WM_HBKWIN, _cbBkWin);
- 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。
3. 显示FrameWin。
4. 隐藏FrameWin。
5. 桌面窗口回调函数,主要看WM_NOTIFY_PARENT消息,进入后再分为4个button的消息。
6. FrameVideo的回调函数。
7. FrameWinTest的回调函数。
8. (1)创建两个文本控件。
(2)创建四个按钮,分别实现创建,删除,显示和隐藏窗口。
(3)创建FrameWin。
这个例子相对要简单很多,下面是这个例子的实际显示效果:
35.4 总结
本期教程就跟大家讲这么多,希望通过本期教程让大家对窗口管理器有更好的认识,不过还需要大家在模拟器或者开发板上面多做这方面的练习。