home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / C++-7 / DISK10 / MFC / SRC / WINAPP.CP$ / winapp
Encoding:
Text File  |  1992-03-17  |  9.3 KB  |  349 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992 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 Microsoft
  7. // QuickHelp documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11.  
  12. #include "afxwin.h"
  13. #pragma hdrstop
  14. #include "window_.h"
  15. #include "penwin.h"     // MFC Apps are PenAware by default
  16.  
  17. #ifdef AFX_CORE_SEG
  18. #pragma code_seg(AFX_CORE_SEG)
  19. #endif
  20.  
  21. #ifdef _DEBUG
  22. #include "trace_.h"
  23. #undef THIS_FILE
  24. static char BASED_CODE THIS_FILE[] = __FILE__;
  25. #endif
  26.  
  27. /////////////////////////////////////////////////////////////////////////////
  28. // Define global state in ordinary "C" globals
  29.  
  30. extern "C"
  31. {
  32. CWinApp* afxCurrentWinApp = NULL;
  33. HANDLE afxCurrentInstanceHandle = NULL;
  34. HANDLE afxCurrentResourceHandle = NULL;
  35. const char* afxCurrentAppName = NULL;
  36. }
  37.  
  38. /////////////////////////////////////////////////////////////////////////////
  39. // other globals (internal library use)
  40.  
  41. // Proc addresses for Win3.1 specifics
  42. #ifndef _WINDLL
  43. HOOKPROC (WINAPI* _afxSetWindowsHookExProc)(int, HOOKPROC, HINSTANCE, HTASK);
  44. static void (FAR PASCAL *_afxRegisterPenAppProc)(UINT, BOOL);
  45. #endif //!_WINDLL
  46.  
  47. /////////////////////////////////////////////////////////////////////////////
  48.  
  49. IMPLEMENT_DYNAMIC(CWinApp, CObject)
  50.  
  51. #ifdef _DEBUG
  52. void CWinApp::AssertValid() const
  53. {
  54.     CObject::AssertValid();
  55.     ASSERT(afxCurrentWinApp == this);
  56.     ASSERT(afxCurrentInstanceHandle == m_hInstance);
  57. }
  58.  
  59. void CWinApp::Dump(CDumpContext& dc) const
  60. {
  61.     CObject::Dump(dc);
  62.     dc << "\nm_hInstance = " << (UINT)m_hInstance;
  63.     dc << "\nm_hPrevInstance = " << (UINT)m_hPrevInstance;
  64.     dc << "\nm_lpCmdLine = " << m_lpCmdLine;
  65.     dc << "\nm_nCmdShow = " << m_nCmdShow;
  66.     dc << "\nm_pMainWnd = " << m_pMainWnd;
  67. }
  68. #endif
  69.  
  70. inline void CWinApp::SetCurrentHandles()
  71. {
  72.     ASSERT(this == afxCurrentWinApp);
  73.     afxCurrentInstanceHandle = m_hInstance; // for instance tagging
  74.     afxCurrentResourceHandle = m_hInstance; // for resource loading
  75.  
  76.     if (m_pszAppName == NULL)
  77.     {
  78.         // get name/path of executable
  79.         char szName[256];
  80.         ::GetModuleFileName(m_hInstance, szName, sizeof(szName)-1);
  81.         m_pszAppName = _strdup(szName);
  82.     }
  83.     afxCurrentAppName = m_pszAppName;
  84.     ASSERT(afxCurrentAppName != NULL);
  85. }
  86.  
  87. /////////////////////////////////////////////////////////////////////////////
  88.  
  89. CWinApp::CWinApp(const char* pszAppName)
  90. {
  91.     m_pszAppName = pszAppName;
  92.     // in non-running state until WinMain
  93.     m_hInstance = NULL;
  94.     m_pMainWnd = NULL;
  95.  
  96.     ASSERT(afxCurrentWinApp == NULL);   // only one CWinApp object please
  97.     afxCurrentWinApp = this;        // hook for WinMain
  98.  
  99. #ifdef _DEBUG
  100.     m_nDisablePumpCount = 0;
  101. #endif
  102. }
  103.  
  104. #ifdef _DEBUG
  105. void CWinApp::EnablePump(BOOL bEnable)
  106. {
  107.     if (bEnable)
  108.         m_nDisablePumpCount--;
  109.     else
  110.         m_nDisablePumpCount++;
  111.     ASSERT(m_nDisablePumpCount >= 0);
  112. }
  113. #endif // _DEBUG
  114.  
  115.  
  116. BOOL CWinApp::PumpMessage()
  117. {
  118. #ifdef _DEBUG
  119.     if (m_nDisablePumpCount != 0)
  120.     {
  121.         TRACE("Error: CWinApp::PumpMessage() called when not permitted\n");
  122.         ASSERT(FALSE);
  123.     }
  124. #endif
  125.  
  126.     if (!::GetMessage(&m_msgCur, NULL, NULL, NULL))
  127.     {
  128. #ifdef _DEBUG
  129.         if (afxTraceFlags & 2)
  130.             TRACE("PumpMessage - Received WM_QUIT\n");
  131.         m_nDisablePumpCount++; // application must die
  132.             // NOTE: prevents calling message loop things in 'ExitInstance'
  133.             // will never be decremented
  134. #endif
  135.         return FALSE;
  136.     }
  137.  
  138. #ifdef _DEBUG
  139.     if (afxTraceFlags & 2)
  140.         AfxTraceMsg("PumpMessage", &m_msgCur);
  141. #endif
  142.  
  143.     // process this message
  144.     if (!PreTranslateMessage(&m_msgCur))
  145.     {
  146.         ::TranslateMessage(&m_msgCur);
  147.         ::DispatchMessage(&m_msgCur);
  148.     }
  149.     return TRUE;
  150. }
  151.  
  152. int CWinApp::Run()
  153. {
  154.     /* Acquire and dispatch messages until a WM_QUIT message is received. */
  155.  
  156.     while (1)
  157.     {
  158.         LONG lIdleCount = 0;
  159.         // check to see if we can do idle work
  160.         while (!::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE) &&
  161.             OnIdle(lIdleCount++))
  162.         {
  163.             // more work to do
  164.         }
  165.         
  166.         // either we have a message, or OnIdle returned false
  167.  
  168.         if (!PumpMessage())
  169.             break;
  170.     }
  171.  
  172.     return ExitInstance();
  173. }
  174.  
  175. /////////////////////////////////////////////////////////////////////////////
  176. // Stubs for standard initialization
  177.  
  178. BOOL CWinApp::InitApplication()
  179. {
  180.     return TRUE;
  181. }
  182.  
  183. BOOL CWinApp::InitInstance()
  184. {
  185.     return TRUE;
  186. }
  187.  
  188. /////////////////////////////////////////////////////////////////////////////
  189. // Stubs for standard implementation
  190.  
  191. BOOL CWinApp::PreTranslateMessage(MSG* pMsg)
  192. {
  193.     register HWND hWnd;
  194.     register CWnd* pWnd;
  195.  
  196.     // walk from the target window up to the desktop window seeing
  197.     //  if any window wants to translate this message
  198.     for (hWnd = pMsg->hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd))
  199.     {
  200.         if ((pWnd = CWnd::FromHandlePermanent(hWnd)) != NULL)
  201.         {
  202.             // target window is a C++ window
  203.             if (pWnd->PreTranslateMessage(pMsg))
  204.                 return TRUE; // trapped by target window (eg: accelerators)
  205.  
  206.             if (pWnd == m_pMainWnd)
  207.                 return FALSE;       // got to our main window without interest
  208.         }
  209.     }
  210.  
  211.     // in case of modeless dialogs, last chance route through main window's
  212.     //   accelerator table
  213.     if (m_pMainWnd != NULL && m_pMainWnd->PreTranslateMessage(pMsg))
  214.         return TRUE; // trapped by main window (eg: accelerators)
  215.     
  216.     return FALSE;       // no special processing
  217. }
  218.  
  219.  
  220. BOOL CWinApp::OnIdle(LONG /*lCount*/)
  221. {
  222.     CGdiObject::DeleteTempMap();
  223.     CDC::DeleteTempMap();
  224.     CMenu::DeleteTempMap();
  225.     CWnd::DeleteTempMap();
  226.     return FALSE;   // no more processing (sleep please)
  227. }
  228.  
  229. int CWinApp::ExitInstance()
  230. {
  231.     return m_msgCur.wParam; // Returns the value from PostQuitMessage
  232. }
  233.  
  234. /////////////////////////////////////////////////////////////////////////////
  235. // Standard init called by WinMain
  236.  
  237. static BOOL NEAR RegisterWithIcon(register WNDCLASS* pWndCls,
  238.     const char* szClassName, UINT nIDIcon)
  239. {
  240.     pWndCls->lpszClassName = szClassName;
  241.     if ((pWndCls->hIcon = ::LoadIcon(pWndCls->hInstance,
  242.       MAKEINTRESOURCE(nIDIcon))) == NULL)
  243.     {
  244.         // use default icon
  245.         pWndCls->hIcon = ::LoadIcon(NULL, IDI_APPLICATION);
  246.     }
  247.     return RegisterClass(pWndCls);
  248. }
  249.  
  250. /////////////////////////////////////////////////////////////////////////////
  251.  
  252. extern "C"
  253. BOOL AfxWinInit(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  254.     LPSTR lpCmdLine, int nCmdShow)
  255. {
  256.     register CWinApp* pApp = AfxGetApp();
  257.  
  258.     ASSERT(pApp != NULL);   // must have one
  259.  
  260.     // fill in the initial state for the application
  261.     pApp->m_hInstance = hInstance;
  262.     pApp->m_hPrevInstance = hPrevInstance;
  263.     pApp->m_lpCmdLine = lpCmdLine;
  264.     pApp->m_nCmdShow = nCmdShow;
  265.     pApp->SetCurrentHandles();
  266.  
  267.     // Windows version specific initialization
  268. #ifndef _WINDLL
  269.     WORD wVersion = LOWORD(::GetVersion());
  270.     if (LOBYTE(wVersion) > 3 || HIBYTE(wVersion) >= 10)
  271.     {
  272.         HINSTANCE hPenWin;
  273.         if ((hPenWin = (HINSTANCE)GetSystemMetrics(SM_PENWINDOWS)) != NULL)
  274.         {
  275.             static char BASED_CODE szRegisterPenApp[] = "RegisterPenApp";
  276.             _afxRegisterPenAppProc = (void (WINAPI*)(UINT, BOOL))
  277.                 ::GetProcAddress(hPenWin, szRegisterPenApp);
  278.             if (_afxRegisterPenAppProc != NULL)
  279.                 (*_afxRegisterPenAppProc)(RPA_DEFAULT, TRUE);
  280.         }
  281.  
  282.         // Windows 3.1 or better - use SetWindowsHookEx (USER.291)
  283.         static char BASED_CODE szUSER[] = "USER";
  284.         _afxSetWindowsHookExProc =
  285.             (HOOKPROC (WINAPI*)(int, HOOKPROC, HINSTANCE, HTASK))
  286.             ::GetProcAddress(::GetModuleHandle(szUSER), MAKEINTRESOURCE(291));
  287.     }
  288. #endif //!_WINDLL
  289.  
  290.     if (hPrevInstance == NULL)  // one instance initialization
  291.     {
  292.         // register basic WndClasses
  293.         WNDCLASS wndcls;
  294.         memset(&wndcls, 0, sizeof(WNDCLASS));   // start with NULL defaults
  295.  
  296.         // common initialization
  297.         wndcls.lpfnWndProc  = AfxWndProc;
  298.         wndcls.hInstance    = hInstance;
  299.         wndcls.hCursor      = ::LoadCursor(NULL, IDC_ARROW);
  300.         wndcls.style        = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
  301.  
  302.         // Child windows - no brush, no icon
  303.         wndcls.lpszClassName = _afxWnd;
  304.         if (!::RegisterClass(&wndcls))
  305.             return FALSE;
  306.  
  307.         // MDI Frame windows
  308.         if (!RegisterWithIcon(&wndcls, _afxMDIFrameWnd, AFX_IDI_STD_MDIFRAME))
  309.             return FALSE;
  310.  
  311.         // SDI Frame or MDI Child windows - normal colors
  312.         wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  313.         if (!RegisterWithIcon(&wndcls, _afxFrameWnd, AFX_IDI_STD_FRAME))
  314.             return FALSE;
  315.     }
  316.  
  317.     return TRUE;
  318. }
  319.  
  320. extern "C"
  321. void AfxWinTerm(void)
  322. {
  323.     // These static CWnd objects refer to HWNDs that don't exist
  324.     // so let's not call ::DestroyWindow when CWnd::~CWnd() is invoked.
  325.     ((CWnd&)CWnd::wndTop).m_hWnd = NULL;
  326.     ((CWnd&)CWnd::wndBottom).m_hWnd = NULL;
  327.     ((CWnd&)CWnd::wndTopMost).m_hWnd = NULL;
  328.     ((CWnd&)CWnd::wndNoTopMost).m_hWnd = NULL;
  329.  
  330. #ifndef _WINDLL
  331.     // if we registered ourself with PenWin, deregister now
  332.     if (_afxRegisterPenAppProc != NULL)
  333.         (*_afxRegisterPenAppProc)(RPA_DEFAULT, FALSE);
  334. #endif //!_WINDLL
  335. }
  336.  
  337. /////////////////////////////////////////////////////////////////////////////
  338. // force WinMain or LibMain inclusion
  339.  
  340. #ifdef _WINDLL
  341. extern "C" int PASCAL LibMain(HINSTANCE, WORD, WORD, LPSTR);
  342. static FARPROC linkAddr = (FARPROC) &LibMain;
  343. #else
  344. extern "C" int PASCAL WinMain(HINSTANCE, HINSTANCE, LPSTR, int);
  345. static FARPROC linkAddr = (FARPROC) &WinMain;
  346. #endif //!_WINDLL
  347.  
  348. /////////////////////////////////////////////////////////////////////////////
  349.