QQ分组控件的简单实现

QQ的上下拉的抽屉式控件估计已经深入民心了。课程设计作业需要,花了半天时间写了一个类似的控件,可以实现对每个抽屉按钮设置不同的视图控件,不过没有美化,只是有骨没有肉的控件。

 

//QQGroupCtrl.h文件

#pragma once #include <vector> using namespace std; // QQGroupCtrl #define GROUPCTRL_HIGHT 22 #define GROUPCTRL_INITBUTTONID 90000//分组按钮的id号,自增 //QQ分组按钮 class QQGroupButton : public CButton { DECLARE_DYNAMIC(QQGroupButton) public: QQGroupButton(); virtual ~QQGroupButton(); protected: DECLARE_MESSAGE_MAP() public: afx_msg void OnLButtonDown(UINT nFlags, CPoint point); }; //分组按钮信息,关联按钮和窗口 class TGroupInfo { public: TGroupInfo():m_szName(_T("")), m_pWnd(NULL){} virtual ~TGroupInfo(){} public: CString m_szName; // 组名称 CWnd *m_pWnd; // 组窗口指针 QQGroupButton *Button; //自己 }; //分组控件,包含N个分组 class QQGroupCtrl : public CWnd { DECLARE_DYNAMIC(QQGroupCtrl) public: QQGroupCtrl(); virtual ~QQGroupCtrl(); protected: DECLARE_MESSAGE_MAP() public: virtual BOOL Create(LPCTSTR lpszWindowName, DWORD dwStyle, const RECT &rect, CWnd *pParentWnd, UINT uID); bool AddOneGroup(TCHAR* szName, CWnd *pWnd = NULL); void ChangeView(QQGroupButton* selectButton); private: vector<TGroupInfo*> m_vecGroups;// 组信息列表 int m_iDown; // 当前鼠标按下的索引 CRect m_rtClient; // 客户区大小 int m_initBUttonID; //初始化按钮id };

  

//QQGroupCtrl.cpp文件

// QQGroupCtrl.cpp : 实现文件 // #include "stdafx.h" #include "CustomQQ.h" #include "QQGroupCtrl.h" #include "Mmsystem.h" // QQGroupButton IMPLEMENT_DYNAMIC(QQGroupButton, CButton) QQGroupButton::QQGroupButton() { } QQGroupButton::~QQGroupButton() { } BEGIN_MESSAGE_MAP(QQGroupButton, CButton) ON_WM_LBUTTONDOWN() END_MESSAGE_MAP() void QQGroupButton::OnLButtonDown(UINT nFlags, CPoint point) { QQGroupCtrl* parent=(QQGroupCtrl*)this->GetParent(); parent->ChangeView(this);//分组按钮 CButton::OnLButtonDown(nFlags,point); } ////////////////////////////////////////////////////////////////////////// // QQGroupCtrl IMPLEMENT_DYNAMIC(QQGroupCtrl, CWnd) QQGroupCtrl::QQGroupCtrl() { m_initBUttonID=GROUPCTRL_INITBUTTONID; m_iDown=0;//选中的分组索引 } //析构 QQGroupCtrl::~QQGroupCtrl() { vector <TGroupInfo*>::iterator Iter=m_vecGroups.begin( ) ; while (Iter != m_vecGroups.end( )) { TGroupInfo* groupinfo=*Iter; if (groupinfo->Button) { delete groupinfo->Button; } if (groupinfo->m_pWnd) { delete groupinfo->m_pWnd; } Iter++ ; } } BEGIN_MESSAGE_MAP(QQGroupCtrl, CWnd) END_MESSAGE_MAP() BOOL QQGroupCtrl::Create(LPCTSTR lpszWindowName, DWORD dwStyle, const RECT &rect, CWnd *pParentWnd, UINT uID) { CWnd* pWnd = this; return pWnd->Create(NULL, lpszWindowName, dwStyle, rect, pParentWnd, uID); } bool QQGroupCtrl::AddOneGroup(TCHAR* szName, CWnd *pWnd) { TGroupInfo* ginfo=new TGroupInfo; ginfo->m_szName=CString(szName); ginfo->m_pWnd=pWnd; QQGroupButton* b=new QQGroupButton; CRect rect(0,0,0,0); b->Create(ginfo->m_szName,WS_CHILD|WS_VISIBLE,rect,this,m_initBUttonID); ginfo->Button=b; m_vecGroups.push_back(ginfo); //每加进一个组,重新计算面板的大小 CRect groupClient; GetClientRect(&groupClient); int index=0; int count=m_vecGroups.size();//总数 vector <TGroupInfo*>::iterator Iter; for ( Iter = m_vecGroups.begin( ) ; Iter != m_vecGroups.end( ) ; Iter++ ) { TGroupInfo* groupinfo=*Iter; //计算按钮的坐标 if (index==0) { CPoint leftPoint(0,0); CSize bsize(groupClient.Width(),GROUPCTRL_HIGHT); CRect rect(leftPoint,bsize); groupinfo->Button->MoveWindow(rect); } else { //从下往上数的高度是bottom-(count-index)*buttonHight CSize bsize(groupClient.Width(),GROUPCTRL_HIGHT); CPoint leftPoint(0,groupClient.bottom-(count-index)*GROUPCTRL_HIGHT); CRect rect(leftPoint,bsize); groupinfo->Button->MoveWindow(rect); } //计算按钮的所对应窗口的坐标,即传来的pwnd if (groupinfo->m_pWnd)//移动到按钮的下面 { CPoint leftPoint(0,index*GROUPCTRL_HIGHT+GROUPCTRL_HIGHT); CSize bsize(groupClient.Width(),groupClient.Height()-count*GROUPCTRL_HIGHT); CRect rect(leftPoint,bsize); groupinfo->m_pWnd->MoveWindow(rect); if (index==0) { groupinfo->m_pWnd->ShowWindow(SW_SHOW); } else { groupinfo->m_pWnd->ShowWindow(SW_HIDE); } } index++; m_initBUttonID++; } GetClientRect(&m_rtClient); return true; } void QQGroupCtrl::ChangeView(QQGroupButton* selectButton) { vector <TGroupInfo*>::iterator Iter; int selectIndex=0; BOOL bPtIn=FALSE;//鼠标是否点中按钮 int count=m_vecGroups.size(); //得到上一次按钮,隐藏上次的pwnd TGroupInfo* &lastinfo=m_vecGroups.at(m_iDown); if (lastinfo->m_pWnd) { lastinfo->m_pWnd->ShowWindow(SW_HIDE); } //得到选择索引 for ( Iter = m_vecGroups.begin( ) ; Iter != m_vecGroups.end( ) ; Iter++ ) { TGroupInfo* groupinfo=*Iter; if (selectButton==groupinfo->Button) { bPtIn=TRUE; break; } selectIndex++; } if (!bPtIn)//没有点中 { return ; } int i=0; for ( Iter = m_vecGroups.begin( ) ; Iter != m_vecGroups.end( ) ; Iter++ ) { TGroupInfo* groupinfo=*Iter; //所选择的分组以及其以上的所有分组,均上移 if (i<=selectIndex) { groupinfo->Button->MoveWindow(0,i*GROUPCTRL_HIGHT,m_rtClient.Width(),GROUPCTRL_HIGHT,TRUE); } //所选择的分组以下的分组下移,不包括自己 else { if (selectIndex+1<count) groupinfo->Button->MoveWindow(0,m_rtClient.bottom-(count-i)*GROUPCTRL_HIGHT,m_rtClient.Width(),GROUPCTRL_HIGHT,TRUE); } i++;//索引值 } //显示所选择的分组窗口 TGroupInfo* &currentInfo=m_vecGroups.at(selectIndex); if (currentInfo->m_pWnd) { currentInfo->m_pWnd->ShowWindow(SW_SHOW);//显示本次的pwnd } //保存选中的按钮索引 m_iDown=selectIndex; //UpdateWindow和Invalidate都不行,只能这样刷新了 ShowWindow(SW_HIDE); ShowWindow(SW_SHOW); } 

 

原理不太难,在AddOneGroup传来的视图控件位置,是根据按钮的多少事先来调整的。而你每次按分组控件时候,所按分组以及以上的分组全部上移,所按分组的下移部分全部下移。同时,先保存一个上次按钮的索引,来隐藏上次的视图,再显示新的所选索引的视图即可。

 

 

使用代码:

QQGroupCtrl* gCtrl=new QQGroupCtrl;
gCtrl->Create(L"group",WS_VISIBLE | WS_CHILD, rect, this, 10000);   
gCtrl->AddOneGroup(L"我的好友",NULL);
gCtrl->AddOneGroup(L"我的群组",NULL);
gCtrl->AddOneGroup(L"最近联系人",NULL);
gCtrl->AddOneGroup(L"自定义",NULL);

效果图

QQ分组控件的简单实现_第1张图片


你可能感兴趣的:(qq,vector,null,delete,iterator,Class)