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

    技术2022-05-19  30

    首先看看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)