MFC를 시작한지 어언 3년이 넘은 지금에서야 제대로 리스트컨트롤을 사용할 수 있게 되었다.

머 그닥 특별한 기능을 가지고 있지 않다면야 그냥 아이템 넣어서 사용하면 되지만,

적어도 탐색기와 같이 컬럼 클릭으로 asc, desc 소팅을 한다던지 또한 팅했을 때 asc, desc 에 해당하는 이미지를 컬럼에 삽입하는 것.

그리고 아이템, 서브아이템에 임의의 아이콘을 출력한다던지 한다는 것을

그냥 지금까지는 되는데로 막 사용했지만 소팅클래스의 메카니즘을 이해하고 CListCtrl 에 적용하는 방법을

정석적으로 사용한 건 이번이 처음이다.

또한 파일 크기별로 유닛단위로 출력하는 것이 출력은 유닛으로 하더라도 소팅시 제대로 소팅되게 하는 것.

초반에는 파싱해서 유닛을 분리해서 생각했는데 굳이 그렇게 할 필요가 없다는 것이다.

대략 제대로 사용하기 위해서는 아래와 같은 절차가 필요함을 알아두자.

먼저 초기화 할때 헤더 컨트롤에 이미지 리스트를 맹글어야 한다.

▲ ▼ 이런 이미지가 필요한데 제대로 탐색기 처럼 보이기 위해서는 마스크를 씌워야 한다.


사용자 삽입 이미지 사용자 삽입 이미지



보통 RGB(255,0,255) 로 마스크를 입히기 때문에 그렇게 해주면 된다.

헤더에 이미지 리스트를 셋팅하고 이미지 리스트는 detach 해준다.

참!  comctl32.dll 6.0 버젼부터는 HDF_SORTDOWN, HDF_SORTUP 이란 플래그가 존재한다고 하니

굳이 만들 필요없이 플래그 셋팅만으로 이미지가 나타날 수 (?) 도 있다. 하지만 아직 난 해보지 않았다는 거...

( 난 아직 vc6 환경 ㅠ_ㅠ )

이 것으로 소팅의 기본 바탕은 준비가 된 것이다.

그 다음 필요한 것이 리스트에서 각 컬럼별 소팅을 하게 될 때 단순히 스트링 비교인지, 숫자 비교인지,

유닛이 포함된 숫자 비교, 콤마(,) 가 포함된 숫자 인지, ole 타입의 날짜 시간 타입의 비교인지를 정리하고

소팅 클래스를 사용해야 한다.

그리고 리스트컨트롤을 이쁘게 보이기 위해서는 몇가지 셋팅을 해주는데..

나의 경우는

m_List.SetExtendedStyle( LVS_EX_FULLROWSELECT |
                                    LVS_EX_GRIDLINES |
                                   LVS_EX_CHECKBOXES |
                                    LVS_EX_SUBITEMIMAGES);

m_List.SetCallbackMask(LVIS_FOCUSED);

위와 같이 해준다.

LVS_EX_FULLROWSELECT 는 선택시 전체 로우를 선택하는 것을 말하고
LVS_EX_GRIDLINES 는 엑셀과 같이 각 셀의 라인이 그려지는 것을 말하고
LVS_EX_CHECKBOXES 는 체크박스를 사용할 경우,
LVS_EX_SUBITEMIMAGES 는 아이템이나 서브아이템에 아이콘이 들어갈 경우 설정한다.

마지막으로 LVIS_FOCUSED 플래그는 로우가 선택될 때 색반전과 동시에 점선의 포커스가 생기는데

그닥 이쁘지 않기 때문에 표시하지 않겠다는 의미이다.

변수 선언시 컬럼 이름과 정렬 정보는 헤더 클릭시 필요하기 때문에 전역 배열로 선언해야 한다.

이정도 작업만 한다면 이제 소팅 클래스와 헤더 이미지 셋팅 함수 2개만 잇으면 탐색기에서 보여주는 기본적인

기능을 가진 리스트 컨트롤이 완성된다.

아래는 그 두 함수의 기본적인 틀을 보여준다.

void CXXXX::OnColumnclickLstContents(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;

	static int nSortedCol = -1;
	static bool bSortAscending = true;

	LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
	
	if(pNMLV->iSubItem == nSortedCol)
		bSortAscending = !bSortAscending;
	else
		bSortAscending = TRUE;

	nSortedCol = pNMLV->iSubItem;

	CListCtrlSort csc(&m_List, nSortedCol);


	if (pNMLV->iSubItem == 0)
	{
		for ( int i=0; i<m_List.GetItemCount(); i++ )
		{
			m_List.SetCheck( i, m_bAllCheck );
		}
		
		m_bAllCheck = ! m_bAllCheck;
	}
	else switch (pNMLV->iSubItem)
	{
		case 1:
		case 2:
		case 4:
		case 6:
		case 7:
			SetIndicatorOnColumn( pNMLV->iSubItem , bSortAscending );
			csc.Sort(bSortAscending, CListCtrlSort::dtSTRING);
			break;
		case 3:
			SetIndicatorOnColumn( pNMLV->iSubItem, bSortAscending );
			csc.Sort( bSortAscending, CListCtrlSort::dtDWORD );
			break;

	}
	*pResult = 0;
}

void CXXXX::SetIndicatorOnColumn(int Col, bool asc)
{
	CHeaderCtrl* pHeader = m_List.GetHeaderCtrl();
	
	HDITEM hItem;

	
    for(int i=0; i<pHeader->GetItemCount(); i++) {

		RECT rect;
		
		pHeader->GetItemRect( i, &rect );


		memset( &hItem, 0, sizeof( HDITEM ));		

        BOOL bReturn = pHeader->GetItem(i, &hItem);
		
        if(i == Col) {
			
			hItem.mask = HDI_TEXT  | HDI_FORMAT  | HDI_WIDTH | HDI_IMAGE | HDI_FORMAT ;
			hItem.fmt = HDF_STRING | HDF_BITMAP | HDF_BITMAP_ON_RIGHT | HDF_IMAGE ;

			switch (i)
			{
			case 3:
			case 5: hItem.fmt |= HDF_RIGHT;		break;
			case 7 :hItem.fmt |= HDF_CENTER;	break;
			}

			hItem.pszText = achHeaderName[i];
			hItem.cchTextMax = strlen( achHeaderName[i] ) + 1;
//			hItem.cxy = iHeaderCx[i];
			hItem.cxy = rect.right - rect.left;
			
            if ( asc )
			{
				hItem.iImage = 0;
			}
			else
			{
				hItem.iImage = 1;
			}
			
            pHeader->SetItem(i, &hItem);
        }
		
        else {
			
			hItem.mask = HDI_TEXT  | HDI_FORMAT  | HDI_WIDTH ;
			hItem.fmt = HDF_STRING ;
			switch (i)
			{
			case 3:
			case 5: hItem.fmt |= HDF_RIGHT;		break;
			case 7 :hItem.fmt |= HDF_CENTER;	break;
			}
			hItem.pszText = achHeaderName[i];
			hItem.cchTextMax = strlen( achHeaderName[i] ) + 1;
//			hItem.cxy = iHeaderCx[i];
			hItem.cxy = rect.right - rect.left;


			pHeader->SetItem(i, &hItem);
        }

		
    }
}
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기