CView
BOOL check = TRUE;
void C핸들러실습View::OnTestOption01()
{
// TODO: 여기에 명령 처리기 코드를 추가합니다.
this->PostMessage(WM_COMMAND, ID_TEST_STOP32774);
check = !check;
}
void C핸들러실습View::OnUpdateTestOption01(CCmdUI* pCmdUI)
{
// TODO: 여기에 명령 업데이트 UI 처리기 코드를 추가합니다.
//this->PostMessage(WM_COMMAND, ID_TEST_STOP32774);
pCmdUI->SetCheck(check);
}
위처럼 check라는 전역변수가 등록 되어있고 Option01 메뉴를 누를 때마다 check에 값이 바뀌면서 UpdateEventHandler로 인해 매번 check를 세팅한다.
근데 위처럼 check를 전역변수로 설정하는 것은 좋지 않다.
pch.h
#ifndef PCH_H
#define PCH_H
// 여기에 미리 컴파일하려는 헤더 추가
#include "framework.h"
class CAppOption {
public:
static BOOL check;
};
#endif //PCH_H
pch.cpp
// pch.cpp: 미리 컴파일된 헤더에 해당하는 소스 파일
#include "pch.h"
// 미리 컴파일된 헤더를 사용하는 경우 컴파일이 성공하려면 이 소스 파일이 필요합니다.
BOOL CAppOption::check = TRUE;
CView
void C핸들러실습View::OnTestOption01()
{
// TODO: 여기에 명령 처리기 코드를 추가합니다.
this->PostMessage(WM_COMMAND, ID_TEST_STOP32774);
CAppOption::check = !CAppOption::check;
}
void C핸들러실습View::OnUpdateTestOption01(CCmdUI* pCmdUI)
{
// TODO: 여기에 명령 업데이트 UI 처리기 코드를 추가합니다.
//this->PostMessage(WM_COMMAND, ID_TEST_STOP32774);
pCmdUI->SetCheck(CAppOption::check);
}
pch.h
class CAppOption {
public:
static BOOL check;
static BOOL startOrStop;
};
pch.cpp
// pch.cpp: 미리 컴파일된 헤더에 해당하는 소스 파일
#include "pch.h"
// 미리 컴파일된 헤더를 사용하는 경우 컴파일이 성공하려면 이 소스 파일이 필요합니다.
BOOL CAppOption::check = TRUE;
BOOL CAppOption::startOrStop = FALSE;
CView.cpp
void C핸들러실습View::OnTestOption01()
{
// TODO: 여기에 명령 처리기 코드를 추가합니다.
this->PostMessage(WM_COMMAND, ID_TEST_STOP32774);
CAppOption::check = !CAppOption::check;
}
void C핸들러실습View::OnUpdateTestStartTest(CCmdUI* pCmdUI)
{
// TODO: 여기에 명령 업데이트 UI 처리기 코드를 추가합니다.
pCmdUI->Enable(CAppOption::startOrStop);
}
void C핸들러실습View::OnUpdateTestStop32774(CCmdUI* pCmdUI)
{
// TODO: 여기에 명령 업데이트 UI 처리기 코드를 추가합니다.
pCmdUI->Enable(!CAppOption::startOrStop);
}
위처럼 처리할 수 있다.
void C핸들러실습View::OnRButtonDblClk(UINT nFlags, CPoint point)
{
// TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.
CMenu menu;
menu.LoadMenu(IDR_MENU_POPUP);
CMenu *pSubMenu = menu.GetSubMenu(0);
//Point는 클라이언트 기준 마우스 좌표이기 때문에 현재 윈도우 기준 좌표로 바꾼다.
CPoint ptPopup = point;
this->ClientToScreen(&ptPopup);
pSubMenu->TrackPopupMenu(
TPM_LEFTBUTTON | TPM_LEFTALIGN,
ptPopup.x, ptPopup.y, this);
CView::OnRButtonDblClk(nFlags, point);
}
GDI는 Graphics Device Interface의 약자로, Microsoft Windows 운영 체제에서 그래픽 출력을 처리하는 API(Application Programming Interface)이다. GDI는 그래픽 관련 작업을 수행하는 데 필요한 함수, 구조체 및 데이터 유형을 제공하여 사용자 인터페이스와 그래픽 응용 프로그램을 지원한다.
DC는 Windows에서 그래픽 디바이스와 관련된 정보를 포함하고 있는 객체다. DC는 다양한 그래픽 출력 장치에 대한 정보를 담고 있으며, 이를 통해 화면에 그래픽을 그리거나 프린터에 출력할 수 있다.
//지금 윈도우에 대한 dc이다.
CPaintDC dc(this); // device context for painting
// 그리기 메시지에 대해서는 CView::OnPaint()을(를) 호출하지 마십시오.
//기본 검정펜 설정
//하지만 NULL 펜을 사용해서 외곽선을 지우고 싶어서 NULL펜 정의
CPen nullPen(PS_NULL, 0, RGB(0, 0, 0));
//윈도우 배경
CRect window;
CBrush newBrush(RGB(100, 100, 300));
this->GetClientRect(&window);
//dc.SelectObject(&newBrush);
//dc.SelectObject(&nullPen);
//dc.Rectangle(&window);
//FillSolidRect로 브러쉬없이 네모를 채울 수 잇다.
//nullPen도 기본적으로 탑재되어 있다.
dc.FillSolidRect(&window, RGB(145, 245, 300));
//네모 만들기
//브러시
CBrush brush(RGB(245, 245, 245));
dc.SelectObject(&brush);
dc.SelectObject(&nullPen);
CRect rect(0, 0, 300, 300);
dc.Rectangle(&rect);
//새로운 펜으로 변경
CPen pen(PS_SOLID, 5, RGB(192, 0, 0));
CPen* pOldPen = dc.SelectObject(&pen);
//선 그림
dc.MoveTo(100, 100);
dc.LineTo(200, 100);
dc.SelectObject(pOldPen);

TextOut() 예시
dc.SetBkMode(TRANSPARENT); //배경이 그대로
//dc.SetBkMode(OPAQUE); //문자열 배경만 따로
dc.SetBkColor(RGB(255, 255, 255));
dc.TextOut(50,300,_T("TEST STRING"));
비트맵은 크게 2가지가 있다.
DiB -> File (.bmp) -> 리소스로 등록
DDB -> 모니터 -> Video (장치 비트맵)
응용 프로그램 리소스로 비트맵을 포함 시킨 후 활용
리소스에서 비트맵을 로드 한 후 출력하는 방식
메모리 DC는 이미지(DIB)을 들고있는 디바이스 컨텍스트이다.
이제 화면(DDB)에 화면 DC에 합성해 화면에 출력한다.
비트맵을 리소스 추가하고 OnPaint 핸들러를 edit하자
//DDB DC
CPaintDC dcBitMap(this); // device context for painting
//DIB DC
CDC memdc;
memdc.CreateCompatibleDC(&dcBitMap);
CBitmap bmp;
bmp.LoadBitmap(IDB_NULLNULL);
//메모리 DC와 Bitmap을 연결
memdc.SelectObject(&bmp);
dcBitMap.MoveTo(100, 100);
dcBitMap.LineTo(200, 200); //화면 DC말고 메모리 DC에 바로 쓰면 속도가 더 빨라질 것이다.
dcBitMap.BitBlt(0, 0, 300, 300,
&memdc, 0, 0, SRCCOPY);
CPaintDC dc(this); // device context for painting
// TODO: 여기에 메시지 처리기 코드를 추가합니다.
// 그리기 메시지에 대해서는 CView::OnPaint()을(를) 호출하지 마십시오.
CImage img;
//vcxproj가 있는 디렉토리가 루트
img.Load(_T("res//example.png")); //png 리소스 형식을 추가한뒤 LoadFromResource를 통해 리소스로 직접 가져올 수도 있다.
img.BitBlt(dc.m_hDC, 0, 0);
CImageList list;
list.Create(128, 128, ILC_COLOR32, 3, 0);
list.Add(AfxGetApp()->LoadIcon(IDI_ICON1));
list.Add(AfxGetApp()->LoadIcon(IDI_ICON2));
list.Add(AfxGetApp()->LoadIcon(IDI_ICON3));
list.Add(AfxGetApp()->LoadIcon(IDI_ICON4));
list.Draw(&dc, 0, CPoint(0, 0), ILD_TRANSPARENT);
list.Draw(&dc, 1, CPoint(150, 0), ILD_TRANSPARENT);
list.Draw(&dc, 2, CPoint(300, 0), ILD_TRANSPARENT);
list.Draw(&dc, 3, CPoint(450, 0), ILD_TRANSPARENT);
//ico 파일로 하면 리소스에 추가할 수 있어서 좋다
char
ClientDc dc(this);
CString tmp;
tmp.Format(_T("%c"), nChar);
dc.TextOut(10,10,tmp);
CView::OnChar(nChar, nRepCnt, nFlags);
paint
CPaintDC dc(this);
dc.SetBkMode(OPAQUE);
dc.SetBkColrr(RGB(255,255,255));
if(m_char != 0)
{
CString tmp;
tmp.Format(_T("%c"), m_char);
dc.TextOut(10, 10, tmp);
}
CSampleVies.h
protected:
CEdit m_wndName;
CSampleViews.cpp
int CsampleView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: 여기에 특수화된 작성 코드를 추가합니다.
m_wndName.Create(
ES_LEFT | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER,
CRect(10, 10, 100, 40), this, 1);
return 0;
}
void CsampleView::OnTestGd()
{
// TODO: 여기에 명령 처리기 코드를 추가합니다.
CString tmp;
m_wndName.GetWindowText(tmp);
AfxMessageBox(tmp);
m_wndName.SetWindowTextW(_T("hihi"));
}
public:
CEdit str_id;
CString str_pwd;
afx_msg void OnBnClickedOk();
CString str_id2;
};
void CDlog::OnBnClickedOk()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
if (UpdateData(true)) {
CDialog::OnOK();
}
}
그럼 Dialog를 보자
void Csample3View::OnTestTest()
{
// TODO: 여기에 명령 처리기 코드를 추가합니다.
CDlog dlg;
if (dlg.DoModal() == IDOK)
{
CString message;
message.Format(_T("로그인 성공\n아이디: %s\n비밀번호: %s"), dlg.str_id2, dlg.str_pwd);
AfxMessageBox(message);
}
else {
dlg.DoModal();
}
}