对ListCtrl - button的修改

从别处下了个“ListCtrl-Button”Demo发现总体不错,但有一些小问题,如:


1、Button列不在可视区域时
2、改变列宽时(拖动或双击)
3、滚动时
4、删除时

改后代码如下:

ListCtrlEx.h

代码
/********************************************************************
*     Project  : NetMonitor
*     FileName : ListCtrlEx.h
*     Change   :     
*     Brief    :      
*     Author   : Chen Jun ( chenjun@3cis.com.cn )
*     Copyright ( c ) 2007-2008 3cis 
*     All Right Reserved
********************************************************************
*/

#if !defined( AFX_LISTCTRLEX_H__3D2C6B4A_4031_48EF_8162_492882D99D43__INCLUDED_ )
#define AFX_LISTCTRLEX_H__3D2C6B4A_4031_48EF_8162_492882D99D43__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif  // _MSC_VER > 1000

#include 
"ButtonEx.h"
#include 
<map>
using namespace std;

typedef map
<int,CButtonEx*>button_map;


/************************************************************************/
/* 
* this CListCtrlEx class inherits from ListCtrl
* it display the terminal list and record interrelated infomation
*/ 
/************************************************************************/
class CListCtrlEx : public CListCtrl
{
// 
public:
    CListCtrlEx();

// 
public:

// 
public:

// 
    
// ClassWizard 
    
//{{AFX_VIRTUAL( CListCtrlEx )
    
//}}AFX_VIRTUAL

// 
public:

    
virtual ~CListCtrlEx();

    
// 
protected:
    
//{{AFX_MSG( CListCtrlEx )
        
//

    
//}}AFX_MSG

    DECLARE_MESSAGE_MAP()

public:
    
void createItemButton( int nItem, int nSubItem, LPCTSTR txt,HWND hMain );
    
void release();
    
void deleteItemEx( int nItem );
    button_map m_mButton;

public:
    afx_msg 
void OnLvnEndScroll(NMHDR *pNMHDR, LRESULT *pResult);
public:
//    afx_msg void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct);
public:
    
//afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
    UINT m_uID;
    
void updateListCtrlButtonPos();
    
void enableButton( BOOL bFlag, int iItem );
//    afx_msg void OnPaint();
    
//afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
    afx_msg void OnHdnEndtrack(NMHDR *pNMHDR, LRESULT *pResult);
    
virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/);
protected:
    
virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ 

#endif  // !defined( AFX_LISTCTRLEX_H__3D2C6B4A_4031_48EF_8162_492882D99D43__INCLUDED_ )


ListCtrlEx.CPP

代码
/********************************************************************
*     Project  : NetMonitor
*     FileName : ListCtrlEx.h
*     Change   :     
*     Brief    :      
*     Author   : Chen Jun ( chenjun@3cis.com.cn )
*     Copyright ( c ) 2007-2008 3cis 
*     All Right Reserved
********************************************************************
*/

#include 
"stdafx.h"
#include 
"ListCtrl-Button.h"
#include 
"ListCtrlEx.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif 

#define IDC_BUTTON_ID 0x1235

/////////////////////////////////////////////////////////////////////////////
// CListCtrlEx



CListCtrlEx::CListCtrlEx()
{
    m_uID 
= IDC_BUTTON_ID;
}



CListCtrlEx::
~CListCtrlEx()
{
    
}



BEGIN_MESSAGE_MAP( CListCtrlEx, CListCtrl )
    
//{{AFX_MSG_MAP( CListCtrlEx )        
        
    
//}}AFX_MSG_MAP
    ON_NOTIFY_REFLECT(LVN_ENDSCROLL, &CListCtrlEx::OnLvnEndScroll)
    ON_NOTIFY(HDN_ENDTRACKA, 
0&CListCtrlEx::OnHdnEndtrack)
    ON_NOTIFY(HDN_ENDTRACKW, 
0&CListCtrlEx::OnHdnEndtrack)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CListCtrlEx 儊僢僙乕僕 僴儞僪儔

void CListCtrlEx::createItemButton( int nItem, int nSubItem,  LPCTSTR txt,HWND hMain )
{
    CRect rcTop;
    CRect rcBottom;
    CRect rect;
    CRect rcClient;
    
int buttonHeight = 0;

    
// Make sure that the item is visible
    if!EnsureVisible(nItem, TRUE)) 
        
return ;

    GetSubItemRect(nItem, nSubItem, LVIR_BOUNDS, rect);
    GetClientRect(rcClient);

    
// Now scroll if we need to expose the column
    
    CSize size;
    size.cx 
= 0;
    size.cy 
= 0;
    buttonHeight 
= rect.Height();
    
int nTopIndex,nRowCountPerPage;
    nTopIndex 
= GetTopIndex();
    nRowCountPerPage 
= GetCountPerPage();

    GetSubItemRect(nTopIndex, nSubItem, LVIR_BOUNDS, rcTop);
    GetSubItemRect(nTopIndex, nSubItem, LVIR_BOUNDS, rcBottom);
    rcBottom.OffsetRect(
0,rcTop.Height()*(nRowCountPerPage-2));

    size.cx 
= rect.right - rcClient.right;// + rect.left;
    size.cy = rect.bottom - rcBottom.bottom;
    Scroll(size);

    rect.top 
-= size.cy;
    rect.bottom  
= rect.top+buttonHeight;
    rect.left 
-= size.cx;    
    rect.right 
= rect.left + GetColumnWidth(nSubItem);


    rect.bottom 
= rect.top + rect.Height();

    
int iPageCout = GetCountPerPage();
    
if ( nItem >= iPageCout )
    {
        rect.top 
+= rect.Height();
        rect.bottom 
+= rect.Height();
    }

    DWORD dwStyle 
=  WS_CHILD | WS_VISIBLE;
    CButtonEx 
*pButton = new CButtonEx(nItem,nSubItem,rect,hMain);
    m_uID
++;
    pButton
->Create(txt,dwStyle, rect, this, m_uID);
    m_mButton.insert( make_pair( nItem, pButton ) );

    size.cx
*=-1;
    size.cy
*=-1;
    Scroll(size);
    
if ( nTopIndex > 0 )
    {
        updateListCtrlButtonPos();
    }
    
    
return;
}

void CListCtrlEx::release()
{
    button_map::iterator iter;
    iter 
= m_mButton.begin();
    
while ( iter != m_mButton.end() )
    {
        delete iter
->second;
        iter
->second = NULL;
        iter
++;
    }

}
void CListCtrlEx::deleteItemEx( int nItem )
{
    
int iCount = GetItemCount();
    DeleteItem( nItem );
    button_map::iterator iter;
    button_map::iterator iterNext;
    CButtonEx
* pBtn =NULL;
    iter 
= m_mButton.find( nItem);
    
if ( iter != m_mButton.end() )
    {
        pBtn 
= iter->second;
        delete pBtn;
        iter
->second = NULL;
        iterNext 
= iter;
        iterNext
++;
        
while(iterNext != m_mButton.end())
        {
            iter
->second = iterNext->second;
            iter
->second->m_inItem--;
            iter
++;
            iterNext
++;
        }
        m_mButton.erase( iter );
        updateListCtrlButtonPos();
    }
}
void CListCtrlEx::OnLvnEndScroll(NMHDR *pNMHDR, LRESULT *pResult)
{
    
// 偙偺婡擻偼 Internet Explorer 5.5 偐偦傟埲崀偺僶乕僕儑儞傪昁梫偲偟傑偡丅
    
// 僔儞儃儖 _WIN32_IE 偼 >= 0x0560 偵側傜側偗傟偽側傝傑偣傫丅
    LPNMLVSCROLL pStateChanged = reinterpret_cast<LPNMLVSCROLL>(pNMHDR);
    
// TODO: 偙偙偵僐儞僩儘乕儖捠抦僴儞僪儔 僐乕僪傪捛壛偟傑偡丅
    updateListCtrlButtonPos();
    
*pResult = 0;
}


void CListCtrlEx::updateListCtrlButtonPos()
{
    
int iTopIndex = GetTopIndex();
    
int iLastIndex = iTopIndex + GetCountPerPage();

    
int nItem = iTopIndex;
    button_map::iterator iter;
    button_map::iterator iterUp;
    
int iLine = 0;

    CRect rect;
    
int offset = 0;
    
int nColumnWidth = 0;
    
    
    
// Now scroll if we need to expose the column
    CRect rcClient;
    CRect subItemRect;
    CSize size;
    size.cx 
= 0;
    size.cy 
= 0;
    
    GetClientRect(rcClient);
    CRect rcTop;
    CRect rcBottom;
    


    iter 
= m_mButton.find(0);
    iterUp 
= m_mButton.begin();
    
if(iter != m_mButton.end() )
    {
        GetSubItemRect(iTopIndex,iterUp
->second->m_inSubItem,LVIR_BOUNDS, subItemRect);
        nColumnWidth 
= GetColumnWidth(iterUp->second->m_inSubItem);
        offset 
= subItemRect.right - rcClient.right;

        GetSubItemRect(iTopIndex, iterUp
->second->m_inSubItem, LVIR_BOUNDS, rcTop);
        GetSubItemRect(iTopIndex, iterUp
->second->m_inSubItem, LVIR_BOUNDS, rcBottom);
        rcBottom.OffsetRect(
0,rcTop.Height()*(GetCountPerPage()-2));
    }
    
    
    
while ( iter != m_mButton.end() )
    {
        iter
->second->EnableWindow( iter->second->bEnable );
        
if(iter->second->m_inItem>=iTopIndex&&iter->second->m_inItem<=iLastIndex)
        {
            GetSubItemRect(iter
->second->m_inItem,iter->second->m_inSubItem,LVIR_BOUNDS, subItemRect);
            
if(((subItemRect.left>=rcClient.left&&subItemRect.left<rcClient.right)
                
||(subItemRect.right<=rcClient.right&&subItemRect.right>rcClient.left))
                )
            {
                subItemRect.right 
= subItemRect.left+nColumnWidth;
                iter
->second->ShowWindow(SW_SHOW);
                iter
->second->MoveWindow(subItemRect);
            }
            
else
            {
                iter
->second->ShowWindow(SW_HIDE);
            }
        }
        
else
        {
            iter
->second->ShowWindow(SW_HIDE);
        }
        iter 
++;
        iterUp
++;
    }
    InvalidateRect(rcClient);


}

void CListCtrlEx::enableButton( BOOL bFlag, int iItem )
{
    button_map::iterator iter;

    
int iTopIndex = GetTopIndex();
    
int nItem = iItem - iTopIndex;
    iter 
= m_mButton.find( iItem );
    
if ( iter != m_mButton.end() )
    {
        iter
->second->bEnable = bFlag;
    }
    iter 
= m_mButton.find( nItem );
    
if ( iter != m_mButton.end() )
    {
        iter
->second->EnableWindow( bFlag );
    }
}


void CListCtrlEx::OnHdnEndtrack(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMHEADER phdr 
= reinterpret_cast<LPNMHEADER>(pNMHDR);
    
// TODO: 在此添加控件通知处理程序代码
    *pResult = 0;
    SetColumnWidth(phdr
->iItem,phdr->pitem->cxy);
    updateListCtrlButtonPos();
}

void CListCtrlEx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    
// TODO:  添加您的代码以绘制指定项
    CListCtrl::DrawItem(lpDrawItemStruct);
}


BOOL CListCtrlEx::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT
* pResult)
{
    
// TODO: 在此添加专用代码和/或调用基类

    NMHDR
* pNMHdr = (NMHDR*) lParam; 
    
    BOOL bResult 
= CListCtrl::OnNotify(wParam, lParam, pResult);
    
if (pNMHdr->code == HDN_ITEMCHANGEDA||pNMHdr->code == HDN_ITEMCHANGEDW)
    {
        
// 结束双击列分隔符
        HD_NOTIFY* phdn = (HD_NOTIFY*) pNMHdr;
        
int nWidth = GetColumnWidth(phdn->iItem);

        updateListCtrlButtonPos();
    }
    
return bResult;
}


到目前为此暂时还没发现别的问题

 

posted @ 2010-11-06 23:28  吾非无心  阅读(1061)  评论(1编辑  收藏  举报