应用程序类对象实例初始操作的分析CWinApp::InitInstance()

来源:互联网 发布:基于java的嵌入式开发 编辑:程序博客网 时间:2024/06/07 07:58

首先看看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;
}