1.MFC的外围环境:
Windows C Runtime函数库:LIBC.LIB静态联结MSVCRT.LIB动态联结MSVCRTD.LIB使用Debug模式
DLL Import 函数库:GDI 32.LIB USER32.LIB KERNEL32.LIB
MFC 函数库(AFX 函数库):可静态联结或动态联结,是application framework的本体。MFCXXX.LIB
SDK 程序只要包含WINDOWS.H 就好,所有API 的函数声明、消息定义、常数定义、宏定义。
MFC需要的头文件:
Precompiled header 就是将.H 档第一次编译后的结果保存,第二次再编译时就可以直接从取出来用。
STDAFX.H-这个文件用来做为Precompiled header file,其内只包含其它的MFC 头文件,包含AFXWIN.H。
AFXWIN.H-以及它所包含的文件声明了所有的MFC类别。内含AFX.H,后者又包含AFXVER_.H,后者又包含AFXV_W32.H,后者又包含WINDOWS.H
AFXEXT.H-工具栏、状态列AFXDLGS.H -通用型对话框(Common Dialog)内包COMMDLG.H。
AFXCMN.H-通用型控制组件(Common Control)AFXCOLL.H-Collections Classes
AFXDLLX.H-MFC extension DLLs AFXRES.H -RC 文件必须包含此档。 对于标准资源(例如File、Edit 等菜单项目)的ID 都有默认值,定义于此文件中,例如:
所有MFC 头文件均置于\MSVC\MFC\INCLUDE中。这些文件连同Windows SDK 的包含档WINDOWS.H、COMMDLG.H、TOOLHELP.H、DDEML.H... 每每在编译过程中耗费大量的时间,因此你绝对有必要设定Precompiled header。
2.SDK 程序设计的第一要务是了解最重要的数个API 函数的意义和用法,像RegisterClass、CreateWindow、GetMessage、DispatchMessage,以及消息的获得与分配。
MFC 程序设计的第一要务则是熟记MFC 的类别阶层架构,并清楚知晓其中几个一定会用到的类别。
3.CWinApp-取代 WinMain的地位
CWinApp 之中的成员变量将因为theApp这个全域对象的诞生而获得配置与初值。称为application object,CWinApp 本身就代表一个程式本体。一个程序的本体是与程序本身有关而不与视窗有关的资料或动作:
系统传进来的四个WinMain参数、InitApplication 和InitInstance、消息循环。
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)
CWnd* m_pMainWnd; // main window (optional)记录主窗口的handle
CWnd* m_pActiveWnd; // active main window (may not be m_pMainWnd)
public:
virtual BOOL InitApplication();// hooks for your initialization code
virtual BOOL InitInstance();// overrides for implementation
virtual int Run();// overrides for implementation
——节录自AFXWIN.H的CWinApp 声明
// in APPMODUL.CPP
extern "C" int WINAPI //_tWinMain是为了支持Unicode 而准备的一个宏。
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nCmdShow){
return AfxWinMain (hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}
int AFXAPI AfxWinMain ( //源代码可从MFC 的WINMAIN.CPP 中获得稍加整理去芜存菁
HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nCmdShow){
int nReturnCode = -1;
CWinApp* pApp = AfxGetApp();//一个指向theApp的指针和四个动作
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; }
#define afxCurrentWinApp AfxGetModuleState()->m_pCurrentWinApp//定义于AFXWIN.H
CWinApp::CWinApp(LPCTSTR lpszAppName){
m_pszAppName = lpszAppName;
AFX_MODULE_THREAD_STATE* pThreadState = AfxGetModuleThreadState(); // initialize CWinThread state
pThreadState->m_pCurrentWinThread = this;
m_hThread = ::GetCurrentThread();
m_nThreadID = ::GetCurrentThreadId();
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();// initialize CWinApp state
pModuleState->m_pCurrentWinApp = this; ...//所以this是theApp对象
}
AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE(); //实际情况
#ifdef _AFXDLL
#define _AFX_CMDTARGET_GETSTATE() (m_pModuleState)
#else
#define _AFX_CMDTARGET_GETSTATE() (AfxGetModuleState())
#endif
以上说明CWinApp* pApp = AfxGetApp();返回的指针是指向子类对象theApp,在WinMain中调用的函数:
CWinApp::InitApplication(); //CMyWinApp 只改写CWinApp中的 InitInstance
CMyWinApp::InitInstance();//通常它不改写InitApplication和 Run
CWinApp::Run();
①AfxWinInit--AFX 内部初始化动作
节录自APPINIT.CPP | 节录自THRDCORE.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) 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; } | 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; } } |
WinMain 一开始即调用AfxWinInit,注册四个窗口类别
②BOOL CWinApp::InitApplication(){//在APPCORE.CPP中(大部份情况下不需改写它)
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;
}
③pApp->InitInstance();在CWinApp 中只是个空函数,没有任何内建(预设)动作。
BOOL CMyWinApp::InitInstance(){
m_pMainWnd = new CMyFrameWnd();
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
CMyFrameWnd::CMyFrameWnd(){//由new引发的构造式
Create(NULL, "Hello MFC", WS_OVERLAPPEDWINDOW, rectDefault, NULL,"MainMenu");
}//Create只有前两个参数必须指定
BOOL CFrameWnd::Create(LPCTSTR lpszClassName ,// WINFRM.CPP
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;
}
‹
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 WINCORE.CPP
CREATESTRUCT cs;
cs.dwExStyle = dwExStyle;cs.lpszClass = lpszClassName;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);
...
}
BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs){ //WINFRM.CPP
if (cs.lpszClass == NULL){
AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG);
cs.lpszClass = _afxWndFrameOrView; // COLOR_WINDOW background
}
...
}
#define AfxDeferRegisterClass(fClass) \
((afxRegisteredClasses & fClass) ? TRUE : AfxEndDeferRegisterClass(fClass))// in AFXIMPL.H
#define afxRegisteredClasses AfxGetModuleState()->m_fRegisteredClasses// in AFXWIN.H
BOOL AFXAPI AfxEndDeferRegisterClass(short fClass) // in WINCORE.CPP
4.CFrameWnd-取代WndProc的地位
class CMyFrameWnd : public CFrameWnd{//MFC中
public:
CMyFrameWnd();
afx_msg void OnPaint();//处理WM_PAINT
afx_msg void OnAbout();//WM_COMMAND 的IDM _ABOUT
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)
ON_WM_PAINT()
ON_COMMAND(IDM_ABOUT, OnAbout)
END_MESSAGE_MAP()
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);
}//传统的SDK 窗口函数
}