花了一个礼拜时间,总算把这个代码啃完了,用的虚函数还是不太了解
使用方法:
void CQQList::SetImageLists(CImageList *pImagelist) 设置关联的图像列表控件
void CQQList::AddButton(LPCSTR BtnTitle, UINT8 uID) 添加一个分类按钮,参数 分类名称,ID
void CQQList::AddButtonItems(UINT uID, CString &name, int nImageIndex) 为分类按钮uID添加一个项目,指定名称和图标
CQQList::m_pItemDlbFun 设置回调函数,响应项目双击事件
ListButton.h QQList的分类按钮,内含一些具体项目
class CListButton :
public CButton
{
public:
CListButton(void);
~CListButton(void);
public:
UINT m_Index; //分类按钮的ID
BOOL m_Toped; //分类按钮的位置
CStringList m_Entities; //具体项目的名称
CStringList m_Image; //具体项目的图标
private:
const UINT GetHeight()const;
const UINT GetWidth()const;
public:
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
};
ListButton.cpp
#include "ListButton.h"
CListButton::CListButton(void)
: m_Index(0)
, m_Toped(FALSE)
{
}
CListButton::~CListButton(void)
{
}
const UINT CListButton::GetHeight()const
{
CRect rect;
GetClientRect(rect);
return rect.Height();
}
const UINT CListButton::GetWidth()const
{
CRect rect;
GetClientRect(rect);
return rect.Width();
}
void CListButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CRect rect;
GetClientRect(rect);
CDC dc;
dc.Attach(lpDrawItemStruct->hDC);
dc.SetBkMode(TRANSPARENT);
CBrush m_Brush(RGB(100,140,200));
dc.SelectObject(&m_Brush);
dc.DrawEdge(rect,BDR_RAISEDINNER|BDR_RAISEDOUTER
,BF_BOTTOMLEFT|BF_TOPRIGHT);
dc.Draw3dRect(rect,RGB(51,51,51),RGB(0,0,0));
CRect rc(rect);
rc.DeflateRect(2,2,2,2);
dc.FillRect(rc,&m_Brush);
CString str;
GetWindowText(str);
dc.SetTextColor(RGB(255,255,255));
dc.DrawText(str,CRect(0,0,rect.right,rect.bottom),
DT_CENTER|DT_VCENTER|DT_SINGLELINE);
}
QQList.h
typedef void(ItemDlbFun)(const CListCtrl *pListCtrl,int nItemIndex);
class CQQList :
public CListCtrl
{
public:
CQQList(void);
~CQQList(void);
public:
void SetImageLists(CImageList *pImageList); //设置项目关联的ImageList
void AddButton(LPCSTR Btext, UINT8 nID); //向List增加一个分类按钮
void AddButtonItems(UINT nIndex,CString &strItem,int mImageIdex); //向分类按钮增加一个项目
ItemDlbFun *m_pItemDlbFun; //外部的回调函数
public:
virtual void PreSubclassWindow(void);
BOOL PreTranslateMessage(MSG * pMsg); //截获双击事件,调用回调函数
virtual BOOL OnCmdMsg(UINT nID, int nCode, void * pExtra, AFX_CMDHANDLERINFO * pHandlerInfo);
private:
CListCtrl m_ClientList;
CPtrArray m_pButton;
UINT m_ButtonHeight;
UINT m_LeftMargin;
private:
UINT GetTopBtnsHeightSum(void);
UINT GetBtmBtnsHeightSum(void);
UINT GetFirstBtmIndex(void);
CRect GetNewButtonsRect(void);
CRect GetListClientRect();
void MoveDown(UINT bIndex);
void MoveUp(UINT bIndex);
UINT CommandToIndex(UINT nID);
void ShowButtonItems(UINT nIndex);
void OnButtonDown(UINT bIndex, UINT nID);
};
QQList.cpp
#include "QQList.h"
#include "ListButton.h"
CQQList::CQQList(void)
: m_ButtonHeight(25)
, m_LeftMargin(0)
, m_pItemDlbFun(NULL)
{
}
CQQList::~CQQList(void)
{
int m = m_pButton.GetSize();
for( int i=0;i<m_pButton.GetSize();i++ )
{
((CListButton *)m_pButton[i])->DestroyWindow();
delete((CListButton *)m_pButton[i]);
}
}
/************************************************************
虚函数
************************************************************/
void CQQList::PreSubclassWindow(void)
{
m_ClientList.Create(LVS_ICON,CRect(0,0,0,0),this,101);
m_ClientList.ShowWindow(SW_SHOW);
m_ClientList.SetExtendedStyle(LVS_EX_FLATSB);
m_ClientList.SetBkColor(RGB(255,255,255));
m_ClientList.SetTextBkColor(RGB(255,255,255));
m_ClientList.SetTextColor(RGB(0,0,255));
m_ClientList.Arrange(LVA_ALIGNLEFT);
CListCtrl::PreSubclassWindow();
}
BOOL CQQList::PreTranslateMessage(MSG * pMsg)
{
if((pMsg->hwnd==m_ClientList.m_hWnd)&&(pMsg->message==WM_LBUTTONDBLCLK))
{
int index;
index = m_ClientList.GetSelectionMark();
if (m_pItemDlbFun != NULL)
m_pItemDlbFun(&m_ClientList,index);
}
return CListCtrl::PreTranslateMessage(pMsg);
}
UINT CQQList::CommandToIndex(UINT nID)
{
for(int i = 0;i< m_pButton.GetSize();i++)
{
if(((CListButton*)m_pButton[i])->GetDlgCtrlID()==nID)
{
return ((CListButton*)m_pButton[i])->m_Index;
}
}
return -1;
}
BOOL CQQList::OnCmdMsg(UINT nID, int nCode, void * pExtra, AFX_CMDHANDLERINFO * pHandlerInfo)
{
int index = CommandToIndex(nID);
if(index != -1)
{
OnButtonDown(index,nID);
}
m_ClientList.OnCmdMsg(nID,nCode,pExtra,pHandlerInfo);
return CListCtrl::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}
/************************************************************
区域计算
************************************************************/
CRect CQQList::GetNewButtonsRect(void)
{
const int EXIST_BTN_NUM = m_pButton.GetSize();
int sumheight = 0;
int i = 0;
while( i<EXIST_BTN_NUM )
{
sumheight += ((CListButton*)m_pButton[i])->GetHeight();
i++;
}
CRect TotalRect;
GetClientRect(TotalRect);
return CRect(0,sumheight,TotalRect.Width(),sumheight+m_ButtonHeight);
}
UINT CQQList::GetTopBtnsHeightSum(void)
{
UINT result = 0;
for(int i = 0; i< m_pButton.GetSize();i++)
{
CListButton* aBtn = (CListButton*)m_pButton[i];
if(aBtn->m_Toped)
{
result += aBtn->GetHeight();
}
}
return result;
}
UINT CQQList::GetBtmBtnsHeightSum(void)
{
UINT result = 0;
for(int i = 0; i< m_pButton.GetSize();i++)
{
CListButton* aBtn = (CListButton*)m_pButton[i];
if (aBtn->m_Toped==FALSE)
{
result += aBtn->GetHeight();
}
}
return result;
}
CRect CQQList::GetListClientRect()
{
CRect TotalRect;
GetClientRect(TotalRect);
int TopHeight = GetTopBtnsHeightSum();
int BtmHeight = GetBtmBtnsHeightSum();
CRect ClientRect(0,TopHeight,TotalRect.Width(),TotalRect.Height()-BtmHeight);
return ClientRect;
}
/************************************************************
************************************************************/
UINT CQQList::GetFirstBtmIndex(void)
{
for(int i = 0; i<m_pButton.GetSize();i++)
{
if (((CListButton*)m_pButton[i])->m_Toped==FALSE)
return i;
}
return -1;
}
void CQQList::MoveDown(UINT bIndex)
{
UINT BtmOffset = m_pButton.GetSize()-1-bIndex;
CListButton* target = (CListButton*)m_pButton[bIndex];
CRect wholeRect;
GetClientRect(wholeRect);
CRect rect(
0,
wholeRect.bottom - (target->GetHeight())*(BtmOffset+1),
target->GetWidth(),
wholeRect.bottom - (target->GetHeight())*(BtmOffset)
);
target->MoveWindow(rect);
target->m_Toped = FALSE;
}
void CQQList::MoveUp(UINT bIndex)
{
CListButton* target = (CListButton*)m_pButton[bIndex];
CRect wholeRect;
GetClientRect(wholeRect);
CRect rect(
0,
wholeRect.top + (target->GetHeight())*(bIndex),
target->GetWidth(),
wholeRect.top + (target->GetHeight())*(bIndex+1)
);
target->MoveWindow(rect);
target->m_Toped = TRUE;
}
//显示第nIndex个按钮内的内容
void CQQList::ShowButtonItems(UINT nIndex)
{
m_ClientList.DeleteAllItems();
CRect showrect = GetListClientRect();
const UINT LEFT_MARGIN = showrect.Width()/2-20;
CListButton* temp = (CListButton*)m_pButton[nIndex];
if(temp->m_Entities.GetCount()>0)
{
int m = 0;
POSITION pos = temp->m_Entities.GetHeadPosition();
POSITION index = temp->m_Image.GetHeadPosition();
while( pos != NULL && index != NULL )
{
CString itemName = temp->m_Entities.GetNext(pos);
int itemId = atoi(temp->m_Image.GetNext(index));
m_ClientList.InsertItem(m,itemName,itemId);
m_ClientList.SetItemPosition(m,CPoint(LEFT_MARGIN,m*(48+5)));
m++;
};
}
}
void CQQList::OnButtonDown(UINT btnIdx, UINT nID)
{
if(m_pButton.GetSize()<2)
{
return;
}
CListButton* aBtn = (CListButton*)m_pButton[btnIdx];
if(aBtn->m_Toped)
{
int targetBtnIdx = m_pButton.GetSize()-1;
while( targetBtnIdx>btnIdx )
{
MoveDown(targetBtnIdx--);
}
}
else
{
int targetBtnIdx = GetFirstBtmIndex();
while( targetBtnIdx<=btnIdx )
{
MoveUp(targetBtnIdx++);
}
}
CRect rectclt = GetListClientRect();
m_ClientList.MoveWindow(rectclt);
ShowButtonItems(btnIdx);
}
/**************************************************
用户接口
**************************************************/
void CQQList::SetImageLists(CImageList *pImagelist)
{
if(pImagelist)
m_ClientList.SetImageList(pImagelist,LVSIL_NORMAL);
}
void CQQList::AddButton(LPCSTR BtnTitle, UINT8 uID)
{
CListButton *pBtn = new CListButton;
pBtn->Create(BtnTitle,WS_CHILD|BS_OWNERDRAW,GetNewButtonsRect(),this,uID);
pBtn->m_Index = m_pButton.GetSize();
pBtn->ShowWindow(SW_SHOW);
m_pButton.Add(pBtn);
}
void CQQList::AddButtonItems(UINT nIndex, CString &name, int nImageIdex)
{
CListButton* temp = (CListButton*)m_pButton[nIndex];
temp->m_Entities.AddTail(name);
CString strIndex;
strIndex.Format("%d",nImageIdex);
temp->m_Image.AddTail(strIndex);
}