clayui界面库系列教程之五:仿QQ2010风格的登录下拉框

预览图如下:

        

        


         例子工程下载


         这次的例子工程是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进行详细说明:


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


         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的鼠标移入,鼠标移出消息来实现动画效果


         提示:如果您对这里有疑问,请看:SetFrameFlags


         对下拉框的设置就完毕了,然后我们需要对加入的文字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来。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值