유튜브에 무료 동영상 강의를 업로드하였습니다.
ModifyDialog.h
변경 대화상자는 CDialogEx 기반 클래스에서 파생합니다. 이 외에도 도서 추가 이벤트와 삭제 이벤트를 수신하기 위한 이벤트 핸들러를 기반으로 구현 약속합니다.
class ModifyDialog : public CDialogEx,
public AddBookEventHandler,
public RemoveBookEventHandler
public:
virtual void AddedBook(Book* book);
virtual void RemovedBook(int bno);
컨트롤과 매핑하는 변수를 캡슐화합니다.
private:
CListCtrl list_book;
CStatic pic_img;
COleDateTime pubdate;
CString content;
CString image;
CEdit edit_cont;
초기화 과정의 OnInitDialog 메서드를 재정의합니다.
virtual BOOL OnInitDialog();
IDC_EDIT_CONTENT 컨트롤에서 엔터 키를 입력 처리하기 위해 PreTranslateMessage 메서드를 재정의합니다.
virtual BOOL PreTranslateMessage(MSG* pMsg);
IDC_LIST_BOOK 선택항목 변경 처리기와 세 개의 버튼 클릭 처리기를 캡슐화합니다.
afx_msg void OnLvnItemchangedListBook(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnBnClickedButtonCancel();
afx_msg void OnBnClickedButtonImg();
afx_msg void OnBnClickedButtonSub();
다음은 ModifyDialog.h 파일의 전체 코드 내용입니다.
#pragma once
#include "afxdialogex.h"
#include "BookEventHandler.h"
#include "BookManager.h"
// ModifyDialog 대화 상자
class ModifyDialog : public CDialogEx,
public AddBookEventHandler,
public RemoveBookEventHandler
{
DECLARE_DYNAMIC(ModifyDialog)
public:
ModifyDialog(CWnd* pParent = nullptr); // 표준 생성자입니다.
virtual ~ModifyDialog();
// 대화 상자 데이터입니다.
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_DIALOG_MODIFY };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 지원입니다.
DECLARE_MESSAGE_MAP()
private:
CListCtrl list_book;
CStatic pic_img;
COleDateTime pubdate;
CString content;
CString image;
CEdit edit_cont;
public:
virtual void AddedBook(Book* book);
virtual void RemovedBook(int bno);
virtual BOOL OnInitDialog();
virtual BOOL PreTranslateMessage(MSG* pMsg);
afx_msg void OnLvnItemchangedListBook(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnBnClickedButtonCancel();
afx_msg void OnBnClickedButtonImg();
afx_msg void OnBnClickedButtonSub();
};
ModifyDialog.cpp
이제 소스 코드를 구현합시다.
AddedBook
도서 추가 이벤트를 수신하여 처리하는 이벤트 핸들러입니다.
추가한 도서 번호를 얻어온 후에 리스트에 항목 추가합니다.
void ModifyDialog::AddedBook(Book* book)
{
int bno = book->GetNo();
CString title = book->GetTitle();
wchar_t nbuf[256] = TEXT("");
wsprintf(nbuf, TEXT("%d"), bno);
int i = list_book.GetItemCount();
list_book.InsertItem(i, nbuf);
list_book.SetItemText(i, 1, title);
}
RemovedBook
도서 삭제 이벤트를 수신하여 처리하는 이벤트 핸들러입니다.
IDC_LIST_BOOK 컨트롤에서 삭제한 도서 번호에 대응하는 항목를 제거합니다.
void ModifyDialog::RemovedBook(int bno)
{
LVITEM li = { 0 };
wchar_t buf[256] = TEXT("");
int cnt = list_book.GetItemCount();
for (int i = 0; i < cnt; i++)
{
li.iItem = i;
li.iSubItem = 0;
li.mask = LVIF_TEXT;
li.pszText = buf;
li.cchTextMax = 256;
list_book.GetItem(&li);
if (bno == _wtoi(buf))
{
list_book.DeleteItem(i);
return;
}
}
}
OnInitDialog
IDC_LIST_BOOK 컨트롤에 도서 번호와 제목 항목을 추가합니다.
list_book.InsertColumn(0, TEXT("No"), 0, 50);
list_book.InsertColumn(1, TEXT("제목"), 0, 140);
도서 관리자 개체에 도서 추가 및 삭제 이벤트 핸들러를 등록합니다.
BookManager& bm = BookManager::GetBookManager();
bm.AddABEventHandler(this);
bm.AddRBEventHandler(this);
전체 도서 번호 목록을 얻어온 후에 리스트에 항목 추가합니다.
bm.GetBookNoList(&nlist);
NIter seek = nlist.begin();
NIter end = nlist.end();
wchar_t nbuf[256]=TEXT("");
Book* book = 0;
for (int i=0; seek != end; ++seek,i++)
{
wsprintf(nbuf, TEXT("%d"), (*seek));
list_book.InsertItem(i, nbuf);
book = bm.GetBook(*seek);
list_book.SetItemText(i, 1, book->GetTitle());
}
다음은 OnInitDialog 메서드의 코드 내용입니다.
BOOL ModifyDialog::OnInitDialog()
{
__super::OnInitDialog();
// TODO: 여기에 추가 초기화 작업을 추가합니다.
list_book.InsertColumn(0, TEXT("No"), 0, 50);
list_book.InsertColumn(1, TEXT("제목"), 0, 140);
BookManager& bm = BookManager::GetBookManager();
bm.AddABEventHandler(this);
bm.AddRBEventHandler(this);
NList nlist;
bm.GetBookNoList(&nlist);
NIter seek = nlist.begin();
NIter end = nlist.end();
wchar_t nbuf[256]=TEXT("");
Book* book = 0;
for (int i=0; seek != end; ++seek,i++)
{
wsprintf(nbuf, TEXT("%d"), (*seek));
list_book.InsertItem(i, nbuf);
book = bm.GetBook(*seek);
list_book.SetItemText(i, 1, book->GetTitle());
}
return TRUE; // return TRUE unless you set the focus to a control
// 예외: OCX 속성 페이지는 FALSE를 반환해야 합니다.
}
OnLvnItemchangedListBook와 OnBnClickedButtonCancel
IDC_LIST_BOOK 컨트롤 선택 항목 변경 처리기에서 할 작업과 취소 버튼 클릭 처리기에서 할 작업은 같습니다.
둘 다 IDC_LIST_BOOK 컨트롤의 선택 항목을 얻어와서 도서 정보를 컨트롤에 설정하는 작업입니다.
void ModifyDialog::OnLvnItemchangedListBook(NMHDR* pNMHDR, LRESULT* pResult)
{
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
*pResult = 0;
OnBnClickedButtonCancel();
}
void ModifyDialog::OnBnClickedButtonCancel()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
POSITION pos = list_book.GetFirstSelectedItemPosition();
int index = list_book.GetNextSelectedItem(pos);
if (index == -1)
{
return;
}
LVITEM li = { 0 };
li.iItem = index;
li.iSubItem = 0;
wchar_t nbuf[256] = TEXT("");
li.mask = LVIF_TEXT;
li.pszText = nbuf;
li.cchTextMax = 256;
list_book.GetItem(&li);
int no = _wtoi(nbuf);
BookManager& bm = BookManager::GetBookManager();
Book* book = bm.GetBook(no);
content = book->GetContent();
pubdate = book->GetPubdate();
CImage cimg;
image = book->GetImage();
cimg.Load(image);
CDC* cdc = pic_img.GetDC();
RECT rt;
pic_img.GetClientRect(&rt);
cimg.StretchBlt(*cdc, 0, 0, rt.right, rt.bottom, SRCCOPY);
UpdateData(0);
}
OnBnClickedButtonImg
이미지 버튼을 클릭하였을 때 처리기입니다.
파일 열기 대화상자를 열어서 선택한 이미지로 Picture Control에 StretchBlt 합니다.
void ModifyDialog::OnBnClickedButtonImg()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
CFileDialog* fod = new CFileDialog(TRUE, 0);
INT_PTR re = fod->DoModal();
if (re != IDOK)
{
return;
}
image = fod->GetPathName();
CImage cimg;
cimg.Load(image);
CDC* cdc = pic_img.GetDC();
RECT rt;
pic_img.GetClientRect(&rt);
cimg.StretchBlt(*cdc, 0, 0, rt.right, rt.bottom, SRCCOPY);
}
OnBnClickedButtonSub
IDC_BUTTON_SUB 버튼 클릭 처리기입니다.
IDC_LIST_BOOK 컨트롤의 선택 항목을 얻어와서 해당 도서 번호를 알아냅니다.
그리고 컨트롤에 입력한 내용으로 도서 관리자에게 변경을 요청합니다.
void ModifyDialog::OnBnClickedButtonSub()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
UpdateData();
POSITION pos = list_book.GetFirstSelectedItemPosition();
int index = list_book.GetNextSelectedItem(pos);
if (index == -1)
{
return;
}
LVITEM li = { 0 };
li.iItem = index;
li.iSubItem = 0;
wchar_t nbuf[256] = TEXT("");
li.mask = LVIF_TEXT;
li.pszText = nbuf;
li.cchTextMax = 256;
list_book.GetItem(&li);
int no = _wtoi(nbuf);
BookManager& bm = BookManager::GetBookManager();
bm.ModifyBook(no, content, image, pubdate);
}
PreTranslateMessage
IDC_EDIT_CONTENT 컨트롤이 엔터 키 입력을 처리하기 위해 재정의한 메서드입니다.
메시지가 WM_KEYDOWN이고 wParam이 VK_RETURN일 때 개행을 추가합니다.
BOOL ModifyDialog::PreTranslateMessage(MSG* pMsg)
{
// TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다.
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN)
{
int len = edit_cont.GetWindowTextLength();
edit_cont.SetSel(len, len);
edit_cont.ReplaceSel(TEXT("\r\n"));
}
return __super::PreTranslateMessage(pMsg);
}