appcore.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. #include "stdafx.h"
  11. #include <malloc.h>
  12. #ifdef AFX_CORE1_SEG
  13. #pragma code_seg(AFX_CORE1_SEG)
  14. #endif
  15. #ifdef _DEBUG
  16. #undef THIS_FILE
  17. static char THIS_FILE[] = __FILE__;
  18. #endif
  19. AFX_STATIC_DATA const TCHAR _afxFileSection[] = _T("Recent File List");
  20. AFX_STATIC_DATA const TCHAR _afxFileEntry[] = _T("File%d");
  21. AFX_STATIC_DATA const TCHAR _afxPreviewSection[] = _T("Settings");
  22. AFX_STATIC_DATA const TCHAR _afxPreviewEntry[] = _T("PreviewPages");
  23. /////////////////////////////////////////////////////////////////////////////
  24. // globals (internal library use)
  25. // CDocManager statics are in this file for granularity reasons
  26. BOOL CDocManager::bStaticInit = TRUE;
  27. CDocManager* CDocManager::pStaticDocManager = NULL;
  28. CPtrList* CDocManager::pStaticList = NULL;
  29. BEGIN_MESSAGE_MAP(CWinApp, CCmdTarget)
  30. //{{AFX_MSG_MAP(CWinApp)
  31. // Global File commands
  32. ON_COMMAND(ID_APP_EXIT, OnAppExit)
  33. // MRU - most recently used file menu
  34. ON_UPDATE_COMMAND_UI(ID_FILE_MRU_FILE1, OnUpdateRecentFileMenu)
  35. ON_COMMAND_EX_RANGE(ID_FILE_MRU_FILE1, ID_FILE_MRU_FILE16, OnOpenRecentFile)
  36. //}}AFX_MSG_MAP
  37. END_MESSAGE_MAP()
  38. /////////////////////////////////////////////////////////////////////////////
  39. // _AFX_WIN_STATE implementation
  40. #ifndef _AFX_NO_GRAYDLG_SUPPORT
  41. #ifdef AFX_INIT_SEG
  42. #pragma code_seg(AFX_INIT_SEG)
  43. #endif
  44. _AFX_WIN_STATE::_AFX_WIN_STATE()
  45. {
  46. // Note: it is only necessary to intialize non-zero data.
  47. }
  48. #ifdef AFX_TERM_SEG
  49. #pragma code_seg(AFX_TERM_SEG)
  50. #endif
  51. _AFX_WIN_STATE::~_AFX_WIN_STATE()
  52. {
  53. AfxDeleteObject((HGDIOBJ*)&m_hDlgBkBrush);
  54. }
  55. #endif //!_AFX_NO_GRAYDLG_SUPPORT
  56. #ifdef AFX_INIT_SEG
  57. #pragma code_seg(AFX_INIT_SEG)
  58. #endif
  59. CWinApp::CWinApp(LPCTSTR lpszAppName)
  60. {
  61. if (lpszAppName != NULL)
  62. m_pszAppName = _tcsdup(lpszAppName);
  63. else
  64. m_pszAppName = NULL;
  65. // initialize CWinThread state
  66. AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
  67. AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread;
  68. ASSERT(AfxGetThread() == NULL);
  69. pThreadState->m_pCurrentWinThread = this;
  70. ASSERT(AfxGetThread() == this);
  71. m_hThread = ::GetCurrentThread();
  72. m_nThreadID = ::GetCurrentThreadId();
  73. // initialize CWinApp state
  74. ASSERT(afxCurrentWinApp == NULL); // only one CWinApp object please
  75. pModuleState->m_pCurrentWinApp = this;
  76. ASSERT(AfxGetApp() == this);
  77. // in non-running state until WinMain
  78. m_hInstance = NULL;
  79. m_pszHelpFilePath = NULL;
  80. m_pszProfileName = NULL;
  81. m_pszRegistryKey = NULL;
  82. m_pszExeName = NULL;
  83. m_pRecentFileList = NULL;
  84. m_pDocManager = NULL;
  85. m_atomApp = m_atomSystemTopic = NULL;
  86. m_lpCmdLine = NULL;
  87. m_pCmdInfo = NULL;
  88. // initialize wait cursor state
  89. m_nWaitCursorCount = 0;
  90. m_hcurWaitCursorRestore = NULL;
  91. // initialize current printer state
  92. m_hDevMode = NULL;
  93. m_hDevNames = NULL;
  94. m_nNumPreviewPages = 0; // not specified (defaults to 1)
  95. // initialize DAO state
  96. m_lpfnDaoTerm = NULL; // will be set if AfxDaoInit called
  97. // other initialization
  98. m_bHelpMode = FALSE;
  99. m_nSafetyPoolSize = 512; // default size
  100. }
  101. BOOL CWinApp::InitApplication()
  102. {
  103. if (CDocManager::pStaticDocManager != NULL)
  104. {
  105. if (m_pDocManager == NULL)
  106. m_pDocManager = CDocManager::pStaticDocManager;
  107. CDocManager::pStaticDocManager = NULL;
  108. }
  109. if (m_pDocManager != NULL)
  110. m_pDocManager->AddDocTemplate(NULL);
  111. else
  112. CDocManager::bStaticInit = FALSE;
  113. return TRUE;
  114. }
  115. BOOL CWinApp::InitInstance()
  116. {
  117. return TRUE;
  118. }
  119. void CWinApp::LoadStdProfileSettings(UINT nMaxMRU)
  120. {
  121. ASSERT_VALID(this);
  122. ASSERT(m_pRecentFileList == NULL);
  123. if (nMaxMRU != 0)
  124. {
  125. // create file MRU since nMaxMRU not zero
  126. m_pRecentFileList = new CRecentFileList(0, _afxFileSection, _afxFileEntry,
  127. nMaxMRU);
  128. m_pRecentFileList->ReadList();
  129. }
  130. // 0 by default means not set
  131. m_nNumPreviewPages = GetProfileInt(_afxPreviewSection, _afxPreviewEntry, 0);
  132. }
  133. void CWinApp::ParseCommandLine(CCommandLineInfo& rCmdInfo)
  134. {
  135. for (int i = 1; i < __argc; i++)
  136. {
  137. LPCTSTR pszParam = __targv[i];
  138. BOOL bFlag = FALSE;
  139. BOOL bLast = ((i + 1) == __argc);
  140. if (pszParam[0] == '-' || pszParam[0] == '/')
  141. {
  142. // remove flag specifier
  143. bFlag = TRUE;
  144. ++pszParam;
  145. }
  146. rCmdInfo.ParseParam(pszParam, bFlag, bLast);
  147. }
  148. }
  149. /////////////////////////////////////////////////////////////////////////////
  150. // CCommandLineInfo implementation
  151. CCommandLineInfo::CCommandLineInfo()
  152. {
  153. m_bShowSplash = TRUE;
  154. m_bRunEmbedded = FALSE;
  155. m_bRunAutomated = FALSE;
  156. m_nShellCommand = FileNew;
  157. }
  158. CCommandLineInfo::~CCommandLineInfo()
  159. {
  160. }
  161. void CCommandLineInfo::ParseParam(const TCHAR* pszParam,BOOL bFlag,BOOL bLast)
  162. {
  163. if (bFlag)
  164. {
  165. USES_CONVERSION;
  166. ParseParamFlag(T2CA(pszParam));
  167. }
  168. else
  169. ParseParamNotFlag(pszParam);
  170. ParseLast(bLast);
  171. }
  172. #ifdef UNICODE
  173. void CCommandLineInfo::ParseParam(const char* pszParam, BOOL bFlag, BOOL bLast)
  174. {
  175. if (bFlag)
  176. ParseParamFlag(pszParam);
  177. else
  178. ParseParamNotFlag(pszParam);
  179. ParseLast(bLast);
  180. }
  181. #endif // UNICODE
  182. void CCommandLineInfo::ParseParamFlag(const char* pszParam)
  183. {
  184. // OLE command switches are case insensitive, while
  185. // shell command switches are case sensitive
  186. if (lstrcmpA(pszParam, "pt") == 0)
  187. m_nShellCommand = FilePrintTo;
  188. else if (lstrcmpA(pszParam, "p") == 0)
  189. m_nShellCommand = FilePrint;
  190. else if (lstrcmpiA(pszParam, "Unregister") == 0 ||
  191. lstrcmpiA(pszParam, "Unregserver") == 0)
  192. m_nShellCommand = AppUnregister;
  193. else if (lstrcmpA(pszParam, "dde") == 0)
  194. {
  195. AfxOleSetUserCtrl(FALSE);
  196. m_nShellCommand = FileDDE;
  197. }
  198. else if (lstrcmpiA(pszParam, "Embedding") == 0)
  199. {
  200. AfxOleSetUserCtrl(FALSE);
  201. m_bRunEmbedded = TRUE;
  202. m_bShowSplash = FALSE;
  203. }
  204. else if (lstrcmpiA(pszParam, "Automation") == 0)
  205. {
  206. AfxOleSetUserCtrl(FALSE);
  207. m_bRunAutomated = TRUE;
  208. m_bShowSplash = FALSE;
  209. }
  210. }
  211. void CCommandLineInfo::ParseParamNotFlag(const TCHAR* pszParam)
  212. {
  213. if (m_strFileName.IsEmpty())
  214. m_strFileName = pszParam;
  215. else if (m_nShellCommand == FilePrintTo && m_strPrinterName.IsEmpty())
  216. m_strPrinterName = pszParam;
  217. else if (m_nShellCommand == FilePrintTo && m_strDriverName.IsEmpty())
  218. m_strDriverName = pszParam;
  219. else if (m_nShellCommand == FilePrintTo && m_strPortName.IsEmpty())
  220. m_strPortName = pszParam;
  221. }
  222. #ifdef UNICODE
  223. void CCommandLineInfo::ParseParamNotFlag(const char* pszParam)
  224. {
  225. if (m_strFileName.IsEmpty())
  226. m_strFileName = pszParam;
  227. else if (m_nShellCommand == FilePrintTo && m_strPrinterName.IsEmpty())
  228. m_strPrinterName = pszParam;
  229. else if (m_nShellCommand == FilePrintTo && m_strDriverName.IsEmpty())
  230. m_strDriverName = pszParam;
  231. else if (m_nShellCommand == FilePrintTo && m_strPortName.IsEmpty())
  232. m_strPortName = pszParam;
  233. }
  234. #endif
  235. void CCommandLineInfo::ParseLast(BOOL bLast)
  236. {
  237. if (bLast)
  238. {
  239. if (m_nShellCommand == FileNew && !m_strFileName.IsEmpty())
  240. m_nShellCommand = FileOpen;
  241. m_bShowSplash = !m_bRunEmbedded && !m_bRunAutomated;
  242. }
  243. }
  244. /////////////////////////////////////////////////////////////////////////////
  245. // App termination
  246. CWinApp::~CWinApp()
  247. {
  248. // free doc manager
  249. if (m_pDocManager != NULL)
  250. delete m_pDocManager;
  251. // free recent file list
  252. if (m_pRecentFileList != NULL)
  253. delete m_pRecentFileList;
  254. // free static list of document templates
  255. if (!afxContextIsDLL)
  256. {
  257. if (CDocManager::pStaticList != NULL)
  258. {
  259. delete CDocManager::pStaticList;
  260. CDocManager::pStaticList = NULL;
  261. }
  262. if (CDocManager::pStaticDocManager != NULL)
  263. {
  264. delete CDocManager::pStaticDocManager;
  265. CDocManager::pStaticDocManager = NULL;
  266. }
  267. }
  268. // free printer info
  269. if (m_hDevMode != NULL)
  270. AfxGlobalFree(m_hDevMode);
  271. if (m_hDevNames != NULL)
  272. AfxGlobalFree(m_hDevNames);
  273. // free atoms if used
  274. if (m_atomApp != NULL)
  275. ::GlobalDeleteAtom(m_atomApp);
  276. if (m_atomSystemTopic != NULL)
  277. ::GlobalDeleteAtom(m_atomSystemTopic);
  278. // free cached commandline
  279. if (m_pCmdInfo != NULL)
  280. delete m_pCmdInfo;
  281. // cleanup module state
  282. AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
  283. if (pModuleState->m_lpszCurrentAppName == m_pszAppName)
  284. pModuleState->m_lpszCurrentAppName = NULL;
  285. if (pModuleState->m_pCurrentWinApp == this)
  286. pModuleState->m_pCurrentWinApp = NULL;
  287. // free various strings allocated with _tcsdup
  288. free((void*)m_pszAppName);
  289. free((void*)m_pszRegistryKey);
  290. free((void*)m_pszExeName);
  291. free((void*)m_pszHelpFilePath);
  292. free((void*)m_pszProfileName);
  293. // avoid calling CloseHandle() on our own thread handle
  294. // during the CWinThread destructor
  295. m_hThread = NULL;
  296. }
  297. void CWinApp::SaveStdProfileSettings()
  298. {
  299. ASSERT_VALID(this);
  300. if (m_pRecentFileList != NULL)
  301. m_pRecentFileList->WriteList();
  302. if (m_nNumPreviewPages != 0)
  303. WriteProfileInt(_afxPreviewSection, _afxPreviewEntry, m_nNumPreviewPages);
  304. }
  305. int CWinApp::ExitInstance()
  306. {
  307. // if we remember that we're unregistering,
  308. // don't save our profile settings
  309. if (m_pCmdInfo == NULL ||
  310. m_pCmdInfo->m_nShellCommand != CCommandLineInfo::AppUnregister)
  311. {
  312. if (!afxContextIsDLL)
  313. SaveStdProfileSettings();
  314. }
  315. // Cleanup DAO if necessary
  316. if (m_lpfnDaoTerm != NULL)
  317. {
  318. // If a DLL, YOU must call AfxDaoTerm prior to ExitInstance
  319. ASSERT(!afxContextIsDLL);
  320. (*m_lpfnDaoTerm)();
  321. }
  322. return m_msgCur.wParam; // returns the value from PostQuitMessage
  323. }
  324. /////////////////////////////////////////////////////////////////////////////
  325. #ifdef AFX_CORE1_SEG
  326. #pragma code_seg(AFX_CORE1_SEG)
  327. #endif
  328. // Main running routine until application exits
  329. int CWinApp::Run()
  330. {
  331. if (m_pMainWnd == NULL && AfxOleGetUserCtrl())
  332. {
  333. // Not launched /Embedding or /Automation, but has no main window!
  334. TRACE0("Warning: m_pMainWnd is NULL in CWinApp::Run - quitting application.\n");
  335. AfxPostQuitMessage(0);
  336. }
  337. return CWinThread::Run();
  338. }
  339. #ifdef AFX_TERM_SEG
  340. #pragma code_seg(AFX_TERM_SEG)
  341. #endif
  342. void AFXAPI AfxPostQuitMessage(int nExitCode)
  343. {
  344. // cleanup OLE libraries
  345. CWinThread* pThread = AfxGetThread();
  346. if (pThread != NULL && pThread->m_lpfnOleTermOrFreeLib != NULL)
  347. (*pThread->m_lpfnOleTermOrFreeLib)(TRUE, TRUE);
  348. ::PostQuitMessage(nExitCode);
  349. }
  350. /////////////////////////////////////////////////////////////////////////////
  351. // WinHelp Helper
  352. #ifdef AFX_CORE1_SEG
  353. #pragma code_seg(AFX_CORE1_SEG)
  354. #endif
  355. void CWinApp::WinHelp(DWORD dwData, UINT nCmd)
  356. {
  357. CWnd* pMainWnd = AfxGetMainWnd();
  358. ASSERT_VALID(pMainWnd);
  359. // return global app help mode state to FALSE (backward compatibility)
  360. m_bHelpMode = FALSE;
  361. pMainWnd->PostMessage(WM_KICKIDLE); // trigger idle update
  362. pMainWnd->WinHelp(dwData, nCmd);
  363. }
  364. /////////////////////////////////////////////////////////////////////////////
  365. // Special exception handling
  366. LRESULT CWinApp::ProcessWndProcException(CException* e, const MSG* pMsg)
  367. {
  368. // handle certain messages in CWinThread
  369. switch (pMsg->message)
  370. {
  371. case WM_CREATE:
  372. case WM_PAINT:
  373. return CWinThread::ProcessWndProcException(e, pMsg);
  374. }
  375. // handle all the rest
  376. UINT nIDP = AFX_IDP_INTERNAL_FAILURE; // generic message string
  377. LRESULT lResult = 0; // sensible default
  378. if (pMsg->message == WM_COMMAND)
  379. {
  380. if ((HWND)pMsg->lParam == NULL)
  381. nIDP = AFX_IDP_COMMAND_FAILURE; // command (not from a control)
  382. lResult = (LRESULT)TRUE; // pretend the command was handled
  383. }
  384. if (e->IsKindOf(RUNTIME_CLASS(CMemoryException)))
  385. {
  386. e->ReportError(MB_ICONEXCLAMATION|MB_SYSTEMMODAL, nIDP);
  387. }
  388. else if (!e->IsKindOf(RUNTIME_CLASS(CUserException)))
  389. {
  390. // user has not been alerted yet of this catastrophic problem
  391. e->ReportError(MB_ICONSTOP, nIDP);
  392. }
  393. return lResult; // sensible default return from most WndProc functions
  394. }
  395. /////////////////////////////////////////////////////////////////////////////
  396. // CWinApp idle processing
  397. BOOL CWinApp::OnIdle(LONG lCount)
  398. {
  399. if (lCount <= 0)
  400. {
  401. CWinThread::OnIdle(lCount);
  402. // call doc-template idle hook
  403. POSITION pos = NULL;
  404. if (m_pDocManager != NULL)
  405. pos = m_pDocManager->GetFirstDocTemplatePosition();
  406. while (pos != NULL)
  407. {
  408. CDocTemplate* pTemplate = m_pDocManager->GetNextDocTemplate(pos);
  409. ASSERT_KINDOF(CDocTemplate, pTemplate);
  410. pTemplate->OnIdle();
  411. }
  412. }
  413. else if (lCount == 1)
  414. {
  415. VERIFY(!CWinThread::OnIdle(lCount));
  416. }
  417. return lCount < 1; // more to do if lCount < 1
  418. }
  419. /////////////////////////////////////////////////////////////////////////////
  420. // CWinApp idle processing
  421. void CWinApp::DevModeChange(LPTSTR lpDeviceName)
  422. {
  423. if (m_hDevNames == NULL)
  424. return;
  425. LPDEVNAMES lpDevNames = (LPDEVNAMES)::GlobalLock(m_hDevNames);
  426. ASSERT(lpDevNames != NULL);
  427. if (lstrcmp((LPCTSTR)lpDevNames + lpDevNames->wDeviceOffset,
  428. lpDeviceName) == 0)
  429. {
  430. HANDLE hPrinter;
  431. if (!OpenPrinter(lpDeviceName, &hPrinter, NULL))
  432. return;
  433. // DEVMODE changed for the current printer
  434. if (m_hDevMode != NULL)
  435. AfxGlobalFree(m_hDevMode);
  436. // A zero for last param returns the size of buffer needed.
  437. int nSize = DocumentProperties(NULL, hPrinter, lpDeviceName,
  438. NULL, NULL, 0);
  439. ASSERT(nSize >= 0);
  440. m_hDevMode = GlobalAlloc(GHND, nSize);
  441. LPDEVMODE lpDevMode = (LPDEVMODE)GlobalLock(m_hDevMode);
  442. // Fill in the rest of the structure.
  443. if (DocumentProperties(NULL, hPrinter, lpDeviceName, lpDevMode,
  444. NULL, DM_OUT_BUFFER) != IDOK)
  445. {
  446. AfxGlobalFree(m_hDevMode);
  447. m_hDevMode = NULL;
  448. }
  449. ClosePrinter(hPrinter);
  450. }
  451. }
  452. ///////////////////////////////////////////////////////////////////////////
  453. // CWinApp diagnostics
  454. #ifdef _DEBUG
  455. void CWinApp::AssertValid() const
  456. {
  457. CWinThread::AssertValid();
  458. ASSERT(afxCurrentWinApp == this);
  459. ASSERT(afxCurrentInstanceHandle == m_hInstance);
  460. if (AfxGetThread() != (CWinThread*)this)
  461. return; // only do subset if called from different thread
  462. if (m_pDocManager != NULL)
  463. ASSERT_VALID(m_pDocManager);
  464. }
  465. void CWinApp::Dump(CDumpContext& dc) const
  466. {
  467. CWinThread::Dump(dc);
  468. dc << "m_hInstance = " << (UINT)m_hInstance;
  469. dc << "\nm_hPrevInstance = " << (UINT)m_hPrevInstance;
  470. dc << "\nm_lpCmdLine = " << m_lpCmdLine;
  471. dc << "\nm_nCmdShow = " << m_nCmdShow;
  472. dc << "\nm_pszAppName = " << m_pszAppName;
  473. dc << "\nm_bHelpMode = " << m_bHelpMode;
  474. dc << "\nm_pszExeName = " << m_pszExeName;
  475. dc << "\nm_pszHelpFilePath = " << m_pszHelpFilePath;
  476. dc << "\nm_pszProfileName = " << m_pszProfileName;
  477. dc << "\nm_hDevMode = " << (UINT)m_hDevMode;
  478. dc << "\nm_hDevNames = " << (UINT)m_hDevNames;
  479. dc << "\nm_dwPromptContext = " << m_dwPromptContext;
  480. if (m_pRecentFileList != NULL)
  481. {
  482. dc << "\nm_strRecentFiles[] = ";
  483. int nSize = m_pRecentFileList->GetSize();
  484. for (int i = 0; i < nSize; i++)
  485. {
  486. if ((*m_pRecentFileList)[i].GetLength() != 0)
  487. dc << "\n\tFile: " << (*m_pRecentFileList)[i];
  488. }
  489. }
  490. if (m_pDocManager != NULL)
  491. m_pDocManager->Dump(dc);
  492. dc << "\nm_nWaitCursorCount = " << m_nWaitCursorCount;
  493. dc << "\nm_hcurWaitCursorRestore = " << (UINT)m_hcurWaitCursorRestore;
  494. dc << "\nm_nNumPreviewPages = " << m_nNumPreviewPages;
  495. dc << "\nm_msgCur = {";
  496. dc << "\n\thwnd = " << (UINT)m_msgCur.hwnd;
  497. dc << "\n\tmessage = " << (UINT)m_msgCur.message;
  498. dc << "\n\twParam = " << (UINT)m_msgCur.wParam;
  499. dc << "\n\tlParam = " << (void*)m_msgCur.lParam;
  500. dc << "\n\ttime = " << m_msgCur.time;
  501. dc << "\n\tpt = " << CPoint(m_msgCur.pt);
  502. dc << "\n}";
  503. dc << "\n";
  504. }
  505. #endif
  506. #ifdef AFX_INIT_SEG
  507. #pragma code_seg(AFX_INIT_SEG)
  508. #endif
  509. IMPLEMENT_DYNAMIC(CWinApp, CWinThread)
  510. #pragma warning(disable: 4074)
  511. #pragma init_seg(lib)
  512. PROCESS_LOCAL(_AFX_WIN_STATE, _afxWinState)
  513. /////////////////////////////////////////////////////////////////////////////