Files
minigui-docs/programming-guide-zh/MiniGUIProgGuidePart6Chapter20-zh.md
lisimeng123 12ea4e47e4 update
2022-11-18 00:00:48 +08:00

15 KiB
Raw Permalink Blame History

图标型控件

图标型IconView控件提供一个以图标加标签文字的方式供用户浏览条目的界面。这些图标项显示在可滚动的子窗口中用户可通过键盘及鼠标操作来选中某一项或者多个项选中的图标项通常高亮显示。图标型控件的典型用法是作为桌面图标的容器和目录下文件的显示。

使用 CTRL_ICONVIEW 作为控件类名称,可以通过 CreateWindow 函数调用创建图标型控件。

我们在创建图标型控件之后,可以通过发送相应的消息来添加、删除、设置图标尺寸(必须在添加该图标之前)和获取图标标签文字等。

1.1 图标型控件风格

默认状态下,图标型控件窗口只显示图标和其标签文字,显示区域的周围没有边界。你可以在以 CreateWindow 函数创建控件时使用窗口风格标识号 WS_BORDER 来为图标型控件加上边界。另外,还可以使用窗口风格 WS_VSCROLLWS_HSCROLL 来增加垂直和水平滚动条,以便用鼠标来滚动显示列表型控件中的各项内容。

图标型控件是基于 ScrollView(滚动型)控件开发的,它保留了 ScrollView 控件的风格。

1.2 图标型控件消息

1.2.1 图标项的操作

在创建一个图标型控件之后,下一步通常需要往该控件中添加图标项,这是由应用程序向控件发送 IVM_ADDITEM 消息来完成的。

IVITEMINFO ivii;
SendMessage (hIconView, IVM_ADDITEM, 0, (LPARAM)&ivii) ;

其中,ivii 是一个 IVITEMINFO 结构,用来表示所要设置的图标项的信息。IVITEMINFO 结构的定义以及各项意义如下:

typedef struct _IVITEMINFO
{
        /* 图标项的索引值 */
        int nItem;
        /* 图标项的图标 */
        PBITMAP bmp;
        /* 图标项的标签文字 */
        const char *label;
        /* 图标项的附加信息 */
        DWORD addData;
        /* 保留 */
        DWORD dwFlags;
} IVITEMINFO;

图标项的索引值表示了该项在父窗口的位置。添加成功后返回该图标项的句柄,否则返回 0。

在添加图标项之前可以指定图标项的宽度和高度,所有的图标项都将以这个宽高度来显示。这是由 IVM_SETITEMSIZE 来完成的:

int width;
int height;
SendMessage (hIconView, IVM_SETITEMSIZE, width, height) ;

其中,width 是要设置的宽度,height 是要设置的高度。

因为图标型控件是基于 ScrollView 控件的,因此,图标型控件的其余各消息基本上和 ScrollView 的消息一一对应:

  • IVM_RESETCONTENT:对应 SVM_RESETCONTENT,用于清空图标型控件中的图标项。
  • IVM_DELITEM:对应 SVM_DELITEM,用于删除图标型控件中的图标项。
  • IVM_SETITEMDRAW:对应 SVM_SETITEMDRAW,用于设置图标项的绘制函数。
  • IVM_SETCONTWIDTH:对应 SVM_SETCONTWIDTH,用于设置滚动窗口的宽度。
  • IVM_SETCONTHEIGHT:对应 SVM_SETCONTHEIGHT,用于设置滚动窗口的高度。
  • IVM_SETITEMOPS:对应 SVM_ SETITEMOPS,用于设置图标项相关操作的一些回调函数。
  • IVM_GETMARGINS:对应 SVM_GETMARGINS,用于获取图标型控件的边缘范围值。
  • IVM_SETMARGINS:对应 SVM_SETMARGINS,用于设置图标型控件的边缘范围值。
  • IVM_GETLEFTMARGINIVM_GETTOPMARGINIVM_GETRIGHTMARGINIVM_GETBOTTOMMARGIN 分别对应 SVM_GETLEFTMARGINSVM_GETTOPMARGINSVM_GETRIGHTMARGINSVM_GETBOTTOMMARGIN 用于获取图标型控件中的左、上、右、下边缘值。
  • IVM_GETCONTWIDTHIVM_GETCONTHEIGHTIVM_GETVISIBLEWIDTHIVM_GETVISIBLEHEIGHT 分别对应 SVM_GETCONTWIDTHSVM_GETCONTHEIGHTSVM_GETVISIBLEWIDTHSVM_GETVISIBLEHEIGHT,用来获取内容区域的宽度和高度、可视区域的宽度和高度。
  • IVM_SETCONTRANGE:对应 SVM_SETCONTRANGE,用于设置滚动窗口的内容区域的大小。
  • IVM_GETCONTENTXIVM_GETCONTENTY 分别对应 SVM_GETCONTENTXSVM_GETCONTENTY,用于获取内容区域的当前位置值。
  • IVM_SETCONTPOS:对应 SVM_SETCONTPOS,用于设置内容区域的当前位置值,也就是在可视区域中移动内容区域到某个指定位置。
  • IVM_GETCURSELIVM_SETCURSEL 分别对应 SVM_GETCURSELSVM_SETCURSEL,用于获取和设置控件的当前高亮图标项。
  • IVM_SELECTITEM:对应 SVM_SELECTITEM,用于选择一个列表项,被选中的项将高亮显示。
  • IVM_SHOWITEM:对应 SVM_SHOWITEM,用于显示一个图标项。
  • IVM_CHOOSEITEM:对应 SVM_CHOOSEITEM,是 IVM_SELECTITEMIVM_SHOWITEM 消息的组合,用来选中一个图标项并使之可见。
  • IVM_SETITEMINIT:对应 SVM_SETITEMINIT,用于设置图标项的初始操作。
  • IVM_SETITEMDESTROY:对应 SVM_SETITEMDESTROY,用于设置图标项的销毁操作。
  • IVM_SETITEMCMP:对应 SVM_SETITEMCMP,用于设置图标型控件图标项的比较函数。
  • IVM_MAKEPOSVISIBLE:对应 SVM_MAKEPOSVISIBLE,用于使内容区域中的某个位置点成为可见。
  • IVM_GETHSCROLLVALIVM_GETVSCROLLVAL 分别对应 SVM_GETHSCROLLVALSVM_GETVSCROLLVAL,用来获取滚动窗口的当前水平和垂直滚动值(点击滚动条箭头的滚动范围大小)。
  • IVM_GETHSCROLLPAGEVALIVM_GETVSCROLLPAGEVAL 分别对应 SVM_GETHSCROLLPAGEVALSVM_GETVSCROLLPAGEVAL,用来获取滚动窗口的当前水平和垂直页滚动值(翻页操作时的滚动范围大小)。
  • IVM_SETSCROLLVAL:对应 SVM_SETSCROLLVAL,用于设置滚动窗口的水平和(或者)垂直滚动值。
  • IVM_SETSCROLLPAGEVAL:对应 SVM_SETSCROLLPAGEVAL,用于设置滚动窗口的水平和(或者)垂直页滚动值。
  • IVM_SORTITEMS:对应 SVM_SORTITEMS,用于对图标项进行一次性的排序。
  • IVM_GETITEMCOUNT:对应 SVM_GETITEMCOUNT,用于获取当前图标项的数量。
  • IVM_GETITEMADDDATA:对应 SVM_GETITEMADDDATA,用于获取当前图标项的附加信息。
  • IVM_SETITEMADDDATA:对应 SVM_SETITEMADDDATA,用于设置当前图标项的附加信息。
  • IVM_REFRESHITEM:对应 SVM_REFRESHITEM,用于刷新一个图标项区域。
  • IVM_GETFIRSTVISIBLEITEM:对应 SVM_GETFIRSTVISIBLEITEM,用于获取第一个可见的图标项。

1.3 控件通知码

图标型控件在响应用户点击等操作和发生某些状态改变时会产生通知消息,包括:

  • LVN_SELCHANGE:对应 SVN_SELCHANGE,当前高亮图表项发生改变
  • LVN_CLICKED:对应 SVN_CLICKED,用户点击图标项

应用程序需要使用 SetNotificationCallback 函数注册一个通知消息处理函数,在该函数中对收到的各个通知码进行应用程序所需的处理。

LVN_CLICKEDLVN_SELCHANGE 通知消息处理函数传递的附加数据为被点击或者当前高亮的图标项句柄。

1.4 编程实例

清单 1.1 中的代码演示了使用图标型控件来构造一个简单的图标项浏览窗口。该程序的完整源代码可见本指南示例程序包 mg-samples 中的 iconview.c 程序。

清单 1.1 图标型控件示例程序

#define IDC_ICONVIEW    100
#define IDC_BT          200
#define IDC_BT2         300
#define IDC_BT3         400
#define IDC_BT4         500

#define IDC_ADD         600
#define IDC_DELETE      601

static HWND hIconView;

static BITMAP myicons [12];

static const char* iconfiles[12] =
{
        "./res/acroread.png",
        "./res/icons.png",
        "./res/looknfeel.png",
        "./res/package_games.png",
        "./res/tux.png",
        "./res/xemacs.png",
        "./res/gimp.png",
        "./res/kpilot.png",
        "./res/multimedia.png",
        "./res/realplayer.png",
        "./res/usb.png",
        "./res/xmms.png"
};

static const char *iconlabels[12] =
{
        "acroread",
        "icons",
        "looknfeel",
        "games",
        "tux",
        "xemacs",
        "gimp",
        "kpilot",
        "multimedia",
        "realplayer",
        "usb",
        "xmms"
};

static void myDrawItem (HWND hWnd, GHANDLE hsvi, HDC hdc, RECT *rcDraw)
{
        const PBITMAP pbmp = (PBITMAP)iconview_get_item_bitmap (hsvi);
        const char *label = (const char*)iconview_get_item_label (hsvi);
        
        SetBkMode (hdc, BM_TRANSPARENT);
        SetTextColor (hdc, PIXEL_black);
        
        if (iconview_is_item_hilight(hWnd, hsvi)) {
                SetBrushColor (hdc, PIXEL_blue);
        }
        else {
                SetBrushColor (hdc, PIXEL_lightwhite);
        }
        FillBox (hdc, rcDraw->left, rcDraw->top, RECTWP(rcDraw), RECTHP(rcDraw));
        SetBkColor (hdc, PIXEL_blue);
        
        if (label) {
                RECT rcTxt = *rcDraw;
                rcTxt.top = rcTxt.bottom - GetWindowFont (hWnd)->size * 2;
                rcTxt.left = rcTxt.left - (GetWindowFont (hWnd)->size) + 2;
                
                DrawText (hdc, label, -1, &rcTxt, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
        }
        FillBoxWithBitmap (hdc, rcDraw->left, rcDraw->top, 0, 0, pbmp);
}

static int
BookProc (HWND hDlg, int message, WPARAM wParam, LPARAM lParam)
{
        switch (message)
        {
                
                case MSG_INITDIALOG:
                {
                        IVITEMINFO ivii;
                        static int i = 0, j = 0;
                        
                        hIconView = GetDlgItem (hDlg, IDC_ICONVIEW);
                        SetWindowBkColor (hIconView, PIXEL_lightwhite);
                        //SendMessage (hIconView, IVM_SETITEMDRAW, 0, (LPARAM)myDrawItem);
                        SendMessage (hIconView, IVM_SETITEMSIZE, 55, 65);
                        //SendMessage (hIconView, IVM_SETITEMSIZE, 35, 35);
                        for (j = 0; j < 3; j ++) {
                                for (i = 0; i < TABLESIZE(myicons); i++) {
                                        memset (&ivii, 0, sizeof(IVITEMINFO));
                                        ivii.bmp = &myicons[i];
                                        ivii.nItem = 12 * j + i;
                                        ivii.label = iconlabels[i];
                                        ivii.addData = (DWORD)iconlabels[i];
                                        SendMessage (hIconView, IVM_ADDITEM, 0, (LPARAM)&ivii);
                                }
                        }
                        break;
                }
                
                case MSG_COMMAND:
                {
                        int id = LOWORD (wParam);
                        int code = HIWORD (wParam);
                        
                        switch (id) {
                                case IDC_ICONVIEW:
                                if (code == IVN_CLICKED) {
                                        int sel;
                                        sel = SendMessage (hIconView, IVM_GETCURSEL, 0, 0);
                                        printf ("clicking %d\n", sel);
                                }
                                break;
                                case IDC_ADD:
                                {
                                        IVITEMINFO ivii;
                                        char buff [10];
                                        int idx;
                                        int count = SendMessage (hIconView, IVM_GETITEMCOUNT, 0, 0);
                                        
                                        sprintf (buff, "NewIcon%i", count);
                                        memset (&ivii, 0, sizeof (IVITEMINFO));
                                        ivii.bmp = &myicons [0];
                                        ivii.nItem = count;
                                        ivii.label = buff;
                                        ivii.addData = (DWORD)"NewIcon";
                                        
                                        idx = SendMessage (hIconView, IVM_ADDITEM, 0, (LPARAM)&ivii);
                                        SendMessage (hIconView, IVM_SETCURSEL, idx, 1);
                                        break;
                                }
                                
                                case IDC_DELETE:
                                {
                                        int sel = SendMessage (hIconView, IVM_GETCURSEL, 0, 0);
                                        int count = SendMessage (hIconView, IVM_GETITEMCOUNT, 0, 0);
                                        char *label = NULL;
                                        
                                        if (sel >= 0){
                                                label = (char *) SendMessage (hIconView, IVM_GETITEMADDDATA, sel, 0); 
                                                if (label && strlen (label))
                                                printf ("delelete item:%s\n", label);
                                                SendMessage (hIconView, IVM_DELITEM, sel, 0);
                                                if (sel == count - 1)
                                                sel --;
                                                SendMessage (hIconView, IVM_SETCURSEL, sel, 1);
                                        }
                                        break;
                                }
                                
                        } /* end command switch */
                        break;
                }
                
                case MSG_KEYDOWN:
                if (wParam == SCANCODE_REMOVE) {
                        int cursel = SendMessage (hIconView, IVM_GETCURSEL, 0, 0);
                        
                        if (cursel >= 0){
                                SendMessage (hIconView, IVM_DELITEM, cursel, 0);
                                SendMessage (hIconView, IVM_SETCURSEL, cursel, 0);
                        }
                }
                break;
                
                case MSG_CLOSE:
                {
                        EndDialog (hDlg, 0);
                        return 0;
                }
                
        } /* end switch */
        
        return DefaultDialogProc (hDlg, message, wParam, lParam);
}

static CTRLDATA CtrlBook[] =
{
        {
                CTRL_ICONVIEW,
                WS_BORDER | WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL,
                10, 10, 290, 300,
                IDC_ICONVIEW,
                "",
                0
        },
        {
                CTRL_BUTTON,
                WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP,
                90, 330, 50, 30,
                IDC_ADD,
                "Add",
                0
        },
        {
                CTRL_BUTTON,
                WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
                170, 330, 50, 30,
                IDC_DELETE,
                "Delete",
                0
        }
};

static DLGTEMPLATE DlgIcon =
{
        WS_BORDER | WS_CAPTION,
        WS_EX_NONE,
        0, 0, 310, 400,
        "My Friends",
        0, 0,
        TABLESIZE(CtrlBook), CtrlBook,
        0
};

图标型控件 图 1.1 图标型控件