小7的大店铺【淘宝店】 游戏引擎剖析-全篇 公积金相关帖子汇总 魅族M8SDK学习系列不断更新中

[魅族M8] M8SDK学习之三控件使用

[ 7523 查看 / 6 回复 ]

通过UiList学习魅族控件的使用
拿到m8后最希望的就是能用手指操作的感觉,而m8sdk中提供的控件则是实现这些新鲜玩意的元素,通过使用m8sdk可以非常简单的实现一些像Iphone手机上的效果,比如用手指拖动列表,滑动效果及动画窗口效果等等等。看了大部分的的控件后,UiList是比较全面的,于是就从它入手,了解一些奥秒吧。
前面的学习中,已经可以创建窗口了,UiList当然也要放置在窗口上才能显示,所以第一步就是要创建一个应用程序及一个窗口。就直接使用sdk提供的例子进行学习,而且在这个Mzfc_sample_05例子中还可以学习到如何添加资源文件,如果显示模态窗体等技巧。
和前面的例子一样打开这个工程,要记得将图片等资源文件加入进来。直接编绎在模拟器中就可以看到效果了,拖动列表效果来咯。。。。。HOhO
于是我们先来看一下在本例子是如何调用UiList的,看代码:
  1. class CSample1MainWnd: public CMzWndEx
  2. {

  3. MZ_DECLARE_DYNAMIC(CSample1MainWnd);

  4. public:
  5.   UiToolbar_Text m_Toolbar;
  6.   // the list control
  7.   MyList m_List;
  8. ...
  9. }
复制代码

在上面的代码中我们可以看到MyList m_List,是的,而这个MyList并非是UiList,这是因为本例子中继承了UiList并创建了一个新的控件,于是我们找到MyList,看看它的代码:
  1. class MyList:public UiList
  2. {
  3. public:
  4.   // override the DrawItem member function to do your own drawing of the list
  5.   void DrawItem(HDC hdcDst, int nIndex, RECT* prcItem, RECT *prcWin, RECT *prcUpdate)
  6.   {
  7.     // draw the high-light background for the selected item
  8.     if (nIndex == GetSelectedIndex())
  9.     {
  10.       MzDrawSelectedBg(hdcDst, prcItem);
  11.     }

  12.     // draw an image on the left
  13.     ImagingHelper *pimg = ImagingHelper::GetImageObject(MzGetInstanceHandle(), IDR_PNG_SMS, true);
  14.     RECT rcImg = *prcItem;
  15.     rcImg.right = rcImg.left + MZM_MARGIN_MAX*2;
  16.     if (pimg)
  17.     {
  18.       pimg->Draw(hdcDst, &rcImg, false, false);
  19.     }
  20.     // draw the text
  21.     RECT rcText = *prcItem;
  22.     rcText.left = rcImg.right;
  23.     rcText.bottom = rcText.bottom - (rcText.bottom - rcText.top) / 2;

  24.     //draw the text2
  25.     RECT rcText2 = *prcItem;
  26.     rcText2.left = rcImg.right;
  27.     rcText2.top = rcText.bottom;
  28.     ListItem* pItem = GetItem(nIndex);
  29.     if (pItem)
  30.     {
  31.       MzDrawText(hdcDst, pItem->Text.C_Str(), &rcText, DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_END_ELLIPSIS);
  32.       MzDrawText(hdcDst, pItem->Text.C_Str(), &rcText2, DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_END_ELLIPSIS);
  33.     }

  34. }

  35. protected:
  36. private:
  37. };
复制代码


在这个类中第一行代码已经说明了MyList是继承于UiList的,于是我们看这个新的类做了什么修改?代码中只有在public中重写了DrawItem方法。
DrawItem方法中的注释说明了重写这个成员函数可以自定义显示子项目。这下明白了吧,通过这个DrawItem就可以想画什么就画什么上去?在看运行的效果时候发现了MyList的每个子项目都带有一个图标,字体都显示红色。那UiList本身会是什么样子呢?可以试验一下,将上面的代码进行一点点修改就可以看到UiList的效果,在DrawItem的方法第一行加入return;;呵呵,就是在代码一进入就跳出。运行一下看看吧,发现连文字都没了,没关系,这其实这和UiList直接运行的效果相关不大了,可以发现这种情况下在模拟器中操作比之前有了极大的改善,看来画画还是要花费很大地呀。

回到例子中的代码,开始是一个if语句,这一个结构中实现了MyList的选中项目画背景的效果,代码一看便知了,GetSelectedIndex就是获取选中项目的索引值,MzDrawSelectedBg就是画背景咯。


接下来的代码实现了画项目中图标的功能,ImagingHelper就是图片处理类,用它就可以实现图片的加载,看看它调用了ImagingHelper的GetImageObject方法,这个方法看名字就明白了,只不过里面的参数需要说明一下:

lMzGetInstanceHandle()

这是第一个参数,返回的是应用程序的句柄,也就是本例子运行时的进程实例句柄;


lIDR_PNG_SMS

这就是资源文件的索引值啦,可以在Resource.h文件中找到它的定义,而资源文件就存在xxx.rc文件中,在例子中有个mzfc_sample_05.rc文件中,可以查看一下,就能见到IDR_PNG_SMS的定义咯;


lTrue

这个参数偶也不太明白意思,只不过是跟图片处理有关。呵呵


接下来的代码中看到:RECT rcImg = *prcItem;这一句代码为变更rcImg获得了函数传入参数prcItem的值,RECT是个矩形类型,标出了一个矩形的上下左右坐标。而这个prcItem就是MyList的每一个项目Item的矩形了,因为DrawItem是画单独的项目的。

往下看rcImg.right = rcImg.left + MZM_MARGIN_MAX*2;这行代码可以看到调整了rcImg的右间距,看计算式子就明白了,就是计算一下图标显示在项目框中的宽度。

pimg->Draw(hdcDst, &rcImg, false, false);这句代码就是将图片画上去;


接下来的代码可能你会发现有红色标注的字样,这部分内容是我加上去的,在例子代码中没有。目的是想在原来基础上再显示一行字,到这里你应该明白了吧,其实在电脑屏幕上所有的东西都是画上去的,有时想想电脑真累。至于使用方法和显示图标类似,只不过这里换成了MzDrawText这个方法,函数名已经告诉我们了画文本。在修改代码时我只是修改了一下画文本的矩形就达到了目的。


控件已经完成了,需要将它显示在窗口上,见代码:
  1. // Then init the controls & other things in the window
  2. m_List.SetPos(0,0,GetWidth(),GetHeight()-MZM_HEIGHT_TEXT_TOOLBAR);
  3. m_List.SetID(MZ_IDC_LIST);
  4. m_List.EnableScrollBarV(true);
  5. m_List.EnableNotifyMessage(true);
  6. m_List.SetItemHeight(90);
  7. m_List.SetTextColor(RGB(255,0,0));
  8. AddUiWin(&m_List);
复制代码

这里就几个特别的方法:
lEnableScrollBarV:开启垂直卷动,就是用在屏幕上划动时列表会滑动的效果。
lEnableNotifyMessage;开启通知消息MZ_WM_MOUSE_NOTIFY。这个响应屏幕中的触摸消息。
lSetItemHeight:就是设置项目的显示高度
到这里已经完成了80%了,还有一步要做,就是响应MZ_WM_MOUSE_NOTIFY消息并处理,这个在其窗口容器中获取消息处理就行了,需要重写MzDefWndProc函数。
  1. // override the MZFC window messages handler
  2. LRESULT MzDefWndProc(UINT message, WPARAM wParam, LPARAM lParam)
  3. {
  4.   switch(message)
  5.   {
  6.   case MZ_WM_MOUSE_NOTIFY:
  7.     {
  8.       int nID = LOWORD(wParam);
  9.       int nNotify = HIWORD(wParam);
  10.       int x = LOWORD(lParam);
  11.       int y = HIWORD(lParam);
  12.       // process the mouse left button down notification
  13.       if (nID==MZ_IDC_LIST && nNotify==MZ_MN_LBUTTONDOWN)
  14.       {
  15.           if (!m_List.IsMouseDownAtScrolling() && !m_List.IsMouseMoved())
  16.           {
  17.             int nIndex = m_List.CalcIndexOfPos(x, y);
  18.             m_List.SetSelectedIndex(nIndex);
  19.             m_List.Invalidate();
  20.             m_List.Update();
  21.           }
  22.           return 0;
  23.       }
  24.       // process the mouse move notification
  25.       if (nID==MZ_IDC_LIST && nNotify==MZ_MN_MOUSEMOVE)
  26.       {
  27.           m_List.SetSelectedIndex(-1);
  28.           m_List.Invalidate();
  29.           m_List.Update();
  30.           return 0;
  31.         }
  32.     }
  33.     return 0;
  34. }
  35. return CMzWndEx::MzDefWndProc(message,wParam,lParam);
  36. }
复制代码


这个函数是魅族窗体处理消息的默认方法,在代码中可以看到专门有MZ_WM_MOUSE_NOTIFY的处理代码,这个处理中分两部分,一部分是处理点击消息,另一部分是处理移动消息。
通过对nNotify值判断就可以得出:
l
MZ_MN_LBUTTONDOWN
点击消息,在这个if结构里首先检查是否处于卷动状态,然后通过CalcIndexOfPos方法以计算当前点击的是哪一个项目,返回后SetSelectedIndex设置即可。然后调用界面重绘,这时会触发MyList的DrawItem方法,于是界面中就会为这个项目画上背景了。
l
MZ_MN_MOUSEMOVE
处理卷动效果,此时将选中的项目设置为-1,接着进行重绘,这样做的效果就是取消了选中项目的背景。
      在方法的最后一行中执行了return CMzWndEx::MzDefWndProc(message,wParam,lParam);这一句很重要,因为在这里重写了基类的MzDefWndProc方法用于处理MZ_WM_MOUSE_NOTIFY消息,但为了保证其他 的消息还能正常使用就必须调用基类的方法以继续响应其他消息的处理。
学习了UiList的使用,就可以了解到m8sdkwindows的部封装,明白了如何使用sdk来进行控件重绘和响应消息。



作者:5207
出处:http://www.mini188.com
本文版权归作者所有,欢迎转载请注明出处,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
本主题由 皇帝 5207 于 2009-7-4 11:50:18 执行 主题分类 操作
分享 转发
相信与不相信都是矛盾的.  5207宣!
欢迎您来到迷你论坛
TOP

受益良多哦,谢谢!
另我想想问问:如何改变ListItem中显示字体大小??比如像短信显示的列表一样,标题的字体大,内容的字体小???再次感谢
TOP

原帖由 fanxk_1979 于 2009-5-20 13:35:00 发表
受益良多哦,谢谢!
另我想想问问:如何改变ListItem中显示字体大小??比如像短信显示的列表一样,标题的字体大,内容的字体小???再次感谢


UiListe 有个SetTextSize()方法哟。。
相信与不相信都是矛盾的.  5207宣!
欢迎您来到迷你论坛
TOP

谢谢,但是这样list中所有的字体大小都是一样了,有没有可以单独设置item中标题和内容的字体的方法呢?标题和内容的字体大小不一样!
像短信的列表中显示的这个样子
TOP

原帖由 fanxk_1979 于 2009-5-20 22:36:00 发表
谢谢,但是这样list中所有的字体大小都是一样了,有没有可以单独设置item中标题和内容的字体的方法呢?标题和内容的字体大小不一样!
像短信的列表中显示的这个样子


MiniNote1.0公布的源代码中已经有了这个实现
源代码下载地下:
http://www.mini188.com/showtopic-1070.aspx
相信与不相信都是矛盾的.  5207宣!
欢迎您来到迷你论坛
TOP

再次阅读完毕。继续顶起。
TOP

楼主的帖子实在是写得太好了。文笔流畅,修辞得体,深得魏晋诸朝遗风,更将唐风宋骨发扬得入木三分,能在有生之年看见楼主的这个帖子。实在是我三生之幸啊。看完楼主的这个帖子之后,我竟感发生出一种无以名之的悲痛感——啊,这么好的帖子,如果将来我再也看不到了,那我该怎么办?那我该怎么办?直到我毫不犹豫的把楼主的这个帖子收藏了。我内心的那种激动才逐渐平复下来。可是我立刻想到,这么好的帖子,倘若别人看不到,那么不是浪费楼主的心血吗?经过痛苦的思想斗争,我终于下定决心,我要把这个帖子一直往上顶,往上顶到所有人都看到为止
TOP