카테고리 없음

MFC list control에서 헤더를 누르면 정렬되는 코드

가별이 2014. 1. 16. 17:04

떠도는 소스는 제대로 안되서 한참 애먹고 겨우 잡았다.


일단 다이얼로그 헤더 파일에 다음 내용을 추가한다. 다이얼로그 이름.hㅍ파일로 헤더파일 모여있는 곳에 있다.


#include "afxcmn.h"

#include "resource.h"

#include "afxwin.h"


// CDlgRealtime 대화 상자입니다.


class CDlgRealtime : public CDialogEx

{

DECLARE_DYNAMIC(CDlgRealtime)


public:

CDlgRealtime(CWnd* pParent = NULL); // 표준 생성자입니다.

virtual ~CDlgRealtime();


// 대화 상자 데이터입니다.

enum { IDD = IDD_DLG_REALTIME };


BOOL m_bAscending;

struct SORTPARAM

{

int iSortColumn;

bool bSortDirect;

CListCtrl *pList; 

};



protected:

virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 지원입니다.


DECLARE_MESSAGE_MAP()

public:

CListCtrl m_lsRealtime;

virtual BOOL OnInitDialog();

void InitControls();

void RelocationControls();

afx_msg void OnHdnItemclickList1(NMHDR *pNMHDR, LRESULT *pResult);

static int CALLBACK CompareItem(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);

protected:

afx_msg LRESULT OnRealtimeRefresh(WPARAM wParam, LPARAM lParam);




이제 다이얼로그 이름.cpp를 편집할 차례다.


BEGIN_MESSAGE_MAP(CDlgRealtime, CDialogEx)

ON_MESSAGE(WM_REALTIME_REFRESH, &CDlgRealtime::OnRealtimeRefresh)

ON_NOTIFY(HDN_ITEMCLICK, 0, &CDlgRealtime::OnHdnItemclickList1)

END_MESSAGE_MAP()


메세지 맵에 ON_NOTIFY를 추가한다. 가운데의  &CDlgRealtime  부분은 자기 다이얼로그 클래스 이름에 맞게 바꾼다.

그리고 cpp 파일 맨 아래에 다음의 내용을 붙인다.

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

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

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

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

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

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

*pResult = 0;
}

int CALLBACK CDlgRealtime::CompareItem(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
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);
}

빨갛게 칠한 부분을 자기 리스트 콘트롤 이름에 맞게 바꾼다.

가장 마지막에 애 먹은 부분은
//int nColumn = pNMLV->iSubItem;
int nColumn = pNMLV->iItem;
이 부분으로 iSubItem을 쓰면 0이 나와서 다른 컬럼을 골라도 정렬이 안된다.