티스토리 뷰





CListCtrl 의 헤더를 클릭하면 소팅이 되도록 프로그래밍을 해보자

먼저 CListCtrl의 헤더가 클릭되었을 때 호출되는 콜백함수는 다음과 같다

ON_NOTIFY(HDN_ITEMCLICKA, 0, OnHdnItemClick)
ON_NOTIFY(HDN_ITEMCLICKW, 0, OnHdnItemClick)

원래는 ON_NOTIFY(HDN_ITEMCLICK, 0, OnHdnItemClick)으로 하면될것같지만, MFC 버그인지 먹질않는다.
(관련 링크 : http://www.codeguru.com/forum/archive/index.php/t-207657.html )
참고로 내 프로젝트에서는 리스트컨트롤이 1개만 쓰였으므로
두번째 인자를 0대신에 해당 리스트컨트롤의 리소스이름으로 써도 되지만, 나중에 확장성을 고려해서 0으로 임시로 박아 두었다.

일단 헤더를 클릭하고 다시 클릭을할경우, 소팅이 오름차순에서 내림차순으로 혹은 반대로 변형되어야 하므로
클래스안에
멤버변수로 m_bResultDirect를 선언하였다.
또한 Sorting 되는 컬럼을 자유롭게 하기위해 리스트컨트롤의 포인터만을 매개변수로 쓰지않고
리스트컨트롤과, 클릭한 컬럼, 소팅방향까지 함께 넣을 구조체를 선언하였다.

 struct SORTPARAM
 {
  int iSortColumn;
  bool bSortDirect;
  CListCtrl *pList; 
 };

 bool m_bResultDirect;


호출될 함수를 정의해보자

void CIssueDlg::OnHdnItemClick(NMHDR *pNMHDR, LRESULT *pResult)
{
 LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR);

 SORTPARAM sParam;
// 리스트연결
 sParam.pList = &m_sourceList;
// 몇번째 컬럼인지 저장
 sParam.iSortColumn = phdr->iItem;
// 방향을 저장
 sParam.bSortDirect = m_bResultDirect;

 // 이제 정렬 함수를 호출한다.
 sParam.pList->SortItems(CompareFunc, (LPARAM)&sParam); 
 m_bResultDirect = !m_bResultDirect;
 return
}

호출될 함수에서 결과적으로 SortItems라는 함수를 호출한다. 그런데 그 함수에서는 CompareFunc라는 인자와, 만든 구조체를 넘겨주는데 CompareFunc라는 함수는 무엇일까?

바로 콜백함수이다. C언어에서 qsort함수를 사용할때, Compare 함수를 구현해서 인자로 넣는데, 그 함수와 같은 형식이다.

콜백함수를 구현하기 위해, 클래스에 콜백함수원형을 선언하자.

private:
 static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);




그리고 마지막으로 콜백함수를 구현하면 끝난다.

int CALLBACK CIssueDlg::CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
 
 // lParamSort를 리스트 컨트롤의 포인터로 캐스팅 했다.
 
 // SotrItems함수를 호출할때 두번째 파라미터로 리스트 컨트롤의 포인터를 넘긴 경우이다.

 CListCtrl *pList = ((SORTPARAM *)lParamSort)->pList;
 int iSortColumn = ((SORTPARAM *)lParamSort)->iSortColumn;
 bool bSortDirect = ((SORTPARAM *)lParamSort)->bSortDirect;
 
 LVFINDINFO info1, info2;
 info1.flags = LVFI_PARAM;
 info1.lParam = lParam1;
 info2.flags = LVFI_PARAM;
 info2.lParam = lParam2;
 int irow1 = pList->FindItem(&info1,-1);
 int irow2 = pList->FindItem(&info2,-1);
 
 CString strItem1 = pList->GetItemText(irow1, iSortColumn);
 CString strItem2 = pList->GetItemText(irow2, iSortColumn);
 
 return bSortDirect?strcmp(strItem1, strItem2):-strcmp(strItem1, strItem2);
}

댓글