通过UiList学习魅族控件的使用拿到m8后最希望的就是能用手指操作的感觉,而m8sdk中提供的控件则是实现这些新鲜玩意的元素,通过使用m8sdk可以非常简单的实现一些像Iphone手机上的效果,比如用手指拖动列表,滑动效果及动画窗口效果等等等。看了大部分的的控件后,UiList是比较全面的,于是就从它入手,了解一些奥秒吧。前面的学习中,已经可以创建窗口了,UiList当然也要放置在窗口上才能显示,所以第一步就是要创建一个应用程序及一个窗口。就直接使用sdk提供的例子进行学习,而且在这个Mzfc_sample_05例子中还可以学习到如何添加资源文件,如果显示模态窗体等技巧。和前面的例子一样打开这个工程,要记得将图片等资源文件加入进来。直接编绎在模拟器中就可以看到效果了,拖动列表效果来咯。。。。。HOhO。于是我们先来看一下在本例子是如何调用UiList的,看代码:- class CSample1MainWnd: public CMzWndEx
- {
- MZ_DECLARE_DYNAMIC(CSample1MainWnd);
- public:
- UiToolbar_Text m_Toolbar;
- // the list control
- MyList m_List;
- ...
- }
复制代码 在上面的代码中我们可以看到MyList m_List,是的,而这个MyList并非是UiList,这是因为本例子中继承了UiList并创建了一个新的控件,于是我们找到MyList,看看它的代码:- class MyList:public UiList
- {
- public:
- // override the DrawItem member function to do your own drawing of the list
- void DrawItem(HDC hdcDst, int nIndex, RECT* prcItem, RECT *prcWin, RECT *prcUpdate)
- {
- // draw the high-light background for the selected item
- if (nIndex == GetSelectedIndex())
- {
- MzDrawSelectedBg(hdcDst, prcItem);
- }
- // draw an image on the left
- ImagingHelper *pimg = ImagingHelper::GetImageObject(MzGetInstanceHandle(), IDR_PNG_SMS, true);
- RECT rcImg = *prcItem;
- rcImg.right = rcImg.left + MZM_MARGIN_MAX*2;
- if (pimg)
- {
- pimg->Draw(hdcDst, &rcImg, false, false);
- }
- // draw the text
- RECT rcText = *prcItem;
- rcText.left = rcImg.right;
- rcText.bottom = rcText.bottom - (rcText.bottom - rcText.top) / 2;
- //draw the text2
- RECT rcText2 = *prcItem;
- rcText2.left = rcImg.right;
- rcText2.top = rcText.bottom;
- ListItem* pItem = GetItem(nIndex);
- if (pItem)
- {
- MzDrawText(hdcDst, pItem->Text.C_Str(), &rcText, DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_END_ELLIPSIS);
- MzDrawText(hdcDst, pItem->Text.C_Str(), &rcText2, DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_END_ELLIPSIS);
- }
- }
- protected:
- private:
- };
复制代码 在这个类中第一行代码已经说明了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这个方法,函数名已经告诉我们了画文本。在修改代码时我只是修改了一下画文本的矩形就达到了目的。
控件已经完成了,需要将它显示在窗口上,见代码:- // Then init the controls & other things in the window
- m_List.SetPos(0,0,GetWidth(),GetHeight()-MZM_HEIGHT_TEXT_TOOLBAR);
- m_List.SetID(MZ_IDC_LIST);
- m_List.EnableScrollBarV(true);
- m_List.EnableNotifyMessage(true);
- m_List.SetItemHeight(90);
- m_List.SetTextColor(RGB(255,0,0));
- AddUiWin(&m_List);
复制代码 这里就几个特别的方法:lEnableScrollBarV:开启垂直卷动,就是用在屏幕上划动时列表会滑动的效果。lEnableNotifyMessage;开启通知消息MZ_WM_MOUSE_NOTIFY。这个响应屏幕中的触摸消息。lSetItemHeight:就是设置项目的显示高度到这里已经完成了80%了,还有一步要做,就是响应MZ_WM_MOUSE_NOTIFY消息并处理,这个在其窗口容器中获取消息处理就行了,需要重写MzDefWndProc函数。- // override the MZFC window messages handler
- LRESULT MzDefWndProc(UINT message, WPARAM wParam, LPARAM lParam)
- {
- switch(message)
- {
- case MZ_WM_MOUSE_NOTIFY:
- {
- int nID = LOWORD(wParam);
- int nNotify = HIWORD(wParam);
- int x = LOWORD(lParam);
- int y = HIWORD(lParam);
- // process the mouse left button down notification
- if (nID==MZ_IDC_LIST && nNotify==MZ_MN_LBUTTONDOWN)
- {
- if (!m_List.IsMouseDownAtScrolling() && !m_List.IsMouseMoved())
- {
- int nIndex = m_List.CalcIndexOfPos(x, y);
- m_List.SetSelectedIndex(nIndex);
- m_List.Invalidate();
- m_List.Update();
- }
- return 0;
- }
- // process the mouse move notification
- if (nID==MZ_IDC_LIST && nNotify==MZ_MN_MOUSEMOVE)
- {
- m_List.SetSelectedIndex(-1);
- m_List.Invalidate();
- m_List.Update();
- return 0;
- }
- }
- return 0;
- }
- return CMzWndEx::MzDefWndProc(message,wParam,lParam);
- }
复制代码 这个函数是魅族窗体处理消息的默认方法,在代码中可以看到专门有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的使用,就可以了解到m8sdk对windows的部封装,明白了如何使用sdk来进行控件重绘和响应消息。