Post List

2015년 4월 8일 수요일

XTPReportControl 사용 가이드 ( Xtreme Toolkit Pro : Report Control )

* 본격적인 내용에 앞서...

예전에 C# Project를 진행할 당시에 DevExpress 에 관련한 한글로 된 자료가 없어서,
Naver Blog에 관련 기능들을 정리한 적이 있습니다. ( http://icysword.blog.me )

MFC에서 사용할 만한 UI Component 중 가장 많이 사용하는 것으로 Codejock 의 eXtream Toolkit Pro (XTP) 를 꼽을 수 있습니다.
하지만, 이 녀석은 C# 같이 마우스로 찍. 찍. 찍. 해서 사용이 안되서 사용이 힘들더군요.
한글로 된 사용설명 또한 찾기 힘들구요. (아에 없는 듯 합니다. ㅠㅠ)

XTP 의 모든 Component 들의 사용 가이드는 만들 수 없더라도, 제가 사용했던 것들에 대해서는 정리해서 올릴 예정입니다.

그리고 제가 어떤 방법으로 이렇게 사용이 가능했는지에 대한 설명도 같이 드리겠습니다.

XTP의 설치 및 Visual Studio 에서의 설정은 제 Blog에 이미 설명해 놓았으니 넘어가겠습니다.

http://devluna.blogspot.kr/search/label/XtremeToolkit

위 Link에서 관련 글들의 확인이 가능합니다.

* XTPReportControl

Report Control 은 List를 Column 단위로 관리하면서 Record를 Row로 표현하는데 좋은 Control 입니다.
Grid와는 조금 다릅니다.

먼저 필자는 XTP 16.2 버전을 설치했으며,
Visual Studio 2010을 사용했습니다.

XTP 16.2가 VS2012까지밖에 지원하지 않아서,
Visual Studio 2015 CTP에서 MFC Project를 VS2010 용으로 생성하여서 진행하였습니다.

이제부터 예제를 통해서 사용법을 설명해 드리겠습니다.

1. Project 생성

  MFC Application ProjectDialog를 선택하여 생성하였습니다.
(Project Wizard 목록에는 Toolkit Pro용 Project도 있지만, 좀 더 일반적인 방법으로 접근하고자 MFC Application Project로 진행하였습니다.)
  Project 명은 XTPReportTest 로 하였으며,
  세부 설정은 다음 그림과 같이 하고 바로 Finish를 눌렀습니다.



당연히 Project를 만들었으면, 일단 F5를 눌러서 정상적으로 빌드가 되어서 Dialog가 뜨는지 확인을 하였습니다.

2. XTP 설정

stdafx.h 파일을 열어서 적당한 위치에 XTP용 해더파일을 추가하였습니다.

#include <XTToolkitPro.h>

그런 다음 다시 F7을 눌러서 빌드를 실행하였습니다.
빌드 출력창에 XTP 관련된 내용이 나오는 것을 확인하고, 빌드가 성공적으로 된것까지 확인을 하였습니다.

3. Dialog에 XTPReportControl 올리기

 MFC의 Dialog 편집창에서 마우스로 처리가 불가능합니다.
 (제가 모르는 것일 수도 있으니, 혹시 하는법 아시는분 계시면 알려주시면 감사하겠습니다.)

 그래서 저는 XTP 설치시 같이 설치되는 Sample Project를 보고 거기서 관련 Code들을 보고 적용하였습니다.

resource.h 파일을 열어서 ReportControl의 ID를 생성합니다.

#define IDR_MAINFRAME                        128
#define IDM_ABOUTBOX                         0x0010
#define IDD_ABOUTBOX                         100
#define IDS_ABOUTBOX                         101
#define IDD_XTPREPORTTEST_DIALOG             102
#define IDC_REPORT                           103

103번으로 추가하였습니다.

그런 다음 리소스 파일 (XTPReportTest.rc)을 Code보기로 열어봅니다.



파일 안에서 Dialog 디자인 관련 부분을 찾아서 ReportControl을 한줄 추가 합니다.

IDD_XTPREPORTTEST_DIALOG DIALOGEX  0, 0, 320, 200
STYLE DS_SHELLFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_THICKFRAME | WS_SYSMENU
EXSTYLE WS_EX_APPWINDOW
CAPTION "XTPReportTest"
FONT 8, "MS Shell Dlg"
BEGIN
    DEFPUSHBUTTON   "OK",IDOK,209,179,50,14
    PUSHBUTTON      "Cancel",IDCANCEL,263,179,50,14
    CTEXT           "TODO: Place dialog controls here.",IDC_STATIC,10,96,300,8
    CONTROL          "", IDC_REPORT, "XTPReport", WS_TABSTOP, 10,10,300,150, WS_EX_STATICEDGE
END

그리고 쓸데없는 TEXT 한줄은 지웠습니다.

Dialog 해더 파일 (XTPReportTestDlg.h) 을 열어서 ReportControl을 멤버변수로 선언해 주시구요.

CXTPReportControl m_wndReport;

cpp 파일 (XTPReportTestDlg.cpp) 을 열어서 Control 과 멤버 변수를 연결시켜 줍니다.

void CXTPReportTestDlg::DoDataExchange(CDataExchange* pDX)
{
        CDialogEx::DoDataExchange(pDX);
        DDX_Control(pDX, IDC_REPORT, m_wndReport);
}

그런 다음 F5를 눌러서 실행해 봅니다.
정상적으로 따라오셨으면 Dialog가 실행됩니다.



화면에 텅빈 ReportControl이 추가된 것이 확인가능합니다.
크기나 이동은 이제 리소스 편집창에서 마우스로 가능합니다.

4. XTPReportControl 의 Column 설정

먼저 해더 파일을 열어서 Column을 enum으로 정의하였습니다.

enum REPORT_COLUMN
{
   COLUMN_ID = 0,
   COLUMN_NAME,
   COLUMN_ADDR,
   COLUMN_GRADE
};

cpp파일을 열어서

BOOL CXTPReportTestDlg::OnInitDialog()

안에다가 다음과 같이 Column을 설정합니다.

m_wndReport.ModifyStyle(0, WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_TABSTOP);
m_wndReport.GetReportHeader()->AllowColumnRemove(FALSE);

m_wndReport.AddColumn(new CXTPReportColumn(COLUMN_ID, _T("ID"), 200));
m_wndReport.AddColumn(new CXTPReportColumn(COLUMN_NAME, _T("Name"), 200));
m_wndReport.AddColumn(new CXTPReportColumn(COLUMN_ADDR, _T("Addr"), 200));
m_wndReport.AddColumn(new CXTPReportColumn(COLUMN_GRADE, _T("Grade"), 200, TRUE, -1, FALSE, FALSE));

Column의 Width는 모두 200으로 하였으며, 마지막 줄인 COLUMN_GRADE는 화면에 보이지 않게 설정하였습니다.

다시 F5를 눌러서 제대로 반영되었는지 확인해 봅니다.




5. Record Data 등록

위 Column을 등록한 바로 아래에 다음과 같이 예제 Record들을 등록해 봅시다.

auto AddReport = [&](CString p_sID, CString p_sName, CString p_sAddr, CString p_sGrade)
{
   CXTPReportRecord* pRecord = m_wndReport.AddRecord(new CXTPReportRecord());
   pRecord->AddItem(new CXTPReportRecordItemText(p_sID));
   pRecord->AddItem(new CXTPReportRecordItemText(p_sName));
   pRecord->AddItem(new CXTPReportRecordItemText(p_sAddr));
   pRecord->AddItem(new CXTPReportRecordItemText(p_sGrade));
};

AddReport(_T("ID001"), _T("Yun Seok-joon"), _T("Sangam-dong"), _T("VVIP"));
AddReport(_T("ID002"), _T("Luna Star"), _T("Sky"), _T("Star"));
AddReport(_T("ID003"), _T("Demilune"), _T("Universe"), _T("Dark"));

m_wndReport.Populate();

다시 F5를 눌러서 실행하면 Record들이 등록된 것을 확인 할 수 있습니다.

6. 관련 동작 (Event) 등록하기

XTPReportControl에서 동작가능한 Event 들은 XTP 설치시 같이 설치되는 Document에서 확인이 가능합니다.
Online Help를 실행하여 Report Control 아래에 있는 Macros 를 보면 관련 내용들이 나옵니다.



위 화면에서 Ctrl + F 를 눌러서 Click으로 검색해보면, XTP_NM_REPORT_LBUTTONDOWN 이라는 Event 를 찾을 수 있습니다.
아래 설명에 시키는대로 하면 마우스 클릭 이벤트에 대해서 처리가 가능합니다.
(이번 예제에서는 다루지 않겠습니다.)


다시 SELECT로 검색을 해보았습니다.
XTP_NM_REPORT_SELCHANGED 라는 매크로가 검색되었습니다.
선택된 Record가 변경되었을 때 실행되는 Event 입니다.
이 것을 한번 적용해 보겠습니다.



먼저 해더파일을 열어서
afx_msg void OnReportSelChanged(NMHDR* pNMHDR, LRESULT*);
라는 이벤트 함수를 추가합니다.

// Generated message map functions
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnReportSelChanged(NMHDR* pNMHDR, LRESULT*);
DECLARE_MESSAGE_MAP()

그런 다음 cpp파일을 열어서 Message Map에 관련 내용을 추가 한 뒤

BEGIN_MESSAGE_MAP(CXTPReportTestDlg, CDialogEx)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_NOTIFY(XTP_NM_REPORT_SELCHANGED, IDC_REPORT, OnReportSelChanged)
END_MESSAGE_MAP()

관련 함수를 구현합니다.

afx_msg void CXTPReportTestDlg::OnReportSelChanged(NMHDR* pNMHDR, LRESULT*)
{
    CXTPReportRow* pRow = m_wndReport.GetFocusedRow();
    CXTPReportRecord* pRecord = pRow->GetRecord();
    CXTPReportRecordItem* pItem = pRecord->GetItem(COLUMN_GRADE);
    CString sGrade = pItem->GetCaption();

    AfxMessageBox(sGrade);
}

내용은 선택된 Record에서 우리가 숨긴 Grade 정보를 팝업창으로 보여주는 코드입니다.

위 함수 내용의 5줄을 그냥 한줄로도 표현이 됩니다.

AfxMessageBox(m_wndReport.GetFocusedRow()->GetRecord()->GetItem(COLUMN_GRADE)->GetCaption());

예전에는 아래와 같이 한 줄로 표현하는게 멋있어 보였습니다.
그것보다도 왠지 따로 명시적으로 변수로 선언을 안하니깐 메모리도 절약될것 같고...
하지만 지금은 오히려 아래가 더 병맛같이 보이네요.
(병맛같지만 왠지 멋있어 ? 뭐 그런 ???)
디버깅도 더 힘들구요.
위와 같이 따로따로 명시적으로 선언을 하면 디버깅시 훨씬 편리합니다.
그리고, 명시적으로 선언한다고 메모리를 더 잡아먹거나 그러진 않습니다.
시대가 어느 시댄데... 컴파일러가 어련히 알아서 잘 해주겠죠.

그리고 F5를 눌러서 실행하면 아래와 같이 선택된 레코드의 Grade가 보여집니다.



이상으로 XTPReportControl 사용 가이드에 대한 설명은 마치겠습니다.

댓글 없음:

댓글 쓰기