윈도우 프로그래밍 들어가기
프로젝트란 하나의 실행 파일(exe)을 만들어 내기 위해서 필요한 여러 개의 소스 파일과 헤더 파일들 등을 하나로 묶는 것
솔루션 탐색기 : MFC 응용 프로그램 마법사가 생성해준 파일들을 찾기 쉽게 하기 위해서 이렇게 [리소스파일], [소스파일],[헤더파일] 3종류로 나누어서 보여준다.
클래스 뷰 : 솔루션 탐색기가 물리적인 파일 관계를 보여주는 것이라면 클래스 뷰는 논리적인 클래스 관계를 보여준다.
MFC 응용 프로그램의 기본 골격을 이루는데 절대적인 역할을 하는 클래스를 AFX(Application Framework)클래스라고 하는데, CWinApp, CDocument, CFrameWnd, CView 4개의 클래스로 구성된다.
1.응용 프로그램 클래스(CFirstApp : CWinApp) = MFC 응용 프로그램은 하나의 도큐먼트 템플릿 클래스(CDocTemplate)를 등록하는데 이는 MFC로 프로그램을 작성하는데 기본이 되는 도큐먼트 클래스, 프레임 클래스, 뷰 클래스, 리소스들을 하나로 묶어주고 관리한다.
2.메인 프로그램 윈도우 클래스(CMainFrame : CFrameWnd) = 응용 프로그램이 윈도우(창) 형태로 나타나도록 하는 주된 역할을 하는 클래스 이다.
3.뷰 클래스(CFirstView : CView) = 마우스나 키보드 입력을 받아 처리하는 것과 화면에 응용프로그램이 결과를 출력하는 역할.
4.도큐먼트 클래스(CFirstDoc:CDocument) = 문서의 정보를 내부적으로 저장하고 관리하는 클래스로서 사용자의 눈에 보여지지 않는 작업을 주로 한다.
CDC 클래스와 GDI 오브젝트
DC는 응용 프로그램 화면에 출력하는 작업을 처리하기 위해서 필요한 속성을 정의하고 있는 자료구조 이다. CDC는 텍스트를 출력하거나 그래픽 이미지를 출력하는 등에 관련된 다양한 멤버함수로 구현되어 있다.
GDI는 GraphicDeviceInterface(그래픽 디바이스 인터페이스)의 약어로서 디바이스 컨텍스트의 속성에 해당되며 다음과 같은 것들이 있다.
MFC에서 메시지 처리하기
MFC에서는 발생하는 메시지의 형태에 따라 크게 3가지로 분류 한다.
1.윈도우 메시지(Window Message) 2. 커맨드 메시지(Command Message) 3. 컨트롤 통보 메시지(Contorl Notification Message)
WM으로 시작하는 윈도우 메시지는 응용 프로그램의 윈도우 영역에서 발생하는 메시지로서 다양한 종류가 제공된다. WM_COMMAND 형태로 제공되는 커맨드 메시지는 메뉴를 선택하면 발생하는 메시지로 메뉴의 ID로 어떤 메뉴가 선택되었는지 구분한다.
마우스 메시지는 클라이언트 영역에 있을 때에는 뷰로 전달되지만, 프레임 윈도우의 타이틀 바에 있을 때에는 프레임 윈도우로 전달된다. 메시지 맵은 구현 파일(.cpp)에 BEGIN_MESSAGE_MAP(), END_MESSAGE_MAP() 매크로로 둘러 싸여 있다. 둘 매크로 사이에 실제 구현할 메시지 처리기에 대한 매크로 정의가 포함된다.
_T()메크로 함수: _T()는 유니코드 플랫폼 환경에서 사용된 문자열 형태로 변화하기 위해서 사용하는 매크로 함수 이다.
대화 상자와 기본 다루기
대화 상자란 윈도우 응용 프로그램에서 사용자로부터 정보를 입력받거나 필요한 정보를 출력하기 위한 용도로 사용되는 일종의 윈도우 이다.
대화 상자 작성 절차: 1. [리소스 뷰] 창에서 대화 상자 템플릿을 새로 추가하여 컨트롤를 배치한다. 2. 대화 상자 템플릿에 대한 대화 상자 클래스를 CDialog의 파생 클래스로 만든다 3. [리소스 뷰] 창에서 대화 상자를 출력하기 위한 메뉴를 새로 추가한다. 4. 메뉴에 대한 이벤트 처리기를 만든 후에 대화 상자 객체를 생성한 후 DoModal() 함수를 호출하여 대화 상자를 출력한다. 스테틱 컨트롤은 프로그램 상에서 아무런 역할이 없기 때문에 ID는 따로 지정해주지 않고 기본적으로 주어지는 IDC_STATIC이라는 값을 그대로 사용하고 Caption값만 변경 해준다. MFC에서는 클래스에서 상관없이 어디서나 사용할 수 있는 전역함수가 있는데 이런 함수들은 이름 앞에 Afx가 붙어 있다.
stdafx.h
stdafx.h 란 자누 쓰이는 헤더들 여러 개를 한꺼번에 미리 컴파일 해놓아서 나중에 다시 컴파일하지 않고 그냥 다시 쓰겠다는 헤더
#pragma once
컴파일러가 번역 단위의 첫 번째 파일 이후에 파일을 다시 열고 읽지 않으므로 빌드 시간을 줄일 수 있음
CWinApp
이 클래스의 이름 구성만 봐도 알겠지만 CWinApp 클래스는 응용 프로그램과 관련된 작업(Window Class 등록, 메인 윈도우 생성, 메시지처리)을 처리하는 클래스
버튼, 에디트 컨트롤, 스태틱 컨트롤
버튼 생성 방법: 두구 상자에서, 버튼을 더블 클릭하여 버튼을 하나 생성
리소스뷰에서 버튼을 클릭하면 우측 속성 창에 많은 내용이 표시 -> 그 중 ID는 버튼의 리소스 아이디, Caption은 버튼 위에 표시되는 텍스트
도구 상자에서 에디트 컨트롤을 더블 클릭하시면 리소스뷰에 에디트 컨트롤이 생성 됩니다.afx_msg void OnBnClickedButton(); CString m_wirte; // edit control 변수 CStatic m_result; // static text 변수 DDX_Text(pDX, IDC_EDIT_TEST, m_wirte); //소스파일에 DoDataExchange에 넣기 DDX_Control(pDX, IDC_STATIC_TEST, m_result);
리스트 컨트롤
리스트 컨트롤 속성 중 맨 아래 View에 Icon, Small Icon, List, Report가 있는데 그 중 Report를 선택 합니다.
DDX_Control(pDX, IDC_LIST_TEST, m_list); CListCtrl m_list; (헤더 파일에 적기) //list Control 컬럼 추가 (소스 파일에 적기) m_list.InsertColumn(0, _T("Column 0"), LVCFMT_CENTER, 100); // 번호, 이름,정렬, 넓이 m_list.InsertColumn(1, _T("Column 1"), LVCFMT_CENTER, 100); m_list.InsertColumn(2, _T("Column 2"), LVCFMT_CENTER, 100); m_list.InsertColumn(3, _T("Column 3"), LVCFMT_CENTER, 100); m_list.InsertColumn(4, _T("Column 4"), LVCFMT_CENTER, 100); //list Control 아이템 추가 m_list.InsertItem(0, _T("Item 0-0")); //아이템 번호, 텍스트 m_list.InsertItem(1, _T("Item 1-0")); //아이템 번호, 텍스트 //list Control 서브 아이템 추가 m_list.SetItemText(0, 3, _T("Item 0-1")); //칼럼 번호, 아이템 row, 텍스트 //list Control 아이템 삭제(전체) //m_list.DeleteAllItems(); //list Contorl 아이템 삭제(선택) m_list.DeleteItem(0); 아이콘 넣기 CImageList m_imgList; // 이미지 리스트(헤더 파일) m_imgList.Create(64, 64, ILC_COLOR32, 2, 0); m_imgList.Add(AfxGetApp()->LoadIcon(IDI_ICON1)); m_imgList.Add(AfxGetApp()->LoadIcon(IDI_ICON2)); m_list2.SetImageList(&m_imgList, LVSIL_NORMAL);
타이머
메세지로 정해진 시간마다 반복적으로 실행시킬 수 있는 방법입니다.
void CMFCDlg::OnTimer(UINT_PTR nIDEvent) //On Timer 함수 { // TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다. CString sTxt; switch (nIDEvent) { case 1: sTxt.Format(_T("%d"), m_iCount++); m_staticDisp.SetWindowText(sTxt); break; } CDialogEx::OnTimer(nIDEvent); } void CMFCDlg::OnBnClickedButtonStart() { SetTimer(1, 1000, NULL);// 타이머 아이디, 시간, 간격 } void CMFCDlg::OnBnClickedButtonEnd() { KillTimer(1);// 타이머 아이디 }
쓰레드
헤더 파일에 아래와 같이 스태틱 컨트롤 멤버변수와 쓰레드 멤버 변수를 입력합니다. CWinThread *m_pThread; //쓰레드 변수 초기화 필수 CStatic m_staticDisp; void CMFCDlg::OnBnClickedButtonCreate() { // TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다. if (NULL == m_pThread) { m_pThread = ::AfxBeginThread(TestThread, this); if (NULL == m_pThread) { ::AfxMessageBox(_T("AfxBeginThread Fail")); } } } UINT CMFCDlg::TestThread(LPVOID lpVoid) { CMFCDlg *pDlg = (CMFCDlg *)lpVoid; int iNumber = 0; CString sTxt; while (1) { sTxt.Format(_T("%d"), iNumber++); pDlg->m_staticDisp.SetWindowText(sTxt); Sleep(1000); } return 0; } void CMFCDlg::OnBnClickedButtonStop() { if (NULL != m_pThread) { ::SuspendThread(m_pThread->m_hThread); } } void CMFCDlg::OnBnClickedButtonRestart() { if (NULL != m_pThread) { ::ResumeThread(m_pThread->m_hThread); } } void CMFCDlg::OnBnClickedButtonFinish() { if (NULL != m_pThread) { if (::TerminateThread(m_pThread->m_hThread, 1)) { ::CloseHandle(m_pThread->m_hThread); m_pThread = NULL; } else { ::AfxMessageBox(_T("TerminateThread Fail")); } } }
탭 컨트롤
여러 개의 컨트롤들을 하나의 화면에 볼 수 있게 관리해 주는 컨트롤
라디오 버튼