아주 기초적인 사용법에 대해 적어보고자 합니다.
이런식으로 전체적인 레이아웃을 잡고 시작한다고 봐야겠죠?
그리고 중요한 컨트롤의 컨트롤의 ID 의 값을 각각 아래와 같이 정하고 시작하겠습니다.
각각의 컨트롤에 대해서는 WM_COMMAND 메시지를 다루면 되겠죠.
추가
추가의 경우에는 지난번에 했던 방식 그대로
ListView_InsertItem 과 ListView_SetItemText 매크로를 이용하면 됩니다.
li.mask=LVIF_TEXT;
li.state=0;
li.stateMask=0;
idx=ListView_GetItemCount(hList);
GetDlgItemText(hWnd,IDC_NAME,szName,255);
GetDlgItemText(hWnd,IDC_SEX,szSex,255);
GetDlgItemText(hWnd,IDC_ADDR,szAddr,255);
li.iItem=idx;
li.iSubItem=0;
li.pszText=szName;
ListView_InsertItem(hList,&li);
ListView_SetItemText(hList,idx,1,szSex);
ListView_SetItemText(hList,idx,2,szAddr);
그나마 지난번과 달라진건 컨트롤의 값을 읽어오는 GetDlgItemText 와
리스트 뷰의 아이템들의 수를 읽는 ListView_GetItemCount 가 추가된 것 밖에 없겠군요 ^^
int ListView_GetItemCount(HWND hWnd)
이게 원형입니다. sizeof 와 비슷하다고 보면 되겠군요.
삭제
삭제를 하기 위해서 사용되는 매크로는 아래와 같습니다.
int ListView_GetNextItem(HWND hWnd, int iStart, UINT flags);
BOOL ListView_DeleteItem(HWND hWnd, int iItem)
ListView_GetNextItem 의 첫번째 인수는 당연히 리스트의 핸들이고,
두번째는 어디서부터 찾을 것인가를 정하는 것입니다. -1 의 경우는
전체에서 찾는 것이고 주어지는 값에 따라 그 인덱스부터 차례로 찾아가는 것이죠.
리턴값이 int 형인데 이건 찾은 인덱스 값을 리턴합니다 ^^ 몇 번째 존재하는지를 리턴하죠.
세번째 인수는 Flags 값을 지정하는 것인데 LVNI_ALL | LVNI_SELECTED 를 보통 지정합니다.
왜 그런가 싶으면 LVNI_ALL 이나 LVNI_SELECTED 를 하나씩 삭제하여 컴파일해보면 알겠죠?
idx=ListView_GetNextItem(hList, -1, LVNI_ALL | LVNI_SELECTED);
이 경우는 만약 찾았을 경우에는 idx 의 값에는 해당 인덱스가 들어가겠지만,
찾기 실패하였을 경우에는 idx 에 -1 값이 들어갑니다.
idx=ListView_GetNextItem(hList,-1,LVNI_ALL|LVNI_SELECTED);
if(idx==-1)
MessageBox(hWnd,"삭제할 아이템을 선택하세요","Error",MB_OK);
else
{
while(idx!=-1)
{
ListView_DeleteItem(hList,idx);
idx=ListView_GetNextItem(hList,idx-1,LVNI_ALL|LVNI_SELECTED);
}
}
여기서 중요한 것은 while 문의 ListView_GetNextItem 에 idx-1 이 들어간다는 것이죠.
선택된 아이템들을 하나씩 찾아서 지워주는 것이기 때문에 idx 보다 -1 된 것을 넣어야
차례로 지워나갑니다. idx 를 그대로 넣어준다면 무슨 일이 일어나는지는 직접 해보시면 압니다.
선택된 아이템들이 전부 삭제가 되지 않겠죠;
수정
수정은 추가와 비슷하여 상당히 쉽습니다. 다만 ListView_InsertItem 매크로 대신
ListView_SetItem 을 통하여 재설정을 해줘야 합니다. 아주 조금 추가와 다를 뿐,
기본 방식은 같습니다.
idx=ListView_GetNextItem(hList,-1,LVNI_ALL|LVNI_SELECTED);
if(idx==-1)
MessageBox(hWnd,"수정할 아이템을 선택하세요","Error",MB_OK);
else
{
GetDlgItemText(hWnd,IDC_NAME,szName,255);
GetDlgItemText(hWnd,IDC_SEX,szSex,255);
GetDlgItemText(hWnd,IDC_ADDR,szAddr,255);
li.iItem=idx;
li.iSubItem=0;
ListView_SetItem(hList,&li);
ListView_SetItemText(hList,idx,0,szName);
ListView_SetItemText(hList,idx,1,szSex);
ListView_SetItemText(hList,idx,2,szAddr);
}
보시면 아시겠지만 일단 선택된 것을 찾아서 idx 에 그 인덱스 값을 넣어줍니다.
만약 선택되지 않았다면 Error 메시지박스가 뜨겠죠. 이제 LVITEM 구조체인
li 의 iItem 에 idx 값을 지정하고 iSubItem 멤버에도 첫번째 컬럼을 의미하는 0을 지정한 뒤
ListView_SetItem 으로 li 를 hList 에 설정합니다.
일단 내가 몇 번째 리스트 뷰 아이템을 설정한다고 알려주는 것이죠.
그런 뒤 ListView_SetItemText 매크로를 통하여 수정해주면 됩니다 ^^
검색
다행히 검색을 할 때도 편리하게(?) 매크로가 존재합니다.
int ListView_FindItem(HWND hWnd, int iStart, const LPLVFINDINFO plvfi);
여기서 중요한건 LVFINFO 구조체가 들어가는데요, 이건 검색의 조건으로
typedef struct tagLVFINDINFO {
UINT flags;
LPCTSTR psz;
LPARAM lParam;
POINT pt;
UINT vkDirection;
} LVFINDINFO, *LPFINDINFO;
flags 멤버로 중요한건
LVFI_STRING psz 멤버가 지정하는 문자열과 일치하는 텍스트를 가진 항목을 검색
LVFIN_WRAP 검색 대상이 발견되지 않을 경우 처음부터 다시 검색
이 두 개 정도로만 봐도 가장 기초적인 곳에서는 사용할 수 있습니다.
그리고 vkDirection 이라는 특이한 멤버가 존재하는데요,
이건 VK_LEFT , VK_DOWN, VK_HOME 등 가상 키를 넣어주는겁니다.
대게 VK_DOWN 을 설정하는 편이라는군요.
LVFINDINFO fi;
GetDlgItemText(hWnd,IDC_NAME,szName,255);
fi.flags=LVFI_STRING;
fi.psz=szName;
fi.vkDirection=VK_DOWN;
idx=ListView_FindItem(hList,-1,&fi);
if(idx==-1)
MessageBox(hWnd,"검색된 아이템이 없습니다","Error",MB_OK);
else
{
ListView_SetItemState(hList,-1,0,LVIS_FOCUSED|LVIS_SELECTED);
ListView_SetItemState(hList,idx,LVIS_FOCUSED|LVIS_SELECTED,0x000F);
ListView_EnsureVisible(hList,idx,FALSE);
}
이렇게 IDC_NAME 의 값을 읽어와 psz 에 설정한 후 ListView_FindItem 매크로에서 찾아주면 되네요.
ListView_FindItem 에서 -1 은 가장 처음에서 찾는, 전체에서 찾는다는 의미죠. 같은 문자열로 찾기를
계속 이어주려면 idx-1 값으로 루프를 돌려주면서 찾으면 되겠군요 ^^
찾았을 경우 ListView_SetItemState 로 상태를 설정해줘야하는데요.
ListView_SetItemState(hList,-1, 0,LVIS_FOCUSED|LVIS_SELECTED);
ListView_SetItemState(hList,idx,LVIS_FOCUSED|LVIS_SELECTED,0x000F);
이 두개가 왜 존재할까요? -1은 전체를 의미하고, 0은 상태를 없앤다고 보면 되죠.
일단 리스트 뷰에 어떤 항목들이 선택되어있거나 한다면 리플래시를 시켜 없앱니다.
그게 바로 ListView_SetItemState(hList,-1, 0,LVIS_FOCUSED|LVIS_SELECTED) 입니다.
그리고 나서 찾은 idx 번째의 리스트 뷰의 아이템을 선택해야하는데요, 그게 바로 두 번째인
ListView_SetItemState(hList,idx,LVIS_FOCUSED|LVIS_SELECTED,0x000F);
입니다. 마지막 인수가 16진수로 되어있지만 이것도 역시 아래와 같이 바꿀 수 있습니다.
ListView_SetItemState(hList,idx,LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED);
여기까지가 가장 기초적인(?) 방법이었네요.
사실상 개인적으로 시간이 많이 먹었던 부분이예요.
좀더 자세한건 소스 첨부 했으니 참고하시면 되구요 ^^;
다음엔 WM_NOTIFY 에 해당되는 리스트 뷰의 메시지 관리를 적어보겠습니다.
출처 : http://cafe.naver.com/seen/131
'C/C++언어 > 윈도우 MFC' 카테고리의 다른 글
좌표 매핑 관련 함수 (0) | 2008.10.03 |
---|---|
GetWindowRect, GetClientRect, ScreenToClient (0) | 2008.09.26 |
MFC클래스 간의 통신 (포인터 얻기) (0) | 2007.11.11 |
스크롤 범위 세팅 (0) | 2007.11.11 |
리스트뷰 컨트롤(ListView Control) (0) | 2007.11.11 |