I N D E X 목원대학교컴퓨터공학부 - 수업내용요약 - 교과목 : 고급프로그래밍1 구분 : (1~3 중에서 ) PART 1 학기 : 2013년 1학기 ( ~5주차 ) 교수 : 박기홍 참고문헌 : Visual C++ 2000 MFC Programming ( 생능출판사, 2013) 윈도우프로그래밍-Visual C++ MFC Programming ( 한빛미디어, 2011, 개정판 ) Visual C++ 6.0 완벽가이드 ( 영진닷컴, 2007) 0. 0. Visual C++ 2010 MFC 프로그래밍사전알기 (SDI / MDI) 2 1. 유니코드와멀티바이트, OLE(Object Linking and Embedding) 3 2. ActiveX controls, 프로젝트워크스페이스구성 (SDI) 4 3. 1. MFC 개요및아키텍처, MFC 클래스의기본구조 5 4. SDI Template Class, 클래스로부터 Instance 얻기 (SDI / MDI) 6 5. 2. 윈도우메시지처리를위한클래스및함수알기 7 6. 3. 윈도우메시지처리, 메시지의종류, 메시지맵 11 실습해보기 #1 12 7. 윈도우관리메시지와메시지핸들러함수, AfxMessageBox() 15 실습해보기 #2 15 8. 자주사용하는마우스 / 키보드메시지와핸들러함수 16 9. 자주사용하는가상키코드 16 10. 4. 대화상자 17 11. 대화상자계층도, 대화상자프로그램동작원리 17 12. 대화상자, 프로젝트워크스페이스구성 18 13. 대화상자폼을구성하기위한도구상자컨트롤들 18 14. 대화상자컨트롤들을위한관련클래스및함수 19 실습해보기 #3 20-1 -
0 Visual C++ 2010 MFC 프로그래밍사전알기 MFC 응용프로그램마법사 Visual C++ 는서버 / 클라이언트 (Server/Client) 솔루션에서부터고성능멀티미디어애플리케이션까지다양한솔루션을생성하는데필요한도구를제공하는생산성높은시각적인개발도구를제공함. MDI(Multiple Document Interface) 애플리케이션구조 - 여러개의 SDI 형태 - Main Frame: 독립적으로설정되어있고, 그안에 Template 형태 - Template: Child Frame, View Window, Document SDI(Single Document Interface) 애플리케이션구조 - Template: 윈도우로출력되는형태 (Main Frame, View, Document) - Main Frame: 윈도우외곽경계를담당하고 menu, toolbar, status bar를가지고있음. - View window: 실제화면처리담당 ( 문자, 그래픽출력 ) - Document: 내부에서데이터를읽고저장 SDI 와 MDI 구조를도식화하여비교하시오. - 2 -
유니코드 (Unicode) 와멀티바이트 (MBCS) Visual Studio에서문자인코딩을설정하기위한두가지방식. 영어권국가에서는초창기알파벳 (a~z, A~Z) 을표현하기위해각각 1byte(ANSI 문자 ) 로표현이가능 (1) 하였지만한글이나일본의간자와같이 1byte로표현할수있는 256가지의경우의수를초과하는경우 (2) 에대해문자인코딩방식을달리함. MFC 응용프로그램마법사 : 복합문서지원단계 1 유니코드 (Unicode) - Park기홍 문자열은각문자가 2byte로 12byte로표현됨. - Park기홍 2+2+2+2+2+2 = 12 byte 2 멀티바이트 (MBCS) - Park기홍 문자열은 12byte로표현됨. - Park기홍 1+1+1+1+2+2= 8byte OLE(Object Linking and Embedding) 응용프로그램간에데이터를공유할수있도록해주는기능으로, 윈도우의멀티태스킹 (Multi-tasking) 기능을효과적으로이용할수있음. 다른응용프로그램들이프로그램안에있는데이터를편집할수있도록하는메커니즘. 예를들어, 워드 (Word) 문서안에엑셀 (Excel) 에서작성한그래프를포함시켰을때, 그그래프를더블클릭하면엑셀프로그램이실행되는경우. 개체삽입의예 : 프로그램실행후개체삽입을했을경우 - 3 -
ActiveX controls MicroSoft사의 ActiveX 기술에서파생된것으로, 기존컴포넌트를이용하여인터랙티브한웹페이지와네트워크를구축할수있도록해주는컨트롤. ActiveX 컨트롤은웹브라우저를통해자동으로다운로드하여수행될수있음. Visual C++ MFC, 프로젝트워크스페이스구성 (SDI) 프로젝트워크스페이스구성 (test01 로생성함 ) 인쇄기능, 윈도우소켓, 자동화, 다시시작관리자지원 MFC 응용프로그램마법사 : 고급단계 프로젝트워크스페이스의항목별설명 탐색기및뷰솔루션탐색기클래스뷰리소스뷰 내용클래스소스가설정되어있는파일들 MFC 클래스를상속받아탄생된새로운클래스프로그램에필요한메뉴, 아이콘, 문자열, 대화상자등 - 4 -
1 MFC 개요및아키텍처 MFC 클래스의기본구조 - CSingleDocTemplate 클래스 (SDI) / CMultiDocTemplate 클래스 (MDI) CWnd 클래스 - 윈도우를구동하기위한모든기능을내포한클래스 - 화면에출력되는모든윈도우의기저클래스 - CCmdTarget의파생클래스로서메시지맵의기능을지원. CFrameWnd 클래스 - 윈도우의외곽경계를정의하는기저클래스 - CMainFrame 클래스 (SDI) / CMDIFrameWnd, CMDIChildWnd (MDI) CObject 클래스 ( 최상위클래스 ) - MFC의최상위기저클래스로써메모리에클래스를설정하는기능을가진클래스로직렬화 (Serialization), Run-Time 클래스정보, 객체의검사출력, 컬렉션클래스에대한호환성을제공. CCmdTarget 클래스 - MFC의메시지맵아키텍처를지원하기위한클래스 - 윈도우메시지를처리하는 MFC 클래스는모두 CCmdTarget 클래스나 CCmdTarget의파생클래스로부터상속받은클래스 CView 클래스 - 윈도우의작업영역을정의하는기저클래스 - 작업영역으로들어오는메시지들을처리하는클래스 CDocument 클래스 - 애플리케이션에서사용되는데이터를저장하고제어하는클래스 - 애플리케이션의내부를담당하고있음. CDialog 클래스 - 모든대화상자의기본이되는클래스 CWinThread 클래스 - 하나의윈도우를스레드로구동될수있게하는클래스 CWinApp 클래스 - 애플리케이션을생성할때가장먼저애플리케이션자체를나타내는 CWinApp로파생클래스의객체가생성됨. - 5 -
SDI, Template Class 클래스뷰에서아래와같이 Ctest01App 클래스에서 InitInstance() 함수를클릭하여 Template을확인해보자. 3 View 클래스의 Instance 를얻는방법 CExSDIView *pview = (CExSDIView *)pframe->getactiveview() 4 Document 클래스의 Instance 를얻는방법 CExSDIDoc *pdoc = (CExSDIDoc *)pframe->getactivedocument() MDI 경우, 각클래스로의 Instance 얻어오는방법 1 App 클래스의 Instance를얻는방법 CExMDIApp *papp = (CExMDIApp *)AfxGetApp(); 2 MainFrame 클래스의 Instance를얻는방법 CMainFrame *pframe = (CMainFrame *)AfxGetMainWnd(); 3 ChildFrame 클래스의 Instance를얻는방법 SDI 경우, 각클래스로의 Instance 얻어오는방법 1 App 클래스의 Instance를얻는방법 CExSDIApp *papp = (CExSDIApp *)AfxGetApp(); 2 MainFrame 클래스의 Instance를얻는방법 - 자주사용하는방법이므로, 사용예를살펴보자. (304 page) - 메뉴의툴바, 상태표시줄등의상태를바꾸기위해서는메인프레임클래스에접근해야하고, 형변환이필요함. CChildFrame *pchild = (CChildFrame *)pframe->getactiveview() 4 View 클래스의 Instance를얻는방법 CExMDIView *pview = (CExMDIView *)pchild->getactiveview() 5 Document 클래스의 Instance를얻는방법 CExMDIDoc *pdoc = (CExMDIDoc *)pchild->getactivedocument() CMainFrame *pframe = (CMainFrame *)AfxGetMainWnd(); - 6 -
MEMO 2 윈도우메시지처리를위한클래스및함수알기 CString 클래스 프로그램에서가장많이사용하는것이문자열이고, MFC에서는문자열을처리하는클래스인 CString 클래스를제공함. CString 클래스의멤버함수 멤버함수 내용 ( 설명 ) GetLength 설정된문자의길이를반환함. IsEmpty 현재클래스에문자열버퍼가비워있는가? Empty 문자열을삭제하여버퍼를지움. GetAt 문자열의특정위치의문자값을얻음. SetAt 문자열의특정위치에새로운문자를삽입함. Compare 문자열과인자의문자열을비교함. MakeUpper 문자열의소문자를대문자로바꿈. MakeLower 문자열의대문자를소문자로바꿈. Format 문자열에형식을갖추어문자들을넣음. Find 문자열에서특정문자나문자열을찾음. CString::GetLength() 함수 int GetLength() const; CString 객체에서바이트수를얻기위해호출되는함수 CString::Delete() 함수 int Delete(int nindex, int ncount=1) CString 객체에서데이터를삭제할때이용하는함수 nindex: 지우고자하는첫번째문자 - 7 -
ncount: 문자를 ncount 개수만큼지움. CString::IsEmpty() 함수 BOOL IsEmpty() const CString 객체의문자열버퍼가비어있는지체크하는함수 반환값 : 버퍼가비어있으면 true, 비어있지않으면 false 반환 CString::Empty() 함수 void Empty() OnDraw() 함수 virtual void OnDraw(CDC* pdc)=0; WM_PAINT 메시지는화면에보이는모습이변할때마다메시지가날아오고, 이메시지를처리하는메시지핸들러함수는 OnPaint() 임. WM_PAINT 메시지가날아올때 OnPaint() 함수와 OnDraw() 함수가둘다호출되어화면을복원함. OnDraw() 함수는메시지핸들러함수가아닌가상함수임. pdc : DC(Device Context) 를가지는포인터 CString 객체의문자열을삭제하여버퍼를비우는함수 Invalidate() 함수 void Invalidate(BOOL berase = TRUE); 윈도우의클라이언트영역을다시그리는함수. Invalidate() 함수는 WM_PAINT 메시지를직접호출하진않으나전체클라이언트영역을윈도우 update region에더해시스템이 WM_PAINT를호출하도록함. WM_PAINT 메시지는 OnDraw() 함수를호출해서화면을다시그리는역할을함. Invalidate(TRUE) & Invalidate(FALSE) - TRUE 일때는 background를전부지운후 BeginPaint() 함수를 이용하여다시그리고, FALSE 인경우에는바뀐부분만그림. CDC::TextOut() 함수 BOOL TextOut(int x, int y, const CString& str); 문자열을지정된위치에출력하는함수 x : 문자열이출력될 x좌표 y : 문자열이출력될 y좌표 str : 출력될문자열 CRect 클래스 window RECT 구조와유사하며사각형의좌측상단과우측하단의좌표를저장하기위한클래스. CRect 클래스의멤버변수 멤버변수 내용 ( 설명 ) LONG left; 사각형의왼쪽상단의 x좌표 - 8 -
LONG top; 사각형의왼쪽상단의 y좌표 LONG right; 사각형의오른쪽하단의 x좌표 LONG botton; 사각형의오른쪽하단의 y좌표 GetClientRect() 함수 BOOL GetClientRect(LPRECT lprect); 윈도우의클라이언트영역의크기를얻는함수 lprect : 클라이언트좌표를얻기위한포인터, 왼쪽 / 상단을 0으로하고오른쪽과하단은윈도우의너비와높이를포함. DT_CENTER DT_VCENTER DT_CALCRECT DT_SINGLELINE DT_NOCLIP DT_EXPANDTABS MEMO 설정된영역의가로중앙에정렬 설정된영역의세로중앙에정렬 (DT_SINGLELINE과함께지정되어야한다 ) 문자열을출력할사각형의영역을계산행바꿈과라인피드를무시하고한줄로출력클리핑없이문자를출력문자열에탭이포함되어있을때공백을출력 CDC::DrawText() 함수 int DrawText(CString& str, LPRECT lprect, UINT nformat); 화면에문자열을출력할때어느영역을정하고이영역에출력 형식에맞게문자열을출력하는함수. str : 출력될문자열 lprect : 문자열을화면에출력할사각형영역의좌표 nformat : 출력형식플러그이고, 설정할수있는플러그값은다음과같음. 플러그값 내용 ( 설명 ) DT_TOP 설정된영역의상단으로정렬 DT_BOTTOM 설정된영역의하단으로정렬 DT_LEFT 설정된영역의좌단으로정렬 DT_RIGHT 설정된영역의우단으로정렬 (DT_SINGLELINE과함께지정되어야한다 ) - 9 -
SetTimer() 함수 UINT SetTimer(UINT nidevent, UINT nelapse, TIMERPROC lptimerfunc); 지정된시간간격마다 WM_TIMER 메시지를발생시켜타이머를설정하는함수 nidevent: Timer ID nelapse: WM_TIMER 메시지를발생시킬시간 (1000분의 1초 ) 간격 lptimerfunc: WM_TIMER 메시지가발생되었을때실행되는함수. NULL이설정되면 OnTimer() 함수가호출. KillTimer() 함수 BOOL KillTimer(int nidevent); 타이머를해제하는함수 nidevent: SetTimer() 함수에서설정한 Timer ID MEMO - 10 -
3 윈도우메시지 (Message) 처리 윈도우프로그래밍에서가장중요한것은메시지를처리하는것. 메시지맵 ( 아래그림의순서대로확인해보자.) MFC에서메시지를처리하기위해서는다음의 3단계과정. - 1단계 : 윈도우클래스의멤버함수로메시지핸들러함수를선언. - 2단계 : 메시지맵에메시지와메시지핸들러함수를묶는메시지의매크로를추가. - 3단계 : 메시지핸들러함수의기능을구현. 메시지의종류 윈도우메시지 (Windows Message) - WM_ 로시작하는메시지 (WM_COMMAND 는제외 ) 컨트롤통지메시지 (Control Notification Message) - Button, Combo Box와같은제어객체나자식윈도우에서부모윈도우로보내는메시지 명령메시지 (Command Message) - 메뉴, 툴바, 액셀러레이터키와같은사용자인터페이스객체로부터발생되는 WM_COMMAND 메시지 메시지처리의기본개념구분내용 ( 설명 ) Win32 SDK 들어온메시지를 switch문을사용하여처리 MFC 메시지처리를위해메시지맵을사용 - 11 -
실습해보기 #1 윈도우의사이즈가변경 (WM_SIZE) 되었을때, 윈도우의크기변경을알려주는 SDI 프로그램을만들어보자. CString 클래스의멤버변수를생성하고, CString 클래스의멤버함수인 Format() 함수의사용법알기. - 멤버변수 : m_strwindowsize - 윈도우메시지 : WM_SIZE - 윈도우메시지핸들러함수 : OnSize() - CString 클래스의멤버함수인 Format() 함수적용하기. 1 윈도우의크기를나타내는멤버변수 (m_strwindowsize) 추가 변수의추가하는방법은아래와같음. - 12 -
멤버변수 (m_strwindowsize) 가잘추가되었는지확인해보자. 3 헤더파일과소스파일에서해당하는핸들러함수를확인해보자. 2 윈도우메시지 (WM_SIZE) 를추가해보자. 4 OnSize() 함수를아래와같이작성해보자. - 13 -
m_strwindowsize 변수가 CString 타입으로전역변수로추가됨. 따라서점연산자를찍었을때 CString 클래스의멤버변수들이자동화기능 ( 팝다운메뉴 ) 을사용할수있음. MEMO 5 끝으로윈도우크기를조절했을때윈도우의크기를출력해보자. 화면에보이는모습이변할때마다메시지가날아오고이메시지를처리하는 OnPaint() 함수를오버라이딩한 OnDraw() 함수. 6 실행해보기. - 14 -
윈도우관리메시지와메시지핸들러함수 메시지 발생상황 메시지핸들러함수 WM_CREATE 윈도우가생성될때 OnCreate() WM_ACTIVE 윈도우가활성화될때 OnActive WM_PAINT 윈도우가다시그려질때 OnPaint() WM_SIZE 윈도우크기가변경될때 OnSize() WM_MOVE 윈도우가움직일때 OnMove() WM_TIMER 설정된타이머시간이됐을때 OnTimer() WM_DESTROY 윈도우가종료될때 OnDestroy() 아이콘스타일 출력되는아이콘메시지박스아이콘스타일비고 MB_ICONHAND, MB_ICONSTOP, MB_ICONERROR MB_ICONINFORMATION, MB_ICONASTERISK 위험 정보 AfxMessageBox() 함수 MB_ICONQUESTION 물음 int AfxMessageBox(LPCTSTR lpsztext, UINT ntype=mb_ok, UINT nldhelp=0) MB_ICONEXCLAMATION, MB_ICONWARNING 경고 사용자에게간단한메시지를출력하는데사용되는대화상자 lpsztext : 출력하고자하는문자열 ntype : 대화상자에설정되는버튼 nldhelp : 현재상태에서 F1 키를눌러도움말을실행하였을때의도움말 ID 메시지박스스타일사용가능한버튼반환값 MB_OK 확인 IDOK MB_OKCANCEL 확인, 취소 IDOK, IDCANCEL MB_YESNO 예, 아니오 IDYES, IDNO MB_YESNOCANCEL 예, 아니오, 취소 IDYES, IDNO, IDCANCEL MB_RETRYCANCEL 재시도, 취소 IDRETRY, IDCANCEL MB_ABORTRETRYIGNORE 취소, 재시도, 무시 IDABORT, IDRETRY, IDIGNORE 실습해보기 #2 윈도우의프로그램을종료하였을때, 경고창을띄워보자. - 메시지박스스타일 : MB_YESNOCANCEL - 아이콘스타일 : MB_ICONQUESTION 프로그램을실행시키고종료했을때경고창모습. - 15 -
자주사용하는마우스메시지와메시지핸들러함수 메시지 발생상황 메시지핸들러함수 WM_MOUSEMOVE 마우스를이동 OnMouseMove() WM_LBUTTONDBCLK 왼쪽버튼더블클릭 OnLButtonDbClk() WM_LBUTTONDOWN 왼쪽버튼누름 OnLButtonDown() WM_LBUTTONUP 왼쪽버튼놓음 OnLButtonUp() WM_RBUTTONDBCLK 오른족버튼더블클릭 OnRButtonDbClk() WM_RBUTTONDOWN 오른쪽버튼누름 OnRButtonDown() WM_RBUTTONUP 오른쪽버튼놓음 OnRButtonUp() WM_MOUSEWHEEL 마우스휠을움직임 OnMouseWheel() 자주사용하는키보드메시지와메시지핸들러함수 메시지 발생상황 메시지핸들러함수 WM_KEYDOWN 키를눌렀을때 OnKeyDown() WM_KEYUP 키에서손을뗏을때 OnKeyUp() WM_CHAR 화면에문자가표시되는키를누름 OnChar() WM_SYSKEYDOWN 시스템키 (, ) 를눌렀을때 OnSysKeyDown() WM_SYSKEYUP 시스템키를뗏을때 OnSysKeyUp() WM_SYSCHAR 시스템키와문자키가같이누름 OnSysChar() nchar : 눌러진키의가상키코드 nrepcnt : 키를계속누르고있을경우반복된키의입력횟수전달 nflags : 스캔코드, 이전키상태, 키가눌러질때의 키의상태에관한정보전달 자주사용하는가상키코드 가상키 대응되는키보드 가상키 대응되는키보드 VK_CANCEL + VK_LEFT VK_BACK VK_RIGHT VK_TAB VK_UP VK_RETURN VK_DOWN VK_SHIFT VK_INSERT VK_CONTROL VK_DELETE VK_MENU VK_HOME VK_CAPITAL VK_END VK_ESCAPE VK_PRIOR VK_SPACE VK_NEXT VK_SCROLL VK_F1~VK_F10 ~ - 16 -
4 대화상자 대화상자의계층도 대화상자프로그램의동작원리 1 대화상자프로그램을실행하면생성자함수가호출되고, OnCreate() 함수가호출됨. 2 OnCreate() 함수는 CWnd 객체가제대로생성된다면 0을반환하고, 만약프로그램을종료하면 OnDestroy() 함수가호출되어 1을반환함. 3 그다음에 OnInitDialog() 함수가호출됨. OnInitDialog() 함수는대화상자가화면에보이기바로전에실행되므로여기에서초기화기능을부여함. 4 OnPaint() 함수는 OnDraw() 함수와같은기능을함. 5 DoDataExchange() 함수는컨트롤을어떤방식으로이용할것인지를결정함. DoDataExchange() 함수는 UpdateData() 함수를호출할때마다호출되는멤버함수. UpdateData() 함수 구분 UpdateData(TRUE) UpdateData(FALSE) 내용 DDV_ ~~ 를실행 (Dialog Data Validation) 대화상자에있는값이변수로저장 DDX_ ~~ 를실행 (Dialog Data exchange) 변수에있는값이대화상자로보내짐 - 17 -
Visual C++ MFC, 프로젝트워크스페이스구성 (Dialog) 대화상자폼을구성하기위한도구상자컨트롤들 MEMO - 18 -
CListBox::GetCount() 함수 int GetCount() const; List Box의아이템의수를알기위해사용하는함수 반환값 : List Box 안의아이템의수 CListBox::AddString() 함수 int AddString(LPCTSTR lpszitem); List Box의맨뒤에문자열을추가할때사용하는함수 lpszitem: 추가하고자하는문자열 CListBox::DeleteString() 함수 int DeleteString(UINT nindex); List Box의아이템을삭제할때사용하는함수 nindex: 삭제하고자하는 List Box의아이템 index CListBox::GetCurSel() 함수 int GetCurSel() const List Box에서선택된항목의 index를반환하는함수 반환값 : List Box에서선택된아이템의 index를반환하고, 선택된아이템이없으면 LB_ERR을반환함. CComboBox::AddString() 함수 int AddString(LPCTSTR lpszstring) Combo Box에문자열을추가할때사용하는함수 lpszstring: 추가하고자하는문자열 CComboBox::ResetContent() 함수 void ResetContent() Combo Box의모든아이템을제거할때사용하는함수 CListBox::GetText() 함수 void GetText(int nindex, CString& rstring) const List Box에서주어진 index의문자열을얻어올때사용하는함수 nindex: 문자열을가져오고싶은 List Box의아이템 index rstring: 문자열을저장할 CString 객체 CComboBox::GetCurSel() 함수 int GetCurSel() const Combo Box에서선택된항목의 index를 (0부터) 반환하는함수 반환값 : Combo Box에서선택된아이템의 index를반환하고, 선택된아이템이없으면 LB_ERR을반환함. - 19 -
CComboBox::GetLBText() 함수 void GetLBText(int nindex, CString& rstring) const Combo Box에서주어진 index의문자열을얻어올때사용하는함수이고, index는 0부터시작됨. nindex: 문자열을가져오고싶은 Combo Box의아이템 index rstring: 문자열을저장할 CString 객체 실습해보기 #3 대화상자기본컨트롤 ( 에디트컨트롤, 콤보박스, 리스트박스 ) 을활용하여데이터이동또는복사가가능한대화상자를구현해보자. 프로그램기능 - 대화상자에 2개의에디트컨트롤, 콤보박스, 리스트박스를배치하여각컨트롤사이에데이터를교환할수있음. - 콤보박스에서선택된문자열을복사함수는 GetLBText() 함수임. - 컨트롤에서다른컨트롤로데이터를보낼때체크박스를이용하여보내는컨트롤에서의데이터의삭제여부를결정함. MEMO GetItemDlg() 함수를조사하시오. - ( 원형 ) - ( 내용 ) - 20 -
1 각컨트롤들을배치하고 IDC 이름과해당하는변수정하기. 2 MFC Class Wizard ( + + ) 를이용하여해당하는컨트롤에 멤버변수를추가하고, 각컨트롤에대한메시지처리를위한핸들 러함수를추가하자. - 21 -
3 변수및메시지핸들러함수의원형을확인해보자. 4 멤버변수및메시지핸들러함수가잘연결이되었는지확인하자. MEMO 멤버변수, 메시지처리, DoDataExchange(), MESSAGE_MAP 등을확인해보고, 오류처리과정을확인해보자. 5 메시지핸들러함수에대한코드이며, 완성후실행해보자. - 22 -
- 23 -
- 24 -
- 25 -