InsertItem은 중요도도 높고, 다양한 양식을 제공함으로 별도로 취급한다.

1. int InsertItem(int nItem, LPCTSTR lpszItem);
2. int InsertItem(int nItem, LPCTSTR lpszItem, int nImage);
3. int InsertItem(const LVITEM* pItem);

샘플은 이전에 다루었던 장 중에서 하나씩 시작하기의 샘플을 수정하여 진행한다.
또한 LVITEM 구조체에 대한 설명은 링크를 참조한다.

1번과 2번에 대한 설명은 아이템의 인덱스, 레이블 문자열, 아이템의 이미지 인덱스와 같이
이해하기 쉽고 용법도 간단하므로 생략한다. (기존 장에서도 충분히 다루었다.)


아이템에 문자열만 넣기.
-----------------------------------------------------------------------------------
LVITEM item = {0};
item.mask = LVIF_TEXT;
item.iItem = 아이템 인덱스
item.pszText = 해당 문자열
리스트컨트롤.InsertItem(&item);
아주 간단하게 해당 아이템의 인덱스에 문자열만을 넣어 보았다.
item.mask 값에 LVIF_TEXT 가 설정되었는데, 해당 문자열을 처리함을 알려준다.

이미 들어있는 아이템의 문자열을 변경하려면 SetItemText를 이용하여 변경이 가능하고
그 값을 가져오려면 GetItemText를 이용하면 된다.


아이템에 문자열과 이미지 넣기.
-----------------------------------------------------------------------------------
LVITEM item = {0};
item.mask = LVIF_TEXT | LVIF_IMAGE;
item.iItem = 아이템 인덱스
item.pszText = 해당 문자열
item.iImage = 이미지 리스트의 해당 인덱스
리스트컨트롤.InsertItem(&item);
리스트 컨트롤에 이미지 리스트가 연결되어 있다면 LVIF_IMAGE 마스크를 넣어 이미리 리스트에해당하는 인덱스를 넣음으로써 컨트롤에 아이콘이 표시되도록 한다.

이미지 리스트를 연결하였음에도 불구하고, 이미지의 인덱스를 설정하지 않으면 기본값으로
0번 이미지가 그려짐에 주의하자.


한번 넣은 이미지를 변경하기 위한 별도의 메서드는 제공되지 않는다. 이미 넣은 이미지를
변경하기 위해서는 SetItem 메서드를 이용하여 변경이 가능하다.

예) 0번 아이템의 이미지를 5번 이미지로 바꾸기.

리스트컨트롤.SetItem(0, 0, LVIF_IMAGE, NULL, 5, 0, 0, 0);

LVITEM item = {0};
item.mask = LVIF_IMAGE;
item.iItem = 0;
item.iImage = 5;
리스트컨트롤.SetItem(&item);


아이템에 문자열과 부가 정보 넣기.
-----------------------------------------------------------------------------------
LVITEM item = {0};
item.mask = LVIF_TEXT | LVIF_PARAM;
item.iItem = 아이템 인덱스
item.pszText = 해당 문자열
item.lParam = 4바이트 숫자형 데이터 or 부가정보의 포인터
리스트컨트롤.InsertItem(&item);
부가 정보 필드인 LVITEM::lParam은 LPARAM 타입의 변수로 기본타입은 long 이다.

초기 아이템 삽입시 저 정보의 설정이 불필요하고 나중에 설정하거나 가져오려면
SetItemData 와 GetItemData 메서드를 이용하여 처리할 수 있다.


아이템에 상태 정보 넣기.
-----------------------------------------------------------------------------------
LVITEM item = {0};
item.mask = LVIF_TEXT | LVIF_STATE;
item.iItem = 아이템 인덱스
item.pszText = 해당 문자열
item.state = 상태값 조합
item.stateMask = 상태 마스크 플래그 조합
리스트컨트롤.InsertItem(&item);

상태 플래그는 다음과 같다.
LVIS_ACTIVATING
   지원 않함.
LVIS_CUT
   아이콘이 흐리게 보임 (cut & paste 동작시 주로사용)
LVIS_DROPHILITED
   drag&drop시 타겟 리스트 컨트롤일 경우 마우스 오버 상태에 따라 아이템을 하이라이트 시켜줌
LVIS_FOCUSED
   아이템에 포커스 사각형(쩜선 사각형)을 그려줌
LVIS_SELECTED
   아이템이 선택되어진 형태로 표시해줌
LVIS_STATEIMAGEMASK
   아이템의 이미지에 상태 이미지 선택할 수 있도록 함.
LVIS_OVERLAYMASK
   아이템에 오버레이 마스크용 아이콘을 겹쳐서 그려줌

볼드로 표기된 나머지는 상태 마스크와 상태값을 동일하게 넣으면 된다. 내용 자체도 이해하기
쉬우니 간단한 예만 적어본다.

예) 선택되어진 상태로 표시하기.
LVITEM item = {0};
item.mask = LVIF_TEXT | LVIF_STATE;
item.iItem = 아이템 인덱스
item.pszText = 해당 문자열
item.state = LVIS_FOCUSED;
item.stateMask = LVIS_FOCUSED;
리스트컨트롤.InsertItem(&item);

나머지 2개의 상태 마스크는 아래에 별도로 설명을 추가한다.


이미지에 오버레이 마스크 이미지 덧 씌우기.
-----------------------------------------------------------------------------------
LVITEM item = {0};
item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE;
item.iItem = 아이템 인덱스
item.pszText = 해당 문자열
item.iImage = 이미지 리스트의 해당 인덱스
item.state = INDEXTOOVERLAYMASK(오버레이 이미지 인덱스);
item.stateMask = LVIS_OVERLAYMASK;
리스트컨트롤.InsertItem(&item);
오버레이 이미지란 기본 이미지(아이콘) 위에, 다른 아이콘을 덧 씌워 그리는 것을 말한다.
탐색기를 살펴보면 단축 아이콘과 같은 경우

위 그림처럼 기본 이미지위에 오버레이 이미지가 그려져 있는 것을 알 수 있다.
이런 식으로 이미지를 두장 겹처서 그릴 때 사용하는 위와 같은 방법을 사용한다.

오버레이에 사용되는 이미지는 기본으로 연결된 이미지 리스트를 사용한다.


상태 이미지를 별도로 추가하기.
-----------------------------------------------------------------------------------
이건 코드를 달기 전에 먼저 간단한 설명을 전하고, 코드를 이용하여 나머지를 설명할 것이다.
리스트 하나 하나의 아이템이 어떤 상태에 따라 아이콘의 모양이 달라진다면 어떻게 구현할까?


(위 그림은 모두 폴더를 나타내는 아이콘이지만 상태에 따라 서로 다른 이미지를 가진다.)

1. 하나의 이미지 리스트에 몽땅 때려 놓고, 그 때 그 때 이미지를 변경한다.
2. LVSIL_STATE 로 이미지 리스트를 별도로 연결하여 놓고, 그 상태의 이미지를 넣는다.

1번 방법을 이용할 경우, 중간에 이미지가 새로 추가되거나 삭제되면 전체 인덱스 순서에
영향을 미치기 때문에 파급효과가 대단히 크다. 물론 많은 코드 수정도 불가피히다.

2번 방법을 이용할 경우, 이미 인덱스를 별도로 밖아 놓은 코드는 변경을 해야하지만 상태에 따른
이미지 변경 코드는 변화가 없다. 또한 기본 이미지리스트의 인덱스에 영향을 받지 않는다.

헤더파일
이미지리스트 작은이미지;
이미지리스트 큰이미지;
이미지리스트 상태이미지;

소스파일
리스트컨트롤.SetImageList(&작은이미지, LVSIL_SMALL);
리스트컨트롤.SetImageList(&큰이미지, LVSIL_NORMAL);
리스트컨트롤.SetImageList(&상태이미지, LVSIL_STATE);
위와 같이 기본 이미지 리스트와는 별도로 상태 이미지를 담은 이미지 리스트를 만들어 연결한다.

LVITEM item = {0};
item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE;
item.iItem = 아이템 인덱스
item.pszText = 해당 문자열
item.iImage = 이미지 리스트의 해당 인덱스
item.state = INDEXTOSTATEIMAGEMASK(상태 이미지 인덱스);
item.stateMask = LVIS_STATEIMAGEMASK;
리스트컨트롤.InsertItem(&item);


아이템에 이미지 여러개 넣기??? - 이게 정말 맞는 이해인지 모르겠다 (누가좀.. )
-----------------------------------------------------------------------------------

LVITEM item = {0};
item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_INDENT;
item.iItem = 아이템 인덱스
item.pszText = 해당 문자열
item.iImage = 이미지 리스트의 해당 인덱스
item.iIndent = 아이템의 이미지 너비의 복수???
리스트컨트롤.InsertItem(&item);

(iIndent 변수는 common control version 4.7 부터 적용되는 기능입니다.)
리스트 컨트롤에서 레포트 스타일일 경우 첫번째 아이템에 여러개의 이미지가 있는 것을 본적이
있는가? (전 본 기억이 없는듯.. 이것도 오늘 공부해서 써본것입니다. -_-)

저 iIndent 값은 기본적으로 0이며, 저기 숫자를 넣으면, 첫번째 아이템이
저 숫자* 아이콘의 너비 만큼 띄워져서 그려진다.
(아래의 그림은 iIdent를 1로 준 상태입니다.)

그림에서 보는 것 처럼 왼쪽에 아이콘의 너비인 16 픽셀만큼 띄워져서 그림이 그려지고. iIndent 값을 높게 주면 그 배수만큼 띄워져서 그려지게 된다.
Custom Draw나 Owner Draw를 이용하면 저기 비워놓은 공간에 먼가 작업을 해줄 수 있겠지만
그냥 쓸 때는 전혀 의미가 없어보인다. 흠..
(누구 자세히 아시는분 계시면 코멘트좀 달아주세요..)

common control version 6.0 부터는 group 이라는 기능이 지원이 되는데.. 아쉽게도 MFC 6.0
에서는 지원이 되지 않습니다. 현재 깔린 툴이 6.0 뿐이라.. 제 컴에 vs2005를 깔게되면 이 내용에
group에 관련된 내용도 추가하도록 하겠습니다. ㅋ~



위의 내용들을 이용하여 제작된 샘플이다.
-----------------------------------------------------------------------------------

이전에 다루었던 장 중에서 하나씩 시작하기의 샘플을 재 사용(-_-;;;) 하였으며 기존과 달라진 점은 공유 폴더나 단축아이콘도 이미지가 정확하게 표현된다는 점이다.

변경된 내용은 다음과 같다.

BOOL CSampleDlg::OnInitDialog()
{
    ... 중간 생략
    int ndx = 0;
    CFileFind finder;
    SHFILEINFO sfi;
    BOOL bWorking = finder.FindFile("C:\\*.*");
    while (bWorking)
    {
        bWorking = finder.FindNextFile();
        SHGetFileInfo(finder.GetFilePath(),
            0,
            &sfi,
            sizeof(SHFILEINFO),
            SHGFI_DISPLAYNAME | SHGFI_TYPENAME| SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_ATTRIBUTES);
        ndx = AddItem2(finder, sfi, ndx);
    }
    // 찾은 파일의 파일속성 정보를 얻기 위하여 SHGFI_ATTRIBUTES 플래그가 추가되었다.

    ... 중간 생략
}

int CSampleDlg::AddItem2(CFileFind& file, SHFILEINFO& sfi, int ndx)
{
    CString szTemp;
    CTime fTime;

    LVITEM item = {0};
   
    // 아이템의 상태 정보를 넣기 위하여 LVIF_STATE 플래그를 추가함.
    item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE;
    item.iItem = ndx;
    item.iSubItem = 0;
    item.pszText = sfi.szDisplayName;
    item.iImage = sfi.iIcon;
   
    // 단축 아이콘 속성일 경우.. 2번째 이미지를 오버레이 이미지로 사용함.
    if(sfi.dwAttributes & SFGAO_LINK)
    {
        item.state |= INDEXTOOVERLAYMASK(2);
        item.stateMask |= LVIS_OVERLAYMASK;
    }
    // 공뷰 폴더 속성일 경우.. 1번째 이미지를 오버레이 이미지로 사용함.
    else if(sfi.dwAttributes & SFGAO_SHARE)
    {
        item.state |= INDEXTOOVERLAYMASK(1);
        item.stateMask |= LVIS_OVERLAYMASK;
    }

    // 히든 속성일 경우는 별도이 이미지를 사용하지 않고, LVIS_CUT 상태를 이용하여
    // 흐릿하게 보이도록 함.

    if(sfi.dwAttributes & SFGAO_HIDDEN)
        item.state |= LVIS_CUT;

    ndx = m_list.InsertItem(&item);

    ... 중간 생략   
}



+ Recent posts