⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 minigui 体系结构之二 多窗口管理和控件及控件类.htm

📁 minigui--面向实时嵌入式系统的图形用户界面。此文档介绍了miniguide体系结构。
💻 HTM
📖 第 1 页 / 共 4 页
字号:
        <TBODY>
        <TR>
          <TD><PRE>清单 4  控件的子类化

#define IDC_CTRL1     100
#define IDC_CTRL2     110
#define IDC_CTRL3     120
#define IDC_CTRL4     130

#define MY_ES_DIGIT_ONLY    0x0001
#define MY_ES_ALPHA_ONLY    0x0002
static WNDPROC old_edit_proc;
static int RestrictedEditBox (HWND hwnd, int message, WPARAM wParam, LPARAM lParam)
{
    if (message == MSG_CHAR) {
        DWORD my_style = GetWindowAdditionalData (hwnd);

        /* 确定被屏蔽的按键类型 */
        if ((my_style &amp; MY_ES_DIGIT_ONLY) &amp;&amp; (wParam &lt; '0' || wParam &gt; '9'))
            return 0;
        else if (my_style &amp; MY_ES_ALPHA_ONLY)
            if (!((wParam &gt;= 'A' &amp;&amp; wParam &lt;= 'Z') || (wParam &gt;= 'a' &amp;&amp; wParam &lt;= 'z')))
                /* 收到被屏蔽的按键消息,直接返回 */
                return 0;
    }

    /* 由老的窗口过程处理其余消息 */
    return (*old_edit_proc) (hwnd, message, wParam, lParam);
}

static int ControlTestWinProc (HWND hWnd, int message, WPARAM wParam, LPARAM lParam)
{
    switch (message) {
    case MSG_CREATE:
    {
        HWND hWnd1, hWnd2, hWnd3;

        CreateWindow (CTRL_STATIC, "Digit-only box:", WS_CHILD | WS_VISIBLE | SS_RIGHT, 0,
                    10, 10, 180, 24, hWnd, 0);
        hWnd1 = CreateWindow (CTRL_EDIT, "", WS_CHILD | WS_VISIBLE | WS_BORDER, IDC_CTRL1,
                    200, 10, 180, 24, hWnd, MY_ES_DIGIT_ONLY);
        CreateWindow (CTRL_STATIC, "Alpha-only box:", WS_CHILD | WS_VISIBLE | SS_RIGHT, 0,
                    10, 40, 180, 24, hWnd, 0);
        hWnd2 = CreateWindow (CTRL_EDIT, "", WS_CHILD | WS_BORDER | WS_VISIBLE, IDC_CTRL2,
                    200, 40, 180, 24, hWnd, MY_ES_ALPHA_ONLY);
        CreateWindow (CTRL_STATIC, "Normal edit box:", WS_CHILD | WS_VISIBLE | SS_RIGHT, 0,
                    10, 70, 180, 24, hWnd, 0);
        hWnd3 = CreateWindow (CTRL_EDIT, "", WS_CHILD | WS_BORDER | WS_VISIBLE, IDC_CTRL2,
                    200, 70, 180, 24, hWnd, MY_ES_ALPHA_ONLY);

        CreateWindow ("button", "Close", WS_CHILD | BS_PUSHBUTTON | WS_VISIBLE, IDC_CTRL4,
                    100, 100, 60, 24, hWnd, 0);

        /* 用自定义的窗口过程替换编辑框的窗口过程,并保存老的窗口过程。*/
        old_edit_proc = SetWindowCallbackProc (hWnd1, RestrictedEditBox);
        SetWindowCallbackProc (hWnd2, RestrictedEditBox);
        break;
    }

    ...
    }

    return DefaultMainWinProc (hWnd, message, wParam, lParam);
}
</PRE></TD></TR></TBODY></TABLE>
      <P>在清单 4 中,程序首先定义了一个窗口处理过程,即 RestrictedEditBox 函数。然后,在利用 CreateWindow 
      函数建立控件时,将其中两个编辑框的窗口处理过程通过 SetWindowCallbackProc 替换成了自己定义的 
      RestrictedEditBox 函数,并且将该函数返回的值(即老的控件窗口处理过程地址)保存在了 old_edit_box 
      变量中。在建立这些编辑框之后,它们的消息将首先由 RestrictedEditBox 函数处理,然后在某些情况下才由老的窗口处理过程处理。</P>
      <P>限于篇幅,另外两种控件子类化的方法就不在这里讲述。</P><STRONG>4.2 MiniGUI 中控件类的实现</STRONG> 
      <P>MiniGUI 
      函数库实际维护了一个当前所有控件类的数据结构,其中包含了控件类名称以及对应的控件类信息。该数据结构实际是一个哈希表,哈希表的每个入口包含由一个指针,该指针指向所有名程以某个字母开头(不分大小写)的控件类信息链表。控件类信息结构定义如下:</P>
      <TABLE class=code-sample cellPadding=0 width="100%" border=0>
        <TBODY>
        <TR>
          <TD><PRE>#define MAXLEN_CLASSNAME    15
typedef struct _CTRLCLASSINFO
{
    char      name [MAXLEN_CLASSNAME + 1];
                                // 控件类名程
    /*
     * common properties of this class
     */
    DWORD     dwStyle;          // 控件类风格

    HCURSOR   hCursor;          // 控件光标
    int       iBkColor;         // 控件的背景颜色

    int (*ControlProc)(HWND, int, WPARAM, LPARAM);
                                // 控件处理过程

    DWORD dwAddData;            // 附加数据

    int nUseCount;              // 使用计数,即系统中属于该控件类的控件个数
    struct _CTRLCLASSINFO*  next;
                                // 下一个控件类信息结构
} CTRLCLASSINFO;
typedef CTRLCLASSINFO* PCTRLCLASSINFO;
</PRE></TD></TR></TBODY></TABLE>
      <P>在控件类的数据结构中包含了鼠标、光标、控件类的回调函数地址等等信息。在创建属于该控件类的控件时,这些信息会复制到控件数据结构中。这样,新的控件实例就继承了这种控件类的表象和行为。</P>
      <P>该哈希表的哈希函数实际非常简单,它的返回值就是控件类名称首字母的英文字母表顺序值:</P>
      <TABLE class=code-sample cellPadding=0 width="100%" border=0>
        <TBODY>
        <TR>
          <TD><PRE>static int HashFunc (char* szClassname)
{
    /* 判断首字符是否为字母 */
    if (!isalpha (szClassName[0])) return ERR_CTRLCLASS_INVNAME;

    /* 讲所有字符转换为大写 */
    while (szClassName[i]) {
        szClassName[i] = toupper(szClassName[i]);

        i++;
        if (i &gt; MAXLEN_CLASSNAME)
            return ERR_CTRLCLASS_INVLEN;
    }

    /* 获得哈希值 */
    return szClassName[0] - 'A';
}
</PRE></TD></TR></TBODY></TABLE>
      <P>控件类的注册和注销函数非常简单,这里不再赘述。</P><STRONG>4.3 MiniGUI 中控件的实现</STRONG> 
      <P>控件结构相对复杂一些。其中包含了控件在父窗口中的位置信息、控件风格、扩展风格、控件鼠标、图标、控件回调函数地址等等:</P>
      <TABLE class=code-sample cellPadding=0 width="100%" border=0>
        <TBODY>
        <TR>
          <TD><PRE>typedef struct _CONTROL
{
    /*
     * 这些成员和 MAINWIN 结构一致.
     */
    short DataType;         // 内部使用的数据类型
    short WinType;          // 内部使用的窗口类型

    int left, top;          // 控件在父窗口中的位置
    int right, bottom;

    int cl, ct;             // 控件客户区在父窗口中的位置
    int cr, cb;

    DWORD dwStyle;          // 控件风格
    DWORD dwExStyle;        // 控件扩展风格

    int iBkColor;           // 背景颜色
    HMENU hMenu;            // 菜单句柄
    HACCEL hAccel;          // 加速键表句柄
    HCURSOR hCursor;        // 鼠标光标句柄
    HICON hIcon;            // 图标句柄
    HMENU hSysMenu;         // 系统菜单句柄

    HDC   privCDC;          // 私有 DC 句柄
    INVRGN InvRgn;          // 控件的无效区域
    PGCRINFO pGCRInfo;      // 控件的全局剪切区域
    PZORDERNODE pZOrderNode;
                            // Z 序节点
                            // 仅对具有 WS_EX_CTRLASMAINWIN 扩展风格的控件有效

    PCARETINFO pCaretInfo;  // 插入符消息

    DWORD dwAddData;        // 控件附加数据
    DWORD dwAddData2;       // 控件附加数据

    int (*ControlProc) (HWND, int, WPARAM, LPARAM); // 控件消息处理过程

    char* spCaption;         // 控件标题
    int   id;                // 控件标识符,整数

    SCROLLBARINFO vscroll;   // 垂直滚动条信息
    SCROLLBARINFO hscroll;   // 水平滚动条信息

    PMAINWIN pMainWin;       // 包含该控件的主窗口

    struct _CONTROL* pParent;// 控件的父窗口

    /*
     * Child windows.
     */
    struct _CONTROL* children;
                             // 控件的第一个子控件
    struct _CONTROL* active;
                             // 当前活动子控件
    struct _CONTROL* old_under_pointer;
                             // 老的鼠标鼠标所在子控件
    /*
     * 下面这些成员只对控件有效

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -