// This is a part of the Microsoft Foundation Classes C++ library. // Copyright (C) 1992-1998 Microsoft Corporation // All rights reserved. // // This source code is only intended as a supplement to the // Microsoft Foundation Classes Reference and related // electronic documentation provided with the library. // See these sources for detailed information regarding the // Microsoft Foundation Classes product. #include "stdafx.h" #include #ifdef AFX_CORE1_SEG #pragma code_seg(AFX_CORE1_SEG) #endif #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif AFX_STATIC_DATA const TCHAR _afxFileSection[] = _T("Recent File List"); AFX_STATIC_DATA const TCHAR _afxFileEntry[] = _T("File%d"); AFX_STATIC_DATA const TCHAR _afxPreviewSection[] = _T("Settings"); AFX_STATIC_DATA const TCHAR _afxPreviewEntry[] = _T("PreviewPages"); ///////////////////////////////////////////////////////////////////////////// // globals (internal library use) // CDocManager statics are in this file for granularity reasons BOOL CDocManager::bStaticInit = TRUE; CDocManager* CDocManager::pStaticDocManager = NULL; CPtrList* CDocManager::pStaticList = NULL; BEGIN_MESSAGE_MAP(CWinApp, CCmdTarget) //{{AFX_MSG_MAP(CWinApp) // Global File commands ON_COMMAND(ID_APP_EXIT, OnAppExit) // MRU - most recently used file menu ON_UPDATE_COMMAND_UI(ID_FILE_MRU_FILE1, OnUpdateRecentFileMenu) ON_COMMAND_EX_RANGE(ID_FILE_MRU_FILE1, ID_FILE_MRU_FILE16, OnOpenRecentFile) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // _AFX_WIN_STATE implementation #ifndef _AFX_NO_GRAYDLG_SUPPORT #ifdef AFX_INIT_SEG #pragma code_seg(AFX_INIT_SEG) #endif _AFX_WIN_STATE::_AFX_WIN_STATE() { // Note: it is only necessary to intialize non-zero data. } #ifdef AFX_TERM_SEG #pragma code_seg(AFX_TERM_SEG) #endif _AFX_WIN_STATE::~_AFX_WIN_STATE() { AfxDeleteObject((HGDIOBJ*)&m_hDlgBkBrush); } #endif //!_AFX_NO_GRAYDLG_SUPPORT #ifdef AFX_INIT_SEG #pragma code_seg(AFX_INIT_SEG) #endif CWinApp::CWinApp(LPCTSTR lpszAppName) { if (lpszAppName != NULL) m_pszAppName = _tcsdup(lpszAppName); else m_pszAppName = NULL; // initialize CWinThread state AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE(); AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread; ASSERT(AfxGetThread() == NULL); pThreadState->m_pCurrentWinThread = this; ASSERT(AfxGetThread() == this); m_hThread = ::GetCurrentThread(); m_nThreadID = ::GetCurrentThreadId(); // initialize CWinApp state ASSERT(afxCurrentWinApp == NULL); // only one CWinApp object please pModuleState->m_pCurrentWinApp = this; ASSERT(AfxGetApp() == this); // in non-running state until WinMain m_hInstance = NULL; m_pszHelpFilePath = NULL; m_pszProfileName = NULL; m_pszRegistryKey = NULL; m_pszExeName = NULL; m_pRecentFileList = NULL; m_pDocManager = NULL; m_atomApp = m_atomSystemTopic = NULL; m_lpCmdLine = NULL; m_pCmdInfo = NULL; // initialize wait cursor state m_nWaitCursorCount = 0; m_hcurWaitCursorRestore = NULL; // initialize current printer state m_hDevMode = NULL; m_hDevNames = NULL; m_nNumPreviewPages = 0; // not specified (defaults to 1) // initialize DAO state m_lpfnDaoTerm = NULL; // will be set if AfxDaoInit called // other initialization m_bHelpMode = FALSE; m_nSafetyPoolSize = 512; // default size } BOOL CWinApp::InitApplication() { if (CDocManager::pStaticDocManager != NULL) { if (m_pDocManager == NULL) m_pDocManager = CDocManager::pStaticDocManager; CDocManager::pStaticDocManager = NULL; } if (m_pDocManager != NULL) m_pDocManager->AddDocTemplate(NULL); else CDocManager::bStaticInit = FALSE; return TRUE; } BOOL CWinApp::InitInstance() { return TRUE; } void CWinApp::LoadStdProfileSettings(UINT nMaxMRU) { ASSERT_VALID(this); ASSERT(m_pRecentFileList == NULL); if (nMaxMRU != 0) { // create file MRU since nMaxMRU not zero m_pRecentFileList = new CRecentFileList(0, _afxFileSection, _afxFileEntry, nMaxMRU); m_pRecentFileList->ReadList(); } // 0 by default means not set m_nNumPreviewPages = GetProfileInt(_afxPreviewSection, _afxPreviewEntry, 0); } 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); } } ///////////////////////////////////////////////////////////////////////////// // CCommandLineInfo implementation CCommandLineInfo::CCommandLineInfo() { m_bShowSplash = TRUE; m_bRunEmbedded = FALSE; m_bRunAutomated = FALSE; m_nShellCommand = FileNew; } CCommandLineInfo::~CCommandLineInfo() { } void CCommandLineInfo::ParseParam(const TCHAR* pszParam,BOOL bFlag,BOOL bLast) { if (bFlag) { USES_CONVERSION; ParseParamFlag(T2CA(pszParam)); } else ParseParamNotFlag(pszParam); ParseLast(bLast); } #ifdef UNICODE void CCommandLineInfo::ParseParam(const char* pszParam, BOOL bFlag, BOOL bLast) { if (bFlag) ParseParamFlag(pszParam); else ParseParamNotFlag(pszParam); ParseLast(bLast); } #endif // UNICODE void CCommandLineInfo::ParseParamFlag(const char* pszParam) { // OLE command switches are case insensitive, while // shell command switches are case sensitive if (lstrcmpA(pszParam, "pt") == 0) m_nShellCommand = FilePrintTo; else if (lstrcmpA(pszParam, "p") == 0) m_nShellCommand = FilePrint; else if (lstrcmpiA(pszParam, "Unregister") == 0 || lstrcmpiA(pszParam, "Unregserver") == 0) m_nShellCommand = AppUnregister; else if (lstrcmpA(pszParam, "dde") == 0) { AfxOleSetUserCtrl(FALSE); m_nShellCommand = FileDDE; } else if (lstrcmpiA(pszParam, "Embedding") == 0) { AfxOleSetUserCtrl(FALSE); m_bRunEmbedded = TRUE; m_bShowSplash = FALSE; } else if (lstrcmpiA(pszParam, "Automation") == 0) { AfxOleSetUserCtrl(FALSE); m_bRunAutomated = TRUE; m_bShowSplash = FALSE; } } void CCommandLineInfo::ParseParamNotFlag(const TCHAR* pszParam) { if (m_strFileName.IsEmpty()) m_strFileName = pszParam; else if (m_nShellCommand == FilePrintTo && m_strPrinterName.IsEmpty()) m_strPrinterName = pszParam; else if (m_nShellCommand == FilePrintTo && m_strDriverName.IsEmpty()) m_strDriverName = pszParam; else if (m_nShellCommand == FilePrintTo && m_strPortName.IsEmpty()) m_strPortName = pszParam; } #ifdef UNICODE void CCommandLineInfo::ParseParamNotFlag(const char* pszParam) { if (m_strFileName.IsEmpty()) m_strFileName = pszParam; else if (m_nShellCommand == FilePrintTo && m_strPrinterName.IsEmpty()) m_strPrinterName = pszParam; else if (m_nShellCommand == FilePrintTo && m_strDriverName.IsEmpty()) m_strDriverName = pszParam; else if (m_nShellCommand == FilePrintTo && m_strPortName.IsEmpty()) m_strPortName = pszParam; } #endif void CCommandLineInfo::ParseLast(BOOL bLast) { if (bLast) { if (m_nShellCommand == FileNew && !m_strFileName.IsEmpty()) m_nShellCommand = FileOpen; m_bShowSplash = !m_bRunEmbedded && !m_bRunAutomated; } } ///////////////////////////////////////////////////////////////////////////// // App termination CWinApp::~CWinApp() { // free doc manager if (m_pDocManager != NULL) delete m_pDocManager; // free recent file list if (m_pRecentFileList != NULL) delete m_pRecentFileList; // free static list of document templates if (!afxContextIsDLL) { if (CDocManager::pStaticList != NULL) { delete CDocManager::pStaticList; CDocManager::pStaticList = NULL; } if (CDocManager::pStaticDocManager != NULL) { delete CDocManager::pStaticDocManager; CDocManager::pStaticDocManager = NULL; } } // free printer info if (m_hDevMode != NULL) AfxGlobalFree(m_hDevMode); if (m_hDevNames != NULL) AfxGlobalFree(m_hDevNames); // free atoms if used if (m_atomApp != NULL) ::GlobalDeleteAtom(m_atomApp); if (m_atomSystemTopic != NULL) ::GlobalDeleteAtom(m_atomSystemTopic); // free cached commandline if (m_pCmdInfo != NULL) delete m_pCmdInfo; // cleanup module state AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE(); if (pModuleState->m_lpszCurrentAppName == m_pszAppName) pModuleState->m_lpszCurrentAppName = NULL; if (pModuleState->m_pCurrentWinApp == this) pModuleState->m_pCurrentWinApp = NULL; // free various strings allocated with _tcsdup free((void*)m_pszAppName); free((void*)m_pszRegistryKey); free((void*)m_pszExeName); free((void*)m_pszHelpFilePath); free((void*)m_pszProfileName); // avoid calling CloseHandle() on our own thread handle // during the CWinThread destructor m_hThread = NULL; } void CWinApp::SaveStdProfileSettings() { ASSERT_VALID(this); if (m_pRecentFileList != NULL) m_pRecentFileList->WriteList(); if (m_nNumPreviewPages != 0) WriteProfileInt(_afxPreviewSection, _afxPreviewEntry, m_nNumPreviewPages); } int CWinApp::ExitInstance() { // if we remember that we're unregistering, // don't save our profile settings if (m_pCmdInfo == NULL || m_pCmdInfo->m_nShellCommand != CCommandLineInfo::AppUnregister) { if (!afxContextIsDLL) SaveStdProfileSettings(); } // Cleanup DAO if necessary if (m_lpfnDaoTerm != NULL) { // If a DLL, YOU must call AfxDaoTerm prior to ExitInstance ASSERT(!afxContextIsDLL); (*m_lpfnDaoTerm)(); } return m_msgCur.wParam; // returns the value from PostQuitMessage } ///////////////////////////////////////////////////////////////////////////// #ifdef AFX_CORE1_SEG #pragma code_seg(AFX_CORE1_SEG) #endif // Main running routine until application exits int CWinApp::Run() { if (m_pMainWnd == NULL && AfxOleGetUserCtrl()) { // Not launched /Embedding or /Automation, but has no main window! TRACE0("Warning: m_pMainWnd is NULL in CWinApp::Run - quitting application.\n"); AfxPostQuitMessage(0); } return CWinThread::Run(); } #ifdef AFX_TERM_SEG #pragma code_seg(AFX_TERM_SEG) #endif void AFXAPI AfxPostQuitMessage(int nExitCode) { // cleanup OLE libraries CWinThread* pThread = AfxGetThread(); if (pThread != NULL && pThread->m_lpfnOleTermOrFreeLib != NULL) (*pThread->m_lpfnOleTermOrFreeLib)(TRUE, TRUE); ::PostQuitMessage(nExitCode); } ///////////////////////////////////////////////////////////////////////////// // WinHelp Helper #ifdef AFX_CORE1_SEG #pragma code_seg(AFX_CORE1_SEG) #endif void CWinApp::WinHelp(DWORD dwData, UINT nCmd) { CWnd* pMainWnd = AfxGetMainWnd(); ASSERT_VALID(pMainWnd); // return global app help mode state to FALSE (backward compatibility) m_bHelpMode = FALSE; pMainWnd->PostMessage(WM_KICKIDLE); // trigger idle update pMainWnd->WinHelp(dwData, nCmd); } ///////////////////////////////////////////////////////////////////////////// // Special exception handling LRESULT CWinApp::ProcessWndProcException(CException* e, const MSG* pMsg) { // handle certain messages in CWinThread switch (pMsg->message) { case WM_CREATE: case WM_PAINT: return CWinThread::ProcessWndProcException(e, pMsg); } // handle all the rest UINT nIDP = AFX_IDP_INTERNAL_FAILURE; // generic message string LRESULT lResult = 0; // sensible default if (pMsg->message == WM_COMMAND) { if ((HWND)pMsg->lParam == NULL) nIDP = AFX_IDP_COMMAND_FAILURE; // command (not from a control) lResult = (LRESULT)TRUE; // pretend the command was handled } if (e->IsKindOf(RUNTIME_CLASS(CMemoryException))) { e->ReportError(MB_ICONEXCLAMATION|MB_SYSTEMMODAL, nIDP); } else if (!e->IsKindOf(RUNTIME_CLASS(CUserException))) { // user has not been alerted yet of this catastrophic problem e->ReportError(MB_ICONSTOP, nIDP); } return lResult; // sensible default return from most WndProc functions } ///////////////////////////////////////////////////////////////////////////// // CWinApp idle processing BOOL CWinApp::OnIdle(LONG lCount) { if (lCount <= 0) { CWinThread::OnIdle(lCount); // call doc-template idle hook POSITION pos = NULL; if (m_pDocManager != NULL) pos = m_pDocManager->GetFirstDocTemplatePosition(); while (pos != NULL) { CDocTemplate* pTemplate = m_pDocManager->GetNextDocTemplate(pos); ASSERT_KINDOF(CDocTemplate, pTemplate); pTemplate->OnIdle(); } } else if (lCount == 1) { VERIFY(!CWinThread::OnIdle(lCount)); } return lCount < 1; // more to do if lCount < 1 } ///////////////////////////////////////////////////////////////////////////// // CWinApp idle processing void CWinApp::DevModeChange(LPTSTR lpDeviceName) { if (m_hDevNames == NULL) return; LPDEVNAMES lpDevNames = (LPDEVNAMES)::GlobalLock(m_hDevNames); ASSERT(lpDevNames != NULL); if (lstrcmp((LPCTSTR)lpDevNames + lpDevNames->wDeviceOffset, lpDeviceName) == 0) { HANDLE hPrinter; if (!OpenPrinter(lpDeviceName, &hPrinter, NULL)) return; // DEVMODE changed for the current printer if (m_hDevMode != NULL) AfxGlobalFree(m_hDevMode); // A zero for last param returns the size of buffer needed. int nSize = DocumentProperties(NULL, hPrinter, lpDeviceName, NULL, NULL, 0); ASSERT(nSize >= 0); m_hDevMode = GlobalAlloc(GHND, nSize); LPDEVMODE lpDevMode = (LPDEVMODE)GlobalLock(m_hDevMode); // Fill in the rest of the structure. if (DocumentProperties(NULL, hPrinter, lpDeviceName, lpDevMode, NULL, DM_OUT_BUFFER) != IDOK) { AfxGlobalFree(m_hDevMode); m_hDevMode = NULL; } ClosePrinter(hPrinter); } } /////////////////////////////////////////////////////////////////////////// // CWinApp diagnostics #ifdef _DEBUG void CWinApp::AssertValid() const { CWinThread::AssertValid(); ASSERT(afxCurrentWinApp == this); ASSERT(afxCurrentInstanceHandle == m_hInstance); if (AfxGetThread() != (CWinThread*)this) return; // only do subset if called from different thread if (m_pDocManager != NULL) ASSERT_VALID(m_pDocManager); } void CWinApp::Dump(CDumpContext& dc) const { CWinThread::Dump(dc); dc << "m_hInstance = " << (UINT)m_hInstance; dc << "\nm_hPrevInstance = " << (UINT)m_hPrevInstance; dc << "\nm_lpCmdLine = " << m_lpCmdLine; dc << "\nm_nCmdShow = " << m_nCmdShow; dc << "\nm_pszAppName = " << m_pszAppName; dc << "\nm_bHelpMode = " << m_bHelpMode; dc << "\nm_pszExeName = " << m_pszExeName; dc << "\nm_pszHelpFilePath = " << m_pszHelpFilePath; dc << "\nm_pszProfileName = " << m_pszProfileName; dc << "\nm_hDevMode = " << (UINT)m_hDevMode; dc << "\nm_hDevNames = " << (UINT)m_hDevNames; dc << "\nm_dwPromptContext = " << m_dwPromptContext; if (m_pRecentFileList != NULL) { dc << "\nm_strRecentFiles[] = "; int nSize = m_pRecentFileList->GetSize(); for (int i = 0; i < nSize; i++) { if ((*m_pRecentFileList)[i].GetLength() != 0) dc << "\n\tFile: " << (*m_pRecentFileList)[i]; } } if (m_pDocManager != NULL) m_pDocManager->Dump(dc); dc << "\nm_nWaitCursorCount = " << m_nWaitCursorCount; dc << "\nm_hcurWaitCursorRestore = " << (UINT)m_hcurWaitCursorRestore; dc << "\nm_nNumPreviewPages = " << m_nNumPreviewPages; dc << "\nm_msgCur = {"; dc << "\n\thwnd = " << (UINT)m_msgCur.hwnd; dc << "\n\tmessage = " << (UINT)m_msgCur.message; dc << "\n\twParam = " << (UINT)m_msgCur.wParam; dc << "\n\tlParam = " << (void*)m_msgCur.lParam; dc << "\n\ttime = " << m_msgCur.time; dc << "\n\tpt = " << CPoint(m_msgCur.pt); dc << "\n}"; dc << "\n"; } #endif #ifdef AFX_INIT_SEG #pragma code_seg(AFX_INIT_SEG) #endif IMPLEMENT_DYNAMIC(CWinApp, CWinThread) #pragma warning(disable: 4074) #pragma init_seg(lib) PROCESS_LOCAL(_AFX_WIN_STATE, _afxWinState) /////////////////////////////////////////////////////////////////////////////