硬汉嵌入式论坛

 找回密码
 立即注册
查看: 4383|回复: 1
收起左侧

[emWin教程入门篇] 【STemWin教程】第39章 对话框基础知识

[复制链接]

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
发表于 2015-2-27 11:18:27 | 显示全部楼层 |阅读模式
特别说明:完整STemWin的1-60期教程和配套实例下载地址:链接
第39章 对话框基础知识

    在上期教程我们讲解了控件的基础知识,本期教程我们接着讲解一下对话框的基础知识,有了这两部分的基础知识后,后面我们就可以进行每个控件的应用讲解了。
    控件可以创建并独立使用,因为它们本质上就是窗口。如果在对话框上面创建控件的话,就更加的方便了,这样就可以充分利用GUIBulder。
    39. 1 对话框的基本原理
    39. 2 创建对话框
    39. 3 对话框API
    39. 4 总结
39.1 对话框的基本原理
39.1.1 输入焦点
    窗口管理器能记住用户使用触摸屏、鼠标、键盘或用其他方式最终所选择的窗口或窗口对象。该窗口会收到键盘输入消息,即具有输入焦点。追踪输入焦点的主要原因是为了确定键盘命令的发送目的地。具有输入焦点的窗口会接收由键盘所生成的事件。如果要将对话框内的输入焦点移至下一个焦点对话框项目,可以使用GUI_KEY_TAB键。如果要向后移动,则可以使用GUI_KEY_BACKTAB。

39.1.2 阻塞式和非阻塞式对话框
    对话框窗口可以分为阻塞式和非阻塞式。
    阻塞式对话框会阻塞执行的线程。默认情况下,它有输入焦点,用户必须先关闭它,线程才能继续执行。阻塞式对话框不会同时禁用所显示的其他对话框。换言之,阻塞式对话框并非模式对话框。如果对话框为阻塞式,则表示只有在对话框关闭后,所使用的函数 (GUI_ExecDialogBox()或GUI_ExecCreatedDialog())才会返回值。而非阻塞式对话框则不会阻塞调用的线程--在它为可见时,可允许任务继续运行。创建对话框后,函数会立即返回值。
    需要注意的是,切勿从回调函数中调用阻塞式函数。否则,可能会导致应用程序故障。

39.1.3 对话框过程函数
    对话框就是一个窗口,它接收消息的方式与系统中其他所有窗口一样。大多数消息由对话框的窗口回调程序自动处理,而其他消息则传递到建立对话框时所指定的回调程序,这便称为对话框过程函数。

39.1.4 对话框消息
    发送到对话框过程函数的两种附加消息为:WM_INIT_DIALOG和WM_NOTIFY_PARENT。在显示对话框前,WM_INIT_DIALOG消息会立即发送到对话框过程函数。对话框过程函数通常使用该消息来初始化控件,并执行其他任何会影响对话框外观的初始化任务。 WM_NOTIFY_PARENT消息则通过对话框的子窗口发送到对话框,通知任何事件的父窗口以确保同步化。通过子窗口发送的事件取决于其类型,并针对每个类型的控件单独记录。

39.2 创建对话框
    创建对话框需要两个基本要素:资源表和对话框过程;前者定义所要包括的控件,后者定义控件的初始值及其行为。一旦具备这两个要素,则只需进行单个函数调用(GUI_CreateDialogBox()或GUI_ExecDialogBox())就能创建对话框。
    这里只是给大家讲解一下各个部分的原理,具体的创建方法可以参考第4章:uCGUIBulder和GUIBulder的使用。

39.2.1 资源表
   对话框可以基于阻塞(使用GUI_ExecDialogBox())或非阻塞(使用GUI_CreateDialogBox())方式创建。必须首先定义一个资源表,以指定在对话框中所要包括的所有小工具。下面的示例说明了创建资源表的方法:
  1. static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] =
  2. {
  3. { FRAMEWIN_CreateIndirect, "Dialog", 0, 10, 10, 180, 230, FRAMEWIN_CF_MOVEABLE, 0 },
  4. { BUTTON_CreateIndirect, "OK", GUI_ID_OK, 100, 5, 60, 20 },
  5. { BUTTON_CreateIndirect, "Cancel", GUI_ID_CANCEL, 100, 30, 60, 20 },
  6. { TEXT_CreateIndirect, "LText", 0, 10, 55, 48, 15, TEXT_CF_LEFT },
  7. { TEXT_CreateIndirect, "RText", 0, 10, 80, 48, 15, TEXT_CF_RIGHT },
  8. { EDIT_CreateIndirect, NULL, GUI_ID_EDIT0, 60, 55, 100, 15, 0, 50 },
  9. { EDIT_CreateIndirect, NULL, GUI_ID_EDIT1, 60, 80, 100, 15, 0, 50 },
  10. { TEXT_CreateIndirect, "Hex", 0, 10, 100, 48, 15, TEXT_CF_RIGHT },
  11. { EDIT_CreateIndirect, NULL, GUI_ID_EDIT2, 60, 100, 100, 15, 0, 6 },
  12. { TEXT_CreateIndirect, "Bin", 0, 10, 120, 48, 15, TEXT_CF_RIGHT },
  13. { EDIT_CreateIndirect, NULL, GUI_ID_EDIT3, 60, 120, 100, 15 },
  14. { LISTBOX_CreateIndirect, NULL, GUI_ID_LISTBOX0,10, 10, 48, 40 },
  15. { CHECKBOX_CreateIndirect, NULL, GUI_ID_CHECK0, 10, 140, 0, 0 },
  16. { CHECKBOX_CreateIndirect, NULL, GUI_ID_CHECK1, 30, 140, 0, 0 },
  17. { SLIDER_CreateIndirect, NULL, GUI_ID_SLIDER0, 60, 140, 100, 20 },
  18. { SLIDER_CreateIndirect, NULL, GUI_ID_SLIDER1, 10, 170, 150, 30 }
  19. };
复制代码
    对话框中所要包括的任何小工具都必须使用<WIDGET>_CreateIndirect()函数来间接创建。这个在前面38.6.1小节有讲解。

39.2.2 对话框过程函数
    上述示例使用如下所示的空白对话框过程函数创建。在创建任何对话框过程函数时,该基本模板都将作为起始点:
  1. /*********************************************************************
  2. *
  3. 对话框过程函数
  4. */
  5. static void _cbCallback(WM_MESSAGE * pMsg) {
  6. switch (pMsg->MsgId) {
  7. default:
  8. WM_DefaultProc(pMsg);
  9. }
  10. }
复制代码
    对于该示例,对话框显示时会有下列代码行:
                GUI_ExecDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate),&_cbCallback, 0, 0, 0);
    所生成的对话框看起来如下图一样或者与之类似 (实际外观则取决于配置和默认设置):
39.1.png

    创建对话框后,所有资源表中的控件都将可见。尽管这些控件在上面的屏幕截图中可见,但它们是以 “空”的形式出现的。这是因为对话框过程函数尚未包含初始化单个元素的代码。控件的初始值、由它们所引起的行为以及它们之间的交互作用都需要在对话框过程中进行定义。

39.2.3 初始化对话框
    下一步通常是使用它们各自的初始值对小工具进行初始化。在对话框过程函数中,这是对WM_INIT_DIALOG消息做出反应时的通常做法。下面的程序摘要说明了这个过程:
  1. /*********************************************************************
  2. *
  3. 对话框过程函数
  4. */
  5. static void _cbCallback(WM_MESSAGE * pMsg) {
  6. int NCode, Id;
  7. WM_HWIN hEdit0, hEdit1, hEdit2, hEdit3, hListBox;
  8. WM_HWIN hWin = pMsg->hWin;
  9. switch (pMsg->MsgId) {
  10. case WM_INIT_DIALOG:
  11. /* Get window handles for all widgets */
  12. hEdit0 = WM_GetDialogItem(hWin, GUI_ID_EDIT0);
  13. hEdit1 = WM_GetDialogItem(hWin, GUI_ID_EDIT1);
  14. hEdit2 = WM_GetDialogItem(hWin, GUI_ID_EDIT2);
  15. hEdit3 = WM_GetDialogItem(hWin, GUI_ID_EDIT3);
  16. hListBox = WM_GetDialogItem(hWin, GUI_ID_LISTBOX0);
  17. /* Initialize all widgets */
  18. EDIT_SetText(hEdit0, "EDIT widget 0");
  19. EDIT_SetText(hEdit1, "EDIT widget 1");
  20. EDIT_SetTextAlign(hEdit1, GUI_TA_LEFT);
  21. EDIT_SetHexMode(hEdit2, 0x1234, 0, 0xffff);
  22. EDIT_SetBinMode(hEdit3, 0x1234, 0, 0xffff);
  23. LISTBOX_SetText(hListBox, _apListBox);
  24. WM_DisableWindow (WM_GetDialogItem(hWin, GUI_ID_CHECK1));
  25. CHECKBOX_Check( WM_GetDialogItem(hWin, GUI_ID_CHECK0));
  26. CHECKBOX_Check( WM_GetDialogItem(hWin, GUI_ID_CHECK1));
  27. SLIDER_SetWidth( WM_GetDialogItem(hWin, GUI_ID_SLIDER0), 5);
  28. SLIDER_SetValue( WM_GetDialogItem(hWin, GUI_ID_SLIDER1), 50);
  29. break;
  30. default:
  31. WM_DefaultProc(pMsg);
  32. )
  33. }
  34. }
复制代码
    经过初始化的对话框现在如下所示,所有小工具都包含了它们各自的初始值:
39.2.png


39.2.4 定义话框行为
一旦对话框得到初始化,则剩下的所有工作便是向对话框过程函数添加代码,这样可定义小工具的行为,从而使其能充分操作。继续同一个示例,最终的对话框过程函数如下所示:
  1. /*********************************************************************
  2. *
  3. 对话框过程函数
  4. */
  5. static void _cbCallback(WM_MESSAGE * pMsg) {
  6. int NCode, Id;
  7. WM_HWIN hEdit0, hEdit1, hEdit2, hEdit3, hListBox;
  8. WM_HWIN hWin = pMsg->hWin;
  9. switch (pMsg->MsgId) {
  10. case WM_INIT_DIALOG:
  11. /* Get window handles for all widgets */
  12. hEdit0 = WM_GetDialogItem(hWin, GUI_ID_EDIT0);
  13. hEdit1 = WM_GetDialogItem(hWin, GUI_ID_EDIT1);
  14. hEdit2 = WM_GetDialogItem(hWin, GUI_ID_EDIT2);
  15. hEdit3 = WM_GetDialogItem(hWin, GUI_ID_EDIT3);
  16. hListBox = WM_GetDialogItem(hWin, GUI_ID_LISTBOX0);
  17. /* Initialize all widgets */
  18. EDIT_SetText(hEdit0, "EDIT widget 0");
  19. EDIT_SetText(hEdit1, "EDIT widget 1");
  20. EDIT_SetTextAlign(hEdit1, GUI_TA_LEFT);
  21. EDIT_SetHexMode(hEdit2, 0x1234, 0, 0xffff);
  22. EDIT_SetBinMode(hEdit3, 0x1234, 0, 0xffff);
  23. LISTBOX_SetText(hListBox, _apListBox);
  24. WM_DisableWindow (WM_GetDialogItem(hWin, GUI_ID_CHECK1));
  25. CHECKBOX_Check( WM_GetDialogItem(hWin, GUI_ID_CHECK0));
  26. CHECKBOX_Check( WM_GetDialogItem(hWin, GUI_ID_CHECK1));
  27. SLIDER_SetWidth( WM_GetDialogItem(hWin, GUI_ID_SLIDER0), 5);
  28. SLIDER_SetValue( WM_GetDialogItem(hWin, GUI_ID_SLIDER1), 50);
  29. break;
  30. case WM_KEY:
  31. switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key) {
  32. case GUI_ID_ESCAPE:
  33. GUI_EndDialog(hWin, 1);
  34. break;
  35. case GUI_ID_ENTER:
  36. GUI_EndDialog(hWin, 0);
  37. break;
  38. }
  39. break;
  40. case WM_NOTIFY_PARENT:
  41. Id = WM_GetId(pMsg->hWinSrc); /* Id of widget */
  42. NCode = pMsg->Data.v; /* Notification code */
  43. switch (NCode) {
  44. case WM_NOTIFICATION_RELEASED:/* React only if released */
  45. if (Id == GUI_ID_OK) { /* OK Button */
  46. GUI_EndDialog(hWin, 0);
  47. }
  48. if (Id == GUI_ID_CANCEL) { /* Cancel Button */
  49. GUI_EndDialog(hWin, 1);
  50. }
  51. break;
  52. case WM_NOTIFICATION_SEL_CHANGED:/* Selection changed */
  53. FRAMEWIN_SetText(hWin, "Dialog - sel changed");
  54. break;
  55. default:
  56. FRAMEWIN_SetText(hWin, "Dialog - notification received");
  57. }
  58. break;
  59. default:
  60. WM_DefaultProc(pMsg);
  61. }
  62. }
复制代码

39.3 对话框API
    对话框主要有以下四个API:

函数

描述

GUI_CreateDialogBox()

创建非阻塞式对话框。

GUI_ExecCreatedDialog()

执行已创建的对话框。

GUI_ExecDialogBox()

创建并执行对话框。

GUI_EndDialog()

结束对话框。

    关于这几个函数在用户手册中有详细的讲解,这里就不做讲解了

39.4 总结
    有了本期和前面的教程介绍后,后面具体的讲解每个控件时就会方便很多。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

0

主题

19

回帖

0

积分

新手上路

积分
0
QQ
发表于 2016-10-23 11:06:09 | 显示全部楼层
窗口管理器能记住用户使用触摸屏、鼠标、键盘或用其他方式最终所选择的窗口或窗口对象。该窗口会收到键盘输入消息,即具有输入焦点。追踪输入焦点的主要原因是为了确定键盘命令的发送目的地。具有输入焦点的窗口会接收由键盘所生成的事件。如果要将对话框内的输入焦点移至下一个焦点对话框项目,可以使用GUI_KEY_TAB键。如果要向后移动,则可以使用GUI_KEY_BACKTAB。[s:152] [s:152] [s:152] [s:151] [s:151] [s:151] [s:151]
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-6-5 02:48 , Processed in 0.265462 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表