科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件应用程序类对象实例初始操作的分析

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

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

文档视图结构中,应用程序类对象实例初始操作的分析......

作者:佚名 来源:VC编程网 2007年10月22日

关键字: 应用程序 类对象 初始操作

  • 评论
  • 分享微博
  • 分享邮件
文档视图结构中,应用程序类对象实例初始操作的分析

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)
{
// path\DefaultIcon = 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())
{
// path\shell\open\ddeexec = [open("%1")]
strTemp.Format(_afxShellOpenFmt, (LPCTSTR)strFileTypeId,
(LPCTSTR)_afxDDEExec);
if (!_AfxSetRegKey(strTemp, _afxDDEOpen))
continue; // just skip it

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

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

// path\shell\open\command = path /dde
// path\shell\print\command = path /dde
// path\shell\printto\command = path /dde
strOpenCommandLine += _afxDDEArg;
strPrintCommandLine += _afxDDEArg;
strPrintToCommandLine += _afxDDEArg;
}
else
{
strOpenCommandLine += _afxOpenArg;
}
}
else
{
// path\shell\open\command = path filename
// path\shell\print\command = path /p filename
// path\shell\printto\command = path /pt filename printer driver port
strOpenCommandLine += _afxOpenArg;
if (bCompat)
{
strPrintCommandLine += _afxPrintArg;
strPrintToCommandLine += _afxPrintToArg;
}
}

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

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

// path\shell\printto\command = 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;
}

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章