CListCtrl with CView in MFC
프로젝트를 생성할 때 CView 기반으로 뷰클래스를 설정하고 프로젝트가 생성된 후에 뷰 클래스에 멤버변수로 CListCtrl 을 선언한다
//CMyView.h
#pragma once
class CMyView : public CView
{
protected: // serialization에서만 만들어집니다.
CMyView();
DECLARE_DYNCREATE(CMyView)
// 특성입니다.
public:
CMyDoc* GetDocument() const;
CListCtrl m_ListCtrl;
CMyView.cpp 파일을 열고 함수에 다음과 같이 입력한다
void CMyView ::OnInitialUpdate()
{
CView::OnInitialUpdate();
// TODO: Add your specialized code here and/or call the base class
m_ListCtrl.Create(
WS_CHILD|WS_VISIBLE|WS_BORDER|LVS_REPORT|LVS_EDITLABELS,
CRect(0,0,800,500), this, NULL);
m_ListCtrl.SetExtendedStyle( LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES );
m_ListCtrl.DeleteAllItems();
m_ListCtrl.InsertColumn(0, _T("순번"), LVCFMT_LEFT, 40, -1);
m_ListCtrl.InsertColumn(1, _T("환자이름"), LVCFMT_LEFT, 70, -1);
m_ListCtrl.InsertColumn(2, _T("환자번호"), LVCFMT_LEFT, 70, -1);
m_ListCtrl.InsertColumn(3, _T("환자성별"), LVCFMT_LEFT, 70, -1);
m_ListCtrl.InsertColumn(4, _T("진료날짜"), LVCFMT_LEFT, 70, -1);
m_ListCtrl.InsertColumn(5, _T("사진파일"), LVCFMT_LEFT, 600, -1);
//칼럼 추가 인덱스, 칼람명, 정렬방향, 칼럼길이, 서브아이템 갯수
int seq = 0;
CString seq_string;
seq_string.Format(_T("%d"),seq);
CString patientName =_T("홍길동");
CString patientID =_T("365412");
CString patientSex =_T("M");
CString studyDate =_T("20120321");
CString dcmFullPath =_T("D:\\DCM ROOT\\365412\\20123021\\홍길동.dcm");
m_ListCtrl.InsertItem(seq,seq_string);
m_ListCtrl.SetItem(seq,1,LVIF_TEXT,patientName,0,0,0,NULL);
m_ListCtrl.SetItem(seq,2,LVIF_TEXT,patientID,0,0,0,NULL);
m_ListCtrl.SetItem(seq,3,LVIF_TEXT,patientSex,0,0,0,NULL);
m_ListCtrl.SetItem(seq,4,LVIF_TEXT,studyDate,0,0,0,NULL);
m_ListCtrl.SetItem(seq,5,LVIF_TEXT,dcmFullPath,0,0,0,NULL);
seq = 1;
seq_string.Format(_T("%d"),seq);
patientName =_T("박환자");
patientID =_T("145632");
patientSex =_T("F");
studyDate =_T("20130215");
dcmFullPath =_T("D:\\DCM ROOT\\145632\\20130215\\박환자.dcm");
m_ListCtrl.InsertItem(seq,seq_string);
m_ListCtrl.SetItem(seq,1,LVIF_TEXT,patientName,0,0,0,NULL);
m_ListCtrl.SetItem(seq,2,LVIF_TEXT,patientID,0,0,0,NULL);
m_ListCtrl.SetItem(seq,3,LVIF_TEXT,patientSex,0,0,0,NULL);
m_ListCtrl.SetItem(seq,4,LVIF_TEXT,studyDate,0,0,0,NULL);
m_ListCtrl.SetItem(seq,5,LVIF_TEXT,dcmFullPath,0,0,0,NULL);
}
위의 코드를 빌드하고 실행하면 다음과 같이 CListCtrl 이 제대로 작동하는 것을 볼 수 있다.
위의 코드만으로도 데이터를 정렬하여 출력하는데는 문제가 없지만 리스트에서 클릭하거나 더블클릭하더라도 아무런 반응이 없으므로 리스트를 사용하기 위해서는 메시지 핸들러가 필요함을 알 수 있다.
메시지 핸들러 함수는 CListCtrl 클래스를 상속하여 하위 클래스를 정의하고 그 안에 메시지 핸들러 함수를 정의할 수 있기 때문에 CListCtrl 클래스를 상속하여 새로운 하위 콘트롤을 새로 생성해야 함을 의미한다. CListCtrl 클래스를 상속한 하위 클래스가 DCMListCtrl 이라고 할 때, Class View 에서 DCMListCtrl 클래스에 마우스 우측을 눌러 Class Wizard를 열고 Messages 탭을 선택하여 NM_DBLCLK 메시지를 더블클릭하여 OnNMDblclk() 핸들러를 코드에 추가하고 다음과 같이 입력하면 리스트 항목에서 더블클릭할 경우 해당 행의 정보를 가져와서 보여줄 수 있게 된다. 뷰 클래스를 새로 생성하는 것이 아니라 뷰 클래스는 위의 것을 그대로 사옹하고 콘트롤 클래스를 새로 생성하여 뷰 클래스에서 사용함을 의미한다 단지 뷰 클래스에서는 멤버변수의 자료형만 변경해주면 된다.
헤더파일을 열고 아래처럼 변경한다
//CMyView.h
#include "DCMListCtrl.h"
#pragma once
class CMyView : public CView
{
protected: // serialization에서만 만들어집니다.
CMyView();
DECLARE_DYNCREATE(CMyView)
// 특성입니다.
public:
CMyDoc* GetDocument() const;
//CListCtrl m_ListCtrl;
DCMListCtrl m_ListCtrl; // CListCtrl 대신에 CListCtrl 클래스의 하위 클래스로 생성한 DCMListCtrl 클래스를 사용한다
DCMListCtrl.cpp ( CListCtrl 의 하위 클래스로 생성한 DCMListCtrl 클래스에 NM_DBLCLK 메시지 핸들러를 추가한다 )
// ON_NMDBLCLK 메시지 핸들러를 추가한다
void DCMListCtrl::OnNMDblclk(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
*pResult = 0;
// TODO: Add your control notification handler code here
//AfxMessageBox(_T("더블클릭"));
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
int itemindex = pNMListView->iItem;
if( itemindex != -1 )
{
CString strNum = GetItemText( itemindex, 0 );
CString strValue = GetItemText( itemindex, 1 );
CString strFileName = GetItemText( itemindex, 5 );
AfxMessageBox(strNum+", "+strValue+", "+strFileName);
}
*pResult = 0;
}
위의 코드를 빌드하고 실행하여 출력된 리스트에서 두번째 행을 더블클릭했을 경우에 아래처럼 보이게 된다