如何优雅的写UI——选项卡美化

Posted ye-ming

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何优雅的写UI——选项卡美化相关的知识,希望对你有一定的参考价值。

现在做出来的选项卡实在太丑的,咱们怎么把他弄得好看一点呢

tabctrl是可以添加icon图标的,那派生与tabctrl的mfctabctrl肯定也能添加图标,他们两个添加图标的原理一样,但是还是有点不同

首先给项目添加三个图标

技术分享图片

 

然后在成员变量中添加ImageList对象,必须要添加在成员变量中,否则加载不出来图片。

    CImageList m_imglist;

之后在初始化中创建CImageList,他的声明为

BOOL Create(int cx, int cy, UINT nFlags, int nInitial, int nGrow);

其中各项参数的含义为:

cx定义图像的宽度,单位为象素;

cy定义图象的高度,单位为象素;

nFlags确定建立图像列表的类型,

可以是以下值的组合:ILC_COLOR、ILC_COLOR4(图像为24色)、ILC_COLOR8(图像为28色)、ILC_COLOR16(图像为216色)、ILC_COLOR24、ILC_COLOR32、ILC_COLORDDB和ILC_MASK;

nInitial用来确定图像列表包含的图像数量;

nGrow用来确定图像列表可控制的图像数量。

 

 图像控制的属性类包括返回m_hImageList.控制句柄GetSafeHandle、取得图像列表中的图像数量GetImageCount、设置图像列表的背景颜色SetBkColor、取得图像列表的背景颜色SetBkColor和取得图像的有关信息SetBkColor。

图像控制的操作方法包括将一个图像列表绑定到一个对象上Attach、将对象上的图像列表解除绑定并返回句柄Detach、删除一个图像列表DeleteImageList、将一个图像增加到图像列表中Add和将一个图像从图像列表中删除Remove等。

我们来添加三个图标

m_imglist.Create(32, 32, ILC_COLOR32 | ILC_MASK, 3, 1);
    m_imglist.Add(AfxGetApp()->LoadIcon(IDI_ICON1));
    m_imglist.Add(AfxGetApp()->LoadIcon(IDI_ICON2));
    m_imglist.Add(AfxGetApp()->LoadIcon(IDI_ICON3));
    m_tab.SetImageList(m_imglist);//将ImageList绑定到tab上

要注意的是SetImageList这个方法,根据MSDN上的描述,当你创建tabctrl为平面样式,例如 STYLE_FLAT 时,你的图标加载是失败的,平面样式不支持图标的绑定,这个一定要注意了。

例如这样

技术分享图片

 

我们将图标写进了队列,也绑定上了选项卡,但是如何让页面知道我是用到了哪个图标呢,这得回到添加标签页的地方,我们来看AddTab的方法定义

virtual void AddTab(
   CWnd* pTabWnd,
   UINT uiResTabLabel,
   UINT uiImageId = (UINT)-1,
   BOOL bDetachable = TRUE
);

这里给出一个uiImageId 的参数,这个是图标的索引,你第几个页面要用到哪个图标,你就要填这个图标在CImageList 队列里的索引值。例如我第二个画面m_dlg2要用到第一个图标,第一个图标的索引值为0;就应该为

m_tab.AddTab(m_dlg2,L"还没想好些什么控件",0,FALSE);

做好的图标就是这个样子

技术分享图片

 

CSDN上还有很多样式定义,但是也有很多不能用,我不知道为什么,下面来举几个例子

标签在顶部/底部

    m_tab.SetLocation (CMFCTabCtrl::LOCATION_BOTTOM);//Tab标签在底部
    m_tab.SetLocation (CMFCTabCtrl::LOCATION_TOP);//Tab标签在顶部

添加关闭页面按钮

m_tab.EnableActiveTabCloseButton();//是否添加关闭选项卡按钮

把某一页选项置顶

m_tab.SetActiveTab(1); //激活选项卡,以当前选项卡为第一页。

设置选项卡样式

 

    m_tab.ModifyTabStyle (style);//设置CMFCTabCtrl的样式

参数:
STYLE_3D
三维样式。
STYLE_3D_ONENOTE Microsoft OneNote样式。
STYLE_3D_VS2005 Microsoft Visual Studio 2005样式。
STYLE_3D_SCROLLED 三维与矩形选项卡标签的样式。
STYLE_FLAT_SHARED_HORZ_SCROLL 有共享水平滚动条的平面样式。
STYLE_3D_ROUNDED_SCROLL 三维与设置选项卡标签的样式。
 

 

标签拖拽

m_tab.EnableTabSwap (TRUE);//可以拖拽
m_tab.EnableTabSwap (FALSE);//不可拖拽

选项卡标签和边框颜色

    CArray<COLORREF, COLORREF> arColors;
    arColors.Add (RGB (121, 210, 231));
    arColors.Add (RGB (190, 218, 153));
    arColors.Add (RGB (255, 170, 100));

    m_tab.EnableAutoColor (TRUE);
    m_tab.SetAutoColors (arColors);

整个选项卡初始化代码

 

void CtabView::OnInitialUpdate()
{
    CFormView::OnInitialUpdate();
    GetParentFrame()->RecalcLayout();
    ResizeParentToFit();

    CRect rc;
    GetClientRect(rc);

    if (!m_tab.Create(CMFCTabCtrl::STYLE_3D_ONENOTE, rc, this, 3000, CMFCTabCtrl::LOCATION_TOP,0))
    {
        return ;     
    }

    m_dlg1=new CDialog1;
    m_dlg2=new CDialog2;
    m_dlg3=new CDialog3;

    m_dlg1->Create(IDD_DIALOG1,&m_tab);
    m_dlg1->SetFont(&afxGlobalData.fontRegular);
    m_dlg1->SetWindowTextW(L"Listctrl控件");

    m_dlg2->Create(IDD_DIALOG2,&m_tab);
    m_dlg2->SetFont(&afxGlobalData.fontBold);
    m_dlg2->SetWindowTextW(L"还没想好些什么控件");

    m_dlg3->Create(IDD_DIALOG3,&m_tab);
    m_dlg3->SetFont(&afxGlobalData.fontDefaultGUIBold);
    m_dlg3->SetWindowTextW(L"还有什么控件比较难写吗");





    m_imglist.Create(32, 32, ILC_COLOR32 | ILC_MASK, 3, 1);
    m_imglist.Add(AfxGetApp()->LoadIcon(IDI_ICON1));
    m_imglist.Add(AfxGetApp()->LoadIcon(IDI_ICON2));
    m_imglist.Add(AfxGetApp()->LoadIcon(IDI_ICON4));
    m_tab.SetImageList(m_imglist);



    m_tab.AddTab(m_dlg1,L"Listctrl控件",0,TRUE);
    m_tab.AddTab(m_dlg2,L"还没想好些什么控件",1,FALSE);
    m_tab.AddTab(m_dlg3,L"还有什么控件比较难写吗",2,FALSE);


    //m_tab.SetLocation (CMFCTabCtrl::LOCATION_BOTTOM);//Tab标签在底部
    m_tab.SetLocation (CMFCTabCtrl::LOCATION_TOP);//Tab标签在顶部

    m_tab.EnableActiveTabCloseButton();//是否添加关闭选项卡按钮

    m_tab.SetActiveTab(1); //激活选项卡,以当前选项卡为第一页。

    //m_tab.ModifyTabStyle (style);//设置CMFCTabCtrl的样式

    CArray<COLORREF, COLORREF> arColors;
    arColors.Add (RGB (121, 210, 231));
    arColors.Add (RGB (190, 218, 153));
    arColors.Add (RGB (255, 170, 100));

    m_tab.EnableAutoColor (TRUE);
    m_tab.SetAutoColors (arColors);

    m_tab.EnableTabSwap (TRUE);//可以拖拽
    //m_tab.EnableTabSwap (FALSE);//不可拖拽
}

 

 

 

 

阶段效果

技术分享图片

到现在还是觉得这个选项卡难看,咱们继续美化

首先每个窗口背景色太难看了,我们来把背景色换成白的

改变背景色有很多种方法,有OnCtlColor、OnPaint、 OnEraseBkgnd都可以改变背景色,这个现在不用太纠结选哪种,随便用一个就行,但是他们的添加方法都相同。

在每一个子窗口中添加消息函数WM_CTLCOLOR。实现方法返回一个系统自定义的白色画刷WHITE_BRUSH。

HBRUSH CDialog1::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);

    // TODO:  在此更改 DC 的任何特性

    // TODO:  如果默认的不是所需画笔,则返回另一个画笔
     return (HBRUSH)::GetStockObject(WHITE_BRUSH);
}

 

那么美化暂时先到这,要想画出更好看的选项卡,就需要涉及到控件重绘了,也就是自定义控件,这篇帖子我会持续更新的。马上我就要开下一篇功能实现的帖子。

 

代码:选项卡美化.zip 




以上是关于如何优雅的写UI——选项卡美化的主要内容,如果未能解决你的问题,请参考以下文章

如何优雅的写UI——选项卡功能实现

如何更优雅的写for循环

Android:如何在选项卡内从一个片段导航到另一个片段? [关闭]

删除选项卡时在 ActionBar 选项卡片段中运行代码

寻找 Java 代码美化器(或者可能不是美化,而是让代码更优雅的东西)[关闭]

Android:使用Tab检测单个片段viewpager