预览图如下:

        

        


 

         例子工程下载


 

         这次的例子工程是CLAYUIEXP2,与以前的苹果风格按钮 是一个工程,所以在本教程里,关于初始化之类的就不详细解说了,有疑问的请查看本博客内的其他教程


         好的,教程开始了。


         首先,在MFC对话框里添加一个对下拉框初始化的函数:CreateComboBox,在里面,我们对下拉框进行初始化:


         CMyComboBox* combo = new CMyComboBox();
         combo->Init(m_mainframe, m_graphics.m_draw, 0);
         combo->SetLayout(1, 0, "combobox");
         m_mainframe->AddCustomFrame(0, "comboBox", 50, 0, 200, 24, 100, combo);


 

         combo->SetItemsDepth(2);
         combo->SetListHeight(350);


 

         combo->AddMyText(L"小强\n123456", swfitem1);
         combo->AddMyText(L"张三\n123457", swfitem1);
         combo->AddMyText(L"李四\n123458", swfitem1);
         combo->AddMyText(L"王五\n123459", swfitem1);


 

         这里创建了一个combobox,并设置了item的深度,下拉框的高度,添加了4行文字


 

         当然,这么几行代码是不可能实现QQ下拉框的效果的,为了实现自定义的效果,还必须做一个自定义的下拉框控件,所以,这里可以看到,有一个新类:CMyComboBox,这个是自定义的一个下拉框控件类,派生自CLAYUI_ComboBox


 

         下面,我们来对 CMyComboBox进行详细说明:


 

         首先是初始化,重载oadFromMem这个函数,然后添加以下代码:


         m_sys_listbox->GetChildFrame("_SYS_SELRECT_")->SetColorTrans(0, 100, 100, 100, 0, 0, 0, 0);
         m_sys_listbox->GetChildFrame("_SYS_MOUSEINRECT_")->SetColorTrans(0, 100, 100, 100, 0, 0, 0, 0);


 

         先把下拉框里原先的动画元素设为透明,也就是屏蔽掉


         m_sys_listbox->SetFrameFlags(CLAYUI_FS_SENDMSG_RULE_CSES, 1);


 

         然后,设置listbox的消息转发模式为:转发子FRAME的基本消息。这一句很重要,如果不设置,那么comboBox将接收不到下拉框里所有ITEM的消息。我们需要ITEM的鼠标移入,鼠标移出消息来实现动画效果


 

         对下拉框的设置就完毕了,然后我们需要对加入的文字item设置自定义的风格,这里添加一个函数:AddMyText,代码如下:


 

         AddString(string);


 

         先加入文字ITEM


 

         CLAYUI_TTEXT* item = dynamic_cast<CLAYUI_TTEXT*>(GetItem(GetCount() - 1));


 

         得到刚加入的ITEM对象


 

         int textoffset = 35;
         float height;
         m_sys_listbox->GetFrameSize(m_itemwidth, height);
         m_itemwidth += 80;
         item->SetFrameSize(m_itemwidth, m_itemheight);
         item->SetTextColor(0, 255, 0, 255);


 

         将ITEM的大小设置为自定义的大小,这里,我们设置的最终宽度,高度分别为:280, 60;然后设置文字颜色为绿色


 

         item->SetClip(1, m_itemheight + textoffset, 0, m_itemwidth - m_itemheight - textoffset, m_itemheight);


 

         设置文字的裁减矩形,让文字显示在ITEM的(95,0)处。


 

         item->SetTextAlignType(0, 1);


 

         设置文字的对齐方式为左对齐,行居中。


 

         CLAYUI_FRAME_ITEM* fi = GetItem(GetCount() - 1)->AddFrameItem(gitem, NULL, 1, 1, 0, 1, 1, 1);
         fi->SetSkinInfo(1, 0, "button");
         fi->UpdateSkin();


 

         这里,我们先加入一个皮肤对象,然后使用 SetSkinInfo将皮肤替换为皮肤库里的皮肤“button",然后把皮肤更新一下


 

         CLAYUI_GetGItemWH(fi->m_gItem, gw, gh);
         fi->FixToFrameSize(1, gw + 2, gh + 2);
         fi->SetColorTrans(100, 100, 100, 100, 0, -128, -128, 128);


 

         得到皮肤里的图形对象的高宽,然后将皮肤的大小同ITEM的高宽绑定,这样一来,当ITEM的高宽发生改变时,皮肤也会随之而变;然后设置皮肤的颜色为蓝色



         FixToFrameSize函数的说明:


 

         short bfix:是否绑定


 

         int x, int y:当皮肤缩放系数为(1,1)时,对应的frame的高宽

 

 

         CLAYUI_GetGItemWH(gitem, gw, gh);
         fi = GetItem(GetCount() - 1)->AddFrameItem(gitem, NULL, 3, 2, 0, 1, 1, 1);
         fi->FixToFrameSize(1, gw * m_itemwidth / m_itemheight + 6, gh + 8);


 

         将头像也作为ITEM的皮肤加入,同样也是设置与ITEM的高宽绑定。在这里,每个ITEM有2个皮肤对象,一个是蓝色背景,一个是头像


         对ITEM的自定义风格就设置完毕了,那么,接下来,再来设置动画效果,在这里,我们需要对ITEM的鼠标移入,鼠标移出消息进行处理,消息的处理需要重载UserAction函数,代码如下:


         CLAYUI_FRAME* listitem = msginfo->GetFrame(this);


 

         得到消息来源


         if(listitem && listitem->GetParent() == m_sys_listbox && listitem->GetFrameID() >= CLAYUI_LISTBOXITEM_FRAMEID)
        

         判断是否是ITEM发来的消息,判断是否满足如下2个条件:


         1. 消息来源的父FRAME是m_sys_listbox

         2. 消息来源的frameid大于等于CLAYUI_LISTBOXITEM_FRAMEID


         提示:所有加入到LISTBOX里的ITEM的FRAMEID都大于等于 CLAYUI_LISTBOXITEM_FRAMEID


 

         if(msg == CLAYUI_ONMOUSEIN)


 

         判断是否是鼠标移入,在QQ2010的登录下拉框里,鼠标移动到某个ITEM时,此ITEM会放大,并且此ITEM的前一个ITEM也会放大,但会比当前 ITEM小,比其他ITEM大,此ITEM的下一个ITEM也是如此,了解了这个原理后,我们也如法炮制:


         listitem = msginfo->GetFrame(this);
         DWORD animid = (DWORD)listitem;
         char animidname[12];
         sprintf(animidname, "%d", animid);
         SetAnimation(animidname, listitem, m_itemwidth * scaleft, m_itemheight * scaleft, duration);


 

         将当前ITEM的高宽放大到原本的1.6 倍


         这里用item的指针值作为了动画对象的idname,是为了防止重名


 

         int index = GetItemIndex(listitem);
         listitem = GetItem(index - 1);
         if(listitem)
         {
             animid = (DWORD)listitem;
             sprintf(animidname, "%d", animid);
             SetAnimation(animidname, listitem, m_itemwidth * scaleft12, m_itemheight * scaleft12, duration);
         }


 

         将前一个ITEM的高宽放大到原本的1.2倍


         listitem = GetItem(index + 1);
         if(listitem)
         {
             animid = (DWORD)listitem;
             sprintf(animidname, "%d", animid);
             SetAnimation(animidname, listitem, m_itemwidth * scaleft12, m_itemheight * scaleft12, duration);
         }


 

         将下一个ITEM的高宽放大到原本的1.2倍


         然后处理鼠标移出的动画,当鼠标移出时,将发送消息的ITEM,前一个ITEM,后一个ITEM的高宽还原就行了,具体代码这里就不贴了,与上面类似。


         现在,当鼠标移入,鼠标移出时,ITEM的高宽都会发生变化,那么,现在有一个问题,当ITEM高宽发生变化时,他们的坐标并没有改变,那么就会发生ITEM覆盖其他ITEM的现象,为了避免这一现象,我们必须每桢去修正一个ITEM的Y坐标

         需要重载Update函数,代码如下:

         CLAYUI_ComboBox::Update();


         先调用父类的Update,让动画对象处理完毕后,我们再来修正ITEM的Y坐标

         int count = m_sys_listbox->GetCount();

         if(count > 0 && GetListState())


         得到ITEM个数,判断下拉框是否处于弹出状态

         int i;
         CLAYUI_FRAME* item = m_sys_listbox->GetItem(0);
         float x, y;
         item->GetTrans(x, y);
         float w, h;
         item->GetFrameSize(w, h);
         float scalex, scaley;
         item->GetScale(scalex, scaley);


         得到第一个ITEM的坐标,高宽,缩放值

         for(i = 1; i < count; i ++)
         {
             m_sys_listbox->GetItem(i)->MoveTo(x, y + h * scaley - 1);
             item = m_sys_listbox->GetItem(i);
             item->GetTrans(x, y);
             item->GetFrameSize(w, h);
             item->GetScale(scalex, scaley);
         }


         从第2个ITEM开始,循环到最后一个ITEM,修正ITEM的坐标。

         好的,这次的教程就结束了,大家可以尝试在CMyComboBox里做一些修改,做出属于自己的CMyComboBox来。


作者: clayui 发表于 2011-05-31 17:27 原文链接

推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架
新浪微博粉丝精灵,刷粉丝、刷评论、刷转发、企业商家微博营销必备工具"