2/e 1998/04 MFC 1/e Windows MFC MFC 2/e 1998/05 1998 UNALIS 3/e 2/e 2/e 3/e 3/e MFC 2/e MFC 3/e MFC MFC 2/e VC5+MFC42 VC6+MFC421 MFC 2/e 1
MFC 2/e PDF http://www.jjhou.com http://expert.csdn.net/jjhou GBK mirror - anyway solution MFC 1/e MFC 2/e jjhou@ccca.nctu.edu.tw
dissecting MFC 2/e part1.pdf chap1~chap3 3,384,209 dissecting MFC 2/e part2.pdf chap4 2,448,990 dissecting MFC 2/e part3.pdf chap5~chap7 2,158,594 dissecting MFC 2/e part4.pdf chap8~chap16 5,171,266 dissecting MFC 2/e part5.pdf appendix A,B,C,D 1,527,111 -- the end 3
3 深入淺出 MFC 2nd Edition 309
310 第㆔篇淺出 MFC 程式設計
第 5 章總觀 Application Framework Application Framework Application Framework Application Framework Object Oriented 311
第㆔篇淺出 MFC 程式設計! Application Framework Application Framework Framework... MDI OLE ODBC Printing Preview C++ Microsoft MFC Borland OWL IBM OpenClass C Runtime Windows API Application Framework application object MFC CWinApp 312
第 5 章總觀 Application Framework 'new' ) Application Framework Application Framework ) Application Framework CASE Computer Aid Software Engineering tool Application Framework Integrated Development Environment IDE Microsoft Borland Symantec Watcom IBM Application Framework IC POP...... Application Framework MFC OWL OpenClass application object 313
第㆔篇淺出 MFC 程式設計 Application Framework Application Framework Application Framework MFC?! MFC MFC application object MFC CWinApp 5-1 MFC File/Open Application Framework Serialize Serialize UI UI UI application framework Application Framework -- C++ override C++ C++ MFC MFC C++ C++ 314
第 5 章總觀 Application Framework CMyWinApp theapp; // global object... BOOL CMyWinApp::InitInstance() CMultiDocTemplate* pdoctemplate; pdoctemplate = new CMultiDocTemplate( IDR_MYTYPE, RUNTIME_CLASS(CMyDoc), RUNTIME_CLASS(CMyMDIChildWnd), RUNTIME_CLASS(CMyView)); AddDocTemplate(pDocTemplate);... View object CMyMDIFrameWnd* pmymainframe = new CMyMDIFrameWnd; MDIChildWnd object Application object MDIFrameWnd object Document object CObject CCmdTarget CWinThread CView CMyView CFrameWnd CMDIFrameWnd CMDIChildWnd CMyMDIChildWnd CDocument CMyDoc CDocTemplate CWnd CWinApp CMyWinApp CMultiDocTemplate CMyMDIFrameWnd 5-1 MFC Application Framework MFC MFC 315
第㆔篇淺出 MFC 程式設計 MIS MIS Application Framework Application Framework MFC Serialize File/Open File/Save Document Serialization Serialize MFC Windows ) MDI OLE Application Framework Application Framework Framework Framework Application Framework 316
第 5 章總觀 Application Framework Application Framework 1985 Apple MacApp Application Framework The key ideas of a commercial application framework : a generic app on steroids that provides a large amount of general-purpose functionality within a well-planned, welltested, cohesive structure. MacApp Application Framework Application Framework -- 317
第㆔篇淺出 MFC 程式設計 Apple Application Framework an extended collection of classes that cooperate to support a complete application architecture or application model, providing more complete application development support than a simple set of class libraries. Ray Valdes 1992 10 Dr. Dobb's Journal "Sizing up Application Frameworks and Class Libraries" An application framework is an integrated object-oriented software system that offers all the application-level classes(documents, views, and commands)needed by a generic application. An application framework is meant to be used in its entirety, and fosters both design reuse and code reuse. An application framework embodies a particular philosophy for structuring an application, and in return for a large mass of prebuilt functionality, the programmer gives up control over many architectural-design decisions. Donald G. Firesmith "Frameworks : The Golden path of the object Nirvana" Application Framework What are frameworks?they are significant collections of collaborating classes that capture both the small-scale patterns and major mechanisms that, in turn, implement the common requirements and design in a specific application domain. 318
第 5 章總觀 Application Framework Bjarne Stroustrup C++ The C++ Programming Language Application Framework Libraries build out of the kinds of classes described above support design and re-use of code by supplying building blocks and ways of combining them; the application builder designs a framework into which these common building blocks are fitted. An alternative, and sometimes more ambitious, approach to the support of design and reuse is to provide code that establishes a common framework into which the application builder fits application-specific code as building blocks. Such an approach is often called an application framework. The classes establishing such a framework often have such fat interfaces that they are hardly types in the traditional sense. They approximate the ideal of being complete applications, except that they don't do anything. The specific actions are supplied by the application programmer. Kaare Christian 1994/02/08 PC Magazine "C++ Application Frameworks" post-and-beam post-and-beam DIY V Do It Yourself -- Application Framework Windows Application Framework Windows post-and-beam Windows C Windows 319
第㆔篇淺出 MFC 程式設計 C++ Application Framework Windows Application Framework message loops Windows Application Framework -- Windows C++ -- Windows API Application Framework Windows C++ Application Framework Windows Framework Application Framework OCX OLE UI Application Framework Framework Windows Framework Application Framework Visual Basic Application Framework Application Framework C++ Framework 320
第 5 章總觀 Application Framework Application Framework Application Framework PC Application Framework C++ PC PC Application Framework C++ UNIX PC C++ Smalltalk-80 Application Framework Application Framework Application Framework Class Library GUI toolkits robustness raw API GUI toolkits Class Library Application Framework MFC OWL Open Class Library PC Application Framework Application Framework 321
第㆔篇淺出 MFC 程式設計 Application Framework, Class Library, GUI toolkit Class Library GUI toolkit Application Framework Class Library Application Framework Class Library Class Library UI GUI toolkit Class Library UI GUI toolkit assembly GUI Windows GUI toolkit DOS Chatter Box DOS GUI Application Framework Windows API MFC APIs Application Framework Windows API MFC OWL Application Framework Application Framework Application Framework 322
第 5 章總觀 Application Framework Application Framework Application Framework Windows API Windows API 1.0 1985.11 379? 2.0 1987.11 458? 3.0 1990.05 578? Multimedia Ex. 1991.12 120? 3. 1 1992.04 973 271 Win32s 1993.08 838 287 Win32 1993.08 1449 291 API Jungle 323
第㆔篇淺出 MFC 程式設計 Microsoft Foundation Classes(MFC) PC C++ Application Frameworks Microsoft MFC Microsoft Foundation Classes Borland OWL Object WindowLibrary IBM VisualAge C++ Open Class Library C++ Watcom Symantec Metaware Integraded Development Environment IDE Application Framework MFC Delphi Pascal Application Framework Java Application Framework Delphi Visual Basic RAD Rapid Application Development PME Properties-Method-Event components properties events methods Borland 1997 C++ Builder PME Visual Component Library VCL C++ Builder RAD Windows SDK Software Development Kit Windows API Windows... API Application Programming Interface 324
第 5 章總觀 Application Framework Windows APIs APIs Windows MFC APIs 1989 Application Framework AFX C++ Windows AFX "X" "utilize the latest in object oriented technology to provide tools and libraries for developers writing the most advanced GUI applications on the market" Windows -- Windows -- "deliver the power of object-oriented solutions to programmers to enable them to build world-class Windows based applications in C++." Windows 3.0 C++ AFX MFC C++ C++ Windows MFC WinMain RegisterClass Window Procedure Windows Windows 325
第㆔篇淺出 MFC 程式設計 MFC AFX Windows Message Mapping Message routing C++ MFC MFC Application Framework MFC MFC 5-3 MFC... LRU MDI About menu toolbar MDI Help statusbar indicator pane 5-3 MFC 326
第 5 章總觀 Application Framework Visual C++ MFC 1992/04 C/C++ 7.0 MFC 1.0 20,000 C++ 60 Windows "thin and efficient C++ transformation of the Windows API" 32 1992/07 Win32 SDK MFC 1.0 AFX Document/View UI AFX MFC UNIX XWindow OS/2 PM Mac System 7 Windows 16 Windows 3.x 32 Windows 95 Windows NT 16 32 Visual C++ 1.0 C/C++ 8.0 MFC 2.0 1993/03 Windows 3.x 16 1993/08 Windows NT Visual C++ 1.1 for Windows NT MFC 2.1 MFC 2.0 60,000 C++ 100 Visual C++ Wizards MFC 2.0 1993/12 16 Visual C++ 1.5 MFC 2.5 OLE2 ODBC 327
第㆔篇淺出 MFC 程式設計 1994/09 Visual C++ 2.0 MFC 3.0 32 Windows NT Windows 95 thread-safe UI Property Sheet miniframe MFC collections template-based Segmented Executable Linker Incremental Linker OBJ EXE, Win32 memory-mapped file, Windows NT Windows 95 editbuildrun-debug, Incremental Linker 1995/01 MAPI Messaging API WinSock MFC 3.1 32 13 Windows 95 tree tooltip spin slider progress RTF edit 1995/07 MFC 3.2 1995/09 32 MFC 4.0 DAO OCX containers Visual C++ 4.0 template RTTI C++ IDE Class View Resource View File View Wizardbar ClassWizard Components Gallery AppWizard 1996 MFC 4.1 ISAPI Internet Server API CHttpServer CHttpFilter CHttpServerContext CHttpFilterContext CHtmlStream Web ISAPI Extension Wizard Visual C++ 4.1 Game SDK Windows 95 Visual C++ 4.1 328
第 5 章總觀 Application Framework OLE OCXs OLE ActiveX Visual C++ 4.1 VxD 1996 MFC 4.2 ActiveX Standard C++ Library Win32 Internet WinInet Internet 22 40 binding data sources Visual C++ 4.2 Wizard ActiveX Web GIF JPEG 1997 Visual C++ 5.0 Visual C++ Visual Tools Visual Studio 97 Visual C++ Visual Basic Visual J++ Visual InterDev Visual FoxPro Visual Studio 97 MFC 4.21 ATL Active Template Library 2.1 ActiveX MFC Windows C++ MFC/C++ Application Framework MFC MFC MFC application framework MFC 329
第㆔篇淺出 MFC 程式設計 MFC General Purpose classes -... indows API classes - Windows API DC... pplication framework classes - Document/View level abstractions - operation system extensions - OLE ODBC DAO MAPI WinSock ISAPI General Purpose classes MFC Windows MFC Windows DOS CObject MFC CObject CObject RTTI Persistence Dynamic Creation Diagnostic DOS MFC CArchive CDumpContext CRuntimeClass collection classes collection Array 330
第 5 章總觀 Application Framework List Map List key String-to-String Map - Word-to-Ptr 16 Map Serialization S MFC collection classes CObject CObject CArray (template) CByteArray CDWordArray CObArray CPtrArray CStringArray CUIntArray CWordArray Arrays of of user types CList (template) CPtrList CObList CStringList Lists of of user types Typed Template Collections CTypedPtrArray CTypedPtrList CTypedPtrMap CMap (template) CMapWordToPtr CMapPtrToWord CMapPtrToPtr CMapWordToOb CMapStringToPtr CMapStringToOb CMapStringToString Maps of of user types CRect - Windows RECT Windows CRect MFC CSize - Windows SIZE CPoint - Windows POINT Windows 331
第㆔篇淺出 MFC 程式設計 CPoint MFC CTime - static GetCurrentTime + - += -+ CTimeSpan - CString - = += < > exception handling classes exception MFC Exception Handling MFC 11 CException CArchiveException CDaoException CDBException CFileException CMemoryException CNotSupportedException COleException COleDispatchException CResourceException CUserException 332
第 5 章總觀 Application Framework Windows API classes MFC Windows API CWinThread - MFC 3.0 MFC thread-safe SDK CWinApp - MFC CWinThread 32 Windows CWinApp m_szexename ProcessShellCommand CWnd - view C++ handle C++ C++ CWnd WM_ WM_COMMAND handle C++ CWnd m_hwnd handle CWnd CWnd handle HWND hwnd = pwnd->m_hwnd; CCmdTarget - CWnd WM_COMMAND GDI DC Menu 333
第㆔篇淺出 MFC 程式設計 Application framework classes Document/View MFC application framework Document/View Document/View/Frame Document Template CDocTemplate CSingleDocTemplate CMultiDocTemplate - Document Template Document View Frame CSingleDocTemplate CMultiDocTemplate MDI SDI MDI CSingleDocTemplate SDI CMultiDocTemplate MDI SDK MDI CMultiDocTemplate SDI CSingleDocTemplate CDocument - CDocument Serialize Scribble Step1 CView - OnDraw Scribble Step1 View High level abstractions UI CToolBar CStatusBar CDialogBar View ScrollView 334
第 5 章總觀 Application Framework CFormView CEditView CTreeView RTF CRichEditView Afx C++ SmallTalk Java MFC Afx Afx AfxWinInit WinMain MFC MFC GUI AfxWinInit - AFX MFC console Visual C++ Tear AfxBeginThread AfxEndThread AfxFormatString1 AfxFormatString2 AfxMessageBox AfxOutputDebugString AfxGetApp AfxGetMainWnd AfxGetInstance AfxRegisterClass 14 # 756 14 # 756 printf printf Windows API MessageBox D # 924 application object CWinApp instance handle WNDCLASS MFC MFC macros CObject CRuntimeClass object services RTTI Serialization... CObject 335
第㆔篇淺出 MFC 程式設計 -- MFC RTTI Serialization "persistent" Dynamic object creation document view frame framework OLE OLE server OLE items OLE client MFC DECLARE_DYNAMIC IMPLEMENT_DYNAMIC DECLARE_DYNCREATE IMPLEMENT_DYNCREATE DECLARE_SERIAL IMPLEMENT_SERIAL DECLARE_OLECREATE OLE IMPLEMENT_OLECREATE OLE 336
第 5 章總觀 Application Framework MFC Message Mapping Command Routing MFC DECLARE_MESSAGE_MAP BEGIN_MESSAGE_MAP ON_COMMAND ON_CONTROL ON_MESSAGE??? ON_OLECMD ON_REGISTERED_MESSAGE ON_REGISTERED_THREAD_ MESSAGE ON_THREAD_MESSAGE ON_UPDATE_COMMAND_UI END_MESSAGE_MAP MFC Programming MFC MFC 337
第㆔篇淺出 MFC 程式設計 MFC data types MFC Win32 SDK Win32 SDK BOOL BSTR BYTE Boolean TRUE FALSE 32-bit 8-bit COLORREF 32-bit DWORD LONG LPARAM LPCSTR LPSTR LPCTSTR 32-bit 32-bit 32-bit callback 32-bit 32-bit 32-bit Unicode DBCS LPTSTR 32-bit Unicode DBCS LPVOID LPRESULT 32-bit 32-bit callback UINT Win16 16-bit Win32 32-bit WNDPROC WORD 32-bit 16-bit WPARAM callback Win16 16 bits Win32 32 bits 338
第 5 章總觀 Application Framework MFC POSITION collection MFC collection classes LPCRECT 32-bit RECT MFC C++ WINDEF.H (_MSC_VER >= 800) #define NULL 0 #define far // Win32 far near memory model #define near // flat model pascall #define pascal stdcall // stdcall #define cdecl _cdecl #define CDECL _cdecl #define CALLBACK stdcall // Windows programming #define WINAPI stdcall // PASCAL CALLBACK WINAPI #define WINAPIV cdecl // APIENTRY stdcall #define APIENTRY WINAPI // #define APIPRIVATE stdcall #define PASCAL stdcall #define FAR #define NEAR #define CONST far near const typedef unsigned long typedef int typedef unsigned char typedef unsigned short typedef float typedef FLOAT typedef BOOL near typedef BOOL far typedef BYTE near typedef BYTE far DWORD; BOOL; BYTE; WORD; FLOAT; *PFLOAT; *PBOOL; *LPBOOL; *PBYTE; *LPBYTE; 339
第㆔篇淺出 MFC 程式設計 typedef int near typedef int far typedef WORD near typedef WORD far typedef long far typedef DWORD near typedef DWORD far typedef void far typedef CONST void far typedef int typedef unsigned int typedef unsigned int *PINT; *LPINT; *PWORD; *LPWORD; *LPLONG; *PDWORD; *LPDWORD; *LPVOID; *LPCVOID; INT; UINT; *PUINT; /* Types use for passing & returning polymorphic values */ typedef UINT WPARAM; typedef LONG LPARAM; typedef LONG LRESULT; typedef DWORD typedef DWORD COLORREF; *LPCOLORREF; typedef struct tagrect LONG left; LONG top; LONG right; LONG bottom; RECT, *PRECT, NEAR *NPRECT, FAR *LPRECT; typedef const RECT FAR* LPCRECT; typedef struct tagpoint LONG x; LONG y; POINT, *PPOINT, NEAR *NPPOINT, FAR *LPPOINT; typedef struct tagsize LONG cx; LONG cy; SIZE, *PSIZE, *LPSIZE; 340
第 5 章總觀 Application Framework 341
342 第㆔篇淺出 MFC 程式設計
第 6 章 MFC 程式的生死因果 MFC C/SDK Windows MFC Application Framework MFC MFC Windows WinMain RegisterClass CreateWindow Message Loop Window Procedure MFC MFC MFC Windows API Application Framework 343
第㆔篇淺出 MFC 程式設計 SDK/MFC WinMain Windows Procedure message handler ClassWizard click click click!!! Wizard VC/MFC Wizard raw Windows API << Windows Application >> various Windows APIs... Window Procedure GetMessage/DispatchMessage CreateWindow RegisterClass WinMain 344
第 6 章 MFC 程式的生死因果 MFC << MFC Application >> CObject MFC CCmdTarget CWinThread CWinApp CMyWinApp CWnd CView CMyView CFrameWnd CMyFrameWnd MFC CDocument CMyDoc Visual C++ << MFC Application >> Dynamic Creation, Serialization. Message Mapping, Message Routing. Windows APIs MFC Window Procedure GetMessage/DispatchMessage CWinApp::Run CreateWindow CWinApp::InitInstance MFC Visual C++ 345
第㆔篇淺出 MFC 程式設計 MFC MFC MFC 1.0 SDK API 2.0 Application Framework Document-View OLE DAO... Document-View C++/MFC AppWizard ClassWizard Wizards Wizards Wizards Document-View MFC SDK API RegisterClass CreateWindow GetMessage DispatchMessage MFC MFC MFC 4.2 "Hello MFC" MFC 6-1 346
第 6 章 MFC 程式的生死因果 CObject CObject CCmdTarget CCmdTarget CWinThread CWinThread CWnd CWnd CWinApp CWinApp CMyWinApp CMyWinApp CFrameWnd CMyFrameWnd CMyFrameWnd 6-1 MFC MFC SDK MFC VC++ 5.0 LIBC.LIB 898826 C Runtime MSVCRT.LIB 510000 C Runtime MSVCRTD.LIB 803418 'D' Debug Large/Medium/Small 32 #38 347
第㆔篇淺出 MFC 程式設計 DLL Import VC++ 5.0 GDI32.LIB 307520 for GDI32.DLL(136704 bytes in Win95) USER32.LIB 517018 for USER32.DLL(45568 bytes in Win95) KERNEL32.LIB 635638 for KERNEL32 DLL(413696 bytes in Win95)... MFC AFX MFC application framework AppWizard MFC import MFC AFX ) VC++ 5.0 MFC 4.2 MFC42.LIB 4200034 MFC42.DLL(941840 bytes) 的 import MFC42D.LIB 3003766 MFC42D.DLL(1393152 bytes) 的 import MFCS42.LIB 168364 MFCS42D.LIB 169284 MFCN42D.LIB 91134 MFCD42D.LIB 486334 MFCO42D.LIB 2173082... link.exe HELLO.MAK Visual C++ makefile makefile 348
第 6 章 MFC 程式的生死因果 SDK WINDOWS.H API WINDOWS.H CommDlg ToolHelp DDEML....H WINDOWS.H 5000.H WINDOWS.H "Master included file for Windows applications" MFC.H STDAFX.H - Precompiled header file MFC STDAFX.H Hello STDAFX.H AFXWIN.H AFXWIN.H - Windows MFC MFC AFX.H AFXVER_.H AFXV_W32.H WINDOWS.H AFXEXT.H - AFXDLGS.H - Common Dialog MFC COMMDLG.H AFXCMN.H - Windows 95 Common Control MFC AFXCOLL.H - Collections Classes AFXDLLX.H - MFC extension DLLs AFXRES.H - MFC RC MFC File Edit ID 349
第㆔篇淺出 MFC 程式設計 // File commands #define ID_FILE_NEW #define ID_FILE_OPEN #define ID_FILE_CLOSE #define ID_FILE_SAVE #define ID_FILE_SAVE_AS... // Edit commands #define ID_EDIT_COPY #define ID_EDIT_CUT... 0xE100 0xE101 0xE102 0xE103 0xE104 0xE122 0xE123 AppWizard Scribble step0 RC STRINGTABLE DISCARDABLE BEGIN ID_FILE_NEW "Create a new document" ID_FILE_OPEN "Open an existing document" ID_FILE_CLOSE "Close the active document" ID_FILE_SAVE "Save the active document" ID_FILE_SAVE_AS "Save the active document with a new name"... ID_EDIT_COPY "Copy the selection and puts it on the Clipboard" ID_EDIT_CUT "Cut the selection and puts it on the Clipboard"... END MFC \MSVC\MFC\INCLUDE Windows SDK WINDOWS.H COMMDLG.H TOOLHELP.H DDEML.H... Precompiled header 350
第 6 章 MFC 程式的生死因果 Precompiled Header Windows.H Precompiled header.h Borland C/C++ Microsoft Visual C++ 1.0 MFC Document/View MFC Application Framework Hello "Hello, MFC" MFC MFC MFC CWinApp CFrameWnd Hello 6-2 MFC CWinApp::InitInstance Hello Hello 6-3 Hello MFC MFC MFC 6-3 Hello MFC Windows API MFC 351
第㆔篇淺出 MFC 程式設計 WinMain RegisterClass CreateWindow Message Loop GetMessage/DispatchMessage Window Procedure Hello HELLO.MAK - makefile RESOURCE.H - ID IDM_ABOUT JJHOUR.ICO - HELLO.RC - STDAFX.H - AFXWIN.H STDAFX.CPP - STDAFX.H Precompiled header HELLO.H - CMyWinApp CMyFrameWnd HELLO.CPP - CMyWinApp CMyFrameWnd.DEF WM_PAINT Hello MFC Application object CWinApp MainFrame object CFrameWnd 352 6-2 Hello
第 6 章 MFC 程式的生死因果 STDAFX.H #include <afxwin.h> STDAFX.CPP #include <stdafx.h> HELLO.H CMyWinApp class declaration CMyFrameWnd class declaration RESOURCE.H #define IDM_xxx HELLO.CPP #include <stdafx.h> #include "resource.h" #include "hello.h" CMyWinApp theapp; CMyWinApp class definition CMyFrameWnd class definition HELLO.RC #include "resource.h" #include <afxres.h> Icon description Menu description Dialog Template Message Map 6-3 Hello.CPP HELLO.MAK DOS nmake hello.mak p.224 #0001 # filename : hello.mak #0002 # make file for hello.exe (MFC 4.0 Application) #0003 # usage : nmake hello.mak (Visual C++ 5.0) #0004 #0005 Hello.exe : StdAfx.obj Hello.obj Hello.res #0006 link.exe /nologo /subsystem:windows /incremental:no \ #0007 /machine:i386 /out:"hello.exe" \ #0008 Hello.obj StdAfx.obj Hello.res \ #0009 msvcrt.lib kernel32.lib user32.lib gdi32.lib mfc42.lib #0010 #0011 StdAfx.obj : StdAfx.cpp StdAfx.h #0012 cl.exe /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" \ #0013 /D "_AFXDLL" /D "_MBCS" /Fp"Hello.pch" /Yc"stdafx.h" \ #0014 /c StdAfx.cpp #0015 #0016 Hello.obj : Hello.cpp Hello.h StdAfx.h #0017 cl.exe /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" \ #0018 /D "_AFXDLL" /D "_MBCS" /Fp"Hello.pch" /Yu"stdafx.h" \ #0019 /c Hello.cpp #0020 #0021 Hello.res : Hello.rc Hello.ico jjhour.ico #0022 rc.exe /l 0x404 /Fo"Hello.res" /D "NDEBUG" /D "_AFXDLL" Hello.rc 353
第㆔篇淺出 MFC 程式設計 RESOURCE.H #0001 // resource.h #0002 #define IDM_ABOUT 100 HELLO.RC #0001 // hello.rc #0002 #include "resource.h" #0003 #include "afxres.h" #0004 #0005 JJHouRIcon ICON DISCARDABLE "JJHOUR.ICO" #0006 AFX_IDI_STD_FRAME ICON DISCARDABLE "JJHOUR.ICO" #0007 #0008 MainMenu MENU DISCARDABLE #0009 #0010 POPUP "&Help" #0011 #0012 MENUITEM "&About HelloMFC...", IDM_ABOUT #0013 #0014 #0015 #0016 AboutBox DIALOG DISCARDABLE 34, 22, 147, 55 #0017 STYLE DS_MODALFRAME WS_POPUP WS_CAPTION WS_SYSMENU #0018 CAPTION "About Hello" #0019 #0020 ICON "JJHouRIcon",IDC_STATIC,11,17,18,20 #0021 LTEXT "Hello MFC 4.0",IDC_STATIC,40,10,52,8 #0022 LTEXT "Copyright 1996 Top Studio",IDC_STATIC,40,25,100,8 #0023 LTEXT "J.J.Hou",IDC_STATIC,40,40,100,8 #0024 DEFPUSHBUTTON "OK",IDOK,105,7,32,14,WS_GROUP #0025 STDAFX.H #0001 // stdafx.h : include file for standard system include files, #0002 // or project specific include files that are used frequently, #0003 // but are changed infrequently #0004 #0005 #include <afxwin.h> // MFC core and standard components 354
第 6 章 MFC 程式的生死因果 STDAFX.CPP #0001 // stdafx.cpp : source file that includes just the standard includes #0002 // Hello.pch will be the pre-compiled header #0003 // stdafx.obj will contain the pre-compiled type information #0004 #0005 #include "stdafx.h" HELLO.H #0001 //--------------------------------------------------------------- #0002 // MFC 4.0 Hello Sample Program #0003 // Copyright (c) 1996 Top Studio * J.J.Hou #0004 // #0005 // #0006 // #0007 // #0008 // #0009 // : hello.h : : hello.mak Hello : CMyFrameWnd CMyWinApp #0010 //--------------------------------------------------------------- #0011 #0012 class CMyWinApp : public CWinApp #0013 #0014 public: #0015 BOOL InitInstance(); // #0016 ; #0017 #0018 //--------------------------------------------------------------- #0019 class CMyFrameWnd : public CFrameWnd #0020 #0021 public: #0022 CMyFrameWnd(); // constructor #0023 afx_msg void OnPaint(); // for WM_PAINT #0024 afx_msg void OnAbout(); // for WM_COMMAND (IDM_ABOUT) #0025 #0026 private: #0027 DECLARE_MESSAGE_MAP() // Declare Message Map #0028 static VOID CALLBACK LineDDACallback(int,int,LPARAM); #0029 // : callback "static" 'this' #0030 ; 355
第㆔篇淺出 MFC 程式設計 HELLO.CPP #0001 //--------------------------------------------------------------- #0002 // MFC 4.0 Hello sample program #0003 // Copyright (c) 1996 Top Studio * J.J.Hou #0004 // #0005 // #0006 // #0007 // #0008 // #0009 // #0010 // : hello.cpp : : hello.mak MFC Document/View WM_PAINT GDI LineDDA() "Hello, MFC" #0011 //--------------------------------------------------------------- #0012 #include "Stdafx.h" #0013 #include "Hello.h" #0014 #include "Resource.h" #0015 #0016 CMyWinApp theapp; // application object #0017 #0018 //--------------------------------------------------------------- #0019 // CMyWinApp's member #0020 //--------------------------------------------------------------- #0021 BOOL CMyWinApp::InitInstance() #0022 #0023 m_pmainwnd = new CMyFrameWnd(); #0024 m_pmainwnd->showwindow(m_ncmdshow); #0025 m_pmainwnd->updatewindow(); #0026 return TRUE; #0027 #0028 //--------------------------------------------------------------- #0029 // CMyFrameWnd's member #0030 //--------------------------------------------------------------- #0031 CMyFrameWnd::CMyFrameWnd() #0032 #0033 Create(NULL, "Hello MFC", WS_OVERLAPPEDWINDOW, rectdefault, #0034 NULL, "MainMenu"); // "MainMenu" #0035 #0036 //--------------------------------------------------------------- #0037 BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd) #0038 ON_COMMAND(IDM_ABOUT, OnAbout) #0039 ON_WM_PAINT() #0040 END_MESSAGE_MAP() #0041 //--------------------------------------------------------------- #0042 void CMyFrameWnd::OnPaint() #0043 #0044 CPaintDC dc(this); 356
第 6 章 MFC 程式的生死因果 #0045 CRect rect; #0046 #0047 GetClientRect(rect); #0048 #0049 dc.settextalign(ta_bottom TA_CENTER); #0050 #0051 ::LineDDA(rect.right/2, 0, rect.right/2, rect.bottom/2, #0052 (LINEDDAPROC) LineDDACallback, (LPARAM) (LPVOID) &dc); #0053 #0054 //--------------------------------------------------------------- #0055 VOID CALLBACK CMyFrameWnd::LineDDACallback(int x, int y, LPARAM lpdc) #0056 #0057 static char sztext[] = "Hello, MFC"; #0058 #0059 ((CDC*)lpdc)->TextOut(x, y, sztext, sizeof(sztext)-1); #0060 for(int i=1; i<50000; i++); // #0061 #0062 //--------------------------------------------------------------- #0063 void CMyFrameWnd::OnAbout() #0064 #0065 CDialog about("aboutbox", this); // #0066 about.domodal(); #0067 "AboutBox" RC MFC CWinApp CFrameWnd MFC BOOL VOID MFC DECLARE_MESSAGE_MAP BEGIN_MESSAGE_END END_MESSAGE_MAP MFC C++ HELLO.H afx_msg #23 CALLBACK #28 WINDEF.H CALLBACK #define CALLBACK stdcall // AFXWIN.H afx_msg #define afx_msg // intentional placeholder // MFC causal relations C/SDK MFC 357
第㆔篇淺出 MFC 程式設計 MFC MFC Windows WinMain Hello theapp application object WinMain application object CWinApp CFrameWnd 6-2 MFC Hello Generic WinMain WndProc MFC WinMain CWinApp WndProc CFrameWnd CWinApp CFrameWnd Frame Window WinMain WndProc class CMyWinApp : public CWinApp... ; class CMyFrameWnd : public CFrameWnd... ; "My" 358
第 6 章 MFC 程式的生死因果 CWinApp- 取代 WinMain 的地位 CWinApp application CWinApp object SDK WinMain InitApplication InitInstance CWinApp AFXWIN.H class CWinApp : public CWinThread // Attributes // Startup args (do not change) HINSTANCE m_hinstance; HINSTANCE m_hprevinstance; LPTSTR m_lpcmdline; int m_ncmdshow; // Running args (can be changed in InitInstance) LPCTSTR m_pszappname; // human readable name LPCTSTR m_pszregistrykey; // used for registry entries public: // set in constructor to override default LPCTSTR m_pszexename; // executable name (no spaces) LPCTSTR m_pszhelpfilepath; // default based on module path LPCTSTR m_pszprofilename; // default based on app name public: // hooks for your initialization code virtual BOOL InitApplication(); // overrides for implementation virtual BOOL InitInstance(); virtual int ExitInstance(); virtual int Run(); virtual BOOL OnIdle(LONG lcount);... ; 359
第㆔篇淺出 MFC 程式設計 CWinApp WinMain SDK MFC WinMain SDK WinMain CWinApp virtual BOOL InitApplication(); virtual BOOL InitInstance(); virtual int Run(); WinMain CWinApp handle C++ MFC 2.5 m_pmainwnd MFC AFXWIN.H 2.5 class CWinApp : public CCmdTarget // Attributes // Startup args (do not change) HINSTANCE m_hinstance; HINSTANCE m_hprevinstance; LPSTR m_lpcmdline; int m_ncmdshow; // Running args (can be changed in InitInstance) CWnd* m_pmainwnd; // main window (optional) CWnd* m_pactivewnd; // active main window (may not be m_pmainwnd) const char* m_pszappname; // human readable name public: // set in constructor to override default const char* m_pszexename; // executable name (no spaces) const char* m_pszhelpfilepath; // default based on module path const char* m_pszprofilename; // default based on app name public: // hooks for your initialization code virtual BOOL InitApplication(); virtual BOOL InitInstance(); // running and idle processing virtual int Run(); virtual BOOL OnIdle(LONG lcount); 360
第 6 章 MFC 程式的生死因果 // exiting virtual int ExitInstance();... ; MFC m_pmainwnd 4.x CWinThread CWinApp MFC AFXWIN.H 4.x class CWinThread : public CCmdTarget // Attributes CWnd* m_pmainwnd; // main window (usually same AfxGetApp()->m_pMainWnd) CWnd* m_pactivewnd; // active main window (may not be m_pmainwnd) // only valid while running HANDLE m_hthread; // this thread's HANDLE DWORD m_nthreadid; // this thread's ID int GetThreadPriority(); BOOL SetThreadPriority(int npriority); // Operations DWORD SuspendThread(); DWORD ResumeThread(); // Overridables // thread initialization virtual BOOL InitInstance(); // running and idle processing virtual int Run(); virtual BOOL PreTranslateMessage(MSG* pmsg); virtual BOOL PumpMessage(); // low level message pump virtual BOOL OnIdle(LONG lcount); // return TRUE if more idle processing public: // valid after construction AFX_THREADPROC m_pfnthreadproc;... ; Win32 CWinThread SuspendThread ResumeThread 361
第㆔篇淺出 MFC 程式設計 CFrameWnd- 取代 WndProc 的地位 CFrameWnd SDK long FAR PASCAL WndProc(HWND hwnd, UNIT msg, WORD wparam, LONG lparam) switch(msg) case WM_COMMAND : switch(wparam) case IDM_ABOUT : OnAbout(hWnd, wparam, lparam); break; break; case WM_PAINT : OnPaint(hWnd, wparam, lparam); break; default : DefWindowProc(hWnd, msg, wparam, lparam); MFC Hello CMyFrameWnd class CMyFrameWnd : public CFrameWnd public: CMyFrameWnd(); afx_msg void OnPaint(); afx_msg void OnAbout(); DECLARE_MESSAGE_MAP() ; OnPaint OnAbout WM_PAINT WM _COMMAND IDM_ABOUT HELLO.CPP DECLARE MAP 362
第 6 章 MFC 程式的生死因果 MFC Message Map DECLARE_MESSAGE_MAP BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd) ON_WM_PAINT() ON_COMMAND(IDM_ABOUT, OnAbout) END_MESSAGE_MAP() 363
第㆔篇淺出 MFC 程式設計 引爆器 -Application object HELLO.H HELLO.CPP application object Hello MFC MFC HELLO.CPP 1 CMyWinApp theapp; // application object WINMAIN.CPP int int AFXAPI AFXAPI AfxWinMain AfxWinMain (...) (...) CWinApp* CWinApp* papp papp = AfxGetApp(); AfxGetApp(); AfxWinInit(...); BOOL CMyWinApp::InitInstance() m_pmainwnd = new CMyFrameWnd(); m_pmainwnd->showwindow(m_ncmdshow); m_pmainwnd->updatewindow(); return TRUE; papp->initapplication(); papp->initinstance(); nreturncode nreturncode = papp->run(); papp->run(); AfxWinTerm(); AfxWinTerm(); CMyFrameWnd::CMyFrameWnd() Create(NULL, "Hello MFC",..., "MainMenu"); void CMyFrameWnd::OnPaint()... void CMyFrameWnd::OnAbout()... BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd) ON_COMMAND(IDM_ABOUT, OnAbout) ON_WM_PAINT() END_MESSAGE_MAP() theapp Hello application MFC object Hello CMyWinApp CWinApp APPCORE.CPP 364
第 6 章 MFC 程式的生死因果 CWinApp::CWinApp(LPCTSTR lpszappname) m_pszappname = lpszappname; // initialize CWinThread state AFX_MODULE_THREAD_STATE* pthreadstate = AfxGetModuleThreadState(); pthreadstate->m_pcurrentwinthread = this; m_hthread = ::GetCurrentThread(); m_nthreadid = ::GetCurrentThreadId(); // initialize CWinApp state AFX_MODULE_STATE* pmodulestate = AfxGetModuleState(); pmodulestate->m_pcurrentwinapp = this; // in non-running state until WinMain m_hinstance = NULL; m_pszhelpfilepath = NULL; m_pszprofilename = NULL; m_pszregistrykey = NULL; m_pszexename = NULL; m_lpcmdline = NULL; m_pcmdinfo = NULL;... CWinApp theapp theapp : 365
第㆔篇淺出 MFC 程式設計 1 HELLO.CPP CMyWinApp theapp; // application object WINMAIN.CPP int int AFXAPI AFXAPI AfxWinMain AfxWinMain (...) (...) CWinApp* CWinApp* papp papp = AfxGetApp(); AfxGetApp(); AfxWinInit(...); AfxWinInit(...); BOOL CMyWinApp::InitInstance() m_pmainwnd = new CMyFrameWnd(); m_pmainwnd->showwindow(m_ncmdshow); m_pmainwnd->updatewindow(); return TRUE; papp->initapplication(); papp->initapplication(); papp->initinstance(); nreturncode nreturncode = papp->run(); papp->run(); AfxWinTerm(); AfxWinTerm(); CMyFrameWnd::CMyFrameWnd() Create(NULL, "Hello MFC",..., "MainMenu"); void CMyFrameWnd::OnPaint()... void CMyFrameWnd::OnAbout()... BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd) ON_COMMAND(IDM_ABOUT, OnAbout) ON_WM_PAINT() END_MESSAGE_MAP() theapp WinMain WinMain MFC 6-4 _twinmain -t Unicode // in APPMODUL.CPP extern "C" int WINAPI _twinmain(hinstance hinstance, HINSTANCE hprevinstance, LPTSTR lpcmdline, int ncmdshow) // call shared/exported WinMain return AfxWinMain(hInstance, hprevinstance, lpcmdline, ncmdshow); DLLMODUL.CPP DllMain DLL 366
第 6 章 MFC 程式的生死因果 // in WINMAIN.CPP #0001 ///////////////////////////////////////////////////////////////// #0002 // Standard WinMain implementation #0003 // Can be replaced as long as 'AfxWinInit' is called first #0004 #0005 int AFXAPI AfxWinMain (HINSTANCE hinstance, HINSTANCE hprevinstance, #0006 LPTSTR lpcmdline, int ncmdshow) #0007 #0008 ASSERT(hPrevInstance == NULL); #0009 #0010 int nreturncode = -1; #0011 CWinApp* papp = AfxGetApp(); #0012 #0013 // AFX internal initialization #0014 if (!AfxWinInit(hInstance, hprevinstance, lpcmdline, ncmdshow)) #0015 goto InitFailure; #0016 #0017 // App global initializations (rare) #0018 ASSERT_VALID(pApp); #0019 if (!papp->initapplication()) #0020 goto InitFailure; #0021 ASSERT_VALID(pApp); #0022 #0023 // Perform specific initializations #0024 if (!papp->initinstance()) #0025 #0026 if (papp->m_pmainwnd!= NULL) #0027 #0028 TRACE0("Warning: Destroying non-null m_pmainwnd\n"); #0029 papp->m_pmainwnd->destroywindow(); #0030 #0031 nreturncode = papp->exitinstance(); #0032 goto InitFailure; #0033 #0034 ASSERT_VALID(pApp); #0035 #0036 nreturncode = papp->run(); #0037 ASSERT_VALID(pApp); #0038 #0039 InitFailure: #0040 #0041 AfxWinTerm(); #0042 return nreturncode; #0043 6-4 Windows MFC WINMAIN.CPP 367
第㆔篇淺出 MFC 程式設計 int AFXAPI AfxWinMain (HINSTANCE hinstance, HINSTANCE hprevinstance, LPTSTR lpcmdline, int ncmdshow) int nreturncode = -1; CWinApp* papp = AfxGetApp(); AfxWinInit(hInstance, hprevinstance, lpcmdline, ncmdshow); papp->initapplication(); papp->initinstance(); nreturncode = papp->run(); AfxWinTerm(); return nreturncode; AfxGetApp AFXWIN1.INL _AFXWIN_INLINE CWinApp* AFXAPI AfxGetApp() return afxcurrentwinapp; afxcurrentwinapp AFXWIN.H #define afxcurrentwinapp AfxGetModuleState()->m_pCurrentWinApp CWinApp::CWinApp AfxGetApp CMyWinApp AfxWinMain CWinApp* papp = AfxGetApp(); papp->initapplication(); papp->initinstance(); nreturncode = papp->run(); CMyWinApp::InitApplication(); CMyWinApp::InitInstance(); CMyWinApp::Run(); CWinApp::InitApplication(); // CMyWinApp InitApplication CMyWinApp::InitInstance(); // CMyWinApp InitInstance CWinApp::Run(); // CMyWinApp Run 368
第 6 章 MFC 程式的生死因果 SDK InitApplication InitInstance Run MFC MFC MFC application framework MFC MFC AfxWinMain 369
第㆔篇淺出 MFC 程式設計 AfxWinInit AFX HELLO.CPP 1 CMyWinApp theapp; // application object WINMAIN.CPP int AFXAPI AfxWinMain (...) CWinApp* papp = AfxGetApp(); 2 AfxWinInit(...); BOOL CMyWinApp::InitInstance() m_pmainwnd = new CMyFrameWnd(); m_pmainwnd->showwindow(m_ncmdshow); m_pmainwnd->updatewindow(); return TRUE; papp->initapplication(); papp->initinstance(); nreturncode = papp->run(); AfxWinTerm(); CMyFrameWnd::CMyFrameWnd() Create(NULL, "Hello MFC",..., "MainMenu"); void CMyFrameWnd::OnPaint()... void CMyFrameWnd::OnAbout()... BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd) ON_COMMAND(IDM_ABOUT, OnAbout) ON_WM_PAINT() END_MESSAGE_MAP() AfxWinInit CWinApp APPINIT.CPP BOOL AFXAPI AfxWinInit(HINSTANCE hinstance, HINSTANCE hprevinstance, LPTSTR lpcmdline, int ncmdshow) ASSERT(hPrevInstance == NULL); // set resource handles AFX_MODULE_STATE* pstate = AfxGetModuleState(); pstate->m_hcurrentinstancehandle = hinstance; pstate->m_hcurrentresourcehandle = hinstance; // fill in the initial state for the application CWinApp* papp = AfxGetApp(); if (papp!= NULL) // Windows specific initialization (not done if no CWinApp) 370
第 6 章 MFC 程式的生死因果 papp->m_hinstance = hinstance; papp->m_hprevinstance = hprevinstance; papp->m_lpcmdline = lpcmdline; papp->m_ncmdshow = ncmdshow; papp->setcurrenthandles(); // initialize thread specific data (for main thread) if (!afxcontextisdll) AfxInitThread(); return TRUE; AfxInitThread THRDCORE.CPP void AFXAPI AfxInitThread() if (!afxcontextisdll) // attempt to make the message queue bigger for (int cmsg = 96;!SetMessageQueue(cMsg) && (cmsg -= 8); ) ; // set message filter proc _AFX_THREAD_STATE* pthreadstate = AfxGetThreadState(); ASSERT(pThreadState->m_hHookOldMsgFilter == NULL); pthreadstate->m_hhookoldmsgfilter = ::SetWindowsHookEx(WH_MSGFILTER, _AfxMsgFilterHook, NULL, ::GetCurrentThreadId()); // intialize CTL3D for this thread _AFX_CTL3D_STATE* pctl3dstate = _afxctl3dstate; if (pctl3dstate->m_pfnautosubclass!= NULL) (*pctl3dstate->m_pfnautosubclass)(afxgetinstancehandle()); // allocate thread local _AFX_CTL3D_THREAD just for automatic termination _AFX_CTL3D_THREAD* ptemp = _afxctl3dthread; Visual C++ WinMain AfxWinInit MFC AfxWinInit 371
第㆔篇淺出 MFC 程式設計 CWinApp::InitApplication 1 HELLO.CPP CMyWinApp theapp; // application object WINMAIN.CPP int AFXAPI AfxWinMain (...) CWinApp* papp = AfxGetApp(); 2 AfxWinInit(...); BOOL CMyWinApp::InitInstance() m_pmainwnd = new CMyFrameWnd(); m_pmainwnd->showwindow(m_ncmdshow); m_pmainwnd->updatewindow(); return TRUE; 3 papp->initapplication(); papp->initinstance(); nreturncode = papp->run(); AfxWinTerm(); CMyFrameWnd::CMyFrameWnd() Create(NULL, "Hello MFC",..., "MainMenu"); void CMyFrameWnd::OnPaint()... void CMyFrameWnd::OnAbout()... BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd) ON_COMMAND(IDM_ABOUT, OnAbout) ON_WM_PAINT() END_MESSAGE_MAP() AfxWinInit papp->initapplication papp CMyWinApp theapp papp->initapplication(); CMyWinApp::InitApplication(); CMyWinApp CWinApp InitApplication CWinApp CWinApp::InitApplication(); APPCORE.CPP 372
第 6 章 MFC 程式的生死因果 BOOL CWinApp::InitApplication() if (CDocManager::pStaticDocManager!= NULL) if (m_pdocmanager == NULL) m_pdocmanager = CDocManager::pStaticDocManager; CDocManager::pStaticDocManager = NULL; if (m_pdocmanager!= NULL) m_pdocmanager->adddoctemplate(null); else CDocManager::bStaticInit = FALSE; return TRUE; MFC Document Template CDocManager 373
第㆔篇淺出 MFC 程式設計 CMyWinApp::InitInstance 1 HELLO.CPP CMyWinApp theapp; // application object WINMAIN.CPP int AFXAPI AfxWinMain (...) CWinApp* papp = AfxGetApp(); 2 AfxWinInit(...); BOOL CMyWinApp::InitInstance() m_pmainwnd = new CMyFrameWnd(); m_pmainwnd->showwindow(m_ncmdshow); m_pmainwnd->updatewindow(); return TRUE; 3 4 papp->initapplication(); papp->initinstance(); nreturncode = papp->run(); AfxWinTerm(); CMyFrameWnd::CMyFrameWnd() Create(NULL, "Hello MFC",..., "MainMenu"); void CMyFrameWnd::OnPaint()... void CMyFrameWnd::OnAbout()... BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd) ON_COMMAND(IDM_ABOUT, OnAbout) ON_WM_PAINT() END_MESSAGE_MAP() InitApplication AfxWinMain papp->initinstance CMyWinApp theapp papp->initinstance(); CMyWinApp::InitInstance(); CMyWinApp CWinApp InitInstance CWinApp CMyWinApp InitInstance 374
第 6 章 MFC 程式的生死因果 APPCORE.CPP base class CWinApp virtual BOOL InitApplication(); virtual BOOL InitInstance(); virtual int Run(); virtual int ExitInstance(); HELLO.CPP overridden virtual BOOL InitInstance(); CMyWinApp derived class ㆒般而言,CMyWinApp 只改寫 CWinApp 的 InitInstance, 通常它不改寫 InitApplication 和 Run InitInstance CWinApp 375
第㆔篇淺出 MFC 程式設計 CFrameWnd::Create HELLO.CPP 1 CMyWinApp theapp; // application object WINMAIN.CPP int AFXAPI AfxWinMain (...) CWinApp* papp = AfxGetApp(); 2 AfxWinInit(...); BOOL CMyWinApp::InitInstance() 5 m_pmainwnd = new CMyFrameWnd(); m_pmainwnd->showwindow(m_ncmdshow); m_pmainwnd->updatewindow(); return TRUE; 3 4 papp->initapplication(); papp->initinstance(); nreturncode = papp->run(); AfxWinTerm(); CMyFrameWnd::CMyFrameWnd() 6 Create(NULL, "Hello MFC",..., "MainMenu"); void CMyFrameWnd::OnPaint()... void CMyFrameWnd::OnAbout()... BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd) ON_COMMAND(IDM_ABOUT, OnAbout) ON_WM_PAINT() END_MESSAGE_MAP() CMyWinApp::InitInstance new CMyFrameWnd C++ new CMyFrameWnd::CMyFrameWnd Create(NULL, "Hello MFC", WS_OVERLAPPEDWINDOW, rectdefault, NULL, "MainMenu"); Create CFrameWnd RegisterClass C++ CFrameWnd::Create 376
第 6 章 MFC 程式的生死因果 BOOL Create( LPCTSTR lpszclassname, LPCTSTR lpszwindowname, DWORD dwstyle = WS_OVERLAPPEDWINDOW, const RECT& rect = rectdefault, CWnd* pparentwnd = NULL, LPCTSTR lpszmenuname = NULL, DWORD dwexstyle = 0, CCreateContext* pcontext = NULL ); lpszclassname WNDCLASS NULL MFC Create lpszwindowname "Hello MFC" dwstyle WS_OVERLAPPEDWINDOW WINDOWS.H #define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED WS_CAPTION WS_SYSMENU WS_THICKFRAME WS_MINIMIZEBOX WS_MAXIMIZEBOX) Create(NULL, "Hello MFC", WS_OVERLAPPED WS_CAPTION WS_SYSMENU WS_THICKFRAME rectdefault, NULL, "MainMenu"); dwexstyle ::CreateWindowEx ::CreateWindow CFrameWnd ::Create ::CreateWindowEx Windows 3.1 377
第㆔篇淺出 MFC 程式設計 WS_EX_DLGMODALFRAME WS_EX_NOPARENTNOTIFY WS_EX_TOPMOST WS_EX_ACCEPTFILES WS_EX_TRANSPARENT Windows 95 WS_EX_WINDOWEDGE WS_EX_CLIENTEDGE 3D Framework Create rect rectdefault static Windows SDK CW_USEDEFAULT CreateWindow Create(NULL, "Hello MFC", WS_OVERLAPPEDWINDOW, CRect(40, 60, 240, 460), // 起始位置 (40,60), 寬 200, 高 400) NULL, "MainMenu"); pparentwnd top-level NULL desktop lpszmenuname RC MainMenu pcontext CCreateContext framework Document/View CDocTemplate CDocument / CView / CFrameWnd Document/View pcontext NULL CFrameWnd::Create MFC MFC 378
第 6 章 MFC 程式的生死因果 WINFRM.CPP BOOL CFrameWnd::Create(LPCTSTR lpszclassname, LPCTSTR lpszwindowname, DWORD dwstyle, const RECT& rect, CWnd* pparentwnd, LPCTSTR lpszmenuname, DWORD dwexstyle, CCreateContext* pcontext) HMENU hmenu = NULL; if (lpszmenuname!= NULL) // load in a menu that will get destroyed when window gets destroyed HINSTANCE hinst = AfxFindResourceHandle(lpszMenuName, RT_MENU); hmenu = ::LoadMenu(hInst, lpszmenuname); m_strtitle = lpszwindowname; // save title for later CreateEx(dwExStyle, lpszclassname, lpszwindowname, dwstyle, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, pparentwnd->getsafehwnd(), hmenu, (LPVOID)pContext); return TRUE; CreateEx CWnd CreateEx CFrameWnd CFrameWnd::CreateEx CWnd CreateEx :: WINCORE.CPP BOOL CWnd::CreateEx(DWORD dwexstyle, LPCTSTR lpszclassname, LPCTSTR lpszwindowname, DWORD dwstyle, int x, int y, int nwidth, int nheight, HWND hwndparent, HMENU nidorhmenu, LPVOID lpparam) // allow modification of several common create parameters CREATESTRUCT cs; cs.dwexstyle = dwexstyle; cs.lpszclass = lpszclassname; 379
第㆔篇淺出 MFC 程式設計 cs.lpszname = lpszwindowname; cs.style = dwstyle; cs.x = x; cs.y = y; cs.cx = nwidth; cs.cy = nheight; cs.hwndparent = hwndparent; cs.hmenu = nidorhmenu; cs.hinstance = AfxGetInstanceHandle(); cs.lpcreateparams = lpparam; PreCreateWindow(cs); AfxHookWindowCreate(this); // HWND hwnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszclass, cs.lpszname, cs.style, cs.x, cs.y, cs.cx, cs.cy, cs.hwndparent, cs.hmenu, cs.hinstance, cs.lpcreateparams);... PreCreateWindow CWnd CFrameWnd this CFrameWnd::PreCreateWindow WINFRM.CPP // CFrameWnd second phase creation BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs) if (cs.lpszclass == NULL) AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG); cs.lpszclass = _afxwndframeorview; // COLOR_WINDOW background... AfxDeferRegisterClass AFXIMPL.H 380
第 6 章 MFC 程式的生死因果 AFXIMPL.H #define AfxDeferRegisterClass(fClass) \ ((afxregisteredclasses & fclass)? TRUE : AfxEndDeferRegisterClass(fClass)) afxregisteredclasses fclass MFC AfxEndDeferRegisterClass(fClass) afxregisteredclasses AFXWIN.H // in AFXWIN.H #define afxregisteredclasses AfxGetModuleState()->m_fRegisteredClasses WINCORE.CPP : #0001 BOOL AFXAPI AfxEndDeferRegisterClass(short fclass) #0002 #0003 BOOL bresult = FALSE; #0004 #0005 // common initialization #0006 WNDCLASS wndcls; #0007 memset(&wndcls, 0, sizeof(wndclass)); // start with NULL defaults #0008 wndcls.lpfnwndproc = DefWindowProc; #0009 wndcls.hinstance = AfxGetInstanceHandle(); #0010 wndcls.hcursor = afxdata.hcurarrow; #0011 #0012 AFX_MODULE_STATE* pmodulestate = AfxGetModuleState(); #0013 if (fclass & AFX_WND_REG) #0014 #0015 // Child windows - no brush, no icon, safest default class styles #0016 wndcls.style = CS_DBLCLKS CS_HREDRAW CS_VREDRAW; #0017 wndcls.lpszclassname = _afxwnd; #0018 bresult = AfxRegisterClass(&wndcls); #0019 if (bresult) #0020 pmodulestate->m_fregisteredclasses = AFX_WND_REG; #0021 #0022 else if (fclass & AFX_WNDOLECONTROL_REG) #0023 #0024 // OLE Control windows - use parent DC for speed #0025 wndcls.style = CS_PARENTDC CS_DBLCLKS CS_HREDRAW CS_VREDRAW; #0026 wndcls.lpszclassname = _afxwndolecontrol; #0027 bresult = AfxRegisterClass(&wndcls); #0028 if (bresult) 381
第㆔篇淺出 MFC 程式設計 #0029 pmodulestate->m_fregisteredclasses = AFX_WNDOLECONTROL_REG; #0030 #0031 else if (fclass & AFX_WNDCONTROLBAR_REG) #0032 #0033 // Control bar windows #0034 wndcls.style = 0; // control bars don't handle double click #0035 wndcls.lpszclassname = _afxwndcontrolbar; #0036 wndcls.hbrbackground = (HBRUSH)(COLOR_BTNFACE + 1); #0037 bresult = AfxRegisterClass(&wndcls); #0038 if (bresult) #0039 pmodulestate->m_fregisteredclasses = AFX_WNDCONTROLBAR_REG; #0040 #0041 else if (fclass & AFX_WNDMDIFRAME_REG) #0042 #0043 // MDI Frame window (also used for splitter window) #0044 wndcls.style = CS_DBLCLKS; #0045 wndcls.hbrbackground = NULL; #0046 bresult = RegisterWithIcon(&wndcls, _afxwndmdiframe, AFX_IDI_STD_MDIFRAME); #0047 if (bresult) #0048 pmodulestate->m_fregisteredclasses = AFX_WNDMDIFRAME_REG; #0049 #0050 else if (fclass & AFX_WNDFRAMEORVIEW_REG) #0051 #0052 // SDI Frame or MDI Child windows or views - normal colors #0053 wndcls.style = CS_DBLCLKS CS_HREDRAW CS_VREDRAW; #0054 wndcls.hbrbackground = (HBRUSH) (COLOR_WINDOW + 1); #0055 bresult = RegisterWithIcon(&wndcls, _afxwndframeorview, AFX_IDI_STD_FRAME); #0056 if (bresult) #0057 pmodulestate->m_fregisteredclasses = AFX_WNDFRAMEORVIEW_REG; #0058 #0059 else if (fclass & AFX_WNDCOMMCTLS_REG) #0060 #0061 InitCommonControls(); #0062 bresult = TRUE; #0063 pmodulestate->m_fregisteredclasses = AFX_WNDCOMMCTLS_REG; #0064 #0065 #0066 return bresult; #0067 382
第 6 章 MFC 程式的生死因果 #define AFX_WND_REG (0x0001) #define AFX_WNDCONTROLBAR_REG (0x0002) #define AFX_WNDMDIFRAME_REG (0x0004) #define AFX_WNDFRAMEORVIEW_REG (0x0008) #define AFX_WNDCOMMCTLS_REG (0x0010) #define AFX_WNDOLECONTROL_REG (0x0020) WINC const TCHAR _afxwnd[] = AFX_WND; const TCHAR _afxwndcontrolbar[] = AFX_WNDCONTROLBAR; const TCHAR _afxwndmdiframe[] = AFX_WNDMDIFRAME; const TCHAR _afxwndframeorview[] = AFX_WNDFRAMEORVIEW; const TCHAR _afxwndolecontrol[] = AFX_WNDOLECONTROL; AFX_ AFXIMPL.H #ifndef _UNICODE #define _UNICODE_SUFFIX #else #define _UNICODE_SUFFIX _T("u") #endif #ifndef _DEBUG #define _DEBUG_SUFFIX #else #define _DEBUG_SUFFIX _T("d") #endif #ifdef _AFXDLL #define _STATIC_SUFFIX #else #define _STATIC_SUFFIX _T("s") #endif #define AFX_WNDCLASS(s) \ _T("Afx") _T(s) _T("42") _STATIC_SUFFIX _UNICODE_SUFFIX _DEBUG_SUFFIX #define AFX_WND #define AFX_WNDCONTROLBAR #define AFX_WNDMDIFRAME #define AFX_WNDFRAMEORVIEW #define AFX_WNDOLECONTROL AFX_WNDCLASS("Wnd") AFX_WNDCLASS("ControlBar") AFX_WNDCLASS("MDIFrame") AFX_WNDCLASS("FrameOrView") AFX_WNDCLASS("OleControl") 383
第㆔篇淺出 MFC 程式設計 Windows 95 non-unicode MFC "AfxWnd42d" "AfxControlBar42d" "AfxMDIFrame42d" "AfxFrameOrView42d" "AfxOleControl42d" Windows NT Unicode MFC "AfxWnd42sud" "AfxControlBar42sud" "AfxMDIFrame42sud" "AfxFrameOrView42sud" "AfxOleControl42sud" AfxEndDeferRegisterClass RegisterWithIcon AfxRegisterClass static BOOL AFXAPI RegisterWithIcon(WNDCLASS* pwndcls, LPCTSTR lpszclassname, UINT nidicon) pwndcls->lpszclassname = lpszclassname; HINSTANCE hinst = AfxFindResourceHandle( MAKEINTRESOURCE(nIDIcon), RT_GROUP_ICON); if ((pwndcls->hicon = ::LoadIcon(hInst, MAKEINTRESOURCE(nIDIcon))) == NULL) // use default icon pwndcls->hicon = ::LoadIcon(NULL, IDI_APPLICATION); return AfxRegisterClass(pWndCls); BOOL AFXAPI AfxRegisterClass(WNDCLASS* lpwndclass) WNDCLASS wndcls; 384
第 6 章 MFC 程式的生死因果 if (GetClassInfo(lpWndClass->hInstance, lpwndclass->lpszclassname, &wndcls)) // class already registered return TRUE; ::RegisterClass(lpWndClass);... return TRUE; PreCreateWindow NULL PreCreateWindow Framework // in WINCORE.CPP BOOL CWnd::PreCreateWindow(CREATESTRUCT& cs) AfxDeferRegisterClass(AFX_WND_REG);... cs.lpszclass = _afxwnd; CWnd _afxwnd return TRUE; // in WINFRM.CPP BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs) if (cs.lpszclass == NULL) AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG);... cs.lpszclass = _afxwndframeorview; CFrameWnd _afxwndframeorview... // in WINMDI.CPP BOOL CMDIFrameWnd::PreCreateWindow(CREATESTRUCT& cs) 385
第㆔篇淺出 MFC 程式設計 if (cs.lpszclass == NULL) AfxDeferRegisterClass(AFX_WNDMDIFRAME_REG);... cs.lpszclass = _afxwndmdiframe; return TRUE; CMDIFrameWnd _afxwndmdiframe // in WINMDI.CPP BOOL CMDIChildWnd::PreCreateWindow(CREATESTRUCT& cs)... return CFrameWnd::PreCreateWindow(cs); CMDIChildWnd _afxwndframeorview // in VIEWCORE.CPP BOOL CView::PreCreateWindow(CREATESTRUCT & cs) if (cs.lpszclass == NULL) AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG);... cs.lpszclass = _afxwndframeorview; CView _afxwndframeorview... Create icon Create Create SDK RegisterClass CreateWindow MFC RegisterClass MFC HELLO.RC AFX_IDI_STD_FRAME ICON DISCARDABLE "HELLO.ICO" AfxEndDeferRegisterClass 55 RegisterWithIcon icon AFX_IDI_STD_FRAME 386
第 6 章 MFC 程式的生死因果 AfxRegisterWndClass Cursor Create Afx:b:14ae:6:3e8f CFrameWnd::Create CMDIFrameWnd::LoadFrame MFC Create LoadFrame PreCreateWindow Win95 MFC 4.2 "AfxWnd42d" "AfxControlBar42d" "AfxMDIFrame42d" "AfxFrameOrView42d" "AfxOleControl42d" Spy++ VC++ Afx:b:14ae:6:3e8f Application Framework Afx:x:y:z:w 387
第㆔篇淺出 MFC 程式設計 x: window hex style y: hex z: hex w: icon hex MFC PreCreateWindow Create LoadFrame API GetClassInfo lpszclassname hicon AfxRegisterClass #0000 #define MY_CLASSNAME "MyClassName" #0001 #0002 BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) #0003 #0004 static LPCSTR classname = NULL; #0005 #0006 if (!CFrameWnd::PreCreateWindow(cs)) #0007 return FALSE; #0008 #0009 if (classname==null) #0010 // One-time class registration #0011 // The only purpose is to make the class name something #0012 // meaningful instead of "Afx:0x4d:27:32:hup1hup:hike!" #0013 // #0014 WNDCLASS wndcls; #0015 ::GetClassInfo(AfxGetInstanceHandle(), cs.lpszclass, &wndcls); #0016 wndcls.lpszclassname = MY_CLASSNAME; #0017 wndcls.hicon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); #0018 VERIFY(AfxRegisterClass(&wndcls)); #0019 classname=tracewnd_classname; #0020 #0021 cs.lpszclass = classname; #0022 #0023 return TRUE; #0024 MFC Debug Window DBWIN 388
第 6 章 MFC 程式的生死因果 1 HELLO.CPP CMyWinApp theapp; // application object WINMAIN.CPP int AFXAPI AfxWinMain (...) CWinApp* papp = AfxGetApp(); 2 AfxWinInit(...); BOOL CMyWinApp::InitInstance() 5 m_pmainwnd = new CMyFrameWnd(); 7 m_pmainwnd->showwindow(m_ncmdshow); 8 m_pmainwnd->updatewindow(); return TRUE; 3 4 papp->initapplication(); papp->initinstance(); nreturncode = papp->run(); AfxWinTerm(); CMyFrameWnd::CMyFrameWnd() 6 Create(NULL, "Hello MFC",..., "MainMenu"); void CMyFrameWnd::OnPaint()... void CMyFrameWnd::OnAbout()... BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd) ON_COMMAND(IDM_ABOUT, OnAbout) ON_WM_PAINT() END_MESSAGE_MAP() CMyFrameWnd::CMyFrameWnd CMyWinApp::InitInstance ShowWindow UpdateWindow Hello WM _PAINT WM _PAINT MFC SDK GetMessage /DispatchMesage 389
第㆔篇淺出 MFC 程式設計 HELLO.CPP WINMAIN.CPP int AFXAPI AfxWinMain (...) CWinApp* papp = AfxGetApp(); 2 3 4 9 AfxWinInit(...); papp->initapplication(); papp->initinstance(); nreturncode = papp->run(); AfxWinTerm(); CWinApp::Run CWinThread::Run do do ::GetMessage(&msg,...); ::GetMessage(&msg,...); PreTranslateMessage&msg); PreTranslateMessage&msg); ::TranslateMessage(&msg); ::TranslateMessage(&msg); ::DispatchMessage(&msg); ::DispatchMessage(&msg);...... while while (::PeekMessage(...)); (::PeekMessage(...)); 1 CMyWinApp theapp; // application object BOOL CMyWinApp::InitInstance() 5 m_pmainwnd = new CMyFrameWnd(); 7 m_pmainwnd->showwindow(m_ncmdshow); 8 m_pmainwnd->updatewindow(); return TRUE; CMyFrameWnd::CMyFrameWnd() 6 Create(NULL, "Hello MFC",..., "MainMenu"); void CMyFrameWnd::OnPaint()... void CMyFrameWnd::OnAbout()... BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd) ON_COMMAND(IDM_ABOUT, OnAbout) ON_WM_PAINT() END_MESSAGE_MAP() DefWindowProc DefWindowProc hooking and subclassing (please see chap9, p.560, Minotauros and Theseus ) AfxWndProc AfxWndProc Hello WM_PAINT papp->run papp CMyWinApp theapp papp->run(); CMyWinApp::Run(); 390
第 6 章 MFC 程式的生死因果 CMyWinApp CWinApp Run CWinApp CWinApp::Run(); APPCORE.CPP int CWinApp::Run() if (m_pmainwnd == NULL && AfxOleGetUserCtrl()) // Not launched /Embedding or /Automation, but has no main window! TRACE0("Warning: m_pmainwnd is NULL in CWinApp::Run - quitting application.\n"); AfxPostQuitMessage(0); return CWinThread::Run(); 32 MFC 16 MFC CWinApp CCmdTarget CWinThread THRDCORE.CPP int CWinThread::Run() // for tracking the idle time state BOOL bidle = TRUE; LONG lidlecount = 0; // acquire and dispatch messages until a WM_QUIT message is received. for (;;) // phase1: check to see if we can do idle work while (bidle &&!::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE)) // call OnIdle while in bidle state if (!OnIdle(lIdleCount++)) bidle = FALSE; // assume "no idle" state // phase2: pump messages while available do // pump message, but quit on WM_QUIT 391
第㆔篇淺出 MFC 程式設計 if (!PumpMessage()) return ExitInstance(); // reset "no idle" state after pumping "normal" message if (IsIdleMessage(&m_msgCur)) bidle = TRUE; lidlecount = 0; while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE)); ASSERT(FALSE); // not reachable BOOL CWinThread::PumpMessage() if (!::GetMessage(&m_msgCur, NULL, NULL, NULL)) return FALSE; // process this message if (m_msgcur.message!= WM_KICKIDLE &&!PreTranslateMessage(&m_msgCur)) ::TranslateMessage(&m_msgCur); ::DispatchMessage(&m_msgCur); return TRUE; SDK DispatchMessage MFC Hello MFC AfxEndDeferRegisterClass wndcls.lpfnwndproc = DefWindowProc; 392
第 6 章 MFC 程式的生死因果 DefWindowProc AfxWndProc MFC hook subclassing WinMain MFC MFC MFC MFC Message Map 393
第㆔篇淺出 MFC 程式設計 HELLO.CPP 1 CMyWinApp theapp; // application object WINMAIN.CPP int AFXAPI AfxWinMain (...) CWinApp* papp = AfxGetApp(); 2 AfxWinInit(...); BOOL CMyWinApp::InitInstance() 5 m_pmainwnd = new CMyFrameWnd(); 7 m_pmainwnd->showwindow(m_ncmdshow); 8 m_pmainwnd->updatewindow(); return TRUE; 3 4 9 papp->initapplication(); papp->initinstance(); nreturncode = papp->run(); AfxWinTerm(); AfxWndProc WM_PAINT 10 message routing WM_PAINT message map CMyFrameWnd::CMyFrameWnd() 6 Create(NULL, "Hello MFC",..., "MainMenu"); void CMyFrameWnd::OnPaint()... 11 void CMyFrameWnd::OnAbout()... BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd) ON_COMMAND(IDM_ABOUT, OnAbout) ON_WM_PAINT() END_MESSAGE_MAP()... Message Map SDK MFC HELLO.H CMyFrameWnd DECLARE_MESSAGE _MAP 394
第 6 章 MFC 程式的生死因果 class CMyFrameWnd : public CFrameWnd public: CMyFrameWnd(); afx_msg void OnPaint(); afx_msg void OnAbout(); DECLARE_MESSAGE_MAP() ; HELLO.CPP BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd) ON_WM_PAINT() ON_COMMAND(IDM_ABOUT, OnAbout) END_MESSAGE_MAP() WM_PAINT OnPaint WM_COMMAND IDM_ABOUT OnAbout ON_WM_PAINT WM_PAINT OnPaint MFC Message Map : Windows WM_xxx ON_WM_CHAR WM_CHAR OnChar ON_WM_CLOSE WM_CLOSE OnClose ON_WM_CREATE WM_CREATE OnCreate ON_WM_DESTROY WM_DESTROY OnDestroy ON_WM_LBUTTONDOWN WM_LBUTTONDOWN OnLButtonDown ON_WM_LBUTTONUP WM_LBUTTONUP OnLButtonUp ON_WM_MOUSEMOVE WM_MOUSEMOVE OnMouseMove ON_WM_PAINT WM_PAINT OnPaint... 395
第㆔篇淺出 MFC 程式設計 WM_COMMAND ON_COMMAND(<id>,<memberFxn>) ON_COMMAND(IDM_ABOUT, OnAbout) ON_COMMAND(IDM_FILENEW, OnFileNew) ON_COMMAND(IDM_FILEOPEN, OnFileOpen) ON_COMMAND(IDM_FILESAVE, OnFileSave) Notification BN_xxx Button ON_BN_CLICKED(<id>,<memberFxn>) memberfxn ComboBox ON_CBN_DBLCLK(<id>,<memberFxn>) memberfxn Edit ON_EN_SETFOCUS(<id>,<memberFxn>) memberfxn ListBox ON_LBN_DBLCLK(<id>,<memberFxn>) memberfxn afx_msg void Message Map Message Map MFC Message Map Message Map Message Routing SDK DefWindowProc MFC CCmdTarget Message Map 396
第 6 章 MFC 程式的生死因果 Document/View Dynamic Creation Serialization MFC SDK MFC MFC Application object Afx WinMain AfxWinInit AfxInitThread Afx WinMain InitApplication CWinApp AfxWinMain InitInstance CWinApp CMyWinApp ::InitInstance 'new' CMyFrameWnd CMyFrameWnd Create NULL MFC "AfxFrameOrView42d" InitInstance ShowWindow UpdateWindow WM_PAINT AfxWinMain Run WM_PAINT CWinApp::Run ::GetMessage WM_PAINT ::DispatchMessage CWnd::DefWindowProc 397
第㆔篇淺出 MFC 程式設計 CWnd::DefWindowProc Message Map BEGIN_MESSAGE_MAP END_MESSAGE_MAP WM_PAINT OnPaint File/Close WM_CLOSE CMyFrameWnd WM_CLOSE WM_CLOSE ::DestroyWindow WM_DESTROY WM_DESTROY ::PostQuitMessage WM_QUIT CWinApp::Run WM_QUIT ExitInstance CWinApp CMyWinApp ExitInstance CWinApp::Run CMyWinApp::ExitInstance CWinApp::ExitInstance AfxWinMain AfxWinTerm Hello OnPaint WM_PAINT "Hello, MFC" LineDDA API MFC Windows API LineDDA 398
第 6 章 MFC 程式的生死因果 LineDDA void WINAPI LineDDA(int, int, int, int, LINEDDAPROC, LPARAM); Bresenham ) LineDDA callback typedef void (CALLBACK* LINEDDAPROC)(int, int, LPARAM); callback Windows LineDDA LineDDA 32 Hello Device Context Bresenham (x1, y1) (x2, y2) LineDDACallback(int, int, PLARAM)......... LineDDA Bresenham 6-6 LineDDA 399
第㆔篇淺出 MFC 程式設計 LineDDA MFC C++ "scope operator" :: void CMyFrameWnd::OnPaint() CPaintDC dc(this); CRect rect; GetClientRect(rect); dc.settextalign(ta_bottom TA_CENTER); ::LineDDA(rect.right/2, 0, rect.right/2, rect.bottom/2, (LINEDDAPROC) LineDDACallback, (LPARAM) (LPVOID) &dc); LineDDACallback callback class CMyFrameWnd : public CFrameWnd... private: static VOID CALLBACK LineDDACallback(int,int,LPARAM); ; callback "static" C++ this ) Windows callback --- callback C++ callback Windows callback Windows Windows API callback API 400
第 6 章 MFC 程式的生死因果 SetTimer LineDDA EnumObjects API callback 6-6 LineDDA callback EnumObjects Device Context GDI object callback C++ callback C++ callback C++ Windows callback CMyclass class CMyclass private : int ncount; int CALLBACK _export public : EnumObjectsProc(LPSTR lplogobject, LPSTR lpdata); void enumit(cdc& dc); void CMyclass::enumIt(CDC& dc) // callback dc.enumobjects(obj_brush, EnumObjectsProc, NULL); C++ CMyclass::enumIt void CMyclass::enumIt(CDC& dc) // callback CDC::EnumObjects(OBJ_BRUSH, EnumObjectsProc, NULL, (CDC *)&dc); (CDC *)&dc this this 401
第㆔篇淺出 MFC 程式設計 --- C++ this ncount = 0; this->ncount = 0; EnumObjectsProc C++ callback Windows Windows this callback this callback C++ this 1. callback 2. static static C callback OO C++ static static ) static static static 402
第 6 章 MFC 程式的生死因果 Hello MFC idle time Win32 PeekMessage Microsoft CWinApp CWinThread CWinApp::Run - int CWinThread::Run()... for (;;) while (bidle &&!::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE)) // call OnIdle while in bidle state if (!OnIdle(lIdleCount++)) bidle = FALSE; // assume "no idle" state... // msg loop CThread::OnIdle CWinApp OnIdle CWinApp::OnIdle THRDCORE.CPP APPCORE.CPP O MFC MFC idle time CWinApp OnIdle virtual BOOL OnIdle(LONG lcount); 403
第㆔篇淺出 MFC 程式設計 lcount Hello lcount CWinThread::Run 0 Jeff Prosise Programming Windows 95 with OnIdle MFC lcount 0 WM _SYSTIMER WM_PAINT lcount 0 Hello 1. CMyWinApp OnIdle class CMyWinApp : public CWinApp public: virtual BOOL InitInstance(); // virtual BOOL OnIdle(LONG lcount); // OnIdle idle time ; 2. CMyFrameWnd IdleTimeHandler lcount OnIdle CMyFrameWnd DC class CMyFrameWnd : public CFrameWnd public: CMyFrameWnd(); // constructor afx_msg void OnPaint(); // for WM_PAINT afx_msg void OnAbout(); // for WM_COMMAND (IDM_ABOUT) void IdleTimeHandler(LONG lcount); // we want it call by CMyWinApp::OnIdle... ; 3. HELLO.CPP CMyWinApp ::OnIdle 404
第 6 章 MFC 程式的生死因果 BOOL CMyWinApp::OnIdle(LONG lcount) CMyFrameWnd* pwnd = (CMyFrameWnd*)m_pMainWnd; pwnd->idletimehandler(lcount); return TRUE; 4. HELLO.CPP CMyFrameWnd::IdleTimeHandler void CMyFrameWnd::IdleTimeHandler(LONG lcount) CString str; CRect rect(10,10,200,30); CDC* pdc = new CClientDC(this); str.format("%010d", lcount); pdc->drawtext(str, &rect, DT_LEFT DT_TOP); lcount MFC CString CRect CDC C++ Windows DC Device Context Hello lcount lcount 0 405
第㆔篇淺出 MFC 程式設計 SDK RC Template C MFC CDialog MFC HELLO.CPP WM_COMMAND (IDM_ABOUT) void CMyFrameWnd::OnAbout() CDialog about("aboutbox", this); about.domodal(); HELLO.RC AboutBox DIALOG DISCARDABLE 34, 22, 147, 55 STYLE DS_MODALFRAME WS_POPUP WS_CAPTION WS_SYSMENU CAPTION "About Hello" ICON "JJHouRIcon",IDC_STATIC,11,17,18,20 LTEXT "Hello MFC 4.0",IDC_STATIC,40,10,52,8 LTEXT "Copyright 1996 Top Studio",IDC_STATIC,40,25,100,8 LTEXT "J.J.Hou",IDC_STATIC,40,40,100,8 DEFPUSHBUTTON "OK",IDOK,105,7,32,14,WS_GROUP File/About Message Map WM _COMMAND IDM_ABOUT OnAbout OnAbout CDialog about CDialog about "About" CDialog CDialog::DoModal 406
第 6 章 MFC 程式的生死因果 File Open Save As Windows 3.1 Windows API Common Dialogs API COMMDLG.DLL 32 COMDLG32.DLL MFC CCommonDialog CFileDialog CPrintDialog CFindReplaceDialog CColorDialog CFontDialog CPageSetupDialog COleDialog File Open Save As Print Find and Replace Color Font Page Setup MFC 4.0 Ole CObject CObject CCmdTarget CCmdTarget CWnd CWnd CDialog CDialog CCommonDialog CColorDialog CColorDialog CFileDialog CFindReplaceDialog CFontDialog CFontDialog COleDialog COleDialog CPageSetupDialog CPageSetupDialog CPrintDialog CPrintDialog 407
第㆔篇淺出 MFC 程式設計 C/SDK OPENFILENAME API GetOpenFileName MFC Windows API Open char szfileters[] = "Text fiels (*.txt) *.txt All files (*.*) *.* " CFileDialog opendlg (TRUE, "txt", "*.txt", OFN_FILEMUSTEXIST OFN_HIDEREADONLY, szfilters, this); if (opendlg.domodal() == IDOK) filename = opendlg.getpathname(); opendlg TRUE Open Save As "txt" "*.txt" file name OFN_ szfilters DoModal CFileDialog GetPathName GetFileName GetFileTitle MFC 408
第 6 章 MFC 程式的生死因果 MFC CWinApp application object WinMain application object InitInstance CFrameWnd CFrameWnd::Create MFC WinMain Run WM_COMMAND IDM_ABOUT WM_PAINT OnAbout OnPaint MFC SDK MFC raw Windows API MFC MFC MFC MFC MFC OLE MFC Hello Windows MDI Document/View UI... 409
410 第㆔篇淺出 MFC 程式設計
第 7 章簡單而完整 :MFC 骨幹程式 Hello MFC MFC MFC CWinApp CFrameWnd CDialog MFC UI Document/View MFC AppWizard MFC Scribble step0 MFC MFC ODBC OLE 7-1 6-1 411
第㆔篇淺出 MFC 程式設計 CObject CObject CCmdTarget CCmdTarget CWinThread CWinThread CWnd CWnd CWinApp CWinApp CView CView CMyWinApp CMyWinApp CMyView CFrameWnd CFrameWnd CDocument CDocument CMDIFrameWnd CMDIFrameWnd CMyDoc CMyDoc CDocTemplate CDocTemplate CMDIChildWnd CMDIChildWnd CMultiDocTemplate CMultiDocTemplate CMyMDIFrameWnd CMyMDIChildWnd CMyMDIChildWnd CControlBar CControlBar CStatusBar CStatusBar CToolBar CToolBar CDialog CDialog CMyDialog CMyDialog 7-1 MFC 6-1 7-2 Windows MDI MFC UI MFC 412
第 7 章簡單而完整 :MFC 骨幹程式 7-2a Microsoft Word for Windows document document Word 413
第㆔篇淺出 MFC 程式設計 7-2b Microsoft Excel document 414
第 7 章簡單而完整 :MFC 骨幹程式 7-2c Microsoft PowerPoint document MFC Visual C++ AppWizard MFC 415
第㆔篇淺出 MFC 程式設計 File Edit View CEditView 416
第 7 章簡單而完整 :MFC 骨幹程式 MDI Window Help About dockable 417
第㆔篇淺出 MFC 程式設計 File Print... Preview Document View AppWizard View CEditView 292 418
第 7 章簡單而完整 :MFC 骨幹程式 Document/View MFC Application Framework Document/View OLE Document MDI Document MFC Document "Document" "Object" OLE PaintBrush bitmap SoundRecorder Wave Excel Word OLE OLE object item MFC Document CDocument?! char name[20]; char address[30]; int age; bool sex; struct dbllistnode struct dbllistnode *next, *prev; struct info_t int left; int top; 419
第㆔篇淺出 MFC 程式設計 ; int width; int height; void (*cursor)(); *item; CDocument Document CDocument CView 7-3a... CView CMyDoc::Serialize(...) CMyView::OnDraw(...) // // Document // Document // GDI // The C++ compiler gen ings, all of which a are caused by the ol... Hello, I am J.J.Hou, a goodman.... The difference, omit lpcmdline parameter... 7-3a Document View 420
第 7 章簡單而完整 :MFC 骨幹程式 View View Document ( 7-3b) CMyDoc::Serialize(...) CMyView::OnLButtonDown(...) // Document // DWORD // DWORD Document 04 00 FF FF 01 00 07 43 53 74 72 6F 6B 65 00 02 00 26 00 08 00... LButtonDown CMyView::OnLButtonDown 00 08 00 01 80 05 00 00 26 00 1C 00 27 00... 00 27 00 1C 00 01 80... 7-3b View Document Document/View MFC CDocument Serialize CView OnDraw OnPaint CMyDoc CMyView CMyDoc::Serialize CMyView::OnDraw 421
第㆔篇淺出 MFC 程式設計 File/Open Application Framework CMyDoc::Serialize Application Framework CMyView::OnDraw WM_PAINT Framework CMyView::OnDraw Display DC File/Print... Framework CMyView::OnDraw Printer DC MFC MFC Framework GUI MFC Document/View GUI Document/View Application Framework Visual C++ IC MFC MFC MFC AppWizard Scribble Step0 422
第 7 章簡單而完整 :MFC 骨幹程式 AppWizard Scribble Step0 #if...#endif // //.H.CPP.CPP.H 7-4 Scribble step0 CScribbleApp CWinApp Scribble.h Scribble.cpp CMainFrame CMDIFrameWnd Mainfrm.h Mainfrm.cpp CChildFrame CMDIChildWnd Childfrm.h Childfrm.cpp CScribbleDoc CDocument ScribbleDoc.h ScribbleDoc.cpp CScribbleView CView ScribbleView.h ScribbleView.cpp CAboutDlg CDialog Scribble.cpp Scribble.cpp 7-4 Scribble Scribble step0 MFC Document/View MFC MDI 423
第㆔篇淺出 MFC 程式設計 MFC CWinApp CScribbleApp application object CMDIFrameWnd CMainFrame MDI CMultiDocTemplate Document/View CDocument CScribbleDoc Document CView CScribbleView View CMDIChildWnd CChildFrame MDI CToolBar CStatusBar CDialog CAboutDlg About MFC 7-1 Document/View MDI SDI AppWizard Options 4-2b SDI MDI MFC 7-4 Scribble step0 7-5 424
第 7 章簡單而完整 :MFC 骨幹程式 Application CWinApp Document Template CMultiDocTemplate Document CDocument CToolBar MDI Frame CMDIFrameWnd CStatusBar MDI Child CDialog View Document Frame CView CMDIChildWnd 7-5 Scribble step0 MFC MDI 7-6 Scribble step0 #0001 class CScribbleApp : public CWinApp #0002 #0003 virtual BOOL InitInstance(); // HelloMFC #0004 afx_msg void OnAppAbout(); // "About" #0005 DECLARE_MESSAGE_MAP() // CWinApp #0006 ; // #0007 // #0008 class CMainFrame : public CMDIFrameWnd #0009 #0010 DECLARE_DYNAMIC(CMainFrame) #0011 CStatusBar m_wndstatusbar; #0012 CToolBar m_wndtoolbar; #0013 afx_msg int OnCreate(LPCREATESTRUCT lpcreatestruct); #0014 DECLARE_MESSAGE_MAP() #0015 ; #0016 #0017 class CChildFrame : public CMDIChildWnd #0018 425
第㆔篇淺出 MFC 程式設計 #0019 DECLARE_DYNCREATE(CChildFrame) #0020 DECLARE_MESSAGE_MAP() #0021 ; #0022 #0023 class CScribbleDoc : public CDocument #0024 #0025 DECLARE_DYNCREATE(CScribbleDoc) #0026 virtual void Serialize(CArchive& ar); #0027 DECLARE_MESSAGE_MAP() #0028 ; #0029 #0030 class CScribbleView : public CView #0031 #0032 DECLARE_DYNCREATE(CScribbleView) #0033 CScribbleDoc* GetDocument(); #0034 #0035 virtual void OnDraw(CDC* pdc); #0036 DECLARE_MESSAGE_MAP() // MFC 內部 #0037 ; Int AfxAPI AfxWinMain( K) #0038 #0039 class CAboutDlg : public CDialog CWinApp* papp = AfxGetApp(); #0040 AfxWinInit( K); ➁ #0041 DECLARE_MESSAGE_MAP() #0042 ; papp->initapplication(); ➂ #0043 papp->initinstance(); ➃ #0044 //------------------------------------------------------------------- nreturncode = papp->run(); ➊ #0045 #0046 CScribbleApp theapp; ➀ #0047 #0048 BEGIN_MESSAGE_MAP(CScribbleApp, CWinApp) #0049 ON_COMMAND(ID_APP_ABOUT, OnAppAbout) ➍ #0050 ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) #0051 ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) ➋ #0052 ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) #0053 END_MESSAGE_MAP() #0054 #0055 BOOL CScribbleApp::InitInstance() ➄ #0056 #0057... #0058 CMultiDocTemplate* pdoctemplate; #0059 pdoctemplate = new CMultiDocTemplate( ➅ #0060 IDR_SCRIBTYPE, #0061 RUNTIME_CLASS(CScribbleDoc), #0062 RUNTIME_CLASS(CChildFrame), #0063 RUNTIME_CLASS(CScribbleView)); #0064 AddDocTemplate(pDocTemplate); 426
第 7 章簡單而完整 :MFC 骨幹程式 #0065 #0066 CMainFrame* pmainframe = new CMainFrame; ➆ #0067 pmainframe->loadframe(idr_mainframe); ➇ #0068 m_pmainwnd = pmainframe; #0069 K #0070 pmainframe->showwindow(m_ncmdshow); ➉ #0071 pmainframe->updatewindow(); #0072 return TRUE; #0073 #0074 #0075 BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) #0076 END_MESSAGE_MAP() #0077 #0078 void CScribbleApp::OnAppAbout() ➎ #0079 #0080 CAboutDlg aboutdlg; #0081 aboutdlg.domodal(); #0082 #0083 #0084 IMPLEMENT_DYNAMIC(CMainFrame, CMDIFrameWnd) #0085 #0086 BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) #0087 ON_WM_CREATE() #0088 END_MESSAGE_MAP() #0089 #0090 static UINT indicators[] = #0091 #0092 ID_SEPARATOR, #0093 ID_INDICATOR_CAPS, #0094 ID_INDICATOR_NUM, #0095 ID_INDICATOR_SCRL, #0096 ; #0097 #0098 int CMainFrame::OnCreate(LPCREATESTRUCT lpcreatestruct) ➈ #0099 #0100 m_wndtoolbar.create(this); #0101 m_wndtoolbar.loadtoolbar(idr_mainframe); #0102 m_wndstatusbar.create(this); // MFC 內部 CFrameWnd::Create CWnd::CreateEx ::CreateWindowEx WM_CREATE wmˍcre #0103 m_wndstatusbar.setindicators(indicators, #0104 sizeof(indicators)/sizeof(uint)); #0105 #0106 m_wndtoolbar.setbarstyle(m_wndtoolbar.getbarstyle() #0107 CBRS_TOOLTIPS CBRS_FLYBY CBRS_SIZE_DYNAMIC); #0108 #0109 m_wndtoolbar.enabledocking(cbrs_align_any); 427
第㆔篇淺出 MFC 程式設計 #0110 EnableDocking(CBRS_ALIGN_ANY); #0111 DockControlBar(&m_wndToolBar); #0112 return 0; #0113 #0114 #0115 IMPLEMENT_DYNCREATE(CChildFrame, CMDIChildWnd) #0116 #0117 BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWnd) #0118 END_MESSAGE_MAP() #0119 #0120 IMPLEMENT_DYNCREATE(CScribbleDoc, CDocument) #0121 #0122 BEGIN_MESSAGE_MAP(CScribbleDoc, CDocument) #0123 END_MESSAGE_MAP() #0124 #0125 void CScribbleDoc::Serialize(CArchive& ar) ➌ #0126 #0127 if (ar.isstoring()) #0128 #0129 // TODO: add storing code here #0130 #0131 else #0132 #0133 // TODO: add loading code here #0134 #0135 #0136 #0137 IMPLEMENT_DYNCREATE(CScribbleView, CView) #0138 #0139 BEGIN_MESSAGE_MAP(CScribbleView, CView) #0140 ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) #0141 ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) #0142 ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) #0143 END_MESSAGE_MAP() #0144 #0145 void CScribbleView::OnDraw(CDC* pdc) #0146 #0147 CScribbleDoc* pdoc = GetDocument(); #0148 // TODO: add draw code for native data here #0149 7-6 Scribble step0 428
第 7 章簡單而完整 :MFC 骨幹程式 7-6 ➀~➃ Hello ➄ InitInstance ➅ new CMultiDocTemplate Document View Document Frame ➆ new CMyMDIFrameWnd ➇ LoadFrame IDR_MAINFRAME LoadFrame Create CreateWindowEx WM _CREATE ➈ CMainFrame WM _CREATE ON_WM_CREATE WM _CREATE Framework OnCreate ➉ InitInstance ShowWindow ➊ InitInstance AfxWinMain Run Hello ➋ Message Message Routing Map WM_COMMAND/ID_FILE_OPEN CWinApp::OnFileOpen MFC File Serialize Open ➌ Serialize ➍ WM_COMMAND/ID_APP_ABOUT OnAppAbout ➎ OnAppAbout CDialog 429
第㆔篇淺出 MFC 程式設計 Document Template Document/View View MDI Document SDI Frame Document OLE Frame Document Frame Document View Frame 1. Document 2. View 3. CMDIChildWnd Document Template CMultiDocTemplate BOOL CScribbleApp::InitInstance()... CMultiDocTemplate* pdoctemplate; pdoctemplate = new CMultiDocTemplate( IDR_SCRIBTYPE, RUNTIME_CLASS(CScribbleDoc), RUNTIME_CLASS(CChildFrame), RUNTIME_CLASS(CScribbleView)); AddDocTemplate(pDocTemplate);... TEXT BITMAP Document Template: 430
第 7 章簡單而完整 :MFC 骨幹程式 BOOL CMyWinApp::InitInstance()... CMultiDocTemplate* pdoctemplate; pdoctemplate = new CMultiDocTemplate( IDR_TEXTTYPE, RUNTIME_CLASS(CTextDoc), RUNTIME_CLASS(CChildFrame), RUNTIME_CLASS(CTextView)); AddDocTemplate(pDocTemplate); pdoctemplate = new CMultiDocTemplate( IDR_BMPTYPE, RUNTIME_CLASS(CBmpDoc), RUNTIME_CLASS(CChildFrame), RUNTIME_CLASS(CBmpView)); AddDocTemplate(pDocTemplate);... CMultiDocTemplate CMultiDocTemplate::CMultiDocTemplate(UINT nidresource, CRuntimeClass* pdocclass, CRuntimeClass* pframeclass, CRuntimeClass* pviewclass); 1. nidresource ID IDR_SCRIBTYPE RC ID IDR_SCRIBTYPE ICON DISCARDABLE "res\\scribbledoc.ico" IDR_SCRIBTYPE MENU PRELOAD DISCARDABLE... STRINGTABLE PRELOAD DISCARDABLE BEGIN IDR_MAINFRAME "Scribble Step0" IDR_SCRIBTYPE "\nscrib\nscrib\nscribble Files (*.scb)\n.scb\n Scribble.Document\nScrib Document" END '\n' MDI 431
第㆔篇淺出 MFC 程式設計 ICON MENU STRINGTABLE 2. pdocclass Document CDocument CRuntimeClass 3. pframeclass Child CMDIChildWnd CRuntimeClass 4. pviewclass CView CRuntimeClass CRuntimeClass RTTI CRuntimeClass DECLARE_DYNAMIC DECLARE_DYNCREATE DECLARE_SERIAL static CRuntimeClass Document Template CRuntimeClass Document Template document view document frame window MFC Document Template CMultiDocTemplate IDR_SCRIBTYPE RC MENU ICON STRING '\n' AppWizard Advanced Options 432
第 7 章簡單而完整 :MFC 骨幹程式 RC IDR_MAINFRAME: "Scribble Step0" IDR_SCRIBTYPE( ): \n Scrib\n Scrib\n Scribble Files (*.scb)\n.scb\n Scribble.Document\n Scrib Document CDocTemplate::GetDocString 1~7 CDocTemplate CDocTemplate // in AFXWIN.H class CDocTemplate : public CCmdTarget... enum DocStringIndex windowtitle, // default window title docname, // user visible name for default document filenewname, // user visible name for FileNew // for file based documents: filtername, // user visible name for FileOpen filterext, // user visible extension for FileOpen // for file based documents with Shell open support: regfiletypeid, // REGEDIT visible registered file type identifier regfiletypename // Shell visible registered file type name ;... ; 433
第㆔篇淺出 MFC 程式設計 CString strdefext, strdocname; pdoctemplate->getdocstring(strdefext, CDocTemplate::filterExt); pdoctemplate->getdocstring(strdocname, CDocTemplate::docName); index 1. CDocTemplate::windowTitle SDI MDI IDR_MAINFRAME 2. CDocTemplate::docName "Scrib" "Scrib1" "Untitled" 3. CDocTemplate::fileNewName File/New File/New File/New 13 #743 4. CDocTemplate::filterName (wildcard filter string) "Scribble(*.scb)" File Open List Files Of Type 5. CDocTemplate::filterExt "scb" File Open 6. CDocTemplate::regFileTypeId ::RegisterShellFileTypes Registry HKEY_CLASSES_ROOT subkey Windows 7. (drag and drop) CDocTemplate::regFileTypeName Registry 434
第 7 章簡單而完整 :MFC 骨幹程式 Scribble 1 CDocTemplate::windowTitle 3 p.743 New 2 CDocTemplate::docName 4 CDocTemplate::filterName 5 CDocTemplate::filterExt 7 6 CDocTemplate::regFileTypeName CDocTemplate::regFileTypeId AppWizard AppW 435
第㆔篇淺出 MFC 程式設計 Document View CDocument Collections Classes MFC CView CDC CGdiObject MFC Document/View 7-3 View View Document View Document View Document Document Frame Document Views Views Document View CScrollView -- Serialization Serialize CMyDoc Serialize Scribble step1 step0 CScribbleDoc Serialize 436
第 7 章簡單而完整 :MFC 骨幹程式 void CScribbleDoc::Serialize(CArchive& ar) if (ar.isstoring()) // TODO: add storing code here else // TODO: add loading code here View Document Document Frame CView View 1. Document Frame WM _PAINT View OnPaint OnPaint OnDraw OnDraw OnPaint 12 2. View View afx_msg void OnLButtonDown(UINT nflags, CPoint point); afx_msg void OnLButtonUp(UINT nflags, CPoint point); afx_msg void OnMouseMove(UINT nflags, CPoint point); Scribble step0 void CScribbleView::OnDraw(CDC* pdc) CScribbleDoc* pdoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here 437
第㆔篇淺出 MFC 程式設計 Hello CFrameWnd MDI CMDIFrameWnd MDI new CMDIFrameWnd LoadFrame // in WNDFRM.CPP BOOL CFrameWnd::LoadFrame(UINT nidresource, DWORD dwdefaultstyle, CWnd* pparentwnd, CCreateContext* pcontext) CString strfullstring; if (strfullstring.loadstring(nidresource)) AfxExtractSubString(m_strTitle, strfullstring, 0); // first sub-string if (!AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG)) return FALSE; // attempt to create the window LPCTSTR lpszclass = GetIconWndClass(dwDefaultStyle, nidresource); LPCTSTR lpsztitle = m_strtitle; if (!Create(lpszClass, lpsztitle, dwdefaultstyle, rectdefault, pparentwnd, MAKEINTRESOURCE(nIDResource), 0L, pcontext)) return FALSE; // will self destruct on failure normally // save the default menu handle m_hmenudefault = ::GetMenu(m_hWnd); // load accelerator resource LoadAccelTable(MAKEINTRESOURCE(nIDResource)); if (pcontext == NULL) // send initial update SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE); return TRUE; 438
第 7 章簡單而完整 :MFC 骨幹程式 BOOL CScribbleApp::InitInstance()... CMainFrame* pmainframe = new CMainFrame; if (!pmainframe->loadframe(idr_mainframe)) return FALSE; m_pmainwnd = pmainframe;... CFrameWnd::LoadFrame CFrameWnd::LoadFrame CFrameWnd::Create CFrameWnd::Create CWnd::CreateEx ::CreateWindowEx ::CreateWindowEx WM_CREATE BEGIN_MESSAGE_MAP(CMainFrame, BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) CMDIFrameWnd) ON_WM_CREATE() ON_WM_CREATE()...... END_MESSAGE_MAP() END_MESSAGE_MAP() CMainFrame::OnCreate CMainFrame::OnCreate WM _CREATE CMainFrame ::OnCreate Lo IDR_MAINFRAME CFrameWnd::LoadFrame // defined in SCRIBBLE.RC IDR_MAINFRAME ICON DISCARDABLE "res\\scribble.ico" IDR_MAINFRAME MENU PRELOAD DISCARDABLE... IDR_MAINFRAME ACCELERATORS PRELOAD MOVEABLE PURE... STRINGTABLE PRELOAD DISCARDABLE BEGIN IDR_MAINFRAME "Scribble Step0".. END LoadFrame Create 439
第㆔篇淺出 MFC 程式設計 CToolBar CStatusBar CMainFrame class CMainFrame : public CMDIFrameWnd protected: // control bar embedded members CStatusBar m_wndstatusbar; CToolBar m_wndtoolbar;... ; WM _CREATE WM _CREATE Message Map BEGIN_MESSAGE_MAP(CMyMDIFrameWnd, CMDIFrameWnd) ON_WM_CREATE() END_MESSAGE_MAP() ON_WM_CREATE WM _CREATE OnCreate AppWizard OnCreate int CMainFrame::OnCreate(LPCREATESTRUCT lpcreatestruct) if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; if (!m_wndtoolbar.create(this)!m_wndtoolbar.loadtoolbar(idr_mainframe)) TRACE0("Failed to create toolbar\n"); return -1; // fail to create if (!m_wndstatusbar.create(this)!m_wndstatusbar.setindicators(indicators, sizeof(indicators)/sizeof(uint))) TRACE0("Failed to create status bar\n"); return -1; // fail to create 440
第 7 章簡單而完整 :MFC 骨幹程式 // TODO: Remove this if you don't want tool tips or a resizeable toolbar m_wndtoolbar.setbarstyle(m_wndtoolbar.getbarstyle() CBRS_TOOLTIPS CBRS_FLYBY CBRS_SIZE_DYNAMIC); // TODO: Delete these three lines if you don't want the toolbar to // be dockable m_wndtoolbar.enabledocking(cbrs_align_any); EnableDocking(CBRS_ALIGN_ANY); DockControlBar(&m_wndToolBar); return 0; m_wndtoolbar.create(this) this m_wndtoolbar.loadtoolbar(idr_mainframe) RC IDR _MAINFRAME RC IDR_MAINFRAME BITMAP MOVEABLE PURE "RES\\TOOLBAR.BMP" IDR_MAINFRAME TOOLBAR DISCARDABLE 16, 15 BEGIN BUTTON ID_FILE_NEW BUTTON ID_FILE_OPEN BUTTON ID_FILE_SAVE SEPARATOR BUTTON ID_EDIT_CUT BUTTON ID_EDIT_COPY BUTTON ID_EDIT_PASTE SEPARATOR BUTTON ID_FILE_PRINT BUTTON ID_APP_ABOUT END LoadToolBar LoadBitmap + SetButtons LoadToolBar BITMAP TOOLBAR VC++ BITMAP TOOLBAR TOOLBAR ID 441
第㆔篇淺出 MFC 程式設計 m_wndstatusbar.create(this) this m_wndstatusbar.setindicators(,...) Indicator On/Off AFXRES.H indicators #define ID_INDICATOR_EXT #define ID_INDICATOR_CAPS #define ID_INDICATOR_NUM #define ID_INDICATOR_SCRL #define ID_INDICATOR_OVR #define ID_INDICATOR_REC #define ID_INDICATOR_KANA 0xE700 // extended selection indicator 0xE701 // cap lock indicator 0xE702 // num lock indicator 0xE703 // scroll lock indicator 0xE704 // overtype mode indicator 0xE705 // record mode indicator 0xE706 // kana lock indicator static static UINT UINT indicators[] indicators[] = = ID_SEPARATOR, ID_SEPARATOR, // // status status line line indicator indicator ID_INDICATOR_CAPS, ID_INDICATOR_CAPS, ID_INDICATOR_NUM, ID_INDICATOR_NUM, ID_INDICATOR_SCRL, ID_INDICATOR_SCRL, ; ; MFC Drag and Drop Shell Windows 95 Document Frame Shell 442
第 7 章簡單而完整 :MFC 骨幹程式 SDK Drag and Drop Shell Shell WM _DROPFILES WM _DROPFILES WS_EX _ACCEPTFILES CreateWindow WS_EX _ACCEPTFILES WM_DROPFILES wparam DragQueryFile DragQueryPoint API SDK MFC BOOL CScribbleApp::InitInstance()... // Enable drag/drop open m_pmainwnd->dragacceptfiles(); // Enable DDE Execute open EnableShellOpen(); RegisterShellFileTypes(TRUE);... CWnd::DragAcceptFile(BOOL baccept=true); TRUE Shell CFrameWnd OnDropFiles WM _DROPFIELS application OnOpenDocument 443
第㆔篇淺出 MFC 程式設計 CWinApp::EnableShellOpen(); Shell Framework DDE Dynamic Data Exchange DDE CDocManager DDE RegisterShellFileTypes CWinApp::RegisterShellFileTypes(); Shell Shell Document Template registry Windows Registry.reg Windows regedit.exe.reg Registry ::RegCreateKey ::RegSetValue Win32 Registry MFC CWinApp::RegisterShellFileTypes.txt Notepad.bmp PBrush.ppt PowerPoint.xls Excel Scribble.txt Shell Notepad Scribble.bmp Shell Scribble Scribble 444
第 7 章簡單而完整 :MFC 骨幹程式 CCmdTarget Message Map DECLARE_MESSAGE_MAP.CPP BEGIN_MESSAGE_MAP END_MESSAGE_MAP 7-6 Scribble Message Map CScribbleApp WM_COMMAND BEGIN_MESSAGE_MAP(CScribbleApp, CWinApp) ON_COMMAND(ID_APP_ABOUT, OnAppAbout) ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) END_MESSAGE_MAP() ID_APP_ABOUT OnAppAbout CWinApp 445
第㆔篇淺出 MFC 程式設計 MDI IDR_MAINFRAME IDR_SCRIBTYPE 446
第 7 章簡單而完整 :MFC 骨幹程式 File View Help IDR _MAINFRAME IDR _SCRIBTYPE RC MFC Framework Framework Open Save Print As Print Setup Find Replace Edit CEditView File LRU Appwizard View Window Cascade Tile Yes Message No Map ID File New ID_FILE_NEW CWinApp::OnFileNew No Open ID_FILE_OPEN CWinApp::OnFileOpen No Close ID_FILE_CLOSE CDocument::OnFileClose Yes Save ID_FILE_SAVE CDocument::OnFileSave Yes Save As ID_FILE_SAVEAS CDocument::OnFileSaveAs Yes Print ID_FILE_PRINT CView::OnFilePrint No Print Pre&view ID_FILE_PRINT_PREVIEW CView::OnFilePrintPreview No Print Setup ID_FILE_PRINT_SETUP CWinApp::OnFilePrintSetup No "Recent File Name" ID_FILE_MRU_FILE1~4 CWinApp::OnOpenRecentFile Yes 447
第㆔篇淺出 MFC 程式設計 ID Exit ID_APP_EXIT CWinApp::OnFileExit Yes Edit Undo ID_EDIT_UNDO None Cut ID_EDIT_CUT None Copy ID_EDIT_COPY None Paste ID_EDIT_PASTE None View Toolbar ID_VIEW_TOOLBAR FrameWnd::OnBarCheck Yes Status Bar ID_VIEW_STATUS_BAR FrameWnd::OnBarCheck Yes Window(MDI only) New Window ID_WINDOW_NEW MDIFrameWnd::OnWindowNew Yes Cascade ID_WINDOW_CASCADE MDIFrameWnd::OnWindowCmd Yes Tile ID_WINDOW_TILE_HORZ MDIFrameWnd::OnWindowCmd Yes Arrange Icons ID_WINDOW_ARRANGE MDIFrameWnd::OnWindowCmd Yes Help About AppName ID_APP_ABOUT None No Message AppWizar Map BEGIN_MESSAGE_MAP(CScribbleApp, CWinApp)... ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) END_MESSAGE_MAP() BEGIN_MESSAGE_MAP(CScribbleView, CView)... ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) END_MESSAGE_MAP() 448
第 7 章簡單而完整 :MFC 骨幹程式 Scribble About WM _COMMAND ID_APP_ABOUT Message Map: BEGIN_MESSAGE_MAP(CScribbleApp, CWinApp) ON_COMMAND(ID_APP_ABOUT, OnAppAbout) ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) END_MESSAGE_MAP() OnAppAbout void CScribbleApp::OnAppAbout() CAboutDlg aboutdlg; aboutdlg.domodal(); CAboutDlg CDialog class CAboutDlg : public CDialog enum IDD = IDD_ABOUTBOX ; // IDD_ABOUTBOX RC... DECLARE_MESSAGE_MAP() ; SDK SDK dialog C template CDialog DoModal 10 DDX 449
第㆔篇淺出 MFC 程式設計 Scribble step0 AppWizard CScribbleView CView CEditView CEditView Edit SerializeRaw Edit raw text AppWizard CView CEditView void CScribbleDoc::Serialize(CArchive& ar) // CEditView contains an edit control which handles all serialization ((CEditView*)m_viewList.GetHead())->SerializeRaw(ar); void CScribbleView::OnDraw(CDC* pdc) 450
第 7 章簡單而完整 :MFC 骨幹程式 CScribbleDoc* pdoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here 451
452 第㆔篇淺出 MFC 程式設計