主窗口的诞生过程

《深入浅出MFC》这本书,对于VC程序员来说,应该算是如雷贯耳。此书对于MFC程序的来龙去脉阐述颇为精彩,但也许是出于描述的方便,在讲到“主窗口如何产生”这一话题时,侯老师将我们平常在VC下看到的CMyApp::InitInstance()修改了一下,如下所示:

//the original codes
BOOL CSellManagerApp::InitInstance()
{
 // 如果一个运行在 Windows XP 上的应用程序清单指定要
 // 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
 //则需要 InitCommonControls()。否则,将无法创建窗口。
 InitCommonControls();

 CWinApp::InitInstance();

 // 初始化 OLE 库
 if (!AfxOleInit())
 {
  AfxMessageBox(IDP_OLE_INIT_FAILED);
  return FALSE;
 }
 AfxEnableControlContainer();
 // 标准初始化
 // 如果未使用这些功能并希望减小
 // 最终可执行文件的大小,则应移除下列
 // 不需要的特定初始化例程
 // 更改用于存储设置的注册表项
 // TODO: 应适当修改该字符串,
 // 例如修改为公司或组织名
 SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
 LoadStdProfileSettings(4);  // 加载标准 INI 文件选项(包括 MRU)
 // 注册应用程序的文档模板。文档模板
 // 将用作文档、框架窗口和视图之间的连接
 CSingleDocTemplate* pDocTemplate;
 pDocTemplate = new CSingleDocTemplate(
  IDR_MAINFRAME,
  RUNTIME_CLASS(CSellManagerDoc),
  RUNTIME_CLASS(CMainFrame),       // 主 SDI 框架窗口
  RUNTIME_CLASS(CSellManagerView));
 if (!pDocTemplate)
  return FALSE;
 AddDocTemplate(pDocTemplate);
 // 分析标准外壳命令、DDE、打开文件操作的命令行
 CCommandLineInfo cmdInfo;
 ParseCommandLine(cmdInfo);
 // 调度在命令行中指定的命令。如果
 // 用 /RegServer、/Register、/Unregserver 或 /Unregister 启动应用程序,则返回 FALSE。
 if (!ProcessShellCommand(cmdInfo))
  return FALSE;
 // 唯一的一个窗口已初始化,因此显示它并对其进行更新
 m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED);
 m_pMainWnd->UpdateWindow();
 // 仅当存在后缀时才调用 DragAcceptFiles,
 //  在 SDI 应用程序中,这应在 ProcessShellCommand  之后发生
 return TRUE;
}

//codes in <distectting the MFC>
BOOL CMyWinApp::InitInstance()
{
m_pMainWnd = new CMyFrameWnd();
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}


在侯老师的代码中有:“m_pMainWnd=new CMyFrameWnd();  ”。显然这也是很符合逻辑的,一个程序肯定是先创建好主窗口,然后才会处理其他的消息。于是,我就试图在FrameWork生成的代码中找类似的代码,显然上文中是没有任何的线索。我采取了这么一个办法。在InitInstance的开头加入:bool bIsNull=false;然后在原来的每行代码后添加:
if(NULL==m_pMainWnd)
  bIsNull=true;
于是,如上的代码变成如下:
        bool bIsNull=true;
 InitCommonControls();
 if(NULL==m_pMainWnd)
  bIsNull=false;

 CWinApp::InitInstance();
 if(NULL==m_pMainWnd)
  bIsNull=false;
       //
       ...
       //end
通过调试,我发现在执行“ProcessShellCommand(cmdInfo)”后,bIsNull发生了变化。于是设置断点,进行跟踪调试,最终发现在这个函数的执行过程存在着类似“m_pMainWnd=new CMyFrameWnd();  ”的代码。
现在,我来描述一下ProcessShellCommand:首先判断运行时系统传递的命令行参数,当我们双击应用程序(如"sellmanager.exe"),那么就是得到的消息是FileNew。对于FileNew,将是一连串函数调用,过程如下:
CWinApp::OnFileNew()->CDocManager::OnFileNew()->CSingleDocTemplate::OpenDocumentFile().在OpenDocumentFile中,程序判断m_pMainWnd是否为空,如果为空将创建CMainWnd对象,然后调用该对象的LoadFrame,由于我在程序中没有重写该函数,也就是调用CFrameWnd::LoadFrame,在LoadFrame中,将会看到:
if (!Create(lpszClass, strTitle, dwDefaultStyle, rectDefault,
   pParentWnd, MAKEINTRESOURCE(nIDResource), 0L, pContext))
{
   return FALSE;   // will self destruct on failure normally
}

对主窗口的诞生过程有了了解之后,就对编写程序有一定帮助。比如,我们做了一个管理软件,这中软件大多数是有登录对话框的,等用户输入正确的密码后,才会进入我们界面。那么,这个登录对话框要放在代码中的哪个位置呢?显然,可以把他放在InitInstance中,并将它放在ProcessShellCommand之前。为什么呢?因为,此时主窗口还尚未创建。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值