도서 관리 프로그램 – 7. 자세히 보기 대화상자 정의[MFC]

VerifyDialog.h

자세히 보기 대화상자

유튜브에 무료 동영상 강의를 업로드하였습니다.

자세히 보기 대화 상자는 VerifyDialog 이름의 클래스로 정의할게요.

자세히 보기는 CDialogEx 형식 외에 도서 추가 이벤트 핸들러와 도서 삭제 이벤트 핸들러를 기반으로 추상 메서드를 재정의 합니다.

class VerifyDilaog : public CDialogEx,
	public AddBookEventHandler,
	public RemoveBookEventHandler
public:
	virtual void AddedBook(Book* book);
	virtual void RemovedBook(int bno);

컨트롤과 매핑하는 변수를 캡슐화합니다.

private:
	CComboBox cbox_no;
	CString title;
	CString content;
	CStatic pbox_img;
	COleDateTime pubdate;

OnInitDialog 메서드를 재정의합니다.

	virtual BOOL OnInitDialog();

IDC_COMBO_BNO 컴보 박스 컨트롤의 선택항목 변경 처리기를 캡슐화합니다.

	afx_msg void OnCbnSelchangeComboBno();

다음은 VerifyDialog.h 파일의 소스 코드 전체 내용입니다.

#pragma once
#include "afxdialogex.h"
#include "BookEventHandler.h"

// VerifyDilaog 대화 상자

class VerifyDilaog : public CDialogEx,
	public AddBookEventHandler,
	public RemoveBookEventHandler
{
	DECLARE_DYNAMIC(VerifyDilaog)

public:
	VerifyDilaog(CWnd* pParent = nullptr);   // 표준 생성자입니다.
	virtual ~VerifyDilaog();

// 대화 상자 데이터입니다.
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_DIALOG_VERIFY };
#endif

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

	DECLARE_MESSAGE_MAP()
private:
	CComboBox cbox_no;
	CString title;
	CString content;
	CStatic pbox_img;
	COleDateTime pubdate;
public:	
	virtual void AddedBook(Book* book);	
	virtual void RemovedBook(int bno);
	virtual BOOL OnInitDialog();
	afx_msg void OnCbnSelchangeComboBno();
};

VerifyDialog.cpp

OnInitDialog

도서 관리자 개체에게 도서 추가 및 삭제 이벤트를 수신할 수 있게 이벤트 핸들러를 등록합니다.

	BookManager &bm = BookManager::GetBookManager();
	bm.AddABEventHandler(this);//도서 추가하면 나한테 알려줘
	bm.AddRBEventHandler(this);//도서 삭제하면 나한테 알려줘

전체 도서 번호 목록을 얻어와서 콤보 박스에 추가합니다.

	NList* nlist = new NList();
	bm.GetBookNoList(nlist);
	NIter seek = nlist->begin();
	NIter end = nlist->end();
	wchar_t buf[256];
	for (; seek != end; ++seek)
	{
		wsprintf(buf, TEXT("%d"), (*seek));
		cbox_no.AddString(buf);
	}

다음은 OnInitDialog 메서드 코드입니다.

BOOL VerifyDilaog::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// TODO:  여기에 추가 초기화 작업을 추가합니다.
	BookManager &bm = BookManager::GetBookManager();
	bm.AddABEventHandler(this);//도서 추가하면 나한테 알려줘
	bm.AddRBEventHandler(this);//도서 삭제하면 나한테 알려줘
	NList* nlist = new NList();
	bm.GetBookNoList(nlist);
	NIter seek = nlist->begin();
	NIter end = nlist->end();
	wchar_t buf[256];
	for (; seek != end; ++seek)
	{
		wsprintf(buf, TEXT("%d"), (*seek));
		cbox_no.AddString(buf);
	}

	return TRUE;  // return TRUE unless you set the focus to a control
	// 예외: OCX 속성 페이지는 FALSE를 반환해야 합니다.
}

AddedBook

도서 추가 이벤트를 수신하였을 때 동작하는 핸들러 메서드입니다.

추가한 도서 번호를 콤보 박스에 넣는 작업을 수행합니다.

void VerifyDilaog::AddedBook(Book* book)
{
	wchar_t buf[256];
	wsprintf(buf, TEXT("%d"), book->GetNo());
	cbox_no.AddString(buf);
}

RemoveBook

도서 삭제 이벤트를 수신하였을 때 동작하는 핸들러 메서드입니다.

콤보 박스에 있는 도서 번호와 삭제한 도서 번호가 같은 항목을 삭제합니다.

void VerifyDilaog::RemovedBook(int bno)
{
	int cnt = cbox_no.GetCount();
	int bno2;
	CString nos;
	for (int i = 0; i < cnt; i++)
	{
		cbox_no.GetLBText(i, nos);
		bno2 = _wtoi(nos);
		if (bno == bno2)
		{
			cbox_no.DeleteString(i);
			return;
		}
	}
}

OnCbnSelchangeComboBno

IDC_COMBO_BNO 콤보 박스의 항목 선택을 변경하였을 때 처리기입니다.

현재 콤보 박스 선택 항목을 얻어옵니다.

	int index = cbox_no.GetCurSel();

선택항목이 없을 때 제목, 내용, 출판일을 디폴트 값으로 설정합니다.

	if (index == -1)
	{
		title = TEXT("");
		content = TEXT("");
		pubdate.SetDate(2023, 1, 1);
	}

선택 항목이 있을 때 선택 항목 도서 번호에 대응하는 도서 개체를 얻어와서 컨트롤 변수에 매핑합니다.

	else
	{
		CString nos;
		cbox_no.GetLBText(index, nos);
		int bno = _wtoi(nos);
		BookManager& bm = BookManager::GetBookManager();
		Book *book = bm.GetBook(bno);
		if (book == 0)
		{
			throw "이런... 잘못 짰나봐. 빨리 버그 잡어라...";
		}
		title = book->GetTitle();
		content = book->GetContent();
		pubdate = book->GetPubdate();
		CImage cimg;
		cimg.Load(book->GetImage());
		CDC* cdc = pbox_img.GetDC();
		RECT rt;
		pbox_img.GetClientRect(&rt);
		cimg.StretchBlt(*cdc, 0, 0, rt.right, rt.bottom, SRCCOPY);
	}

컨트롤 변수의 값을 컨트롤에 매핑할 수 있게 UpdateData 메서드를 호출합니다.

	UpdateData(0);//변수=>컨트롤

다음은 OnCbnSelchangeComboBno 메서드 코드 내용입니다.

void VerifyDilaog::OnCbnSelchangeComboBno()
{
	// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
	int index = cbox_no.GetCurSel();
	if (index == -1)
	{
		title = TEXT("");
		content = TEXT("");
		pubdate.SetDate(2023, 1, 1);
	}
	else
	{
		CString nos;
		cbox_no.GetLBText(index, nos);
		int bno = _wtoi(nos);
		BookManager& bm = BookManager::GetBookManager();
		Book *book = bm.GetBook(bno);
		if (book == 0)
		{
			throw "이런... 잘못 짰나봐. 빨리 버그 잡어라...";
		}
		title = book->GetTitle();
		content = book->GetContent();
		pubdate = book->GetPubdate();
		CImage cimg;
		cimg.Load(book->GetImage());
		CDC* cdc = pbox_img.GetDC();
		RECT rt;
		pbox_img.GetClientRect(&rt);
		cimg.StretchBlt(*cdc, 0, 0, rt.right, rt.bottom, SRCCOPY);
	}
	UpdateData(0);//변수=>컨트롤
}

VerifyDilaog.cpp 전체 소스 코드 내용

// VerifyDilaog.cpp: 구현 파일
//

#include "pch.h"
#include "도서 관리 프로그램.h"
#include "afxdialogex.h"
#include "VerifyDilaog.h"
#include "BookManager.h"

// VerifyDilaog 대화 상자

IMPLEMENT_DYNAMIC(VerifyDilaog, CDialogEx)

VerifyDilaog::VerifyDilaog(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_DIALOG_VERIFY, pParent)
	, title(_T(""))
	, content(_T(""))
	, pubdate(COleDateTime::GetCurrentTime())
{

}

VerifyDilaog::~VerifyDilaog()
{
}

void VerifyDilaog::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_COMBO_BNO, cbox_no);
	DDX_Text(pDX, IDC_EDIT_TITLE, title);
	DDX_Text(pDX, IDC_EDIT_CONTENT, content);
	DDX_Control(pDX, IDC_STATIC_IMG, pbox_img);
	DDX_DateTimeCtrl(pDX, IDC_DATETIMEPICKER1, pubdate);
}


BEGIN_MESSAGE_MAP(VerifyDilaog, CDialogEx)
	ON_CBN_SELCHANGE(IDC_COMBO_BNO, &VerifyDilaog::OnCbnSelchangeComboBno)
END_MESSAGE_MAP()


// VerifyDilaog 메시지 처리기


BOOL VerifyDilaog::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// TODO:  여기에 추가 초기화 작업을 추가합니다.
	BookManager &bm = BookManager::GetBookManager();
	bm.AddABEventHandler(this);//도서 추가하면 나한테 알려줘
	bm.AddRBEventHandler(this);//도서 삭제하면 나한테 알려줘
	NList* nlist = new NList();
	bm.GetBookNoList(nlist);
	NIter seek = nlist->begin();
	NIter end = nlist->end();
	wchar_t buf[256];
	for (; seek != end; ++seek)
	{
		wsprintf(buf, TEXT("%d"), (*seek));
		cbox_no.AddString(buf);
	}

	return TRUE;  // return TRUE unless you set the focus to a control
	// 예외: OCX 속성 페이지는 FALSE를 반환해야 합니다.
}
void VerifyDilaog::AddedBook(Book* book)
{
	wchar_t buf[256];
	wsprintf(buf, TEXT("%d"), book->GetNo());
	cbox_no.AddString(buf);
}

void VerifyDilaog::RemovedBook(int bno)
{
	int cnt = cbox_no.GetCount();
	int bno2;
	CString nos;
	for (int i = 0; i < cnt; i++)
	{
		cbox_no.GetLBText(i, nos);
		bno2 = _wtoi(nos);
		if (bno == bno2)
		{
			cbox_no.DeleteString(i);
			return;
		}
	}
}
void VerifyDilaog::OnCbnSelchangeComboBno()
{
	// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
	int index = cbox_no.GetCurSel();
	if (index == -1)
	{
		title = TEXT("");
		content = TEXT("");
		pubdate.SetDate(2023, 1, 1);
	}
	else
	{
		CString nos;
		cbox_no.GetLBText(index, nos);
		int bno = _wtoi(nos);
		BookManager& bm = BookManager::GetBookManager();
		Book *book = bm.GetBook(bno);
		if (book == 0)
		{
			throw "이런... 잘못 짰나봐. 빨리 버그 잡어라...";
		}
		title = book->GetTitle();
		content = book->GetContent();
		pubdate = book->GetPubdate();
		CImage cimg;
		cimg.Load(book->GetImage());
		CDC* cdc = pbox_img.GetDC();
		RECT rt;
		pbox_img.GetClientRect(&rt);
		cimg.StretchBlt(*cdc, 0, 0, rt.right, rt.bottom, SRCCOPY);
	}
	UpdateData(0);//변수=>컨트롤
}