리스트 컨트롤은 많은 메서드를 제공하기 때문에 한방에 써내리기가 쉽지 않다 -_-;;;
간단한 샘플을 시작으로 각각의 메서드와 이용하는 방법들을 샘플을 통하여 알아보자.


위 그림이 리스트 컨트롤을 배워나갈 처음 샘플 화면이다. 익숙한 탐색기의 우측 리스트 부분을
흉내내어 이해하기 쉽도록 작성할 것이다.

이번 장에서 다룰 부분은 다음과 같다.
1. 시스템 이미지 리스트를 얻어와서 컨트롤에 연결하기
2. 컬럼 셑팅하기
3. 원하는 경로의 파일 정보를 가져오기(탐색기를 흉내내다 보니 필요한 작업)
4. 아이템을 리스트에 추가하기.
5. 라디오 버튼 제어하기


화면 구성은 위의 그림과 같다.


헤더에 추가된 내용
---------------------------------------------------------------------------------------
    // 리스트에 연결할 이미지 리스트 2개. 큰것 작은것
    CImageList m_imgShareSmall;
    CImageList m_imgShareLarge;

    // 시스템 이미지 리스트를 로딩한다.
    void ImagelistLoading();

    // 컬럼을 설정한다.
    void ColumnSetting();

    // 2가지 방식으로 아이템을 리스트에 추가한다.
    int  AddItem1(CFileFind& file, SHFILEINFO& sfi, int ndx);
    int  AddItem2(CFileFind& file, SHFILEINFO& sfi, int ndx);

    ...

    // 하단부 4개의 라디오 박스 컴맨드를 묶는다.
    afx_msg LRESULT OnRadioCommandRange(UINT nID);



소스에 추가된 내용
---------------------------------------------------------------------------------------
메시지 맵에 라이오 버튼을 그룹으로 묶어서 넣는다.
ON_COMMAND_RANGE(IDC_RADIO1, IDC_RADIO4, OnRadioCommandRange)


OnInitDialog 초기화 루틴에 기본 내용을 채운다.
BOOL CSampleDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    // 라디오 버튼 1-4개중에 4번째를 선택해준다.

    CheckRadioButton(IDC_RADIO1, IDC_RADIO4, IDC_RADIO4);

    // 시스템 이미지 리스트를 로딩한다.
    ImagelistLoading();

    // 컬럼을 설정한다.
    ColumnSetting();

    int ndx = 0;
    CFileFind finder;
    SHFILEINFO sfi;

    // CFileFind를 이용하여 C:\에 있는 파일과 폴더 정보를 읽어온다.
    BOOL bWorking = finder.FindFile("C:\\*.*");
    while (bWorking)
    {
        // 해당 파일정보를 로딩하고, 포지션을 다음으로 넘긴다.
        bWorking = finder.FindNextFile();

        // SHGetFileInfo 쉘함수를 이용하여 파일의 쉘정보를 가져온다.
        SHGetFileInfo(finder.GetFilePath(),
            0,
            &sfi,
            sizeof(SHFILEINFO),
            SHGFI_DISPLAYNAME | SHGFI_TYPENAME| SHGFI_SYSICONINDEX | SHGFI_SMALLICON);

        // 아이템을 리스트에 추가한다.
        ndx = AddItem1(finder, sfi, ndx);
    }
    return TRUE;
}


시스템 이미지 리스트를 읽어와 리스트에 연결한다.
사실 시스템 이미지를 사용한건 샘플이건 아니건 아이콘을 제작하는게 노가다이기 때문에 -_-;;;;
SHGetFileInfo 에 대한 설명은 링크에 제공되어 있다.
void CSampleDlg::ImagelistLoading()
{
    HIMAGELIST hImageList;
    SHFILEINFO sfi;
   
    // SHGetFileInfo 쉘함수를 이용하여 드라이브상의 모든 아이콘 정보를 가져와
    // 이미지 리스트로 만든다.

    hImageList = (HIMAGELIST)SHGetFileInfo((LPCSTR)"C:\\",
        0,
        &sfi,
        sizeof(SHFILEINFO),
        SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
   
    if(hImageList)
        m_imgShareSmall.Attach(hImageList);
   
    hImageList = (HIMAGELIST)SHGetFileInfo((LPCSTR)"C:\\",
        0,
        &sfi,
        sizeof(SHFILEINFO),
        SHGFI_SYSICONINDEX | SHGFI_LARGEICON);
   
    if(hImageList)
        m_imgShareLarge.Attach(hImageList);
   
    // 만들어진 두개의 이미지 리스트를 상태에 맞게 리스트 컨트롤에 연결한다.
    m_list.SetImageList(&m_imgShareSmall, LVSIL_SMALL);
    m_list.SetImageList(&m_imgShareLarge, LVSIL_NORMAL);
}

CImageList* SetImageList(
   CImageList*
pImageList, // 이미지 리스트의 포인터
   int nImageListType           // 이미지 리스트의 상태 
);

nImageListType 에 올수 있는 플래그
LVSIL_NORMAL  큰 아이콘
LVSIL_SMALL     작은 아이콘
LVSIL_STATE      상태 아이콘


해당 컬럼 정보를 설정한다.
void CSampleDlg::ColumnSetting()
{
    m_list.InsertColumn(0, "이름", LVCFMT_LEFT, 180);
    m_list.InsertColumn(1, "크기", LVCFMT_RIGHT,100);
    m_list.InsertColumn(2, "종류", LVCFMT_LEFT, 150);
    m_list.InsertColumn(3, "수정한 날짜", LVCFMT_LEFT, 250);
}

int InsertColumn(
   int
nCol,                                   // 컬럼 인덱스
   LPCTSTR lpszColumnHeading,  // 컬럼의 디스플레이 이름
   int nFormat = LVCFMT_LEFT,  // 정렬 속성
    int nWidth = -1,                        // 너비 
   int nSubItem = -1                      // 서브아이템 인덱스
);

nFormat 에 나올 수 있는 플래그
LVCFMT_LEFT        왼쪽 정렬
LVCFMT_RIGHT      오른쪽 정렬
LVCFMT_CENTER   가운데 정렬



라디오 버튼의 클릭 이벤트 모음
헤당 라디오 버튼을 누르면 리스트 컨트롤의 아래의 뷰 형태로 변환한다.
LRESULT CSampleDlg::OnRadioCommandRange(UINT nID)
{
    switch(nID)
    {
    case IDC_RADIO1:
        m_list.ModifyStyle(LVS_TYPEMASK, LVS_ICON);
        break;
    case IDC_RADIO2:
        m_list.ModifyStyle(LVS_TYPEMASK, LVS_SMALLICON);
        break;
    case IDC_RADIO3:
        m_list.ModifyStyle(LVS_TYPEMASK, LVS_LIST);
        break;
    case IDC_RADIO4:
        m_list.ModifyStyle(LVS_TYPEMASK, LVS_REPORT);
        break;
    }
    return 0;
}


아이템 추가하기 함수 1번 타입
리스트 컨트롤에 아이템을 추가하는 함수는 4개가 사용되는데 그중에 일반적으로 가장 많이
사용되는 함수 2개를 뽑아서 샘플로 만들었다.

int CSampleDlg::AddItem1(CFileFind& file, SHFILEINFO& sfi, int ndx)
{
    CString szTemp;
    CTime fTime;
   
    // 주어진 정보대로 아이템을 삽입한다.
    ndx = m_list.InsertItem(ndx, sfi.szDisplayName, sfi.iIcon);
 
    // 디렉토리가 아니면 사이즈 정보를 1번 서브아이템의 텍스트로 추가한다.
    if(!file.IsDirectory())
    {
        szTemp.Format("%d KB", file.GetLength64()/1024);
        m_list.SetItemText(ndx, 1, szTemp);
    }

    // 확장자에 따른 타입 이름을 2번 서브아이템의 텍스트로 추가한다.
    m_list.SetItemText(ndx, 2, sfi.szTypeName);

    // 파일의 최종 쓰여진 시간 정보를 읽어서 3번 서브아이템의 텍스트로 추가한다.
    file.GetLastWriteTime(fTime);
    szTemp.Format("%04d-%02d-%02d %02d:%02d:%02d",
        fTime.GetYear(),
        fTime.GetMonth(),
        fTime.GetDay(),
        fTime.GetHour(),
        fTime.GetMinute(),
        fTime.GetSecond());

    m_list.SetItemText(ndx, 3, szTemp);
    return ++ndx;
}

int InsertItem(
   int nItem,                 // 아이템 인덱스
   LPCTSTR lpszItem// 아이템의 텍스트
   int nImage                // 아이템에 연결할 이미지 인덱스
);

BOOL SetItemText(
   int nItem,             // 아이템 인덱스   
   int nSubItem,         // 서브 아이템 인덱스
   LPCTSTR lpszText   // 아이템의 텍스트
);



아이템 추가하기 함수 2번 타입
LVITEM 구조체를 이용하여 아이템을 추가하는 설명
int CSampleDlg::AddItem2(CFileFind& file, SHFILEINFO& sfi, int ndx)
{
    CString szTemp;
    CTime fTime;

    LVITEM item;
    item.mask = LVIF_TEXT | LVIF_IMAGE;
    item.iItem = ndx;
    item.iSubItem = 0;
    item.pszText = sfi.szDisplayName;
    item.iImage = sfi.iIcon;
    ndx = m_list.InsertItem(&item);

    // 동일한 내용이므로 중간 생략

    return ++ndx;
}


int InsertItem(
   const LVITEM* pItem
);

typedef struct _LVITEM {
    UINT mask;                 아이템 적용할 마스크
    int iItem;                     아이템 인덱스
    int iSubItem;                서브아이템 인덱스
    UINT state;                  상태 플래그
    UINT stateMask;          상태 플래그 마스크
    LPTSTR pszText;         아이템 텍스트 
    int cchTextMax;           아이템 텍스트의 길이
    int iImage;                   이미지의 인덱스
    LPARAM lParam;         추가할 확장 데이터의 포인트
#if (_WIN32_IE >= 0x0300)
    int iIndent;                   여러개의 아이템 이미지를 가질 경우 카운터
#endif
#if (_WIN32_IE >= 0x560)
    int iGroupId;                 그룹 아이템 아이디
    UINT cColumns;            그룹 대상으로 지정할 컬럼 아이디
    PUINT puColumns;        컬럼 인덱스의 배열
#endif
} LVITEM, *LPLVITEM;

그룹에 대한 내용은 추후에 자세하게 설명할것이므로, 간단하게 구조체 설명을 마감한다.


일단 이렇게 리스트에 대한 한 발을 내딛었습니다. 초기 샘플치곤 좀 화려하게 시작했지만..
리스트 컨트롤의 여러가지 기능을 잘 표현 하려면 어떤 샘플을 선택하는 지도 중요하거든요..

그럼 다음에..


+ Recent posts