리스트 박스를 사용하면서 주로 쓰이는 기능이 대표적으로 아이템의 추가, 삽입, 삭제 및 선택 기능이다. 기능은 단순하지만, 리스트 박스의 속성에 따라 동작 특성이나 메서드의 응답이 달라진다.
아래의 함수는 리스트박스에 긴 문자열이 들어갔을 경우, 수평 스크롤바를 생성시키는 코드이다.
이전 장에서 다룬것을 조금 확장한 것이고, 앞으로 리스트박스에서 항상 쓰일 함수이다.
{
CSize size;
CDC *pDC = box.GetDC();
CFont* pOld = pDC->SelectObject(box.GetFont());
if ((box.GetStyle() & LBS_USETABSTOPS) == 0)
{
size = pDC->GetTextExtent(lpszText, _tcslen(lpszText));
size.cx += 3;
}
else
{
size = pDC->GetTabbedTextExtent(lpszText, _tcslen(lpszText), 0, NULL);
size.cx += 2;
}
pDC->SelectObject(pOld);
box.ReleaseDC(pDC);
return size.cx;
}
{
if(ndx == -1)
box.AddString(str);
else
box.InsertString(ndx+1, str);
if (iExt > box.GetHorizontalExtent())
box.SetHorizontalExtent(iExt);
}
우선 리스트 박스 하나를 single 선택 모드로 예제를 하나 작성하였다.
리스트 박스를 선택할 때 속성에 따라 동작이 다름에 주의하여야 한다.
각각의 기능을 구현한 함수는 다음과 같다.
void CSssDlg::OnButton1()
{
AddStringEx(m_list, "하나"); AddStringEx(m_list, "둘");
AddStringEx(m_list, "셋"); AddStringEx(m_list, "넷");
AddStringEx(m_list, "다섯"); AddStringEx(m_list, "여섯");
AddStringEx(m_list, "일곱"); AddStringEx(m_list, "여덟");
AddStringEx(m_list, "아홉"); AddStringEx(m_list, "임의의 아이템을 10개를 리스트 박스에 삽입함.");
}
void CSssDlg::OnButton2()
{
UpdateData(TRUE);
AddStringEx(m_list, m_str_insert, m_list.GetCurSel());
}
void CSssDlg::OnButton3()
{
UpdateData(TRUE);
m_list.SetCurSel(m_sel_program);
}
void CSssDlg::OnButton4()
{
m_list.DeleteString(m_list.GetCurSel());
}
void CSssDlg::OnButton5()
{
m_list.ResetContent();
}
single 선택 모드일 경우는 아이템을 하나씩만 선택할 수 있기 때문에, 선택이나 삭제가
위처럼 수월하게 이루어진다.
하지만 multiple나 extended 로 다중 선택할 경우.. GetCurSel의 응답이 약간 달라진다.
single
아이템이 선택되었을 경우 : 선택된 아이템의 인덱스
아이템이 선택되어지지 않았을 경우 : -1
multiple or extended
아이템이 선택되었을 경우 : 최종 선택된 아이템의 인덱스
아이템이 선택되어지지 않았을 경우 : 0
일단 다중 선택이 가능한 상태에서 그럼 어떻게 여러개의 아이템이 선택되어 졌는지를
인식하고, 그 항목들을 가져 올 수 있는지 살펴보자.
void DoSomething(CListBox& box)
{
// 몇개의 아이템이 선택되어졌는지 카운트
int nCount = box.GetSelCount();
// 선택되어진 아이템이 하나도 없으면 리턴.
if(nCount <= 0)
return;
// 배열을 하나 만들고, 크기를 설정한다.
CArray<int,int> aryListBoxSel;
aryListBoxSel.SetSize(nCount);
// 아이템중에서 선택되어진 인덱스를 배열에 읽어온다.
box.GetSelItems(nCount, aryListBoxSel.GetData());
for(int i=0; i<nCount; i++)
{
// 선택된걸 하나씩 뽑아서 먼가 처리를 하겠지...
int sel = aryListBoxSel[i];
// do something...
}
}
위의 함수에서 보았듯이 여러개의 아이템이 선택되어져 있을 경우, 먼저 선택 아이템 카운트를
읽어온다음, 그 인덱스를 배열에 읽어오는 과정을 거친다.
그럼 다중 선택일 경우에 선택아이템을 지우는 버튼의 코드를 수정해보자.
싱글 선택일 경우는 아래와 같았다.
void CSssDlg::OnButton4()
{
m_list.DeleteString(m_list.GetCurSel());
}
멀티 선택일 경우는 다음과 같다.
void CSssDlg::OnButton4()
{
int nCount = box.GetSelCount();
if(nCount <= 0)
return;
CArray<int,int> aryListBoxSel;
aryListBoxSel.SetSize(nCount);
box.GetSelItems(nCount, aryListBoxSel.GetData());
// 앞에꺼 부터 지우게 되면 뒤쪽의 저장해 놓은 인덱스 정보가 틀어지게 되므로
// 뒤에꺼 부터 앞으로 하나씩 지우면 된다.
for(int i=nCount-1; i>=0; i--)
m_list.DeleteString(aryListBoxSel[i]);
}