MFC应用程序类对象实例初始操作的分析

首先看看InitInstance()函数:
BOOL CSomeApp::InitInstance()
{
Enable3dControls();
LoadStdProfileSettings();
AddDocTemplate(...) ...... ShowWindow(...);
m_pMainWnd
->DragAcceptFiles();
EnableShellOpen();
RegisterShellFileTypes(TRUE);
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
if (!ProcessShellCommand(cmdInfo))
return FALSE;
return TRUE;
}
 

 

下面对InitInstance中的一些操作及其流程进行分析

  1.常规设置

     如:
  SetDialogBkColor()
  Enable3dControls()..
  (如果设置了后者,则前者就不必要了)
  SetRegistryKey(指定注册表键,替代INI文件)

  2.LoadStdProfileSettings()

  LoadStdProfileSettings 完成最近文件列表功能,在菜单中添加最近的文件作为菜单项过程:

  建立一个CRecentFileList从注册表或INI文件中读入最近文件列表;

  当菜单建立时,文件列表将添加到菜单中ID_FILE_MRU_FILE*位置;

  3.m_pMainWnd->DragAcceptFiles()接收文件拖入

  使主窗口能响应文件拖入消息WM_DROPFILES;

  当有文件拖入时, 框架窗口的OnDropFiles将处理,以打开这些文件。

 

void  CFrameWnd::OnDropFiles(HDROP hDropInfo)
{
SetActiveWindow(); 
// activate us first !
UINT nFiles = ::DragQueryFile(hDropInfo, (UINT)-1, NULL, 0);

CWinApp
* pApp = AfxGetApp();
ASSERT(pApp 
!= NULL);
for (UINT iFile = 0; iFile < nFiles; iFile++
{
TCHAR szFileName[_MAX_PATH];
::DragQueryFile(hDropInfo, iFile, szFileName, _MAX_PATH);
//应用程序打开拖入文档
pApp->OpenDocumentFile(szFileName);
}

::DragFinish(hDropInfo);
}

 

4.EnableShellOpen();

  为在Windows中使用外壳操作打开文件作准备

 

void  CWinApp::EnableShellOpen()
{
ASSERT(m_atomApp 
== NULL && m_atomSystemTopic == NULL); // do once

m_atomApp 
= ::GlobalAddAtom(m_pszExeName);
m_atomSystemTopic 
= ::GlobalAddAtom(_T("system"));
}

 

5.RegisterShellFileTypes

  向系统注册文件类型,以使用外壳操作。

  将调用m_pDocManager->RegisterShellFileTypes()

  (CDocManager::RegisterShellFileTypes()源码附后)

  要点:将所有文档模板的类型,外壳命令等写入注册表

  包括type ID、shell/open/ddeexec = [open("%1")]、shell/print/ddeexec = [print("%1")]、shell/printto/ddeexec = [printto("%1","%2","%3","%4")]等等。

  6.ProcessShellCommand

  处理命令行、外壳命令等

CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
if (!ProcessShellCommand(cmdInfo))
return FALSE;

  ①先建立CCommandLineInfo对象

  ②再将命令行参数等分解到cmdInfo

 

void  CWinApp::ParseCommandLine(CCommandLineInfo &  rCmdInfo)
{
for (int i = 1; i < __argc; i++
{
LPCTSTR pszParam 
= __targv[i];
BOOL bFlag 
= FALSE;
BOOL bLast 
= ((i + 1) == __argc);
if (pszParam[0== '-' || pszParam[0== '/'
{
// remove flag specifier
bFlag = TRUE;
++pszParam;
}

rCmdInfo.ParseParam(pszParam, bFlag, bLast);
}

}
 
通过该操作,命令行被转化为cmdInfo;

  命令行的意义
  app (新建文件)
  app filename(打开文件)
  app /p filename(打印文件)
  app /pt filename printer driver port (用指定的打印机打印)
  app /dde (运行并接收DDE命令)
  app /Automation (启动为自动化服务器)
  app /Embedding (内嵌式运行)

  ParseCommandLine后,操作类型(打开、新建、打印..)存放在m_nShellCommand; 文件名存放在m_strFileName......

  ③处理命令

  主要操作:

switch  (rCmdInfo.m_nShellCommand)
{
case CCommandLineInfo::FileNew:
OnFileNew()....
break
case CCommandLineInfo::FileOpen:
OpenDocumentFile(rCmdInfo.m_strFileName)....
break
case CCommandLineInfo::FilePrint:
case CCommandLineInfo::FilePrintTo:
打开文件,发送ID_FILE_PRINT_DIRECT,返回FALSE值(导致立即程序退出)
case CCommandLineInfo::FileDDE: 
m_nCmdShow 
= SW_HIDE;(程序被运行,但被隐藏,m_nCmdShow作为ShowWindow的参数)
等等操作 
}
 

附一:CDocManager::RegisterShellFileTypes

void  CDocManager::RegisterShellFileTypes(BOOL bCompat)
{
ASSERT(
!m_templateList.IsEmpty()); // must have some doc templates

CString strPathName, strTemp;

AfxGetModuleShortFileName(AfxGetInstanceHandle(), strPathName);

POSITION pos 
= m_templateList.GetHeadPosition();
//针对每种文档模板进行注册
for (int nTemplateIndex = 1; pos != NULL; nTemplateIndex++
{
CDocTemplate
* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);

CString strOpenCommandLine 
= strPathName;
CString strPrintCommandLine 
= strPathName;
CString strPrintToCommandLine 
= strPathName;
CString strDefaultIconCommandLine 
= strPathName;

if (bCompat)
{
CString strIconIndex;
HICON hIcon 
= ::ExtractIcon(AfxGetInstanceHandle(), strPathName, nTemplateIndex);
if (hIcon != NULL)
{
strIconIndex.Format(_afxIconIndexFmt, nTemplateIndex);
DestroyIcon(hIcon);
}

else
{
strIconIndex.Format(_afxIconIndexFmt, DEFAULT_ICON_INDEX);
}

strDefaultIconCommandLine 
+= strIconIndex;
}


CString strFilterExt, strFileTypeId, strFileTypeName;
if (pTemplate->GetDocString(strFileTypeId,
CDocTemplate::regFileTypeId) 
&& !strFileTypeId.IsEmpty())
{
// enough info to register it
if (!pTemplate->GetDocString(strFileTypeName,
CDocTemplate::regFileTypeName))
strFileTypeName 
= strFileTypeId; // use id name

ASSERT(strFileTypeId.Find(
' ') == -1); // no spaces allowed

// first register the type ID of our server
if (!_AfxSetRegKey(strFileTypeId, strFileTypeName))
continue; // just skip it

if (bCompat)
{
// pathDefaultIcon = path,1
strTemp.Format(_afxDefaultIconFmt, (LPCTSTR)strFileTypeId);
if (!_AfxSetRegKey(strTemp, strDefaultIconCommandLine))
continue; // just skip it
}


// If MDI Application
if (!pTemplate->GetDocString(strTemp, CDocTemplate::windowTitle) ||
strTemp.IsEmpty())
{
// pathshellopenddeexec = [open("%1")]
strTemp.Format(_afxShellOpenFmt, (LPCTSTR)strFileTypeId,
(LPCTSTR)_afxDDEExec);
if (!_AfxSetRegKey(strTemp, _afxDDEOpen))
continue; // just skip it

if (bCompat)
{
// pathshellprintddeexec = [print("%1")]
strTemp.Format(_afxShellPrintFmt, (LPCTSTR)strFileTypeId,
(LPCTSTR)_afxDDEExec);
if (!_AfxSetRegKey(strTemp, _afxDDEPrint))
continue; // just skip it

// pathshellprinttoddeexec = [printto("%1","%2","%3","%4")]
strTemp.Format(_afxShellPrintToFmt, (LPCTSTR)strFileTypeId,
(LPCTSTR)_afxDDEExec);
if (!_AfxSetRegKey(strTemp, _afxDDEPrintTo))
continue; // just skip it

// pathshellopencommand = path /dde
// pathshellprintcommand = path /dde
// pathshellprinttocommand = path /dde
strOpenCommandLine += _afxDDEArg;
strPrintCommandLine 
+= _afxDDEArg;
strPrintToCommandLine 
+= _afxDDEArg;
}

else
{
strOpenCommandLine 
+= _afxOpenArg;
}

}

else
{
// pathshellopencommand = path filename
// pathshellprintcommand = path /p filename
// pathshellprinttocommand = path /pt filename printer driver port
strOpenCommandLine += _afxOpenArg;
if (bCompat)
{
strPrintCommandLine 
+= _afxPrintArg;
strPrintToCommandLine 
+= _afxPrintToArg;
}

}


// pathshellopencommand = path filename
strTemp.Format(_afxShellOpenFmt, (LPCTSTR)strFileTypeId,
(LPCTSTR)_afxCommand);
if (!_AfxSetRegKey(strTemp, strOpenCommandLine))
continue; // just skip it

if (bCompat)
{
// pathshellprintcommand = path /p filename
strTemp.Format(_afxShellPrintFmt, (LPCTSTR)strFileTypeId,
(LPCTSTR)_afxCommand);
if (!_AfxSetRegKey(strTemp, strPrintCommandLine))
continue; // just skip it

// pathshellprinttocommand = path /pt filename printer driver port
strTemp.Format(_afxShellPrintToFmt, (LPCTSTR)strFileTypeId,
(LPCTSTR)_afxCommand);
if (!_AfxSetRegKey(strTemp, strPrintToCommandLine))
continue; // just skip it
}


pTemplate
->GetDocString(strFilterExt, CDocTemplate::filterExt);
if (!strFilterExt.IsEmpty())
{
ASSERT(strFilterExt[
0== '.');

LONG lSize 
= _MAX_PATH * 2
LONG lResult 
= ::RegQueryValue(HKEY_CLASSES_ROOT, strFilterExt,
strTemp.GetBuffer(lSize), 
&lSize);
strTemp.ReleaseBuffer();

if (lResult != ERROR_SUCCESS || strTemp.IsEmpty() ||
strTemp 
== strFileTypeId)
{
// no association for that suffix
if (!_AfxSetRegKey(strFilterExt, strFileTypeId))
continue

if (bCompat)
{
strTemp.Format(_afxShellNewFmt, (LPCTSTR)strFilterExt);
void)_AfxSetRegKey(strTemp, _afxShellNewValue, _afxShellNewValueName);
}

}

}

}

}

}

 
附二:CWinApp::ProcessShellCommand
BOOL CWinApp::ProcessShellCommand(CCommandLineInfo &  rCmdInfo)
{
BOOL bResult 
= TRUE;
switch (rCmdInfo.m_nShellCommand)
{
case CCommandLineInfo::FileNew:
if (!AfxGetApp()->OnCmdMsg(ID_FILE_NEW, 0, NULL, NULL))
OnFileNew();
if (m_pMainWnd == NULL)
bResult 
= FALSE;
break

// If we've been asked to open a file, call OpenDocumentFile()

case CCommandLineInfo::FileOpen:
if (!OpenDocumentFile(rCmdInfo.m_strFileName))
bResult 
= FALSE;
break

// If the user wanted to print, hide our main window and
// fire a message to ourselves to start the printing

case CCommandLineInfo::FilePrintTo:
case CCommandLineInfo::FilePrint:
m_nCmdShow 
= SW_HIDE;
ASSERT(m_pCmdInfo 
== NULL);
OpenDocumentFile(rCmdInfo.m_strFileName);
m_pCmdInfo 
= &rCmdInfo;
m_pMainWnd
->SendMessage(WM_COMMAND, ID_FILE_PRINT_DIRECT);
m_pCmdInfo 
= NULL;
bResult 
= FALSE;
break

// If we're doing DDE, hide ourselves

case CCommandLineInfo::FileDDE:
m_pCmdInfo 
= (CCommandLineInfo*)m_nCmdShow;
m_nCmdShow 
= SW_HIDE;
break

// If we've been asked to unregister, unregister and then terminate
case CCommandLineInfo::AppUnregister:
{
UnregisterShellFileTypes();
BOOL bUnregistered 
= Unregister();

// if you specify /EMBEDDED, we won't make an success/failure box
// this use of /EMBEDDED is not related to OLE

if (!rCmdInfo.m_bRunEmbedded)
{
if (bUnregistered)
AfxMessageBox(AFX_IDP_UNREG_DONE);
else
AfxMessageBox(AFX_IDP_UNREG_FAILURE);
}

bResult 
= FALSE; // that's all we do

// If nobody is using it already, we can use it.
// We'll flag that we're unregistering and not save our state
// on the way out. This new object gets deleted by the
// app object destructor.

if (m_pCmdInfo == NULL)
{
m_pCmdInfo 
= new CCommandLineInfo;
m_pCmdInfo
->m_nShellCommand = CCommandLineInfo::AppUnregister;
}

}

break
}

return bResult;
}

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值