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) CWinApp* pApp = AfxGetApp(); |
4.EnableShellOpen();
为在Windows中使用外壳操作打开文件作准备
void CWinApp::EnableShellOpen() m_atomApp = ::GlobalAddAtom(m_pszExeName); |
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) CString strPathName, strTemp; AfxGetModuleShortFileName(AfxGetInstanceHandle(), strPathName); POSITION pos = m_templateList.GetHeadPosition(); CString strOpenCommandLine = strPathName; if (bCompat) CString strFilterExt, strFileTypeId, strFileTypeName; ASSERT(strFileTypeId.Find(' ') == -1); // no spaces allowed // first register the type ID of our server if (bCompat) // If MDI Application if (bCompat) // path/shell/printto/ddeexec = [printto("%1","%2","%3","%4")] // path/shell/open/command = path /dde // path/shell/open/command = path filename if (bCompat) // path/shell/printto/command = path /pt filename printer driver port pTemplate->GetDocString(strFilterExt, CDocTemplate::filterExt); LONG lSize = _MAX_PATH * 2; if (lResult != ERROR_SUCCESS || strTemp.IsEmpty() || if (bCompat) |
附二:CWinApp::ProcessShellCommand
BOOL CWinApp::ProcessShellCommand(CCommandLineInfo& rCmdInfo) // If we've been asked to open a file, call OpenDocumentFile() case CCommandLineInfo::FileOpen: // If the user wanted to print, hide our main window and case CCommandLineInfo::FilePrintTo: // If we're doing DDE, hide ourselves case CCommandLineInfo::FileDDE: // If we've been asked to unregister, unregister and then terminate // if you specify /EMBEDDED, we won't make an success/failure box if (!rCmdInfo.m_bRunEmbedded) // If nobody is using it already, we can use it. if (m_pCmdInfo == NULL) |