본문으로 바로가기

ColorListCtrl(리스트 컨트롤색상) 소스

category 개발언어/c++ 2016. 7. 16. 19:34

coloredlistctrl.zip



 

// Author: SFr frydaysoft@gmx.de

 

#include "stdafx.h"

#include "ColorListCtrl.h"

 

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

 

 

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

// CColorListCtrl

 

CColorListCtrl::CColorListCtrl(int colSize)

{

m_columnSize=colSize; // number of columns

m_fullColumnLines=TRUE; // paint vert. lines | | |

m_withSingleRect=FALSE; // paint single rect for all sub-items

#ifdef _DEBUG

m_BigFocusRect=TRUE; // focus-rect with small/big dots

#endif

#ifndef _DEBUG

m_BigFocusRect=FALSE; // focus-rect with small/big dots

#endif

IsCreated=FALSE;

}

 

//***************************************************************

CColorListCtrl::~CColorListCtrl()

{

}

 

//***************************************************************

BEGIN_MESSAGE_MAP(CColorListCtrl, CListCtrl)

    //{{AFX_MSG_MAP(CColorListCtrl)

    ON_WM_PAINT()

    ON_WM_DESTROY()

    ON_WM_KILLFOCUS()

    ON_WM_SETFOCUS()

    ON_WM_SIZE()

    //}}AFX_MSG_MAP

END_MESSAGE_MAP()

 

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

// Behandlungsroutinen f? Nachrichten CColorListCtrl

void CColorListCtrl::OnDestroy()

{

    DeleteAllItems();    

    CListCtrl::OnDestroy();

}

 

//***************************************************************

void CColorListCtrl::SetColumnType(BOOL bNew)

{

m_fullColumnLines=bNew; // paint no/vert. lines | | |

if (IsCreated)

{

RedrawWindow();

}

}

void CColorListCtrl::SetRectType(BOOL bNew)

{

m_withSingleRect=bNew; // paint no/single rect for all sub-items

if (IsCreated)

{

RedrawWindow();

}

}

void CColorListCtrl::SetFocusType(BOOL bNew)

{

m_BigFocusRect=bNew; // focus-rect with small/big dots

if (IsCreated)

{

RedrawWindow();

}

}

 

//***************************************************************

CMyLParam*    CColorListCtrl::GetMyLParam(int Index)

{

LVITEM    Item;

    Item.mask        = LVIF_PARAM;

    Item.iItem        = Index;

    Item.iSubItem    = 0;

    CListCtrl::GetItem(&Item);

    return (CMyLParam*)Item.lParam;

}

 

//***************************************************************

CRect CColorListCtrl::GetFullCellRect(int nItem, BOOL outside)

{

    static CRect rectCell;

CListCtrl::GetItemRect(nItem, rectCell, LVIR_BOUNDS);

if (!outside)

{ //decrease 1 pixel

rectCell.left++; rectCell.right--;

rectCell.top++; rectCell.bottom--;

}

    return rectCell;

}

 

//***************************************************************

CRect CColorListCtrl::GetCellRect(int nItem, int nColumn, BOOL outside)

{

    static CRect rectCell;

 

    // Get the height

CListCtrl::GetItemRect(nItem, rectCell, LVIR_BOUNDS);

LV_COLUMN column;

    column.mask = LVCF_WIDTH; // Set the mask to only return the width

 

for (int x=0; x<nColumn; x++)

{

column.iSubItem=1;

CListCtrl::GetColumn(x, &column); // Get rect-edge (left/top)

rectCell.left+=column.cx;

}

column.iSubItem=1;

CListCtrl::GetColumn(nColumn, &column); // Get rect-edge (right/bottom)

rectCell.right = rectCell.left + column.cx;

 

if (!outside)

{ //decrease 1 pixel

rectCell.left++; rectCell.right--;

rectCell.top++; rectCell.bottom--;

}

    return rectCell;

}

 

//***************************************************************

void CColorListCtrl::InvalidateFullItem(int nItem, BOOL bErase)

{

CRect rcBounds=GetFullCellRect(nItem, TRUE);

    InvalidateRect(rcBounds, bErase);

 

}

 

//***************************************************************

// create ListCtrl-head

int CColorListCtrl::InitCtrl(CStringArray *phead, CByteArray *pProcent)

{

if ( (!phead)||(!pProcent)) return 1;

    LV_COLUMN lvc;

    int cx=0;

int count = phead->GetSize();

if (count!=m_columnSize) return 2;

if (pProcent->GetSize() != count) return 3;

for (int x=0; x<count; x++) cx+=pProcent->GetAt(x);

if (cx!=100) return 4;

 

    CRect rect_listbox;

 

    lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;

    GetWindowRect( rect_listbox );

    cx=int((rect_listbox.right-rect_listbox.left)-20); //some Pixel for Scrollbar

 

//set head-columns in ListBox

    lvc.iSubItem = 0;

    lvc.fmt = LVCFMT_LEFT ;        

    

for (x=0; x<count; x++)

{

lvc.cx = int(cx*pProcent->GetAt(x)/100);

     lvc.pszText = (char*)LPCSTR(phead->GetAt(x));

     CListCtrl::InsertColumn(x,&lvc);

}

return 0;

}

 

 

//***************************************************************

// add an item

int CColorListCtrl::AddItem(CStringArray *line, int pos)

{

int ret_index=LISTCTRL_ERROR;

if (!line) return ret_index;

 

    LV_ITEM lvi;

 

    //set List-properties

    lvi.mask = LVIF_TEXT ;

    lvi.iSubItem = 0;

lvi.pszText = "";

 

int count=GetItemCount();

int columns=line->GetSize();

 

if (m_columnSize!=columns) return ret_index;

 

if (DWORD(pos)<=DWORD(count)) count=pos;

      

lvi.iItem = count;

//lvi.lParam= count;

    lvi.mask = LVIF_TEXT ;

    lvi.iSubItem = 0; //refer to no Item

// insert an new line

ret_index=InsertItem(&lvi);

// set item text for additional columns        

for (int x=0; x<columns; x++)

{

CListCtrl::SetItemText(count,x,(char*)LPCSTR(line->GetAt(x)) );

}

    lvi.mask = LVIF_STATE;

    lvi.iSubItem = 1;

    lvi.stateMask = 0xFFFFFFFF ;

    lvi.state = 0;

 

    if (CListCtrl::SetItem(&lvi))

{

CMyLParam *p=new CMyLParam(m_columnSize); //init with: DEF_BACKGROUND, def_text

 

#ifdef TESTCOLOR

// only for TEST

if (ret_index<3)

{

p->SetBackColor(ITEM_COLOR(ret_index+BLUE),0);

p->SetTextColor(ITEM_COLOR(ret_index+RED ),0);

}

else

if (ret_index<=6)

{

p->SetBackColor(ITEM_COLOR(ret_index+BLUE),1);

p->SetTextColor(ITEM_COLOR(ret_index+RED ),1);

}

else

{

p->SetBackColor(ITEM_COLOR((ret_index+BLUE)&0xF),2);

p->SetTextColor(ITEM_COLOR((ret_index+RED )&0xF),2);

}

// end: only for TEST

#endif

 

CListCtrl::SetItemData( ret_index, DWORD(p) );

return ret_index;

}

return LISTCTRL_ERROR;

}

 

//***************************************************************

BOOL CColorListCtrl::DeleteAllItems()

{

    while (CListCtrl::GetItemCount())

CColorListCtrl::DeleteItem(0);

 

return TRUE;

}

 

//***************************************************************

BOOL CColorListCtrl::DeleteItem(int nItem )

{

if (CListCtrl::GetItemCount()<=nItem) return FALSE;

CMyLParam *p=(CMyLParam*)CListCtrl::GetItemData(nItem);

if (p)

{

CListCtrl::SetItemData( nItem, p->GetData() );

delete p;

return CListCtrl::DeleteItem( nItem );

}

return TRUE;

}

 

 

//***************************************************************

DWORD CColorListCtrl::GetItemData( int nItem ) const

{

CMyLParam *p=(CMyLParam*)CListCtrl::GetItemData(nItem);

if (p)

{

return p->GetData();

return TRUE;

}

return 0;

}

 

//***************************************************************

BOOL CColorListCtrl::SetItemData( int nItem, DWORD dwData )

{

CMyLParam *p=(CMyLParam*)CListCtrl::GetItemData(nItem);

if (p)

{

p->SetData(dwData);

return TRUE;

}

return FALSE;

}

 

//***************************************************************

BOOL CColorListCtrl::SetItemBackgndColor(ITEM_COLOR color, int Index, int iSub)    

{

CMyLParam *p=GetMyLParam(Index);

if (!p) return FALSE;

if ( p->SetBackColor(color, iSub) )

{

RedrawItems( Index, Index );

return TRUE;

}

return FALSE;

}

 

//***************************************************************

BOOL CColorListCtrl::SetItemTextColor(ITEM_COLOR color, int Index, int iSub)    

{

CMyLParam *p=GetMyLParam(Index);

if (!p) return FALSE;

if ( p->SetTextColor(color, iSub) )

{

RedrawItems( Index, Index );

return TRUE;

}

return FALSE;

}

 

//***************************************************************

COLORREF CColorListCtrl::GetItemBackgndColor(int Index, int iSub)

{

CMyLParam *p=GetMyLParam(Index);

if (!p) return 0;

return p->GetBackColor(iSub);

}

 

//***************************************************************

COLORREF CColorListCtrl::GetItemTextColor(int Index, int iSub)

{

CMyLParam *p=GetMyLParam(Index);

if (!p) return 0;

return p->GetTextColor(iSub);

}

 

//***************************************************************

void CColorListCtrl::OnPaint()

{

    // First let the control do its default drawing.

    const MSG *msg = GetCurrentMessage();

    DefWindowProc( msg->message, msg->wParam, msg->lParam );

 

if (!m_fullColumnLines) return;

 

    // Draw the lines only for LVS_REPORT mode

    if( (GetStyle() & LVS_TYPEMASK) == LVS_REPORT )

    {

        // Get the number of columns

        CClientDC dc(this );

        CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);

        int nColumnCount = pHeader->GetItemCount();

 

        // The bottom of the header corresponds to the top of the line

        RECT rect;

        pHeader->GetClientRect( &rect );

        int top = rect.bottom;

 

        // Now get the client rect so we know the line length and

        // when to stop

        GetClientRect( &rect );

 

        // The border of the column is offset by the horz scroll

        int borderx = 0 - GetScrollPos( SB_HORZ );

 

CPen *pOldPen;

CPen pen;

CGdiObject *pOldBrush;

pen.CreatePen( PS_DOT, 0, GetColorRef(DEF_DESELTEXT) );

pOldPen =dc.SelectObject(&pen);

pOldBrush=dc.SelectStockObject(NULL_BRUSH);

 

        for( int i = 0; i < nColumnCount; i++ )

        {

            // Get the next border

            borderx += GetColumnWidth( i );

 

            // if next border is outside client area, break out

            if( borderx >= rect.right ) break;

 

            // Draw the line.

            dc.MoveTo( borderx-1, top);

            dc.LineTo( borderx-1, rect.bottom );

        }

dc.SelectObject(pOldPen);

dc.SelectObject(pOldBrush);

 

    }

    // Do not call CListCtrl::OnPaint() for painting messages

}

 

//***************************************************************

void CColorListCtrl::RepaintSelectedItems()

{

    // Invalidate focused item so it can repaint

    int nItem = GetNextItem(-1, LVNI_FOCUSED);

 

    if(nItem != -1)

    {

InvalidateFullItem(nItem, FALSE);

    }

 

    // Invalidate selected items depending on LVS_SHOWSELALWAYS

    if((GetStyle() & LVS_SHOWSELALWAYS))

    {

        for(nItem = GetNextItem(-1, LVNI_SELECTED);

            nItem != -1; nItem = GetNextItem(nItem, LVNI_SELECTED))

        {

InvalidateFullItem(nItem, FALSE);

        }

    }

    UpdateWindow();

}

 

//***************************************************************

BOOL CColorListCtrl::SetSel(int pos, BOOL bSelect)

{

// LVS_ES_FULLROWSELECT only works with newer version of Comctl32

// This style and some of the other new extended styles

// only work with version 4.72 (or higer) of COMCTL32.DLL

 

UINT nState=0;

if (bSelect) nState=LVIS_SELECTED|LVS_EX_FULLROWSELECT; else nState=0;

if (SetItemState(pos, nState, LVIS_SELECTED|LVS_EX_FULLROWSELECT))

{

if((GetStyle() & LVS_SHOWSELALWAYS))

{

InvalidateFullItem(pos, TRUE);

}

return TRUE;

}

return FALSE;

}

//***************************************************************

void CColorListCtrl::OnKillFocus(CWnd* pNewWnd)

{

    SendMessage(WM_PAINT);

CListCtrl::OnKillFocus(pNewWnd);

    // check if we are losing focus

    if(pNewWnd != NULL && pNewWnd->GetParent() == this)

        return;

 

    // repaint items that should change appearance

    if((GetStyle() & LVS_TYPEMASK) == LVS_REPORT)

        RepaintSelectedItems();

}

 

//***************************************************************

void CColorListCtrl::OnSetFocus(CWnd* pOldWnd)

{

    CListCtrl::OnSetFocus(pOldWnd);

    

    // check if we are getting focus

    if(pOldWnd!=NULL && pOldWnd->GetParent()==this)

        return;

 

    // repaint items that should change appearance

    if((GetStyle() & LVS_TYPEMASK)==LVS_REPORT)

        RepaintSelectedItems();

}

 

//***************************************************************

void CColorListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)

{

if (!lpDrawItemStruct) return;

IsCreated=TRUE;

    CDC*        pDC            = CDC::FromHandle(lpDrawItemStruct->hDC);

    CMyLParam*    pMyLParam    = GetMyLParam(lpDrawItemStruct->itemID);

    CRect        rcItem;

 

if (!pMyLParam) return;

int x=0;

typedef enum {R_NOTHINGS=0, R_FOCUS, R_SELECT, R_NORMAL, R_SEL_NOFOCUS} redrawmode;

redrawmode redraw=R_NORMAL;

 

    // Get item image and state info

    LV_ITEM lvi;

    lvi.mask = LVIF_IMAGE | LVIF_STATE;

    lvi.iItem = lpDrawItemStruct->itemID;

    lvi.iSubItem = 0;

    lvi.stateMask = 0xFFFF;        // get all state flags

    GetItem(&lvi);

 

    BOOL bHighlight = ( (lvi.state & LVIS_DROPHILITED)

||

                 (

(lvi.state & LVIS_SELECTED)

&&

( ( GetFocus() == this ) || ( GetStyle() & LVS_SHOWSELALWAYS ) )

                     )

                 );

 

BOOL bLostFocus=(GetFocus()!=this);

 

 

if ( (lpDrawItemStruct->itemAction&ODA_FOCUS)==ODA_FOCUS)

{ //the control gains or loses input focus

if (bLostFocus) redraw=R_SEL_NOFOCUS;

else

if ((lvi.state&LVIS_FOCUSED)==LVIS_FOCUSED) redraw=R_FOCUS;

else

{

if (bHighlight) redraw=R_SELECT;

else redraw=R_NORMAL;

}

}

else

if ((lpDrawItemStruct->itemAction&ODA_SELECT)==ODA_SELECT)

{ //the selection status has changed

if (bHighlight)

{

if (bLostFocus) redraw=R_SEL_NOFOCUS;

else redraw=R_SELECT;

}

else redraw=R_NORMAL;

}

else

{ //redraw the item

if (bLostFocus)

{

if (bHighlight) redraw=R_SEL_NOFOCUS;

else

redraw=R_NORMAL;

}

else

{

if ((lvi.state&LVIS_FOCUSED)==LVIS_FOCUSED) redraw=R_FOCUS;

else

{

if (bHighlight) redraw=R_SELECT;

else redraw=R_NORMAL;

}

}

}

 

CPen *pOldPen;

CPen pen;

CGdiObject *pOldBrush;

 

switch(redraw)

{

 

case R_FOCUS:

rcItem=GetFullCellRect(lpDrawItemStruct->itemID, TRUE);

pDC->FillSolidRect(rcItem, GetColorRef(DEF_SELBACKGROUND));

pDC->SetTextColor(GetColorRef(DEF_SELTEXT));

if (m_BigFocusRect)

{

pen.CreatePen( PS_DOT, 0, GetColorRef(DEF_SELTEXT) );

pOldPen =pDC->SelectObject(&pen);

pOldBrush=pDC->SelectStockObject(NULL_BRUSH);

pDC->Rectangle(rcItem);

pDC->SelectObject(pOldPen);

pDC->SelectObject(pOldBrush);

}

else pDC->DrawFocusRect(rcItem);

for (x=0; x<m_columnSize; x++)

{

rcItem    = GetCellRect(lpDrawItemStruct->itemID, x, FALSE);

pDC->DrawText(CListCtrl::GetItemText(lpDrawItemStruct->itemID,x), rcItem, DT_SINGLELINE | DT_LEFT | DT_VCENTER );

}

break;

case R_SELECT:

rcItem=GetFullCellRect(lpDrawItemStruct->itemID, TRUE);

pDC->FillSolidRect(rcItem, GetColorRef(DEF_SELBACKGROUND));

pDC->SetTextColor(GetColorRef(DEF_SELTEXT));

for (x=0; x<m_columnSize; x++)

{

rcItem    = GetCellRect(lpDrawItemStruct->itemID, x, FALSE);

pDC->DrawText(CListCtrl::GetItemText(lpDrawItemStruct->itemID,x), rcItem, DT_SINGLELINE | DT_LEFT | DT_VCENTER);

}

break;

case R_SEL_NOFOCUS:

rcItem=GetFullCellRect(lpDrawItemStruct->itemID, TRUE);

pDC->FillSolidRect(rcItem, GetColorRef(DEF_DESELBACKGROUND));

pDC->SetTextColor(pMyLParam->GetTextColor(DEF_DESELTEXT));

pen.CreatePen( PS_DOT, 0, GetColorRef(DEF_DESELBACKGROUND) );

pOldPen =pDC->SelectObject(&pen);

pOldBrush=pDC->SelectStockObject(NULL_BRUSH);

if (!m_withSingleRect)

pDC->Rectangle(rcItem);

for (x=0; x<m_columnSize; x++)

{

rcItem    = GetCellRect(lpDrawItemStruct->itemID, x, FALSE);

pDC->DrawText(CListCtrl::GetItemText(lpDrawItemStruct->itemID,x), rcItem, DT_SINGLELINE | DT_LEFT | DT_VCENTER);

}

pDC->SelectObject(pOldPen);

pDC->SelectObject(pOldBrush);

break;

case R_NORMAL:

for (x=0; x<m_columnSize; x++)

{

     rcItem    = GetCellRect(lpDrawItemStruct->itemID, x, TRUE);

pDC->FillSolidRect(rcItem, pMyLParam->GetBackColor(x));

pDC->SetTextColor(pMyLParam->GetTextColor(x));

if (m_withSingleRect)

{

pOldBrush=pDC->SelectStockObject(NULL_BRUSH);

pDC->Rectangle(rcItem);

pDC->SelectObject(pOldBrush);

 

}

rcItem    = GetCellRect(lpDrawItemStruct->itemID, x, FALSE);

pDC->DrawText(CListCtrl::GetItemText(lpDrawItemStruct->itemID,x), rcItem, DT_SINGLELINE | DT_LEFT | DT_VCENTER);

}

break;

}

 

return;

}

 

void CColorListCtrl::OnSize(UINT nType, int cx, int cy)

{

    CListCtrl::OnSize(nType, cx, cy);

if (IsCreated)

{

RedrawWindow();

}

}