티스토리 뷰





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);
}

저작자 표시 비영리 변경 금지
신고
댓글
  • 프로필사진 Jake Yoon 정렬기능을 HDN_ITEMCLICK 함수로 NOTIFY 하다보니
    리스트 컨트롤이 다중으로 정의되어있는 다이얼로그의 경우
    모든 다이얼로그가 이 이벤트를 핸들링하는 버그가 발생하였다.
    이를 해결하기위해 여러가지 문서를 찾아보던중 다음과 같은 것을 발견!~!

    http://www.gungume.com/87

    이를 통해 해결함..

    void CIssueDlg::OnColumnclickListSource(NMHDR *pNMHDR, LRESULT *pResult)
    {
    LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
    // 리스트컨트롤 칼럼 클릭할 때 데이터 정렬

    // 클릭한 칼럼의 인덱스
    int nColumn = pNMLV->iSubItem;

    // 현재 리스트 컨트롤에 있는 데이터 총 자료 개수만큼 저장
    for(int i=0; i<m_sourceList->GetItemCount(); i++)
    {
    m_sourceList->SetItemData(i, i);
    }

    // 정렬 방식 지정(Ascend, Descend)
    m_bResultDirect = !m_bResultDirect;

    // 정렬 관련된 구조체 변수 생성 및 데이터 초기화
    SORTPARAM sortparams;
    sortparams.pList = m_sourceList;
    sortparams.iSortColumn = nColumn;
    sortparams.bSortDirect = m_bResultDirect;

    // 정렬 함수 호출
    m_sourceList->SortItems(&CompareFunc, (LPARAM)&sortparams );

    *pResult = 0;
    }
    2011.02.21 10:57 신고
  • 프로필사진 박재성 위에 댓글 에러가 @_@... 전 떠서 수정.

    LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
    // 리스트컨트롤 칼럼 클릭할 때 데이터 정렬

    // 클릭한 칼럼의 인덱스
    int nColumn = pNMLV->iSubItem;

    // 현재 리스트 컨트롤에 있는 데이터 총 자료 개수만큼 저장
    for (int i = 0; i<m_customerC.GetItemCount(); i++)
    {
    m_customerC.SetItemData(i, i);
    }

    // 정렬 방식 지정(Ascend, Descend)
    m_bResultDirect = !m_bResultDirect;

    // 정렬 관련된 구조체 변수 생성 및 데이터 초기화
    SORTPARAM sortparams;
    sortparams.pList = &m_customerC;
    sortparams.iSortColumn = nColumn;
    sortparams.bSortDirect = m_bResultDirect;

    // 정렬 함수 호출
    m_customerC.SortItems(&CompareFunc, (LPARAM)&sortparams);

    *pResult = 0;
    2017.10.16 17:17 신고
댓글쓰기 폼