完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
转stemwin教程
为了帮助大家更好的理解窗口管理器的回调和消息机制,本期教程专门做了三个相关的例子,帮助大家更好的理解。 34. 1 用户自定义消息类型实例 34. 2 桌面窗口回调函数实例 34. 3 官方WM_Redraw.c实例 34. 4 总结 |
|
相关推荐
|
|
34.1 用户自定义消息类型实例
这里用上期教程所介绍的自定义消息类型做一个实例。代码跟上期教程的三个实例类似。实现源码如下(可以直接将代码复制到模拟器或者开发板上面运行)。 复制代码 #include #include "GUI.h" #include "DIALOG.h" #include "WM.h" #include "BUTTON.h" #include "CHECKBOX.h" #include "DROPDOWN.h" #include "EDIT.h" #include "FRAMEWIN.h" #include "LISTBOX.h" #include "MULTIEDIT.h" #include "RADIO.h" #include "SLIDER.h" #include "TEXT.h" #include "PROGBAR.h" #include "SCROLLBAR.h" #include "LISTVIEW.h" #define WM_UPDATE WM_USER + 1(1) /********************************************************************* * * static data * ********************************************************************** */ GUI_COLOR _acColor[3] = {GUI_BLUE,GUI_RED,GUI_YELLOW}; static char ucBackColor; /********************************************************************* * * Dialog resource * * This table conatins the info required to create the dialog. * It has been created by ucGUIbuilder. */ static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = { { FRAMEWIN_CreateIndirect, "armfly", 0, 0, 0, 800,480,FRAMEWIN_CF_MOVEABLE,0}, { BUTTON_CreateIndirect, "BUTTON0", GUI_ID_BUTTON0, 82, 122,162,37, 0,0}, { BUTTON_CreateIndirect, "BUTTON1", GUI_ID_BUTTON1, 357,123,152,35, 0,0} }; /***************************************************************** ** FunctionName:void PaintDialog(WM_MESSAGE * pMsg) ** Function: to initialize the Dialog items ** ** call this function in _cbCallback --> WM_PAINT *****************************************************************/ void PaintDialog(WM_MESSAGE * pMsg) { WM_HWIN hWin = pMsg->hWin; GUI_SetBkColor(_acColor[ucBackColor]); GUI_Clear(); } /***************************************************************** ** FunctionName:void InitDialog(WM_MESSAGE * pMsg) ** Function: to initialize the Dialog items ** ** call this function in _cbCallback --> WM_INIT_DIALOG *****************************************************************/ void InitDialog(WM_MESSAGE * pMsg) { WM_HWIN hWin = pMsg->hWin; // //FRAMEWIN // FRAMEWIN_SetFont(hWin,&GUI_Font24B_ASCII); FRAMEWIN_SetTextAlign(hWin,GUI_TA_VCENTER|GUI_TA_CENTER); FRAMEWIN_AddCloseButton(hWin, FRAMEWIN_BUTTON_RIGHT, 0); FRAMEWIN_AddMaxButton(hWin, FRAMEWIN_BUTTON_RIGHT, 1); FRAMEWIN_AddMinButton(hWin, FRAMEWIN_BUTTON_RIGHT, 2); FRAMEWIN_SetTitleHeight(hWin,30); /* 默认颜色取*/ ucBackColor = 0; } /********************************************************************* * * Dialog callback routine */ static void _cbCallback(WM_MESSAGE * pMsg) { int NCode, Id; WM_HWIN hWin = pMsg->hWin; switch (pMsg->MsgId) { case WM_UPDATE: (2) ucBackColor++; if (ucBackColor == 3) { ucBackColor = 0; } WM_InvalidateWindow(hWin); break; case WM_MOUSEOVER: break; case WM_PAINT: PaintDialog(pMsg); break; case WM_INIT_DIALOG: InitDialog(pMsg); 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; case GUI_ID_BUTTON0: switch(NCode) { case WM_NOTIFICATION_CLICKED: ucBackColor++; if (ucBackColor == 3) { ucBackColor = 0; } WM_InvalidateWindow(hWin); break; case WM_NOTIFICATION_RELEASED: break; case WM_NOTIFICATION_MOVED_OUT: break; } break; case GUI_ID_BUTTON1: switch(NCode) { case WM_NOTIFICATION_CLICKED: ucBackColor--; if (ucBackColor < 0) { ucBackColor = 2; } WM_InvalidateWindow(hWin); break; case WM_NOTIFICATION_RELEASED: break; case WM_NOTIFICATION_MOVED_OUT: break; } break; } break; default: WM_DefaultProc(pMsg); } } /********************************************************************* * * MainTask * ********************************************************************** */ void MainTask(void) { WM_HWIN hDlg; GUI_Init(); WM_SetDesktopColor(GUI_BLUE); /* Automacally update desktop window */ WM_SetCreateFlags(WM_CF_MEMDEV); /* Use memory devices on all windows to avoid flicker */ PROGBAR_SetDefaultSkin(PROGBAR_SKIN_FLEX); FRAMEWIN_SetDefaultSkin(FRAMEWIN_SKIN_FLEX); PROGBAR_SetDefaultSkin(PROGBAR_SKIN_FLEX); BUTTON_SetDefaultSkin(BUTTON_SKIN_FLEX); CHECKBOX_SetDefaultSkin(CHECKBOX_SKIN_FLEX); DROPDOWN_SetDefaultSkin(DROPDOWN_SKIN_FLEX); SCROLLBAR_SetDefaultSkin(SCROLLBAR_SKIN_FLEX); SLIDER_SetDefaultSkin(SLIDER_SKIN_FLEX); HEADER_SetDefaultSkin(HEADER_SKIN_FLEX); RADIO_SetDefaultSkin(RADIO_SKIN_FLEX); /* 创建一个对话框 */ hDlg = GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), &_cbCallback, 0, 0, 0); while (1) { WM_SendMessageNoPara(WM_GetClientWindow(hDlg), WM_UPDATE); (3) GUI_Delay(500); } } |
|
|
|
|
|
1. 定义一个用户消息WM_UPDATE。一定要以WM_USER作为起始值,防止跟系统其他的数值冲突。
2. 在回调函数中加入咱们定义的消息WM_UPDATE,实现对话框中背景的更新功能。 3. 通过函数WM_SendMessageNoPara()每隔500ms给对话框发送消息。这里要特别的注意一点,这个函数是给窗口发送消息的,而咱们前面创建的是对话框,所以这里必须得通过函数WM_GetClientWindow得到窗口的句柄。 这个程序的显示效果如下: |
|
|
|
|
|
34.2 桌面窗口回调函数实例
这里用上期教程所介绍的自定义消息类型做一个实例。代码跟上期教程的三个实例类似。实现源码如下(可以直接将代码复制到模拟器或者开发板上面运行)。 复制代码 #include #include "GUI.h" #include "DIALOG.h" #include "WM.h" #include "BUTTON.h" #include "CHECKBOX.h" #include "DROPDOWN.h" #include "EDIT.h" #include "FRAMEWIN.h" #include "LISTBOX.h" #include "MULTIEDIT.h" #include "RADIO.h" #include "SLIDER.h" #include "TEXT.h" #include "PROGBAR.h" #include "SCROLLBAR.h" #include "LISTVIEW.h" #define WM_UPDATE WM_USER + 1 /********************************************************************* * * static data * ********************************************************************** */ GUI_COLOR _acColor[3] = {GUI_BLUE,GUI_RED,GUI_YELLOW}; static char ucBackColor; /********************************************************************* * * Dialog resource * * This table conatins the info required to create the dialog. * It has been created by ucGUIbuilder. */ static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = { { FRAMEWIN_CreateIndirect, "armfly", 0, 0, 0, 800,480,FRAMEWIN_CF_MOVEABLE,0}, { BUTTON_CreateIndirect, "BUTTON0", GUI_ID_BUTTON0, 82, 122,162,37, 0,0}, { BUTTON_CreateIndirect, "BUTTON1", GUI_ID_BUTTON1, 357,123,152,35, 0,0} }; /***************************************************************** ** FunctionName:void PaintDialog(WM_MESSAGE * pMsg) ** Function: to initialize the Dialog items ** ** call this function in _cbCallback --> WM_PAINT *****************************************************************/ void PaintDialog(WM_MESSAGE * pMsg) { WM_HWIN hWin = pMsg->hWin; // GUI_SetBkColor(_acColor[ucBackColor]); // GUI_Clear(); } /***************************************************************** ** FunctionName:void InitDialog(WM_MESSAGE * pMsg) ** Function: to initialize the Dialog items ** ** call this function in _cbCallback --> WM_INIT_DIALOG *****************************************************************/ void InitDialog(WM_MESSAGE * pMsg) { WM_HWIN hWin = pMsg->hWin; // //FRAMEWIN // FRAMEWIN_SetFont(hWin,&GUI_Font24B_ASCII); FRAMEWIN_SetTextAlign(hWin,GUI_TA_VCENTER|GUI_TA_CENTER); FRAMEWIN_AddCloseButton(hWin, FRAMEWIN_BUTTON_RIGHT, 0); FRAMEWIN_AddMaxButton(hWin, FRAMEWIN_BUTTON_RIGHT, 1); FRAMEWIN_AddMinButton(hWin, FRAMEWIN_BUTTON_RIGHT, 2); FRAMEWIN_SetTitleHeight(hWin,30); /* 默认颜色取*/ ucBackColor = 0; } /********************************************************************* * * Dialog callback routine */ static void _cbCallback(WM_MESSAGE * pMsg) { int NCode, Id; WM_HWIN hWin = pMsg->hWin; switch (pMsg->MsgId) { case WM_PAINT: PaintDialog(pMsg); break; case WM_INIT_DIALOG: InitDialog(pMsg); 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; case GUI_ID_BUTTON0: switch(NCode) { case WM_NOTIFICATION_CLICKED: break; case WM_NOTIFICATION_RELEASED: break; case WM_NOTIFICATION_MOVED_OUT: break; } break; case GUI_ID_BUTTON1: switch(NCode) { case WM_NOTIFICATION_CLICKED: break; case WM_NOTIFICATION_RELEASED: break; case WM_NOTIFICATION_MOVED_OUT: break; } break; } break; default: WM_DefaultProc(pMsg); } } /********************************************************************* * * Dialog callback routine */ static void _cbBkWindow(WM_MESSAGE * pMsg) (1) { WM_HWIN hWin = pMsg->hWin; switch (pMsg->MsgId) { case WM_PAINT: (2) GUI_SetBkColor(_acColor[ucBackColor]); GUI_Clear(); break; case WM_UPDATE:(3) ucBackColor++; if (ucBackColor == 3) { ucBackColor = 0; } WM_InvalidateWindow(hWin); break; default: WM_DefaultProc(pMsg); } } /********************************************************************* * * MainTask * ********************************************************************** */ void MainTask(void) { WM_HWIN hDlg; /* 使能窗口使用内存设备,这样可以有效避免闪烁 放在GUI_Init前面就包括桌面 窗口,如果放在后面就不包括桌面窗口。 */ WM_SetCreateFlags(WM_CF_MEMDEV); (4) GUI_Init(); /* 设置桌面窗口回调函数 */ WM_SetCallback(WM_HBKWIN, _cbBkWindow);(5) //WM_SetDesktopColor(GUI_BLUE); /* Automacally update desktop window */ (6) PROGBAR_SetDefaultSkin(PROGBAR_SKIN_FLEX); FRAMEWIN_SetDefaultSkin(FRAMEWIN_SKIN_FLEX); PROGBAR_SetDefaultSkin(PROGBAR_SKIN_FLEX); BUTTON_SetDefaultSkin(BUTTON_SKIN_FLEX); CHECKBOX_SetDefaultSkin(CHECKBOX_SKIN_FLEX); DROPDOWN_SetDefaultSkin(DROPDOWN_SKIN_FLEX); SCROLLBAR_SetDefaultSkin(SCROLLBAR_SKIN_FLEX); SLIDER_SetDefaultSkin(SLIDER_SKIN_FLEX); HEADER_SetDefaultSkin(HEADER_SKIN_FLEX); RADIO_SetDefaultSkin(RADIO_SKIN_FLEX); /* 创建一个对话框 */ hDlg = GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), &_cbCallback, 0, 0, 0); while (1) { WM_SendMessageNoPara(WM_HBKWIN, WM_UPDATE); (7) GUI_Delay(500); } } |
|
|
|
|
|
1. 桌面窗口的回调函数(桌面窗口是emWin最底层的窗口,是初始化后自动创建的)。
2. 重绘消息,用于实现桌面颜色的重绘。 3. 这个是自定义消息,功能和上面34.1小节讲的一样。 4. 使能窗口使用内存设备,这样可以有效的避免闪烁。 5. 通过函数WM_SetCallback来设置桌面窗口的回调函数。 6. 函数WM_SetDesktopColor可以实现桌面窗口颜色的自动重绘。 7. 这里要尤其的注意,系统消息由GUI库发送。请勿从用户应用程序向窗口或小工具发送系统定义的消息。要不会出现异常的。也就是说我们不能发WM_PAINT消息,但是可以发自定义消息,进而来触发重绘。 这个DEMO的功能就是每隔500ms改变一次桌面窗口的颜色,实际显示效果如下: |
|
|
|
|
|
下面我们将这个代码分析一下:
复制代码 #include "GUI.h" #include "WM.h" /******************************************************************* * * 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(); _DemoRedraw(); } |
|
|
|
|
|
1. 桌面窗口回调函数。
2. 在回调函数的WM_PAINT消息中清除一块区域。 3. 另一个创建窗口的回调函数。 4. 函数WM_GetInsideRect返回客户区的坐标,该区域由活动小工具尺寸减去边界尺寸确定。此函数向活动窗口发送一条消息,检索内部矩形。如果小工具不处理此消息(也即意味着小工具没有边界),则需使用WM_GetClientRect函数计算出矩形。结果通过窗口坐标给出。也即,GUI_RECT结构中的x0和y0相当于x和y的边界尺寸,x1和y1相当于窗口尺寸减去边界尺寸-1。 5. 调用函数GUI_ClearRectEx清除部分区域。 6. 函数WM_CreateWindow中每个参数的含义需要大家详细研究下官方手册,这里就不做解释了。 7. 通过函数WM_MoveWindow()实现窗口位置的移动,注意这里移动的是相对距离。 8. 删除这个创建的窗口。 9. 通过函数WM_Invalidate(WM_HBKWIN)使得桌面窗口无效,然后调用函数GUI_Exec()就会执行重绘。 10. 执行第一种情况:移动窗口,但是不做桌面窗口的重绘。 11. 给桌面窗口设置专门的回调函数。 12. 执行第二种情况:移动窗口,并执行桌面窗口的重绘。 |
|
|
|
|
|
这个演示实例的主要功能就是两种情况,一种是演示:移动窗口的情况下,但是不做桌面窗口的重绘。另一种是:移动窗口,并执行桌面窗口的重绘。通过这两种情况的演示可以帮助大家对回调函数有一个更好的认识。
第一幅:没有执行桌面回调函数的情况: |
|
|
|
|
|
34.4 总结
本期教程就跟大家讲这么多,希望通过本期教程让大家对窗口管理器有更好的认识,不过还需要大家在模拟器或者开发板上面多做这方面的练习。 |
|
|
|
|
|
7 浏览 0 评论
26 浏览 1 评论
基于瑞萨FPB-RA4E2智能床头灯项目——1编译环境搭建与点亮驱动ws2812全彩LED
13 浏览 0 评论
嵌入式学习-飞凌嵌入式ElfBoard ELF 1板卡-LCD显示图片编程示例之介绍mmap
644 浏览 0 评论
《DNESP32S3使用指南-IDF版_V1.6》第二章 常用的C语言知识点
1000 浏览 0 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
11771 浏览 31 评论
浏览过的版块 |
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-24 18:13 , Processed in 0.694793 second(s), Total 58, Slave 50 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号