AfxWinInit 以及MFC中winMain的主要功能
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
AfxWinInit
Visual Studio 2012
其他版本
此主题尚未评级 - 评价此主题
作为基于GUI 的应用程序的CWinApp初始化的一部分,此函数由由MFC 提供的WinMain函数时,初始化,MFC。
BOOL AFXAPI AfxWinInit(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow
);
参数
hInstance
当前正在运行的模块的句柄。
hPrevInstance
对应用程序的上一个实例的句柄。
对于基于Win32 的应用程序,此参数始终是NULL。
lpCmdLine
指向指定命令行的一个NULL 终止的字符串为应用程序。
nCmdShow
指定GUI 应用程序的主窗口将如何显示。
备注
对于控制台应用程序,不使用由MFC 提供的WinMain功能,您必须直接调用AfxWinInit初始化MFC。
如果调用AfxWinInit,应声明CWinApp类的实例。
对于控制台应用程序中,可以选择从CWinApp不派生您的类并不直接使用CWinApp实例。
,如果您的主的实现,决定将应用程序的所有功能保留此方法很合适。
说明
示例
C++
#include <afx.h>
#include <afxdb.h>
int _tmain(int/*argc*/, TCHAR* /*argv[]*/, TCHAR* /*envp[]*/) {
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL),
NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
_tprintf(_T("Fatal Error: MFC initialization failed\n")); nRetCode = 1;
}
else
{
// try to connect to an ODBC database that doesn't exist
// (this wouldn't work at all without initializing MFC)
CDatabase db;
try
{
db.Open(_T("This Databsae Doesn't Exist"));
// we shouldn't realistically get here
_tprintf_s(_T("Successful!\n")
_T("Closing ...\n"));
db.Close();
_tprintf_s(_T("Closed!"));
}
catch (CDBException* pEx)
{
// we got an exception! print an error message
// (this wouldn't work without initializing MFC)
TCHAR sz[1024];
_tprintf_s(_T("Error: "));
if (pEx->GetErrorMessage(sz, 1024))
_tprintf_s(sz);
else
_tprintf_s(_T("No error message was available")); _tprintf_s(_T("\n"));
pEx->Delete();
nRetCode = 1;
}
}
return nRetCode;
}
要求
Header: afxwin.h
请参见
参考
CWinApp 类
主:启动程序
WinMain
概念
MFC宏和Globals
CWinApp: The Application 类
MFC中WinMain的主要任务流程WinMain()主要执行:
CWinApp* pApp = AfxGetApp();
AfxWinInit();
pApp->InitApplication();
pApp->InitInstance();
nReturnCode = pApp->Run();
1.WinApp
CWinApp 负责程序的初始化执行等等。
2.AfxWinInit();
AfxWinInit主要做的事情是:(1)对winapp进行初始化(2)AfxInitThread()线程初始化的一些操作;
BOOL AFXAPI AfxWinInit(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
ASSERT(hPrevInstance == NULL);
AFX_MODULE_STATE* pState = AfxGetModuleState();
pState->m_hCurrentInstanceHandle = hInstance;
pState->m_hCurrentResourceHandle = hInstance;
CWinApp* pApp = AfxGetApp();
if (pApp != NULL)
{
pApp->m_hInstance = hInstance;
pApp->m_hPrevInstance = hPrevInstance;
pApp->m_lpCmdLine = lpCmdLine;
pApp->m_nCmdShow = nCmdShow;
pApp->SetCurrentHandles();
}
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;
}
}
3.CWinApp::InitApplication()
InitApplication()做的主要是为了内部管理而做的。
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;
}
4.CMyWinApp::InitInstance
BOOL CMyWinApp::InitInstance()
{
m_pMainWnd = new CMyFrameWnd();
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
代码很简单。
其中m_pMainWnd = new CMyFrameWnd()创建了一个新的对象,对象的创建会调用他的构造函数。
CMyFrameWnd::CMyFrameWnd
{
Create(NULL, "Hello MFC", WS_OVERLAPPEDWINDOW, rectDefault, NULL, "MainMenu");
}
而Create(NULL, "Hello MFC", WS_OVERLAPPEDWINDOW, rectDefault, NULL,"MainMenu") 的实现在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()的方法,最后或该窗口的句柄pParentWnd。
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;
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);
...
}
方法中主要完成了CREATESTRUCT cs的初始化。
PreCreateWindow(cs);
AfxHookWindowCreate(this);
CreateWindowEx(...)
PreCreateWindow(cs)代码如下:
BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
{
if (cs.lpszClass == NULL)
{
AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG);
cs.lpszClass = _afxWndFrameOrView; // COLOR_WINDOW background
}
...
}
其中AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG)的宏是
#define AfxDeferRegisterClass(fClass) \
((afxRegisteredClasses & fClass) ? TRUE : AfxEndDeferRegisterClass(fClass)) #define afxRegisteredClasses AfxGetModuleState()->m_fRegisteredClasses 这个宏表示,如果变量afxRegisteredClasses 的值显示系统已经注册了fClass 这种视窗类别,MFC 就啥也不做;否则就调用AfxEndDeferRegisterClass(fClass),准备注册之。
在afxRegisteredClasses()中主要有两个注册方法:一个是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);
}
可见在RegisterWithIcon()方法中,仅仅是做了一个icon的设置,然后又调用了AfxRegisterClass(pWndCls);AfxRegisterClass()中调用了
RegisterClass(lpWndClass)。
CMyFrameWnd::CMyFrameWnd 结束后,窗口已经诞生出来;程序流程又回到CMyWinApp::InitInstance ,于是调用ShowWindow 函数令窗口显示出来,并调用UpdateWindow 函数令Hello 程序送出WM_PAINT 消息。
WM_PAINT消息是在APP->Run()中调用中处理的,Run()中包含的有:
do {
::GetMessage(&msg,...);
PreTranslateMessage{&msg);
::TranslateMessage(&msg);
::DispatchMessage(&msg);
...
} while (::PeekMessage(...));
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();
}
在CWinApp::Run()中调用了CWinThread::Run()
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
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;
}。