使用UiList派生类实现复杂的列表控件
此示例展示以下控件的使用方法:
示例代码展示:
完整示例:
/************************************************************************/ /* * Copyright (C) Meizu Technology Corporation Zhuhai China * All rights reserved. * 中国珠海, 魅族科技有限公司, 版权所有. * * This file is a part of the Meizu Foundation Classes library. * Author: Lynn * Create on: 2009-8-12 */ /************************************************************************/ #include <Windows.h> #include <mzfc\MzString.h> #include <mzfc_inc.h> enum{ E_MYLISTITEM_TYPE_READ = 10, E_MYLISTITEM_TYPE_UNREAD, }; enum{ E_MYLIST_MODE_NORMAL = 0, E_MYLIST_MODE_DELETE, E_MYLIST_MODE_DELETE_PRESSED, E_MYLIST_MODE_SELECT }; class MyListItemData { public: CMzString m_stringTitle; // 项的主文本 CMzString m_stringDescription; // 项的描述文本 CMzString m_stringTime; // 项的时间文本 UINT m_itemType; // 项的类型属性 取值范围; E_MYLISTITEM_TYPE_READ等 bool m_isSelect; }; class UiMyList : public UiList { public: UiMyList(); ~UiMyList(); virtual void DrawItem(HDC hdcDst, int nIndex, RECT* prcItem, RECT *prcWin, RECT *prcUpdate); virtual void OnRemoveItem(int nIndex); virtual int OnLButtonUp(UINT fwKeys, int xPos, int yPos); virtual int OnTimer(UINT_PTR nIDEvent); void SetListMode(UINT mode); UINT GetListMode(); bool IsPointInDeleteRect(int index,int xPos,int yPos); private: UINT m_mode; ImageContainer m_imgContainer; };
#include "UiMyList.h" #include "resource.h" #define RECT_ICON_WIDTH 80 #define RECT_ARROW_ICON_LEFT 430 #define RECT_ARROW_ICON_WIDTH 50 #define RECT_DEL_BUTTON_LEFT 480-MZM_WIDTH_DELETE_BUTTON-MZM_MARGIN_SMALL #define RECT_DEL_BUTTON_TOP 16 #define RECT_DEL_BUTTON_WIDTH MZM_WIDTH_DELETE_BUTTON #define RECT_DEL_BUTTON_HEIGHT 60 #define RECT_TITLE_LEFT 80 #define RECT_TITLE_WIDTH 210 #define RECT_TITLE_TOP 6 #define RECT_TITLE_HEIGHT 28 #define RECT_TITLE_DEL_LEFT 20 #define RECT_TITLE_DEL_WIDTH 210 #define RECT_TITLE_DEL_TOP 10 #define RECT_TITLE_DEL_HEIGHT 30 #define RECT_CONTENT_LEFT 80 #define RECT_CONTENT_WIDTH 350 #define RECT_CONTENT_TOP 37 #define RECT_CONTENT_HEIGHT 57 #define RECT_CONTENT_DEL_LEFT 20 #define RECT_CONTENT_DEL_WIDTH 320 #define RECT_CONTENT_DEL_TOP 40 #define RECT_CONTENT_DEL_HEIGHT 57 #define RECT_TIME_LEFT 300 #define RECT_TIME_TOP RECT_TITLE_TOP #define RECT_TIME_WIDTH 160 #define RECT_TIME_WIDTH_SEL 130 #define RECT_TIME_HEIGHT RECT_TITLE_HEIGHT #define FONTSIZE_CONTENT 20 #define FONTSIZE_TITLE 24 #define FONTSIZE_DEL 22 #define FONTSIZE_TIME 18 #define COLOR_CONTENT RGB(120,120,120) #define COLOR_CONTENT_DEL RGB(255,255,255) #define COLOR_TITLE RGB(0,0,0) #define COLOR_TITLE_DEL RGB(255,255,255) #define COLOR_TIME RGB(120,142,153) #define COLOR_DELETE RGB(70,86,111) UiMyList::UiMyList() : m_mode(E_MYLIST_MODE_NORMAL) { } UiMyList::~UiMyList() { } void UiMyList::DrawItem(HDC hdcDst, int nIndex, RECT* prcItem, RECT *prcWin, RECT *prcUpdate) { ListItem* pItem = GetItem(nIndex); if (!pItem) { return; } MyListItemData* pItemData = reinterpret_cast<MyListItemData*>(pItem->Data); if (!pItemData) { return; } bool isDeleteItem = false; if (nIndex == GetSelectedIndex()) { if (m_mode == E_MYLIST_MODE_DELETE || m_mode == E_MYLIST_MODE_DELETE_PRESSED) { isDeleteItem = true; MzDrawDeleteItemBg(hdcDst, prcItem); } else if (m_mode == E_MYLIST_MODE_NORMAL) { MzDrawSelectedBg(hdcDst,prcItem); } } ImagingHelper* pImgLeft = NULL; switch(pItemData->m_itemType) { case E_MYLISTITEM_TYPE_READ: { pImgLeft = m_imgContainer.LoadImage(MzGetInstanceHandle(), IDR_PNG_READ, true); } break; case E_MYLISTITEM_TYPE_UNREAD: { pImgLeft = m_imgContainer.LoadImage(MzGetInstanceHandle(), IDR_PNG_UNREAD, true); } break; default: break; } RECT rcLeftIcon = *prcItem; rcLeftIcon.right = rcLeftIcon.left + RECT_ICON_WIDTH; if (pImgLeft && !isDeleteItem) { pImgLeft->Draw(hdcDst,&rcLeftIcon); } //计算中间文字区域大小 RECT rcTime = {RECT_TIME_LEFT, RECT_TIME_TOP, RECT_TIME_LEFT + RECT_TIME_WIDTH, RECT_TIME_TOP + RECT_TIME_HEIGHT}; RECT rcTitle = {RECT_TITLE_LEFT, RECT_TITLE_TOP, RECT_TITLE_LEFT + RECT_TITLE_WIDTH, RECT_TITLE_TOP + RECT_TITLE_HEIGHT}; RECT rcContent = {RECT_CONTENT_LEFT, RECT_CONTENT_TOP, RECT_CONTENT_LEFT + RECT_CONTENT_WIDTH, RECT_CONTENT_TOP + RECT_CONTENT_HEIGHT}; if (isDeleteItem) { rcTitle.left = RECT_TITLE_DEL_LEFT; rcTitle.top = RECT_TITLE_DEL_TOP; rcTitle.right = rcTitle.left + RECT_TITLE_DEL_WIDTH; rcTitle.bottom = rcTitle.top + RECT_TITLE_DEL_HEIGHT; rcContent.left = RECT_CONTENT_DEL_LEFT; rcContent.top = RECT_CONTENT_DEL_TOP; rcContent.right = rcContent.left + RECT_CONTENT_DEL_WIDTH; rcContent.bottom = rcContent.top + RECT_CONTENT_DEL_HEIGHT; } if (m_mode == E_MYLIST_MODE_SELECT) { rcTime.right = rcTime.left + RECT_TIME_WIDTH_SEL; } ::OffsetRect(&rcTitle,prcItem->left,prcItem->top); ::OffsetRect(&rcContent,prcItem->left,prcItem->top); ::OffsetRect(&rcTime,prcItem->left,prcItem->top); HFONT hFont = FontHelper::GetFont(FONTSIZE_TITLE,FW_HEAVY); HGDIOBJ hOld = ::SelectObject(hdcDst,hFont); ::SetTextColor(hdcDst, isDeleteItem? COLOR_TITLE_DEL:COLOR_TITLE); MzDrawText(hdcDst, pItemData->m_stringTitle.C_Str(), &rcTitle, DT_LEFT|DT_TOP|DT_SINGLELINE|DT_END_ELLIPSIS); hFont = FontHelper::GetFont(FONTSIZE_CONTENT); SelectObject(hdcDst,hFont); ::SetTextColor(hdcDst, isDeleteItem? COLOR_CONTENT_DEL:COLOR_CONTENT); MzDrawText(hdcDst, pItemData->m_stringDescription.C_Str(), &rcContent, DT_LEFT|DT_TOP|DT_WORDBREAK); if (!isDeleteItem) { hFont = FontHelper::GetFont(FONTSIZE_TIME); SelectObject(hdcDst,hFont); ::SetTextColor(hdcDst, COLOR_TIME); MzDrawText(hdcDst, pItemData->m_stringTime.C_Str(), &rcTime, DT_RIGHT|DT_SINGLELINE|DT_VCENTER); } if(isDeleteItem) { RECT rcDelete = { RECT_DEL_BUTTON_LEFT, RECT_DEL_BUTTON_TOP, RECT_DEL_BUTTON_LEFT + RECT_DEL_BUTTON_WIDTH, RECT_DEL_BUTTON_TOP + RECT_DEL_BUTTON_HEIGHT }; ::OffsetRect(&rcDelete,prcItem->left,prcItem->top); if (m_mode == E_MYLIST_MODE_DELETE) { MzDrawControl(hdcDst, &rcDelete, MZC_BUTTON_DELETE, MZCS_BUTTON_NORMAL); } else if (m_mode == E_MYLIST_MODE_DELETE_PRESSED) { MzDrawControl(hdcDst, &rcDelete, MZC_BUTTON_DELETE, MZCS_BUTTON_PRESSED); } ::SetTextColor(hdcDst, COLOR_DELETE); hFont = FontHelper::GetFont(FONTSIZE_DEL, FW_HEAVY); SelectObject(hdcDst, hFont); MzDrawText(hdcDst, MzLoadString(IDS_DELETE), &rcDelete, DT_VCENTER|DT_CENTER|DT_SINGLELINE); } else if (m_mode == E_MYLIST_MODE_SELECT) { RECT rcSelect = *prcItem; rcSelect.left += RECT_ARROW_ICON_LEFT; rcSelect.right = rcSelect.left + RECT_ARROW_ICON_WIDTH; MzDrawControl(hdcDst, &rcSelect, pItemData->m_isSelect?MZC_SELECTED:MZC_UNSELECTED, 0, 0); } else { RECT rcArrow = *prcItem; rcArrow.left += RECT_ARROW_ICON_LEFT; rcArrow.right = rcArrow.left + RECT_ARROW_ICON_WIDTH; MzDrawControl(hdcDst, &rcArrow, MZC_BUTTON_ARROW_RIGHT, nIndex == GetSelectedIndex() ? MZCS_BUTTON_PRESSED:MZCS_BUTTON_NORMAL, false); } ::SelectObject(hdcDst,hOld); } int UiMyList::OnLButtonUp(UINT fwKeys, int xPos, int yPos) { // 获得控件在鼠标放开前的一些鼠标的相关状态(在调用 UiLst::OnLButtonUp()) bool b1 = IsMouseDownAtScrolling(); bool b2 = IsMouseMoved(); int Ret = UiList::OnLButtonUp(fwKeys, xPos, yPos); if((!b1) && (!b2) && m_mode == E_MYLIST_MODE_SELECT) { // 计算鼠标所在位置的项的索引 int nIndex = CalcIndexOfPos(xPos, yPos); ListItem* pItem = GetItem(nIndex); if (pItem) { MyListItemData* pItemData = (MyListItemData*)(pItem->Data); if (pItemData) { bool bSelect = pItemData->m_isSelect; pItemData->m_isSelect = !bSelect; InvalidateItem(nIndex); Update(); } } } return Ret; } void UiMyList::OnRemoveItem(int nIndex) { int itemHeight = CalcItemHeight(nIndex); m_nDeleteItemTopPos = itemHeight; m_nDeleteItem = GetSelectedIndex(); SetTimer(GetManager()->GetParentWnd(),MZ_TIMER_ID_DELETE_ANIMATION+GetID(),50,NULL); ListItem* pItem = GetItem(nIndex); if (pItem) { MyListItemData* pItemData = (MyListItemData*)(pItem->Data); if(pItemData) delete pItemData; } } void UiMyList::SetListMode(UINT mode) { m_mode = mode; } UINT UiMyList::GetListMode() { return m_mode; } bool UiMyList::IsPointInDeleteRect(int index,int xPos,int yPos) { if (index <0 ) { return false; } POINT pt = {xPos,yPos}; RECT rcList = GetClientRect(); RECT rcItem; CalcItemRect(index,&rcList , &rcItem); RECT rcDel = { RECT_DEL_BUTTON_LEFT, RECT_DEL_BUTTON_TOP, RECT_DEL_BUTTON_WIDTH + RECT_DEL_BUTTON_LEFT, RECT_DEL_BUTTON_HEIGHT + RECT_DEL_BUTTON_TOP }; ::OffsetRect(&rcDel,rcItem.left,rcItem.top); CMzRect rc(rcDel); if (rc.PtInRect(pt)) return true; else return false; return false; } int UiMyList::OnTimer(UINT_PTR nIDEvent) { if (nIDEvent == MZ_TIMER_ID_DELETE_ANIMATION + GetID()) { if (m_nDeleteItemTopPos != 0) { /*m_deleteTopPos -= (m_deleteTopPos>>2);*/ m_nDeleteItemTopPos = (m_nDeleteItemTopPos*3)>>2; if (m_nDeleteItemTopPos < 2) { m_nDeleteItemTopPos = 0; m_nDeleteItem = -1; KillTimer(GetManager()->GetParentWnd(),MZ_TIMER_ID_DELETE_ANIMATION+GetID()); } Invalidate(); Update(); } } return UiList::OnTimer(nIDEvent); }
#pragma once // 包含MZFC库的头文件 #include <mzfc_inc.h> #include "C21_List_ComplexWnd.h" // 从CMzApp派生的应用程序类 class C21_List_ComplexApp: public CMzApp { public: C21_List_ComplexApp(void); ~C21_List_ComplexApp(void); // 应用程序的主窗口 C21_List_ComplexMainWnd m_MainWnd; // 初始化应用程序 virtual BOOL Init(); };
#include "C21_List_ComplexApp.h" C21_List_ComplexApp::C21_List_ComplexApp(void) { } C21_List_ComplexApp::~C21_List_ComplexApp(void) { } BOOL C21_List_ComplexApp::Init() { // 初始化COM CoInitializeEx(0, COINIT_MULTITHREADED); // 获得工作区 RECT rcWork = MzGetWorkArea(); // 创建主窗口 m_MainWnd.Create(rcWork.left,rcWork.top,RECT_WIDTH(rcWork),RECT_HEIGHT(rcWork), 0, 0, 0); m_MainWnd.Show(); // 初始化成功则返回TRUE. return TRUE; } // 全局的应用程序变量 C21_List_ComplexApp theApp;
/************************************************************************/ /* * Copyright (C) Meizu Technology Corporation Zhuhai China * All rights reserved. * 中国珠海, 魅族科技有限公司, 版权所有. * * This file is a part of the Meizu Foundation Classes library. * Author: Lynn * Create on: 2009-8-12 */ /************************************************************************/ #pragma once #include "UiMyList.h" // 从CMzWndEx派生的应用程序主窗口 class C21_List_ComplexMainWnd: public CMzWndEx { MZ_DECLARE_DYNAMIC(C21_List_ComplexMainWnd); public: C21_List_ComplexMainWnd(void); ~C21_List_ComplexMainWnd(void); // 窗口中的按钮 UiMyList m_list; UiToolbar_Text m_toolbar; protected: // 初始化主窗口 virtual BOOL OnInitDialog(); // 重载MZFC的命令处理函数 virtual void OnMzCommand(WPARAM wParam, LPARAM lParam); LRESULT C21_List_ComplexMainWnd::MzDefWndProc(UINT message, WPARAM wParam, LPARAM lParam); };
#include "C21_List_ComplexWnd.h" #include "resource.h" // 按钮控件的ID #define MZ_IDC_LIST 101 #define MZ_IDC_TOOLBAR 102 MZ_IMPLEMENT_DYNAMIC(C21_List_ComplexMainWnd) C21_List_ComplexMainWnd::C21_List_ComplexMainWnd(void) { } C21_List_ComplexMainWnd::~C21_List_ComplexMainWnd(void) { } BOOL C21_List_ComplexMainWnd::OnInitDialog() { // 必须先调用父类的初始化 if (!CMzWndEx::OnInitDialog()) { return FALSE; } // 初始化窗口中的控件 m_toolbar.SetPos(0,GetHeight()-MZM_HEIGHT_TEXT_TOOLBAR,GetWidth(),MZM_HEIGHT_TEXT_TOOLBAR); m_toolbar.SetButton(0, true, true, L"Exit"); m_toolbar.SetButton(2, true, true, L"Select"); m_toolbar.SetID(MZ_IDC_TOOLBAR); AddUiWin(&m_toolbar); 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)); m_list.EnableDragModeH(true); AddUiWin(&m_list); // 往列表控件添加项 wchar_t *bufTitle = L"Title %d"; wchar_t *bufDescription = L"Description %d"; ListItem li; for (int i=0;i<50;i++) { CMzString strTitle(256); CMzString strDescription(256); wsprintf(strTitle.C_Str(), bufTitle, i); wsprintf(strDescription.C_Str(), bufDescription, i); // 设置列表项的自定义数据 MyListItemData *pmlid = new MyListItemData; pmlid->m_stringTitle = strTitle; pmlid->m_stringDescription = strDescription; if (i%5 == 0) { pmlid->m_stringTime = L"2008/8/8 20:08"; pmlid->m_itemType = E_MYLISTITEM_TYPE_UNREAD; } else { pmlid->m_stringTime = L"2008/8/8"; pmlid->m_itemType = E_MYLISTITEM_TYPE_READ; } // 列表项的自定义数据指针设置到ListItem::Data li.Data = pmlid; m_list.AddItem(li); } return TRUE; } void C21_List_ComplexMainWnd::OnMzCommand( WPARAM wParam, LPARAM lParam ) { UINT_PTR id = LOWORD(wParam); switch(id) { case MZ_IDC_TOOLBAR: // 点击了按钮控件 { int index = lParam; switch(index) { case 0: { CMzString test = m_toolbar.GetButtonText(0); if (wcscmp(m_toolbar.GetButtonText(0).C_Str(),MzLoadString(IDS_EXIT).C_Str()) == 0) { PostQuitMessage(0); return; } else if(wcscmp(m_toolbar.GetButtonText(0).C_Str(),MzLoadString(IDS_DELETE).C_Str()) == 0) { for (int i = 0; i <m_list.GetItemCount();) { ListItem* pItem = m_list.GetItem(i); if (pItem) { MyListItemData* pItemData = (MyListItemData*) (pItem->Data); if (pItemData && pItemData->m_isSelect) { m_list.RemoveItem(i); } else { i++; } } } m_list.Invalidate(); m_list.Update(); } } break; case 2: { if (wcscmp(m_toolbar.GetButtonText(2).C_Str(),MzLoadString(IDS_SELECT).C_Str()) == 0) { m_toolbar.SetButtonText(0,MzLoadString(IDS_DELETE)); m_toolbar.SetButtonText(2,MzLoadString(IDS_DONE)); m_list.SetListMode(E_MYLIST_MODE_SELECT); m_list.SetSelectedIndex(-1); Invalidate(); UpdateWindow(); } else if(wcscmp(m_toolbar.GetButtonText(2).C_Str(),MzLoadString(IDS_DONE).C_Str()) == 0) { m_toolbar.SetButtonText(0,MzLoadString(IDS_EXIT)); m_toolbar.SetButtonText(2,MzLoadString(IDS_SELECT)); m_list.SetListMode(E_MYLIST_MODE_NORMAL); Invalidate(); UpdateWindow(); } } break; default: break; } } break; } } LRESULT C21_List_ComplexMainWnd::MzDefWndProc(UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { case MZ_WM_LIST_ITEM_DRAG_H: if (wParam == MZ_IDC_LIST) { int nIndex = m_list.CalcIndexOfPos(LOWORD(lParam), HIWORD(lParam)); int nItemCount = m_list.GetItemCount(); if (nIndex >= 0 && nIndex < nItemCount) { m_list.SetSelectedIndex(nIndex); m_list.SetListMode(E_MYLIST_MODE_DELETE); m_list.Invalidate(); m_list.Update(); } } break; case MZ_WM_MOUSE_NOTIFY: { if (LOWORD(wParam) == MZ_IDC_LIST) { int type = HIWORD(wParam); int xPos = LOWORD(lParam); int yPos = HIWORD(lParam); int nIndex = m_list.CalcIndexOfPos(xPos, yPos); switch(type) { case MZ_MN_LBUTTONDOWN: { if (m_list.GetListMode() == E_MYLIST_MODE_NORMAL) { if (!m_list.IsMouseDownAtScrolling()) { m_list.SetSelectedIndex(nIndex); m_list.Invalidate(); m_list.Update(); } } else if (m_list.GetListMode() == E_MYLIST_MODE_DELETE || m_list.GetListMode() == E_MYLIST_MODE_DELETE_PRESSED) { if (m_list.IsPointInDeleteRect(m_list.GetSelectedIndex(),xPos,yPos)) { m_list.SetListMode(E_MYLIST_MODE_DELETE_PRESSED); } else { m_list.SetSelectedIndex(-1); m_list.SetListMode(E_MYLIST_MODE_NORMAL); } m_list.Invalidate(); m_list.Update(); } } break; case MZ_MN_LBUTTONUP: { if (m_list.GetListMode() == E_MYLIST_MODE_DELETE_PRESSED) { //删除项 m_list.RemoveItem(nIndex); m_list.SetListMode(E_MYLIST_MODE_NORMAL); m_list.SetSelectedIndex(-1); m_list.Invalidate(); m_list.Update(); } } break; case MZ_MN_MOUSEMOVE: { if (m_list.GetListMode() == E_MYLIST_MODE_NORMAL) { m_list.SetSelectedIndex(-1); m_list.SetListMode(E_MYLIST_MODE_NORMAL); m_list.Invalidate(); m_list.Update(); } } break; } } } break; } return CMzWndEx::MzDefWndProc(message,wParam,lParam); }