MFC Microsoft Foundation Class PART 1 Windows MFC

  • Slides: 193
Download presentation
MFC (Microsoft Foundation Class)

MFC (Microsoft Foundation Class)

PART 1 Windows와 MFC의 기초 Chapter 1 Chapter 2 Chapter 3 Chapter 4 Chapter

PART 1 Windows와 MFC의 기초 Chapter 1 Chapter 2 Chapter 3 Chapter 4 Chapter 5 Chapter 6 Chapter 7 Chapter 8 MFC란? 창에 그리기 마우스와 키보드 메뉴 MFC컬렉션 클래스 파일 입출력 및 직렬화 컨트롤 대화상자와 속성시트

1. 개론 - MFC의 역사 1) MFC 1. 0 1992 년 4월 (MS -

1. 개론 - MFC의 역사 1) MFC 1. 0 1992 년 4월 (MS - C/C++ 7. 0) [윈도우와 관련된 클래스 ] 구분 설명 Window management 윈도우 관리 Graphic Device Interface(GDI) 그래픽 장치 인터페이스 Multi Document Interface(MDI) 다중 문서 인터페이스 Menus 메뉴 Dialog boxes 다이얼로그 박스 Windows controls 윈도우 컨트롤 Windows conmmon dialogs 윈도우용 일반 다이얼로그 OLE( Object Linking & Embedding) 1. 0 객체 연결과 삽입 Application services 애플리케이션 서비스

1. 개론 - MFC의 역사 [일반적인 목적의 클래스 ] 구분 설명 Run-time Type Information

1. 개론 - MFC의 역사 [일반적인 목적의 클래스 ] 구분 설명 Run-time Type Information 실행 타입 정보 Object Persistence 객체 보존성 Collection Classes 집합체 클래스 Strings 스트링 Time and Date 시간과 날짜 Exception Handling 예외 처리

1. 개론 - MFC의 역사 2) MFC 2. 0 1993년 8월 (VC++ 1. 0

1. 개론 - MFC의 역사 2) MFC 2. 0 1993년 8월 (VC++ 1. 0 - 93년 2월) [구조적 클래스] 구분 설명 Commands 명령 관리 클래스들 Documents and Views 도큐먼트와 뷰 Printing and Print Preview 프린트와 프린트 미리보기 Dialog Data Exchange and Validateion(DDX/DDV) 다이얼로그 데이터 교환, 확인 Eontext-Sensitive Help 도움말

1. 개론 - MFC의 역사 [Win 32 지원] 구분 설명 New Win 32 APIs

1. 개론 - MFC의 역사 [Win 32 지원] 구분 설명 New Win 32 APIs Win 32 API함수 지원 Multithreading 멀티 Thread 관련 클래스 Unicode support 유니코드 지원 Shared 32 -bit DLLs 공유된 32 bit DLL

1. 개론 - MFC의 역사 5) MFC 3. 1 & 3. 2) [User Interface

1. 개론 - MFC의 역사 5) MFC 3. 1 & 3. 2) [User Interface 클래스] 구분 설명 windows 95 Common Controls Win 95컨트롤 Simple MAPI 단순한 MAPI Windows Sockets 윈도우 소켓

1. 개론 - MFC의 역사 6) MFC 4. 0 – 1995년 9월( VC++ 4.

1. 개론 - MFC의 역사 6) MFC 4. 0 – 1995년 9월( VC++ 4. 0) [User Interface 클래스] 구분 설명 Containment of OLE Controls OLE 컨트롤 DAO ( Data Access Objects) MFC 자체 데이터베이스 엔진 Simplified Windows 95 Common controls 간단 한 95일반 컨트롤 Windows 95 Common Dialogs win 95일반 다이얼로그 Thread synchronization Objects 스레드 동기화 객체

2. MFC(Microsoft Foundation Class)? 윈도우 API이외에도 OLE, ODBC, Winsock 관련 클래스를 포함하여 230 여개의

2. MFC(Microsoft Foundation Class)? 윈도우 API이외에도 OLE, ODBC, Winsock 관련 클래스를 포함하여 230 여개의 클래스를 제공 MFC Collections, Miscellaneous Classes Base MFC Classes Win 32 API (SDK) Windows Base OS Services [17] OLE Classes OLE ODBC Classes ODBC Windows OS Service Extensions

2. MFC – Frame. Work(AFX) Object Oriented Programming

2. MFC – Frame. Work(AFX) Object Oriented Programming

2. MFC – Frame. Work(AFX) Object 분리 예

2. MFC – Frame. Work(AFX) Object 분리 예

2. MFC – Frame. Work(AFX) MFC의 계층 구조 CObject (MFC Base Class) Exceptions Collections

2. MFC – Frame. Work(AFX) MFC의 계층 구조 CObject (MFC Base Class) Exceptions Collections File Services ODBC Support DCs OLE Support Documents GDI Objects Windows Menus Windows Socket Support Command Targets Threads Application Frames Views Utility Classes Dialogs Support Classes Controls Collection Templates [23]

2. MFC – Frame. Work(AFX) CWin. App CObject Exceptions File Services Device Contexts Graphical

2. MFC – Frame. Work(AFX) CWin. App CObject Exceptions File Services Device Contexts Graphical Drawing Objects Menus OLE Support Collections CWnd CCmd. Target Application Objects Document Architecture CCmd. Target Frame Windows Control Bars Views Dialog Boxes Controls CWin. Thread CWin. Application objects are derived from CWin. App. [25] derived application class

2. MFC – Frame. Work(AFX) CFrame. Wnd CObject Exceptions File Services Device Contexts Graphical

2. MFC – Frame. Work(AFX) CFrame. Wnd CObject Exceptions File Services Device Contexts Graphical Drawing Objects Menus OLE Support Collections CWnd CCmd. Target Frame Windows Control Bars Views Dialog Boxes Controls Application Objects Document Architecture CWnd CFrame. Wnd CMDIChild. Wnd user MDI windows Application window objects are derived from the CFrame. Wnd base class. [26] CMDIFrame. Wnd user MDI workspaces

2. MFC – Frame. Work(AFX) Frame. Work Class CObject Framework classes CCmd. Target CWin.

2. MFC – Frame. Work(AFX) Frame. Work Class CObject Framework classes CCmd. Target CWin. App CYour. App CDoc. Template CWnd CFrame. Wnd CView CDialog CYour. Frame CYour. Vw CYour. Dlg [27] CDocument CYour. Doc

2. MFC – Frame. Work(AFX) App. Wizard MFC 기반 클래스 파생 클래스 CObject CCmd.

2. MFC – Frame. Work(AFX) App. Wizard MFC 기반 클래스 파생 클래스 CObject CCmd. Target CWin. App CMy. App CDocument CMy. Doc CWnd CFrame. Wnd CMain. Frame CView CMy. View

CFrame. Wnd protected/private 멤버 멤버 함수 멤버 변수 CWin. App CDocument CView CMy. App

CFrame. Wnd protected/private 멤버 멤버 함수 멤버 변수 CWin. App CDocument CView CMy. App 클래스의 인스턴스 (전역 변수)

2. MFC – Frame. Work(AFX) CWin. App 파생클래스의 동작 CWin. App 상 속 CMy.

2. MFC – Frame. Work(AFX) CWin. App 파생클래스의 동작 CWin. App 상 속 CMy. App 프로그램 시작 Init. Instance( ) 무한 루프 Run( ) Exit. Instance( ) 프로그램 종료 Init. Instance( )

2. MFC – Frame. Work(AFX) CWin. App 파생클래스의 동작 프로그램 시작 Init. Instance( )

2. MFC – Frame. Work(AFX) CWin. App 파생클래스의 동작 프로그램 시작 Init. Instance( ) 무한 루프 Init. Instance( ) Run( ) Exit. Instance( ) 프로그램 종료 Exit. Instance( )

2. MFC – Frame. Work(AFX) CWin. App 파생클래스의 구현 class CMy. App : public

2. MFC – Frame. Work(AFX) CWin. App 파생클래스의 구현 class CMy. App : public CWin. App { public: CMy. App(); }; // Overrides public: virtual BOOL Init. Instance();

2. MFC – Frame. Work(AFX) CWin. App 파생클래스의 구현 class CMy. App : public

2. MFC – Frame. Work(AFX) CWin. App 파생클래스의 구현 class CMy. App : public CWin. App { public: CMy. App(); }; // Overrides public: virtual BOOL Init. Instance();

2. MFC – Frame. Work(AFX) 메시지 큐 윈도우 오퍼레이팅 시스템 메시지 큐 WM_ACTIVATE WM_CREATE

2. MFC – Frame. Work(AFX) 메시지 큐 윈도우 오퍼레이팅 시스템 메시지 큐 WM_ACTIVATE WM_CREATE WM_ACTIVATE WM_MOVE 프로그램 CWin. App: : Run( ) { switch( ) case : } 메시지 핸들러 On. Create On. Activate On. Move

2. MFC – Frame. Work(AFX) CWnd 파생 클래스의 동작 CWnd 상 속 CMy. Wnd

2. MFC – Frame. Work(AFX) CWnd 파생 클래스의 동작 CWnd 상 속 CMy. Wnd WM_CREATE On. Create WM_MOVE On. Move WM_SIZE On. Size( )

3. MFC와 Win 32 API의 밀회 API : BOOL Show. Window( HWND h. Wnd,

3. MFC와 Win 32 API의 밀회 API : BOOL Show. Window( HWND h. Wnd, int n. Cmd. Show ); MFC : BOOL CWnd: : Show. Window(int n. Cmd. Show ); API함수는 해당 함수의 윈도우 핸들이 명시된다. MFC함수는 핸들 값이 클래스의 멤버 변수로 설정되기 때문에 HWND파라 미터가 없다. _AFXWIN_INLINE BOOL CWnd: : Show. Window(int n. Cmd. Show) { ASSERT(: : Is. Window(m_h. Wnd)); return : : Show. Window(m_h. Wnd, n. Cmd. Show); } Afxwin 2. inl

3. MFC와 Win 32 API의 밀회 class CWnd : public CCmd. Target { DECLARE_DYNCREATE(CWnd)

3. MFC와 Win 32 API의 밀회 class CWnd : public CCmd. Target { DECLARE_DYNCREATE(CWnd) protected: static const MSG* PASCAL Get. Current. Message(); // Attributes public: HWND m_h. Wnd; // must be first data member operator HWND() const; BOOL operator==(const CWnd& wnd) const; BOOL operator!=(const CWnd& wnd) const; (Afxwin. h) CWnd클래스가 정의된 코드에 보면 m_h. Wnd가 있음을 확인 할 수 있다.

4. SDK에서 MFC프로그래밍으로의 전환 #include <afxwin. h> class CMy. App: public CWin. App {

4. SDK에서 MFC프로그래밍으로의 전환 #include <afxwin. h> class CMy. App: public CWin. App { public: virtual BOOL Init. Instance(); }; class CMy. Frame: public CFrame. Wnd { protected: afx_msg void On. RButton. Down(UINT n. Flags, CPoint point); DECLARE_MESSAGE_MAP() }; <Test. h>

4. SDK에서 MFC프로그래밍으로의 전환 #include "Test. h" CMy. App the. App; BOOL CMy. App:

4. SDK에서 MFC프로그래밍으로의 전환 #include "Test. h" CMy. App the. App; BOOL CMy. App: : Init. Instance() { CMy. Frame * p. Frame = new CMy. Frame; p. Frame->Create(NULL, "MFC 윈도우 프로그램"); p. Frame->Show. Window(SW_SHOWMAXIMIZED); p. Frame->Update. Window(); m_p. Main. Wnd = p. Frame; return TRUE; } BEGIN_MESSAGE_MAP(CMy. Frame, CFrame. Wnd) ON_WM_RBUTTONDOWN() END_MESSAGE_MAP() void CMy. Frame: : On. RButton. Down(UINT n. Flags, CPoint point) { Message. Box("MFC 예제 프로그램"); } <Test. cpp> [Project->Settings…] <USE MFC in a Shared DLL>로 Setting

4. SDK에서 MFC프로그래밍으로의 전환 class CWin. App : public CWin. Thread { DECLARE_DYNAMIC(CWin. App)

4. SDK에서 MFC프로그래밍으로의 전환 class CWin. App : public CWin. Thread { DECLARE_DYNAMIC(CWin. App) public: // Constructor CWin. App(LPCTSTR lpsz. App. Name = NULL); // app name defaults to EXE name // Attributes HINSTANCE m_h. Instance; HINSTANCE m_h. Prev. Instance; LPTSTR m_lp. Cmd. Line; int m_n. Cmd. Show; <Afxwin. h>

4. SDK에서 MFC프로그래밍으로의 전환 int AFXAPI Afx. Win. Main(HINSTANCE h. Instance, HINSTANCE h. Prev.

4. SDK에서 MFC프로그래밍으로의 전환 int AFXAPI Afx. Win. Main(HINSTANCE h. Instance, HINSTANCE h. Prev. Instance, LPTSTR lp. Cmd. Line, int n. Cmd. Show) { ASSERT(h. Prev. Instance == NULL); int n. Return. Code = -1; CWin. Thread* p. Thread = Afx. Get. Thread(); CWin. App* p. App = Afx. Get. App(); // AFX internal initialization if (!Afx. Win. Init(h. Instance, h. Prev. Instance, lp. Cmd. Line, n. Cmd. Show)) goto Init. Failure; // App global initializations (rare) if (p. App != NULL && !p. App->Init. Application()) goto Init. Failure; // Perform specific initializations if (!p. Thread->Init. Instance()) { if (p. Thread->m_p. Main. Wnd != NULL) { TRACE 0("Warning: Destroying non-NULL m_p. Main. Wndn");

4. SDK에서 MFC프로그래밍으로의 전환 p. Thread->m_p. Main. Wnd->Destroy. Window(); } n. Return. Code =

4. SDK에서 MFC프로그래밍으로의 전환 p. Thread->m_p. Main. Wnd->Destroy. Window(); } n. Return. Code = p. Thread->Exit. Instance(); goto Init. Failure; } n. Return. Code = p. Thread->Run(); Init. Failure: #ifdef _DEBUG // Check for missing Afx. Lock. Temp. Map calls if (Afx. Get. Module. Thread. State()->m_n. Temp. Map. Lock != 0) { TRACE 1("Warning: Temp map lock count non-zero (%ld). n", Afx. Get. Module. Thread. State()->m_n. Temp. Map. Lock); } Afx. Lock. Temp. Maps(); Afx. Unlock. Temp. Maps(-1); #endif Afx. Win. Term(); return n. Return. Code; } <WINMAIN. CPP>

4. SDK에서 MFC프로그래밍으로의 전환 메시지 유형 메시지 맵 엔트리 메시지 핸들러 원형 WM_MOUSEMOVE ON_WM_MOUSEMOVE()

4. SDK에서 MFC프로그래밍으로의 전환 메시지 유형 메시지 맵 엔트리 메시지 핸들러 원형 WM_MOUSEMOVE ON_WM_MOUSEMOVE() WM_KEYDOWN ON_WM_KEYDOWN() WM_DESTORY ON_WM_DESTORY() Void On. Destory() WM_COMMAND ON_COMMAND(id, Func) Void Func() Void On. Mouse. Move (UINT n. Flags, Cpoint); Void On. Key. Down(UINT n. Char, UINT n. Rep. Cnt, UNIT n. Flags);

4. SDK에서 MFC프로그래밍으로의 전환 #define DECLARE_MESSAGE_MAP()  private:  static const AFX_MSGMAP_ENTRY _message. Entries[];

4. SDK에서 MFC프로그래밍으로의 전환 #define DECLARE_MESSAGE_MAP() private: static const AFX_MSGMAP_ENTRY _message. Entries[]; protected: static AFX_DATA const AFX_MSGMAP message. Map; static const AFX_MSGMAP* PASCAL _Get. Base. Message. Map(); virtual const AFX_MSGMAP* Get. Message. Map() const; #define BEGIN_MESSAGE_MAP(the. Class, base. Class) const AFX_MSGMAP* PASCAL the. Class: : _Get. Base. Message. Map() { return &base. Class: : message. Map; } const AFX_MSGMAP* the. Class: : Get. Message. Map() const { return &the. Class: : message. Map; } AFX_COMDAT AFX_DATADEF const AFX_MSGMAP the. Class: : message. Map = { &the. Class: : _Get. Base. Message. Map, &the. Class: : _message. Entries[0] }; AFX_COMDAT const AFX_MSGMAP_ENTRY the. Class: : _message. Entries[] = { #define END_MESSAGE_MAP() {0, 0, Afx. Sig_end, (AFX_PMSG)0 } };

6. App. Wizard에 의해 생성된 내용 CObject CCmd. Target CWin. Thread CDocument CWin. App

6. App. Wizard에 의해 생성된 내용 CObject CCmd. Target CWin. Thread CDocument CWin. App CTest. Doc CWnd CDoc. Template CFrame. Wnd CView CDialog CMain. Frame CTest. View CAbout. Dlg

8. MFC의 계층 구조 아래의 매크로들은 Cobject에서 파생된 크래스에 런타임시 클래스 정보와 객체 생성

8. MFC의 계층 구조 아래의 매크로들은 Cobject에서 파생된 크래스에 런타임시 클래스 정보와 객체 생성 여부 그리고 직렬화 서비스를 제공하는 역할을 한다. 매크로 DECLARE_DYNAMIC, IMPLEMENT_DYNAMIC DECLARE_DYNCREATE IMPLEMENT_DYNCREATE DECLARE_SERIAL IMPLEMENT_SERIAL 실시간클래스 정보 동적생성 여부 Serialize 여부 Cobject: : Is. Kind. Of() CRuntime. Class: : Create. Object() CArchive: : Operator <<

9. App. Wizard가 생성한 코드(App) class CTESTApp : public CWin. App { public: CTESTApp();

9. App. Wizard가 생성한 코드(App) class CTESTApp : public CWin. App { public: CTESTApp(); // Overrides // Class. Wizard generated virtual function overrides //{{AFX_VIRTUAL(CTESTApp) public: virtual BOOL Init. Instance(); //}}AFX_VIRTUAL // Implementation //{{AFX_MSG(CTESTApp) afx_msg void On. App. About(); // NOTE - the Class. Wizard will add and remove member // DO NOT EDIT what you see in these blocks of //}}AFX_MSG DECLARE_MESSAGE_MAP() };

9. App. Wizard가 생성한 코드(App) [구현 파일(Test. cpp)] #ifdef _DEBUG #define new DEBUG_NEW #undef

9. App. Wizard가 생성한 코드(App) [구현 파일(Test. cpp)] #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif BEGIN_MESSAGE_MAP(CTESTApp, CWin. App) //{{AFX_MSG_MAP(CTESTApp) ON_COMMAND(ID_APP_ABOUT, On. App. About) // NOTE - the Class. Wizard will add and remove mapping macros here. // DO NOT EDIT what you see in these blocks of generated code! //}}AFX_MSG_MAP // Standard file based document commands ON_COMMAND(ID_FILE_NEW, CWin. App: : On. File. New) ON_COMMAND(ID_FILE_OPEN, CWin. App: : On. File. Open) // Standard print setup command ON_COMMAND(ID_FILE_PRINT_SETUP, CWin. App: : On. File. Print. Setup) END_MESSAGE_MAP()

9. App. Wizard가 생성한 코드(App) BOOL CTESTApp: : Init. Instance() { Afx. Enable. Control.

9. App. Wizard가 생성한 코드(App) BOOL CTESTApp: : Init. Instance() { Afx. Enable. Control. Container(); #ifdef _AFXDLL Enable 3 d. Controls(); // Call this when using MFC in a shared DLL #else Enable 3 d. Controls. Static(); // Call this when linking to MFC statically #endif Set. Registry. Key(_T("Local App. Wizard-Generated Applications")); Load. Std. Profile. Settings(); // Load standard INI file options (including MRU) CSingle. Doc. Template* p. Doc. Template; p. Doc. Template = new CSingle. Doc. Template( IDR_MAINFRAME, RUNTIME_CLASS(CTESTDoc), RUNTIME_CLASS(CMain. Frame), // main SDI frame window RUNTIME_CLASS(CTESTView)); Add. Doc. Template(p. Doc. Template); // Parse command line for standard shell commands, DDE, file open CCommand. Line. Info cmd. Info; Parse. Command. Line(cmd. Info); // Dispatch commands specified on the command line if (!Process. Shell. Command(cmd. Info)) return FALSE; // The one and only window has been initialized, so show and update it. m_p. Main. Wnd->Show. Window(SW_SHOW); m_p. Main. Wnd->Update. Window(); return TRUE; }

9. App. Wizard가 생성한 코드(App) Init. Instance()를 꼭 재정의 해야 하는 이유 CWin. App:

9. App. Wizard가 생성한 코드(App) Init. Instance()를 꼭 재정의 해야 하는 이유 CWin. App: : Init. Instance()에서는 하는일 이 없다. BOOL CWin. App: : Init. Instance() { return TRUE; } (appcore. cpp에서 참조)

9. App. Wizard가 생성한 코드(App) [afx. Win. Main()] int AFXAPI Afx. Win. Main(HINSTANCE h.

9. App. Wizard가 생성한 코드(App) [afx. Win. Main()] int AFXAPI Afx. Win. Main(HINSTANCE h. Instance, HINSTANCE h. Prev. Instance, LPTSTR lp. Cmd. Line, int n. Cmd. Show) { ASSERT(h. Prev. Instance == NULL); int n. Return. Code = -1; CWin. Thread* p. Thread = Afx. Get. Thread(); CWin. App* p. App = Afx. Get. App(); // AFX internal initialization if (!Afx. Win. Init(h. Instance, h. Prev. Instance, lp. Cmd. Line, n. Cmd. Show)) goto Init. Failure; // App global initializations (rare) if (p. App != NULL && !p. App->Init. Application()) goto Init. Failure; // Perform specific initializations if (!p. Thread->Init. Instance()) { if (p. Thread->m_p. Main. Wnd != NULL) { TRACE 0("Warning: Destroying non-NULL m_p. Main. Wndn");

9. App. Wizard가 생성한 코드(App) [afx. Win. Main()] p. Thread->m_p. Main. Wnd->Destroy. Window(); }

9. App. Wizard가 생성한 코드(App) [afx. Win. Main()] p. Thread->m_p. Main. Wnd->Destroy. Window(); } n. Return. Code = p. Thread->Exit. Instance(); goto Init. Failure; } n. Return. Code = p. Thread->Run(); Init. Failure: #ifdef _DEBUG // Check for missing Afx. Lock. Temp. Map calls if (Afx. Get. Module. Thread. State()->m_n. Temp. Map. Lock != 0) { TRACE 1("Warning: Temp map lock count non-zero (%ld). n", Afx. Get. Module. Thread. State()->m_n. Temp. Map. Lock); } Afx. Lock. Temp. Maps(); Afx. Unlock. Temp. Maps(-1); #endif Afx. Win. Term(); return n. Return. Code; } <WINMAIN. CPP>

9. App. Wizard가 생성한 코드(App) CWin. App: : Run() int CWin. App: : Run()

9. App. Wizard가 생성한 코드(App) CWin. App: : Run() int CWin. App: : Run() { if (m_p. Main. Wnd == NULL && Afx. Ole. Get. User. Ctrl()) { // Not launched /Embedding or /Automation, but has no main window! TRACE 0("Warning: m_p. Main. Wnd is NULL in CWin. App: : Run – quitting application. n"); Afx. Post. Quit. Message(0); } return CWin. Thread: : Run(); } (appcore. cpp에서 참조)

9. App. Wizard가 생성한 코드(App) int CWin. Thread: : Run() { ASSERT_VALID(this); // for

9. App. Wizard가 생성한 코드(App) int CWin. Thread: : Run() { ASSERT_VALID(this); // for tracking the idle time state BOOL b. Idle = TRUE; LONG l. Idle. Count = 0; // acquire and dispatch messages until a WM_QUIT message is received. for (; ; ) { while (b. Idle && !: : Peek. Message(&m_msg. Cur, NULL, PM_NOREMOVE)) // call On. Idle while in b. Idle state if (!On. Idle(l. Idle. Count++)) b. Idle = FALSE; // assume "no idle" state } // phase 2: pump messages while available do { // pump message, but quit on WM_QUIT if (!Pump. Message()) return Exit. Instance(); // reset "no idle" state after pumping "normal" message if (Is. Idle. Message(&m_msg. Cur)) { b. Idle = TRUE; l. Idle. Count = 0; } } while (: : Peek. Message(&m_msg. Cur, NULL, PM_NOREMOVE)); } ASSERT(FALSE); // not reachable } (thrdcore. cpp에서 참조)

9. App. Wizard가 생성한 코드(App) CTESTApp: : On. Idle(LONG l. Count) Message. Queue에 어떤

9. App. Wizard가 생성한 코드(App) CTESTApp: : On. Idle(LONG l. Count) Message. Queue에 어떤 메시지도 있지 않을때 l. Count를 증가하여 함수를 호출 On. Idle(l. Idle. Count++)) 메시지가 있으면 Run()에서 l. Idle. Count변수를 0으로 Setting한다.

9. App. Wizard가 생성한 코드(App) 레지스트리에 특정정보를 저장하고 읽는 작업 CString section = "시작/종료

9. App. Wizard가 생성한 코드(App) 레지스트리에 특정정보를 저장하고 읽는 작업 CString section = "시작/종료 시간"; CString entry = "시작"; CTime time = CTime: : Get. Current. Time(); CString str = time. Format("%C"); Write. Profile. String(section, entry, str); CString section = "시작/종료 시간"; CString entry = “종료"; CTime time = CTime: : Get. Current. Time(); CString str = time. Format("%C"); Write. Profile. String(section, entry, str);

9. App. Wizard가 생성한 코드(App) 레지스트리에 특정정보를 저장하고 읽는 작업 CString section = "시작/종료

9. App. Wizard가 생성한 코드(App) 레지스트리에 특정정보를 저장하고 읽는 작업 CString section = "시작/종료 시간"; CString entry = "시작"; Cstring str; str = Get. Profile. String(section, entry); Afx. Message. Box(str);

10. App. Wizard가 생성한 코드(Main. Frm) class CMain. Frame : public CFrame. Wnd {

10. App. Wizard가 생성한 코드(Main. Frm) class CMain. Frame : public CFrame. Wnd { protected: // create from serialization only CMain. Frame(); DECLARE_DYNCREATE(CMain. Frame) // Attributes public: // Operations public: // Overrides // Class. Wizard generated virtual function overrides //{{AFX_VIRTUAL(CMain. Frame) public: virtual BOOL Pre. Create. Window(CREATESTRUCT& cs); //}}AFX_VIRTUAL

10. App. Wizard가 생성한 코드(Main. Frm) // Implementation public: virtual ~CMain. Frame(); #ifdef _DEBUG

10. App. Wizard가 생성한 코드(Main. Frm) // Implementation public: virtual ~CMain. Frame(); #ifdef _DEBUG virtual void Assert. Valid() const; virtual void Dump(CDump. Context& dc) const; #endif protected: // control bar embedded members CStatus. Bar m_wnd. Status. Bar; CTool. Bar m_wnd. Tool. Bar; // Generated message map functions protected: //{{AFX_MSG(CMain. Frame) afx_msg int On. Create(LPCREATESTRUCT lp. Create. Struct); // NOTE - the Class. Wizard will add and remove member functions here. // DO NOT EDIT what you see in these blocks of generated code! //}}AFX_MSG DECLARE_MESSAGE_MAP() };

10. App. Wizard가 생성한 코드 (Main. Frm) #define DECLARE_DYNAMIC(class_name)  protected:  static CRuntime.

10. App. Wizard가 생성한 코드 (Main. Frm) #define DECLARE_DYNAMIC(class_name) protected: static CRuntime. Class* PASCAL _Get. Base. Class(); public: static const AFX_DATA CRuntime. Class class##class_name; virtual CRuntime. Class* Get. Runtime. Class() const; #define IMPLEMENT_DYNCREATE(class_name, base_class_name) CObject* PASCAL class_name: : Create. Object() { return new class_name; } IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0 x. FFFF, class_name: : Create. Object) #define IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, w. Schema, pfn. New) AFX_COMDAT const AFX_DATADEF CRuntime. Class class_name: : class##class_name = { #class_name, sizeof(class_name), w. Schema, pfn. New, RUNTIME_CLASS(base_class_name), NULL }; CRuntime. Class* class_name: : Get. Runtime. Class() const { return RUNTIME_CLASS(class_name); }

10. App. Wizard가 생성한 코드 (Main. Frm) DECLARE_DYNCREATE()매크로 protected: static CRuntime. Class* PASCAL _Get.

10. App. Wizard가 생성한 코드 (Main. Frm) DECLARE_DYNCREATE()매크로 protected: static CRuntime. Class* PASCAL _Get. Base. Class(); public: static const AFX_DATA CRuntime. Class class##class_name; virtual CRuntime. Class* Get. Runtime. Class() const; static CObject* PASCAL Create. Object(); IMPLEMENT_DYNCREATE()매크로 CObject* PASCAL class_name: : Create. Object() { return new class_name; } AFX_COMDAT const AFX_DATADEF CRuntime. Class class_name: : class##class_name = { #class_name, sizeof(class_name), w. Schema, pfn. New, RUNTIME_CLASS(base_class_name) , NULL }; CRuntime. Class* class_name: : Get. Runtime. Class() const { return RUNTIME_CLASS(class_name); }

10. App. Wizard가 생성한 코드 (Main. Frm) 툴바를 표현하고 관리하는 클래스CTool. Bar의 객체 m_wnd.

10. App. Wizard가 생성한 코드 (Main. Frm) 툴바를 표현하고 관리하는 클래스CTool. Bar의 객체 m_wnd. Tool. Bar 상태바를 표하고 관리하는 클래스 CStatus. Bar의 객체 m_wnd. Status. Bar 포 함 구현 파일 (Main. Frm. cpp) 상태 바의 각 패인(Pane)을 정의하기 위해 사용 static UINT indicators[] = { ID_SEPARATOR, ID_INDICATOR_CAPS, ID_INDICATOR_NUM, ID_INDICATOR_SCRL, };

10. App. Wizard가 생성한 코드 (Main. Frm) 구현 파일 (Main. Frm. cpp) 메인 윈도우의

10. App. Wizard가 생성한 코드 (Main. Frm) 구현 파일 (Main. Frm. cpp) 메인 윈도우의 사용자 영역을 관리하는 뷰 객체를 생성. if (CFrame. Wnd: : On. Create(lp. Create. Struct) == -1) return -1; int CFrame. Wnd: : On. Create(LPCREATESTRUCT lpcs) { CCreate. Context* p. Context = (CCreate. Context*)lpcs->lp. Create. Params; return On. Create. Helper(lpcs, p. Context); } int CFrame. Wnd: : On. Create. Helper(LPCREATESTRUCT lpcs, CCreate. Context* p. Context) { if (CWnd: : On. Create(lpcs) == -1) // return -1; if (!On. Create. Client(lpcs, p. Context)) { TRACE 0("Failed to create client pane/view for frame. n"); return -1; } Recalc. Layout(); return 0; // create ok }

10. App. Wizard가 생성한 코드 (Main. Frm) BOOL CFrame. Wnd: : On. Create. Client(LPCREATESTRUCT,

10. App. Wizard가 생성한 코드 (Main. Frm) BOOL CFrame. Wnd: : On. Create. Client(LPCREATESTRUCT, CCreate. Context* p. Context) { // default create client will create a view if asked for it if (p. Context != NULL && p. Context->m_p. New. View. Class != NULL) { if (Create. View(p. Context, AFX_IDW_PANE_FIRST) == NULL) return FALSE; } return TRUE; } CWnd* CFrame. Wnd: : Create. View(CCreate. Context* p. Context, UINT n. ID) { // Note: can be a CWnd with Post. Nc. Destroy self cleanup CWnd* p. View = (CWnd*)p. Context->m_p. New. View. Class->Create. Object(); ASSERT_KINDOF(CWnd, p. View); // views are always created with a border! if (!p. View->Create(NULL, AFX_WS_DEFAULT_VIEW, CRect(0, 0, 0, 0), this, n. ID, p. Context)) { TRACE 0("Warning: could not create view for frame. n"); return NULL; // can't continue without a view } return p. View; }

10. App. Wizard가 생성한 코드 (Main. Frm) 구현 파일 (Main. Frm. cpp)(계속) m_wnd. Tool.

10. App. Wizard가 생성한 코드 (Main. Frm) 구현 파일 (Main. Frm. cpp)(계속) m_wnd. Tool. Bar를 이용하여 툴바를 생성 m_wnd. Tool. Bar. Create. Ex(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) TBSTYLE_FLAT는 평면 툴바 생성 CBRS_GRIPPER : 좌측에 |(Gripper)생성 CBRS_TOOLTIPS : 툴팁이 생성 CBRS_FLYBY : 툴 바에 커서를 위치하면 상태바에 해당 정보가 출력된다. Load. Tool. Bar() : 리소스의 툴바를 로드한다.

10. App. Wizard가 생성한 코드 (Main. Frm) 구현 파일 (Main. Frm. cpp)(계속) m_wnd. Status.

10. App. Wizard가 생성한 코드 (Main. Frm) 구현 파일 (Main. Frm. cpp)(계속) m_wnd. Status. Bar를 이용하여 상태바를 생성 m_wnd. Tool. Bar. Enable. Docking(CBRS_ALIGN_ANY); Dock. Control. Bar(&m_wnd. Tool. Bar); m_wnd. Tool. Bar. Enable. Docking() : 툴바를 도킹 가능하도록 한다. Enable. Docking(CBRS_ALIGN_ANY) : 메인 프레임 윈도우를 도킹가능 하도 록 한다. Dock. Control. Bar(&m_wnd. Tool. Bar) : Frame. Window에 툴바를 도킹시킨다.

11. App. Wizard가 생성한 코드(View) class CTESTView : public CView { protected: // create

11. App. Wizard가 생성한 코드(View) class CTESTView : public CView { protected: // create from serialization only CTESTView(); DECLARE_DYNCREATE(CTESTView) // Attributes public: CTESTDoc* Get. Document(); // Operations public: // Overrides // Class. Wizard generated virtual function overrides //{{AFX_VIRTUAL(CTESTView) public: virtual void On. Draw(CDC* p. DC); // overridden to draw this view virtual BOOL Pre. Create. Window(CREATESTRUCT& cs); protected: virtual BOOL On. Prepare. Printing(CPrint. Info* p. Info); virtual void On. Begin. Printing(CDC* p. DC, CPrint. Info* p. Info); virtual void On. End. Printing(CDC* p. DC, CPrint. Info* p. Info); //}}AFX_VIRTUAL

11. App. Wizard가 생성한 코드(View) // Implementation public: virtual ~CTESTView(); #ifdef _DEBUG virtual void

11. App. Wizard가 생성한 코드(View) // Implementation public: virtual ~CTESTView(); #ifdef _DEBUG virtual void Assert. Valid() const; virtual void Dump(CDump. Context& dc) const; #endif protected: // Generated message map functions protected: //{{AFX_MSG(CTESTView) // NOTE - the Class. Wizard will add and remove member functions here. // DO NOT EDIT what you see in these blocks of generated code ! //}}AFX_MSG DECLARE_MESSAGE_MAP() }; #ifndef _DEBUG // debug version in TESTView. cpp inline CTESTDoc* CTESTView: : Get. Document() { return (CTESTDoc*)m_p. Document; } #endif

11. App. Wizard가 생성한 코드(View) CTESTDoc* Get. Document(); 자신의 View와 연관된 Document객체를 리턴한다. virtual

11. App. Wizard가 생성한 코드(View) CTESTDoc* Get. Document(); 자신의 View와 연관된 Document객체를 리턴한다. virtual void On. Draw(CDC* p. DC); 화면이나 프린터로 출력 virtual BOOL Pre. Create. Window(CREATESTRUCT& cs); 뷰윈도우를 만들기 전에 호출 #ifndef _DEBUG inline CTESTDoc* CTESTView: : Get. Document() { return (CTESTDoc*)m_p. Document; } #endif 릴리즈 모드에서 속도를 위하여 Get. Document를 inline로 구현

11. App. Wizard가 생성한 코드(View) void CView: : On. Paint() { CPaint. DC dc(this);

11. App. Wizard가 생성한 코드(View) void CView: : On. Paint() { CPaint. DC dc(this); On. Prepare. DC(&dc); On. Draw(&dc); } CPaint. DC: : CPaint. DC(CWnd* p. Wnd) { ASSERT_VALID(p. Wnd); ASSERT(: : Is. Window(p. Wnd->m_h. Wnd)); if (!Attach(: : Begin. Paint(m_h. Wnd = p. Wnd->m_h. Wnd, &m_ps))) Afx. Throw. Resource. Exception(); } CPaint. DC: : ~CPaint. DC() { ASSERT(m_h. DC != NULL); ASSERT(: : Is. Window(m_h. Wnd)); : : End. Paint(m_h. Wnd, &m_ps); Detach(); }

12. App. Wizard가 생성한 코드(Doc) class CTESTDoc : public CDocument { protected: // create

12. App. Wizard가 생성한 코드(Doc) class CTESTDoc : public CDocument { protected: // create from serialization only CTESTDoc(); DECLARE_DYNCREATE(CTESTDoc) public: // Class. Wizard generated virtual function overrides //{{AFX_VIRTUAL(CTESTDoc) public: virtual BOOL On. New. Document(); virtual void Serialize(CArchive& ar); //}}AFX_VIRTUAL public: virtual ~CTESTDoc(); protected: //{{AFX_MSG(CTESTDoc) // NOTE - the Class. Wizard will add and remove member functions here. // DO NOT EDIT what you see in these blocks of generated code ! //}}AFX_MSG DECLARE_MESSAGE_MAP() };

13. 객체간 통신 CWin. App CMain. Frame CChild. Frame CDocument CView Afx. Get. Main.

13. 객체간 통신 CWin. App CMain. Frame CChild. Frame CDocument CView Afx. Get. Main. Wnd() or m_p. Main. Wnd Get. Afx. Main. Wnd() ->MDIGet. Active() Get. Afx. Main. Wnd()->Get. Active. View() ->Get. Document() Get. Afx. Manin. Wnd() ->Get. Active. View() MDIGet. Active() Or Get. Active. Frame() If SDI: Get. Active. View()->Get. Document() If MDI: MDIGet. Active()->Get. Active. View() ->Get. Document() If SDI: Ge. Active. View() if MDI: MDIGet. Active() ->Get. Active. View()->Get. Document() Get. Active. View() CMain. Frame Afx. Get. App() or the. App CChild. Frame Afx. Get. App() Or the. App Get. Parent. Frame() CDocument Afx. Get. App() Or the. App Afx. Get. Main. Wnd() Get. Afx. Main. Wnd()>MDIGet. Active() CView Afx. Get. App() Or the. App Afx. Get. Main. Wnd() Get. Parent. Frame() Get. Document() Any other class Afx. Get. App() Afx. Get. Main. Wnd() ->MDIGet. Active() Or Afx. Get. Main. WNd() ->Get. Active. Frame() If SDI: Afx. Get. Main. Wnd()->Get. Active. View() ->Get. Document() Or if MDI: Afx. Get. Main. Wnd()->MDIGet. Active() ->Get. Active. View()->Get. Document() POSITION pos = Get. First. View. Position(); Get. Next. View(pos); If SDI: AFx. Get. Main. Wnd() ->Get. Active. View() If MDI: Afx. Get. Main. Wnd() ->MDIGet. Active() ->Get. Active. View()

1. DC CDC 클래스 : DC 객체의 최상위 클래스 CDC *p. DC = Get.

1. DC CDC 클래스 : DC 객체의 최상위 클래스 CDC *p. DC = Get. DC(); Release. DC(p. DC); CDC클래스의 주요 속성 Get. Safe. Hdc Set/Get ROP 2 Set/Get Bk. Color Set/Get Text. Color Set/Get Bk. Mode Set/Get Map. Mode Move. To Get. Current. Position Select. Object 현재 오브젝트가 둘러싸고 있는 DC 핸들 리턴 그리기모드 변경(R 2_COPYPEN) 글자출력시 배경의 색상 지정(WHITE) 글자출력 시의 글자색을 지정(BLACK) 배경 모드(OPAQUE) 매핑모드(MM_TEXT) 위치 이동(0, 0) 펜의 객체 선택(BLACK_PEN) 브러쉬의 객체 선택(WHITE_BRUSH) 글꼴의 객체 선택(SYSTEM_FONT)

1. DC MFC의 디바이스 컨텍스트 관련 클래스 Get. DC(h. Wnd)/Release. DC(h. Wnd, h. DC);

1. DC MFC의 디바이스 컨텍스트 관련 클래스 Get. DC(h. Wnd)/Release. DC(h. Wnd, h. DC); Begin. Paint(h. Wnd, &ps)/End. Paint(h. Wnd, &ps); DC를 얻으면 꼭 돌려 주어야 한다. CDC의 생성자와 소멸자를 이용하여 해결 CClient. DC: : CClient. DC(CWnd* p. Wnd) { ASSERT(p. Wnd == NULL || : : Is. Window(p. Wnd->m_h. Wnd)); if (!Attach(: : Get. DC(m_h. Wnd = p. Wnd->Get. Safe. Hwnd()))) Afx. Throw. Resource. Exception(); } CClient. DC: : ~CClient. DC() { ASSERT(m_h. DC != NULL); : : Release. DC(m_h. Wnd, Detach()); }

1. DC CPaint. DC: : CPaint. DC(CWnd* p. Wnd) { ASSERT_VALID(p. Wnd); ASSERT(: :

1. DC CPaint. DC: : CPaint. DC(CWnd* p. Wnd) { ASSERT_VALID(p. Wnd); ASSERT(: : Is. Window(p. Wnd->m_h. Wnd)); if (!Attach(: : Begin. Paint(m_h. Wnd = p. Wnd->m_h. Wnd, &m_ps))) Afx. Throw. Resource. Exception(); } CPaint. DC: : ~CPaint. DC() { ASSERT(m_h. DC != NULL); ASSERT(: : Is. Window(m_h. Wnd)); : : End. Paint(m_h. Wnd, &m_ps); Detach(); } <WINGDI. CPP>

1. DC 사용 예 Void Ctest: : CLButton. Down( UINT n. Flags, Cpoint) {

1. DC 사용 예 Void Ctest: : CLButton. Down( UINT n. Flags, Cpoint) { Crect; Get. Client. Rect(&rect); CClient. DC dc(this); dc. Movo. To(rect. left, rect. top); dc. Line. To(rect. right, rect. bottom); dc. Move. To(rect. right, rect. top); dc. Line. To(rect. left, rect. bottom); }

2. GDI Object void CTEST 1 View: : On. LButton. Down(UINT n. Flags, CPoint

2. GDI Object void CTEST 1 View: : On. LButton. Down(UINT n. Flags, CPoint point) { CClient. DC dc(this); CBrush brush(RGB(255, 0, 0)); dc. Select. Object(&brush); dc. Ellipse(0, 0, 200, 100); } CView: : On. LButton. Down(n. Flags, point); CClient. DC와 Cbrush 는 스택에 생성됨 누가 먼저 소멸? ? - dc가 범위를 벗어나기 전에 관련된 GDI 브러쉬가 삭제됨 Cclient. DC가 소멸되기 전에 원상태로 복구해야 함 따라서 원상태로 복원시켜 주어야 함.

2. GDI Object View: : On. Draw( CDC *p. DC) { CPen new. Pen(PS_DASHDOTDOT,

2. GDI Object View: : On. Draw( CDC *p. DC) { CPen new. Pen(PS_DASHDOTDOT, 2, (COLORREF)0); CPen *p. Old. Pen = p. DC->Select. Object(&new. Pen); p. DC->Move. To( 10, 10); p. DC->Line. To(110, 110); p. DC->Select. Object(p. Old. Pen); // new. Pen이 선택 해제 됨 } // new. Pen이 자동 소멸됨 View: : On. View( ) { CClient. DC dc(this); CPen my. Pen, *p. Old. Pen; my. Pen. Creat. Pen(PS_DOT, 1, RGB(0, 0, 255); p. Old. Pen = dc. Select. Object(&my. Pen); //dc 함수 사용. dc. Select. Object(p. Old. Pen); }

2. GDI Object Stock GDI 객체는 윈도우에 종속적이므로 객체에 대한 해제는 신경쓸 필요가 없다.

2. GDI Object Stock GDI 객체는 윈도우에 종속적이므로 객체에 대한 해제는 신경쓸 필요가 없다. virtual CGDIObject *Select. Object(int n. Index); View: : On. Draw( CDC *p. DC) { CPen new. Pen(PS_DASHDOTDOT, 2, (COLORREF)0); CPen *p. Old. Pen = p. DC->Select. Object(&new. Pen); p. DC->Move. To( 10, 10); p. DC->Line. To(110, 110); p. DC->Select. Object(BLACK_PEN); // new. Pen이 선택 해제 됨 } // new. Pen이 자동 소멸됨

2. GDI Object 시스템 내장(Stock) GDI Object 팬 브러시 폰트 BLACK_PEN BLACK_BRUSH ANSI_FIXED_FONT (ANSI고정

2. GDI Object 시스템 내장(Stock) GDI Object 팬 브러시 폰트 BLACK_PEN BLACK_BRUSH ANSI_FIXED_FONT (ANSI고정 폰트) WHITE_PEN WHITE_BRUSH ANSI_VAR_FONT (ANSI 가변 폰트) NULL_PEN GRAY_BRUSH HOLLOW_BRUSH SYSTEM_FONT (시스템 폰트) 내장 GDI 오브젝트를 사용할 때는 DCD: : Select. Stock. Object()를 호출한다. CGdi. Object *를 리턴하므로 자신이 사용하는 오브젝트에 맞게 형변환하여 사용한다.

2. GDI Object 사용예 : 도형그리기 CClient. DC dc(this); CPoint point 1; point 1.

2. GDI Object 사용예 : 도형그리기 CClient. DC dc(this); CPoint point 1; point 1. x = point. x + 100; point 1. y = point. y + 100; CRect rect(point, point 1); CBrush My. Brush, * p. Old. Brush; My. Brush. Create. Solid. Brush(RGB(255, 0, 0)); p. Old. Brush = dc. Select. Object(&My. Brush); dc. Ellipse(point. x, point. y, point 1. x, point 1. y); dc. Select. Object(p. Old. Brush);

3. 무효화 사각형 void CView: : On. Paint() { // standard paint routine CPaint.

3. 무효화 사각형 void CView: : On. Paint() { // standard paint routine CPaint. DC dc(this); On. Prepare. DC(&dc); On. Draw(&dc); }

5. 매핑모드 void CTEST 1 View: : On. Draw(CDC* p. DC) { CTEST 1

5. 매핑모드 void CTEST 1 View: : On. Draw(CDC* p. DC) { CTEST 1 Doc* p. Doc = Get. Document(); ASSERT_VALID(p. Doc); // TODO: add draw code for native data here CRect rect; Get. Client. Rect(&rect); p. DC->Set. Map. Mode(MM_ANISOTROPIC); // 창의 논리적 크기를 500 * 500 으로 설정 // 자동으로 오른쪽, 아래쪽으로 증가 방향이 됨 p. DC->Set. Window. Ext(500, 500); // 500, -500 // 논리적 크기와 매칭되는 물리적 크기 p. DC->Set. Viewport. Ext(rect. Width(), rect. Height()); p. DC->Ellipse(0, 0, 500); // 500, -500 }

5. 매핑모드 void CTEST 1 View: : On. Draw(CDC* p. DC) { CTEST 1

5. 매핑모드 void CTEST 1 View: : On. Draw(CDC* p. DC) { CTEST 1 Doc* p. Doc = Get. Document(); ASSERT_VALID(p. Doc); // TODO: add draw code for native data here CRect rect; Get. Client. Rect(&rect); p. DC->Set. Map. Mode(MM_ISOTROPIC); // 창의 논리적 크기를 500 * 500 으로 설정 // 자동으로 오른쪽, 아래쪽으로 증가 방향이 됨 p. DC->Set. Window. Ext(500, 500); // 500, -500 // 논리적 크기와 매칭되는 물리적 크기 p. DC->Set. Viewport. Ext(rect. Width(), rect. Height()); p. DC->Ellipse(0, 0, 500); // 500, -500 }

6. 좌표 변환 [매핑 모드의 변환] void CTEST 1 View: : On. Draw(CDC* p.

6. 좌표 변환 [매핑 모드의 변환] void CTEST 1 View: : On. Draw(CDC* p. DC) { CTEST 1 Doc* p. Doc = Get. Document(); ASSERT_VALID(p. Doc); // TODO: add draw code for native data here p. DC->Rectangle( 0, 0, 50); CRect rect; Get. Client. Rect(&rect); CPoint // 창의 픽셀 차원의 값을 리턴 point(rect. Width()/2, rect. Height()/2); p. DC->Set. Map. Mode(MM_LOENGLISH); p. DC->DPto. LP(&point); // 매핑 모드 변경 // 논리 ==> 물리로(픽셀==>인치) p. DC->Rectangle( point. x -50, point. y-50, point. x+50, point. y+50); } MM_TEXT : 논리(픽셀) 물리(픽셀) MM_LOENGLISH : 논리(픽셀) 물리(인치) 좌표 변환 불필요 좌표 변환 필요

6. 좌표 변환 [원점 이동] CClient. DC dc(this); dc. Set. Map. Mode(MM_LOMETRIC); dc. Set.

6. 좌표 변환 [원점 이동] CClient. DC dc(this); dc. Set. Map. Mode(MM_LOMETRIC); dc. Set. Viewport. Org(100, 100); dc. Move. To(0, 0); dc. Line. To(100, -100); // 디바이스 좌표의 원점 이동 (0, 0) (100, 100) 1 cm

6. 좌표 변환 [원점 이동] CClient. DC dc(this); dc. Set. Map. Mode(MM_LOMETRIC); dc. Set.

6. 좌표 변환 [원점 이동] CClient. DC dc(this); dc. Set. Map. Mode(MM_LOMETRIC); dc. Set. Window. Org(100, 100); // 윈도우 좌표의 원점 이동 dc. Move. To(0, 0); dc. Line. To(100, -100); (0, 0) 변경된 원점 1 cm [144] 1 cm

7. 실습 [선 및 곡선 그리기] void CTEST 1 View: : On. Draw(CDC* p.

7. 실습 [선 및 곡선 그리기] void CTEST 1 View: : On. Draw(CDC* p. DC) { CTEST 1 Doc* p. Doc = Get. Document(); ASSERT_VALID(p. Doc); // TODO: add draw code for native data here p. DC->Move. To(10, 10); p. DC->Line. To(10, 100); p. DC->Line. To(100, 100); } // 삼각형 그리기 POINT a. Point[4] = { 200, 100, 300, 200}; p. DC->Polyline(a. Point, 4);

7. 실습 [선 및 곡선 그리기] #include <math. h> #define SEGMENTS 500 #define PI

7. 실습 [선 및 곡선 그리기] #include <math. h> #define SEGMENTS 500 #define PI 3. 1415296 void CTEST 1 View: : On. Draw(CDC* p. DC) { CTEST 1 Doc* p. Doc = Get. Document(); ASSERT_VALID(p. Doc); // TODO: add draw code for native data here CRect rect; Get. Client. Rect(&rect); int n. Width int n. Height CPoint } = rect. Width(); = rect. Height(); a. Point[SEGMENTS]; for( int i=0; i<SEGMENTS; i++) { a. Point[i]. x = (i*n. Width) / SEGMENTS; a. Point[i]. y = (int)( ( n. Height / 2 ) * ( 1 - (sin((2*PI *i)/SEGMENTS)))); } p. DC->Polyline( a. Point, SEGMENTS);

7. 실습 [선 및 곡선 그리기] void CTEST 1 View: : On. Draw(CDC* p.

7. 실습 [선 및 곡선 그리기] void CTEST 1 View: : On. Draw(CDC* p. DC) { CTEST 1 Doc* p. Doc = Get. Document(); ASSERT_VALID(p. Doc); // TODO: add draw code for native data here POINT } a. Point 1[4] = { 120, 100, 120, 200, 250, 150, 500, 40 }; a. Point 2[4] = { 120, 100, 50, 350, 200, 500, 40 }; p. DC->Poly. Bezier(a. Point 1, 4); p. DC->Poly. Bezier(a. Point 2, 4);

7. 실습 typedef struct tag. TEXTMETRIC { LONG tm. Height; LONG tm. Ascent; LONG

7. 실습 typedef struct tag. TEXTMETRIC { LONG tm. Height; LONG tm. Ascent; LONG tm. Descent; LONG tm. Internal. Leading; LONG tm. External. Leading; LONG tm. Ave. Char. Width; LONG tm. Max. Char. Width; LONG tm. Weight; LONG tm. Overhang; LONG tm. Digitized. Aspect. X; LONG tm. Digitized. Aspect. Y; char tm. First. Char; char tm. Last. Char; char tm. Default. Char; char tm. Break. Char; BYTE tm. Italic; BYTE tm. Underlined; BYTE tm. Struck. Out; BYTE tm. Pitch. And. Family; BYTE tm. Char. Set; } TEXTMETRIC;

7. 실습 void CTEST 1 View: : On. LButton. Down(UINT n. Flags, CPoint point)

7. 실습 void CTEST 1 View: : On. LButton. Down(UINT n. Flags, CPoint point) { // TODO: Add your message handler code here and/or call default CRect rect; Get. Client. Rect(&rect); CFont font; font. Create. Point. Font(720, _T("Arial")); CWindow. DC dc(this); dc. Select. Object(&font); dc. Set. Bk. Mode(TRANSPARENT); CString string = _T("Hello, MFC"); rect. Offset. Rect(16, 16); dc. Set. Text. Color(RGB(192, 192)); dc. Draw. Text(string, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); rect. Offset. Rect(-16, -16); dc. Set. Text. Color( RGB(2, 0, 255)); dc. Draw. Text(string, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); CView: : On. LButton. Down(n. Flags, point); }

7. 실습 HFONT Create. Font. Indirect( const LOGFONT *lplf ); CHOOSEFONT cf; CClient. DC

7. 실습 HFONT Create. Font. Indirect( const LOGFONT *lplf ); CHOOSEFONT cf; CClient. DC dc(this); CFont My. Font, * p. Old. Font; LOGFONT log. Font; : : Zero. Memory(&log. Font, sizeof(LOGFONT)); : : Zero. Memory(&cf, sizeof(CHOOSEFONT)); cf. l. Struct. Size = sizeof (CHOOSEFONT); cf. hwnd. Owner = Get. Safe. Hwnd(); cf. Flags = CF_SCREENFONTS | CF_EFFECTS; cf. lp. Log. Font = &log. Font; if (: : Choose. Font(&cf)==TRUE) { My. Font. Create. Font. Indirect(cf. lp. Log. Font); p. Old. Font = (CFont *)dc. Select. Object(&My. Font); dc. Text. Out(0, 0, _T("가나다"), 7); dc. Select. Object(p. Old. Font); }

7. 실습 void CTEST 1 View: : On. LButton. Down(UINT n. Flags, CPoint point)

7. 실습 void CTEST 1 View: : On. LButton. Down(UINT n. Flags, CPoint point) { Get. Client. Rect(&rect); CClient. DC dc(this); dc. Set. Viewport. Org(rect. Width()/2, rect. Height()/2); dc. Set. Bk. Mode(TRANSPARENT); for(int i=0; i<3600; i+=150) { LOGFONT lf; : : Zero. Memory(&lf, sizeof(lf)); lf. Height = 160; lf. Weight = FW_BOLD; lf. Escapement = i; lf. Orientation = i; : : lstrcpy(lf. Face. Name, _T("Arial")); CFont font; font. Create. Point. Font. Indirect(&lf); CFont *p. Old. Font = dc. Select. Object(&font); dc. Text. Out(0, 0, CString( _T(" Hello, MFC"))); dc. Select. Object(p. Old. Font); } CView: : On. LButton. Down(n. Flags, point); }

7. 실습 눈금자(Ruler) 응용 프로그램 void CRuler. View: : Draw. Ruler(CDC *p. DC) {

7. 실습 눈금자(Ruler) 응용 프로그램 void CRuler. View: : Draw. Ruler(CDC *p. DC) { for( i = 50; i<1300; i+= 50 ) // DC 초기화 { p. DC->Set. Map. Mode( MM_LOMETRIC); p. DC->Move. To(i, -84); p. DC->Set. Text. Align(TA_CENTER | TA_BOTTOM); p. DC->Line. To(i, -100); p. DC->Set. Bk. Mode(TRANSPARENT); } // 눈금자 본체 그리기 CBrush brush(RGB(255, 0)); for( i=100; i<1300; i+=100) CBrush *p. Old. Brush = p. DC->Select. Object(&brush); { p. DC->Move. To(i, -75); p. DC->Rectangle(0, 0, 1300, -100); p. DC->Line. To(i, -100); p. DC->Select. Object(p. Old. Brush); // 눈금 및 레이블 그리기 for( int i=25; i<1300; i+= 25 ) { p. DC->Move. To(i, -92); p. DC->Line. To(i, -100); } CString string; string. Format(_T("%d"), (i / 100 ) ); p. DC->Text. Out(i, -75, string); } }

1. 마우스 메시지(HOVER/LEAVE) WM_MOUSELEAVE / WM_MOUSEHOVER 메시지 //Winuse. h typedef strut tag. TRACKMOUSEEVENT{ DWORD

1. 마우스 메시지(HOVER/LEAVE) WM_MOUSELEAVE / WM_MOUSEHOVER 메시지 //Winuse. h typedef strut tag. TRACKMOUSEEVENT{ DWORD cb. Size; DWORD dw. Flags; HWND hwnd. Track; DWORD dw. Hover. Time; }TRACKMOUSEEVENT; // // 구조체 크기 원하는 작업의 플래그 메시지가 발생한 창 핸들 대기 시간 // dw. Falsgs : WM_MOUSELEAVE 호출 값 TME_LEAVE WM_MOUSEHOVER 호출 값 TME_HOVER WM_MOUSELEAVE와 WM_MOUSEHOVER 메시지 취소 TME_CANCEL // dw. Hover. Time 마우스가 정지해 있는 상태로 얼마의 시간이 흐르면 WM_MOUSEHOVER 메시지가 창에 전달되도록 할 것인지의 ms 단위 ( default : 400 ms)

1. 마우스 메시지 WM_MOUSELEAVE / WM_MOUSEHOVER 메시지 // 메시지 맵 지원이 안됨 ON_MESSAGE (WM_MOUSELEAVE,

1. 마우스 메시지 WM_MOUSELEAVE / WM_MOUSEHOVER 메시지 // 메시지 맵 지원이 안됨 ON_MESSAGE (WM_MOUSELEAVE, On. Mouse. Leave) ON_MESSAGE(WM_MOUSEHOVER, On. Mouse. Hover) void CMOUSEECView: : On. Mouse. Move(UINT n. Flags, CPoint point) { if( !m_b. Mouse. Over) { TRACE(_T("Mouse entern")); } m_b. Mouse. Over = TRUE; TRACKMOUSEEVENT tme; tme. cb. Size = sizeof(tme); tme. dw. Flags = TME_HOVER | TME_LEAVE; tme. hwnd. Track = m_h. Wnd; tme. dw. Hover. Time = HOVER_DEFAULT; : : Track. Mouse. Event(&tme); } CView: : On. Mouse. Move(n. Flags, point);

1. 마우스 메시지 WM_MOUSELEAVE / WM_MOUSEHOVER 메시지 LRESULT CMOUSEECView: : On. Mouse. Leave(WPARAM w.

1. 마우스 메시지 WM_MOUSELEAVE / WM_MOUSEHOVER 메시지 LRESULT CMOUSEECView: : On. Mouse. Leave(WPARAM w. Param, LPARAM l. Param) { TRACE(_T("Mouse leaven")); m_b. Mouse. Over = FALSE; return 0; } LRESULT CMOUSEECView: : On. Mouse. Hover(WPARAM w. Param, LPARAM l. Param) { TRACE(_T("Mouse hover( x= %d, y = %d)n"), LOWORD(l. Param), HIWORD(l. Param)); } wsprintf(temp, "Mouse hover( x= %d, y = %d)", LOWORD(l. Param), HIWORD(l. Param)); Afx. Get. Main. Wnd()->Set. Window. Text(temp); return 0; //-----------------------------#define _WIN 32_WINNT 0 x 0400 //--------------------------------

1. 마우스 메시지 WM_MOUSELEAVE / WM_MOUSEHOVER 메시지 LRESULT CMOUSEECView: : On. Mouse. Leave(WPARAM w.

1. 마우스 메시지 WM_MOUSELEAVE / WM_MOUSEHOVER 메시지 LRESULT CMOUSEECView: : On. Mouse. Leave(WPARAM w. Param, LPARAM l. Param) { TRACE(_T("Mouse leaven")); m_b. Mouse. Over = FALSE; return 0; } LRESULT CMOUSEECView: : On. Mouse. Hover(WPARAM w. Param, LPARAM l. Param) { TRACE(_T("Mouse hover( x= %d, y = %d)n"), LOWORD(l. Param), HIWORD(l. Param)); } wsprintf(temp, "Mouse hover( x= %d, y = %d)", LOWORD(l. Param), HIWORD(l. Param)); Afx. Get. Main. Wnd()->Set. Window. Text(temp); return 0; //-----------------------------#define _WIN 32_WINNT 0 x 0400 //--------------------------------

1. 마우스 메시지(Mouse. Wheel) BOOL CMOUSEECView: : On. Mouse. Wheel(UINT n. Flags, short z.

1. 마우스 메시지(Mouse. Wheel) BOOL CMOUSEECView: : On. Mouse. Wheel(UINT n. Flags, short z. Delta, CPoint pt) { BOOL b. Up = TRUE; int n. Delta= z. Delta; if( z. Delta < 0 ) { b. Up n. Delta } } = FALSE; = -n. Delta; UINT n. Wheel. Scroll. Lines; : : System. Parameters. Info(SPI_GETWHEELSCROLLLINES, 0, &n. Wheel. Scroll. Lines, 0); if(n. Wheel. Scroll. Lines == WHEEL_PAGESCROLL) Send. Message(WM_VSCROLL, MAKEWPARAM(b. Up ? SB_PAGEUP : SB_PAGEDOWN, 0); else { int n. Lines = (n. Delta * n. Wheel. Scroll. Lines) / WHEEL_DELTA; while( n. Lines--) Send. Message(WM_VSCROLL, MAKEWPARAM(b. Up ? SB_LINEUP : SB_PAGEDOWN, 0); } return CView: : On. Mouse. Wheel(n. Flags, z. Delta, pt);

2. 커서 1) WNDCLASS 에서 등록된 커서 수정 Cstring str. Wnd. Class = Afx.

2. 커서 1) WNDCLASS 에서 등록된 커서 수정 Cstring str. Wnd. Class = Afx. Register. Wnd. Class( 0, Afx. Get. App()->Load. Standard. Cursor(IDC_CROSS), (HBRUSH)(COLOR_WINDOW + 1 ), Afx. Get. App()->Load. Standard. Icon(IDI_WINLOGO) ); Create(str. Wnd. Class, _T(“Mouse Cursor. Demo”)); 2) WM_SETCURSOR 에서 커서 변경 BOOL CMain. Window: : On. Set. Cursor(CWnd *p. Wnd, UINT n. Hit. Test, UINT message) { if( n. Hit. Test == HTCLIENT) { : : Set. Cursor(m_h. Cursor); return TRUE; } return CFame. Wnd: : On. Set. Cursor(p. Wnd, n. Hit. Test, message); } // true : Windows에게 사용할 커서가 정해졌다는 것을 알림

2. 커서 2) WM_SETCURSOR 에서 커서 변경 BOOL CMain. Window: : On. Set. Cursor(CWnd

2. 커서 2) WM_SETCURSOR 에서 커서 변경 BOOL CMain. Window: : On. Set. Cursor(CWnd *p. Wnd, UINT n. Hit. Test, UINT message) { if( n. Hit. Test == HTCLIENT) { DWORD dw. Pos = : : Get. Message. Pos(); CPoint point( LOWORD(dw. Pos, HIWORD(dw. Pos)); Screen. To. Client(&point); CRect rect; Get. Client. Rect (&rect); : : Set. Cursor( ( point. y < rect. Height() / 2 ) ? m_h. Cursor. Arrow : m_h. Cursor. IBeam); return TRUE; } return CFame. Wnd: : On. Set. Cursor(p. Wnd, n. Hit. Test, message); } // : : Show. Cursor(FALSE) : : Show. Cursor(TRUE);

2 커서 BOOL CTESTView: : On. Set. Cursor(CWnd* p. Wnd, UINT n. Hit. Test,

2 커서 BOOL CTESTView: : On. Set. Cursor(CWnd* p. Wnd, UINT n. Hit. Test, UINT message) { // TODO: Add your message handler code here and/or call default : : Set. Cursor(Afx. Get. App()->Load. Cursor(IDC_CURSOR 1)); return TRUE; } void CTESTView: : On. Change. Curosr() { // TODO: Add your command handler code here HCURSOR h. Cursor; h. Cursor = Afx. Get. App()->Load. Cursor(IDC_CURSOR 1); : : Set. Class. Long(m_h. Wnd, GCL_HCURSOR, (long)h. Cursor); } 툴바를 만들어 처리 void CTESTView: : On. Change. Curosr() { // TODO: Add your command handler code here HCURSOR h. Cursor; h. Cursor = : : Load. Cursor. From. File(“C: \Dog. ani); }

3. 키보드 메시지 유형 가상키 코드 WM_KEYDOWN VK_SHIFT WM_KEYDOWN 65 WM_CHAR ANSI 코드 ‘A’

3. 키보드 메시지 유형 가상키 코드 WM_KEYDOWN VK_SHIFT WM_KEYDOWN 65 WM_CHAR ANSI 코드 ‘A’ WM_KEYUP 65 WM_KEYUP VK_SHIFT void CTEST 11 View: : On. Key. Down(UINT n. Char, UINT n. Rep. Cnt, UINT n. Flags) { if( n. Char == 65 ) // n. Char == ‘a’(대소문자 구분불가) { Afx. Message. Box("TEST"); } CView: : On. Key. Down(n. Char, n. Rep. Cnt, n. Flags); }

3. 키보드 키 입력 메시지 WM_KEYDOWN & WM_KEYUP 키 입력 포커스가 있는 창에 키를

3. 키보드 키 입력 메시지 WM_KEYDOWN & WM_KEYUP 키 입력 포커스가 있는 창에 키를 식별할 수 있는 가상 키 코드 와 함께 WM_KEYDOWN 메시지가 전달됨 두 개(ALT, F 10)를 제외한 모든 키는 해당 메시지를 발생시킴 WM_SYSKEYDOWN & WM_SYSKEYUP (ALT, F 10키 클릭시 발생) : : Get. Key. State(VK_SHIFT); // 원하는 키가 눌려져 있는지 확인 // 눌려 있을때 음수값 반환 void CTEST 11 View: : On. Key. Down(UINT n. Char, UINT n. Rep. Cnt, UINT n. Flags) { if( (n. Char == VK_LEFT) && (: : Get. Key. State(VK_CONTROL) < 0 ) ) { Afx. Message. Box("TEST"); } CView: : On. Key. Down(n. Char, n. Rep. Cnt, n. Flags); } : : Get. Key. State(VK_NUMLOCK) & 0 x 01 // Num Lock, Caps Lock, Scrooll Lock 토글상태 확인

3. 키보드 void CTEST 11 View: : On. Char(UINT n. Char, UINT n. Rep.

3. 키보드 void CTEST 11 View: : On. Char(UINT n. Char, UINT n. Rep. Cnt, UINT n. Flags) { if(( n. Char >= 'A' ) ) && ( n. Char <= 'Z' ))) || (( n. Char >= 'a')) && ( n. Char <= 'z')))) { // 문자 표시 } else if( n. Char == VK_RETURN) { // Enter키 처리 } else if( n. Char == VK_BACK) { // Back. Sapce 키 처리 } CView: : On. Char(n. Char, n. Rep. Cnt, n. Flags); }

3. 키보드 캐럿 void CTEST 11 View: : On. Set. Focus(CWnd* p. Old. Wnd)

3. 키보드 캐럿 void CTEST 11 View: : On. Set. Focus(CWnd* p. Old. Wnd) { CView: : On. Set. Focus(p. Old. Wnd); Create. Solid. Caret(2, 20); } POINT pt = { 10, 10 }; Set. Caret. Pos(pt); Show. Caret(); void CTEST 11 View: : On. Kill. Focus(CWnd* p. New. Wnd) { CView: : On. Kill. Focus(p. New. Wnd); } Hide. Caret(); : : Destroy. Caret();

Chapter 4 메뉴

Chapter 4 메뉴

1 메뉴의 기본(불러오기) 메뉴 불러오기 및 표시하기 Set. Menu에 대한 고찰 2개 이상의 메뉴를

1 메뉴의 기본(불러오기) 메뉴 불러오기 및 표시하기 Set. Menu에 대한 고찰 2개 이상의 메뉴를 하나의 프로그램에서 사용시 유용 Create(NULL, _T(“My Application”)); m_menulong. Load. Menu( IDR_LONGMENU); m_menu. Short. Load. Menu(IDR_SHORTMENU); Set. Menu(m_b. Short. Menu ? &m_menu. Short : &m_menu. Long); //----m_b. Short. Menu = TRUE; Set. Menu(&m_menu. Short); Draw. Menu. Bar(); // 메뉴 변경을 다시 그림 //-----m_b. Short. Menu = FALSE; Set. Menu(&m_menu. Long); Draw. Menu. Bar(); Destroy. Menu를 호출하지 않아도 생성된 메뉴는 정상 제거됨

1 메뉴의 기본(명령에 반응하기) 메뉴 명령에 반응하기 WM_COMMAND - HIWORD(w. Param) : 명령 ID

1 메뉴의 기본(명령에 반응하기) 메뉴 명령에 반응하기 WM_COMMAND - HIWORD(w. Param) : 명령 ID Message. Map : ON_COMMAND(ID_FILE_SAVE, On. File. Save) . h : void CMain. Window: : On. File. Save(); . cpp : void CMain. Window: : On. File. Save() 메뉴 핸들러를 생성시킬 수 있는 객체? { …. }

1 메뉴의 기본(명령의 범위) 메뉴 명령의 범위 ON_COMMAND( ID_COLOR_RED, On. Color. Red) ON_COMMAND( ID_COLOR_GREEN,

1 메뉴의 기본(명령의 범위) 메뉴 명령의 범위 ON_COMMAND( ID_COLOR_RED, On. Color. Red) ON_COMMAND( ID_COLOR_GREEN, On. Color. Green) ON_COMMAND( ID_COLOR_BLUE, On. Color. Blue) void CMain. Window: : On. Color. Red() { m_n. Current. Color = 0; } void CMain. Window: : On. Color. Red() { m_n. Current. Color = 1; } void CMain. Window: : On. Color. Red() { m_n. Current. Color = 2; } // 메시지가 하는 기능은 모두 동일…. ON_COMMAND( ID_COLOR_RED, On. Color) ON_COMMAND( ID_COLOR_GREEN, On. Color) ON_COMMAND( ID_COLOR_BLUE, On. Color) void CMain. Window: : On. Color () { UINT n. ID = (UINT)LOWORD(Get. Current. Message()->w. Param); m_n. Current. Color = n. ID - ID_COLOR_RED; }

1 메뉴의 기본(명령의 범위) 메뉴 명령의 범위 // 메시지가 하는 기능은 모두 동일…. ON_COMMAND_RANGE(

1 메뉴의 기본(명령의 범위) 메뉴 명령의 범위 // 메시지가 하는 기능은 모두 동일…. ON_COMMAND_RANGE( ID_COLOR_RED, ID_COLOR_BLUE, On. Color) void CMain. Window: : On. Color (UINT n. ID) { m_n. Current. Color = n. ID - ID_COLOR_RED; } // RANGE 핸들러는 위자드에서 지원되지 않음 // 단, ID값이 연속선상에 있어야 함 #define ID_COLOR_RED 100 #define ID_COLOR_GREEN 101 #define ID_COLOR_BLUE 102

1 메뉴의 기본(항목 업데이트) 메뉴 항목 업데이트 1단계 void CMain. Window: : On. Color

1 메뉴의 기본(항목 업데이트) 메뉴 항목 업데이트 1단계 void CMain. Window: : On. Color (UINT n. ID) { Cmenu *p. Menu = Get. Menu(); p. Menu->Check. Menu. Item(m_n. Current. Color + ID_COLOR_RED, MF_UNCHECKED); // 제거 p. Menu->Check. Menu. Item(n. ID, MF_CHECKED); // 표시 } m_n. Current. Color = n. ID - ID_COLOR_RED;

1 메뉴의 기본(항목 업데이트) 메뉴 항목 업데이트 2단계(API방식) ON_WM_INITMENUPOPUP 핸들러 void CMain. Window: :

1 메뉴의 기본(항목 업데이트) 메뉴 항목 업데이트 2단계(API방식) ON_WM_INITMENUPOPUP 핸들러 void CMain. Window: : On. Init. Menu. Popup( CMenu *p. Popup. Menu, UINT n. Index, BOOL b. Sys. Menu) { if( !b. Sys. Menu ** ( n. Index == COLOR_MENU_INDEX)) { p. Popup. Menu->Check. Menu. Item(ID_COLOR_RED, MF_UNCHECKED; p. Popup. Menu->Check. Menu. Item(ID_COLOR_GREEN, MF_UNCHECKED); p. Popup. Menu->Check. Menu. Item(ID_COLOR_BLUE, MF_UNCHEKED); } } p. Pupup. Menu->Check. Menu. Item(m_n. Current. Color + ID_COLOR_RED, MF_CHECKED);

1 메뉴의 기본(항목 업데이트) 메뉴 항목 업데이트 3단계(MFC 방식) ON_UPDATE_COMMAND_UI 핸들러 ON_COMMAND_RANGE(ID_COLOR_RED, ID_COLOR_BLUE, On.

1 메뉴의 기본(항목 업데이트) 메뉴 항목 업데이트 3단계(MFC 방식) ON_UPDATE_COMMAND_UI 핸들러 ON_COMMAND_RANGE(ID_COLOR_RED, ID_COLOR_BLUE, On. Color); ON_UPDATE_COMMAND_UI( ID_COLOR_RED, On. Update. Color. Red); ON_UPDATE_COMMAND_UI( ID_COLOR_GREEN, On. Update. Color. Green); ON_UPDATE_COMMAND_UI( ID_COLOR_BLUE, On. Update. Color. Blue); void CMain. Window: : On. Color(UINT n. ID) { m_n. Current. Color = n. ID – ID_COLOR_RED; } void CMain. Window: : On. Updatge. Color. Red(CCmd. UI *p. Cmd. UI) { p. Cmd. UI->Set. Check( m_n. Current. Color == 0 ); } void CMain. Window: : On. Updatge. Color. Green(CCmd. UI *p. Cmd. UI) { p. Cmd. UI->Set. Check( m_n. Current. Color == 1 ); }

1 메뉴의 기본(항목 업데이트) 메뉴 항목 업데이트 3단계(MFC 방식) ON_UPDATE_COMMAND_UI_RANGE 핸들러 ON_COMMAND_RANGE(ID_COLOR_RED, ID_COLOR_BLUE, On.

1 메뉴의 기본(항목 업데이트) 메뉴 항목 업데이트 3단계(MFC 방식) ON_UPDATE_COMMAND_UI_RANGE 핸들러 ON_COMMAND_RANGE(ID_COLOR_RED, ID_COLOR_BLUE, On. Color); ON_UPDATE_COMMAND_UI_RANGE(ID_COLOR_BLUE, On. Update. Color. UI) void CMain. Window: : On. Color(UINT n. ID) { m_n. Current. Color = n. ID – ID_COLOR_RED; } void CMain. Window: : On. Updatge. Color. Red(CCmd. UI *p. Cmd. UI) { p. Cmd. UI->Set. Check( p. Cmd. UI->m_n. ID – ID_COLOR_BLUE == m_n. Current. Color); }

1 메뉴의 기본(키보드 액셀러레이터) // CMain. Window의 생성자에서 m_h. Accel. Table = : :

1 메뉴의 기본(키보드 액셀러레이터) // CMain. Window의 생성자에서 m_h. Accel. Table = : : Load. Accelerators(Afx. Get. Instance. Handle(), MAKEINTRESOURCE(IDR_ACCELERATORS)); // Pre. Translate. Message 재지정 BOOL CMain. Window: : Pre. Translate. Message( MSG *p. Msg) { if( CWnd: : Pre. Translate. Message(p. Msg)) return TRUE; return ((m_h. Accel. Table != NULL && : : Translate. Accelerator(m_h. Wnd, m_h. Accel. Table, p. Msg); } // ex) Shapes응용 프로그램