home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1996 December / PCWKCD1296.iso / vjplusb / activex / inetsdk / samples / axscript / spruuids / src / msgloop.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-15  |  13.8 KB  |  555 lines

  1. //---------------------------------------------------------------------------
  2. // MsgLoop.cpp
  3. //---------------------------------------------------------------------------
  4. // Implementation of message loop for application.  Includes implementation
  5. // of IOleComponentManager.
  6. //---------------------------------------------------------------------------
  7. // (C) Copyright 1995-1996 by Microsoft Corporation.  All rights reserved.
  8. //
  9. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
  10. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
  11. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
  12. // PARTICULAR PURPOSE.
  13. //---------------------------------------------------------------------------
  14.  
  15. #include "Main.h"
  16. #include "MsgLoop.h"
  17.  
  18.  
  19. //---------------------------------------------------------------------------
  20. // DEBUG info
  21. //---------------------------------------------------------------------------
  22. SZTHISFILE
  23.  
  24.  
  25. //---------------------------------------------------------------------------
  26. //
  27. //---------------------------------------------------------------------------
  28. CMsgLoop::CMsgLoop
  29. (
  30.   HWND hwnd
  31. )
  32.   {
  33.   INIT_SIGNATURE(SIG_MsgLoop);
  34.  
  35.   for (int i=0; i<cCOMP; i++)
  36.     m_rgcomp[i].pcomp = NULL;
  37.  
  38.   m_icompActive  = icompNIL;
  39.   m_fInState     = FALSE;
  40.   m_icompState   = icompNIL;
  41.   m_uStateID     = 0;
  42.   m_fScrptReset  = FALSE;
  43.   m_fQuitting    = FALSE;
  44.   m_hwnd         = hwnd;
  45.   m_haccel       = NULL;     // Load accel table here
  46.   m_icompMsgLoop =icompNIL;
  47.  
  48.   m_cref        = 1;
  49.   m_cMsgLoop    = 0;
  50.   }
  51.  
  52.  
  53. //---------------------------------------------------------------------------
  54. //
  55. //---------------------------------------------------------------------------
  56. CMsgLoop::~CMsgLoop
  57. (
  58.   void
  59. )
  60.   {
  61.   CHECK_SIGNATURE(SIG_MsgLoop);
  62.  
  63.   for (int i=0; i<cCOMP; i++)
  64.     if (m_rgcomp[i].pcomp)
  65.       {
  66.       m_rgcomp[i].pcomp->Terminate();
  67.       RELEASEPTR(m_rgcomp[i].pcomp);
  68.       }
  69.  
  70.   DESTROY_SIGNATURE(SIG_MsgLoop);
  71.   }
  72.  
  73.  
  74. //***************************************************************************
  75. // IUnknown methods
  76. //***************************************************************************
  77.  
  78. //---------------------------------------------------------------------------
  79. //
  80. //---------------------------------------------------------------------------
  81. STDMETHODIMP CMsgLoop::QueryInterface
  82. (
  83.   REFIID   riid, 
  84.   void   **ppvObj
  85. )
  86.   {
  87.   *ppvObj = NULL;
  88.  
  89.   if (riid == IID_IUnknown)
  90.     *ppvObj = (LPVOID)(IUnknown *)(IOleComponentManager *)this;
  91.   else if (riid == IID_IOleComponentManager)
  92.     *ppvObj = (LPVOID)(IOleComponentManager *)this; 
  93.  
  94.   if (*ppvObj) 
  95.     {
  96.     this->AddRef();
  97.     return S_OK;
  98.     }
  99.   
  100.   return E_NOINTERFACE;
  101.   }
  102.  
  103.  
  104. //---------------------------------------------------------------------------
  105. //
  106. //---------------------------------------------------------------------------
  107. STDMETHODIMP_(ULONG) CMsgLoop::AddRef
  108. (
  109.   void
  110. )
  111.   {
  112.   CHECK_SIGNATURE(SIG_MsgLoop);
  113.   return ++m_cref;
  114.   }
  115.  
  116.  
  117. //---------------------------------------------------------------------------
  118. //
  119. //---------------------------------------------------------------------------
  120. STDMETHODIMP_(ULONG) CMsgLoop::Release
  121. (
  122.   void
  123. )
  124.   {
  125.   CHECK_SIGNATURE(SIG_MsgLoop);
  126.   if (--m_cref)
  127.     return m_cref;
  128.  
  129.   delete this;
  130.   return 0;
  131.   }
  132.  
  133.  
  134.  
  135. //***************************************************************************
  136. // IOleComponentManager Methods
  137. //***************************************************************************
  138.  
  139. //---------------------------------------------------------------------------
  140. //
  141. //---------------------------------------------------------------------------
  142. STDMETHODIMP CMsgLoop::QueryService
  143. (
  144.   REFGUID guidService, 
  145.   REFIID  iid, 
  146.   void  **ppvObjOut
  147.   {
  148.   *ppvObjOut = NULL;
  149.   return E_NOINTERFACE;
  150.   }
  151.  
  152.  
  153. //---------------------------------------------------------------------------
  154. //
  155. //---------------------------------------------------------------------------
  156. STDMETHODIMP_(BOOL) CMsgLoop::FRegisterComponent
  157. (
  158.   IOleComponent   *piComponent, 
  159.   const CMGRRINFO *pcrinfo, 
  160.   DWORD           *pdwCompIDOut
  161. )
  162.   {
  163.   for (int i=0; i<cCOMP; i++)
  164.     if (!m_rgcomp[i].pcomp)
  165.       {
  166.       piComponent->AddRef();
  167.       m_rgcomp[i].pcomp = piComponent;
  168.       *pdwCompIDOut = i;
  169.       return TRUE;
  170.       }
  171.  
  172.   FAIL("Out of room!");
  173.   return FALSE;
  174.   }
  175.  
  176.  
  177. //---------------------------------------------------------------------------
  178. //
  179. //---------------------------------------------------------------------------
  180. STDMETHODIMP_(BOOL) CMsgLoop::FRevokeComponent
  181. (
  182.   DWORD icomp
  183. )
  184.   {
  185.   ASSERT(m_rgcomp[icomp].pcomp, "Bogus icomp");
  186.   RELEASEPTR(m_rgcomp[icomp].pcomp);
  187.   if (m_icompActive == icomp)
  188.     m_icompActive = icompNIL;
  189.   if (m_icompMsgLoop == icomp)
  190.     m_icompMsgLoop = icompNIL;
  191.   return TRUE;
  192.   }
  193.  
  194.  
  195. //---------------------------------------------------------------------------
  196. //
  197. //---------------------------------------------------------------------------
  198. STDMETHODIMP_(BOOL) CMsgLoop::FUpdateComponentRegistration
  199.   DWORD            dwComponentID, 
  200.   const CMGRRINFO *pcrinfo
  201. )
  202.   {
  203.   // Don't track info anyway, so pretend it worked:
  204.   return TRUE;
  205.   }
  206.  
  207.  
  208. //---------------------------------------------------------------------------
  209. //
  210. //---------------------------------------------------------------------------
  211. STDMETHODIMP_(void) CMsgLoop::OnComponentActivate
  212. (
  213.   DWORD icomp
  214. )
  215.   {
  216.   ASSERT(m_rgcomp[icomp].pcomp, "Bad icomp");
  217.   m_icompActive = icomp;
  218.   return;
  219.   }
  220.  
  221.  
  222. //---------------------------------------------------------------------------
  223. //
  224. //---------------------------------------------------------------------------
  225. STDMETHODIMP_(BOOL) CMsgLoop::FSetTrackingComponent
  226. (
  227.   DWORD dwComponentID, 
  228.   BOOL  fTrack
  229. )
  230.   {
  231.   // UNDONE: Need to support
  232.   return FALSE;
  233.   }
  234.  
  235.  
  236. //---------------------------------------------------------------------------
  237. //
  238. //---------------------------------------------------------------------------
  239. STDMETHODIMP_(void) CMsgLoop::OnComponentEnterState
  240. (
  241.   DWORD icomp,
  242.   ULONG uStateID, 
  243.   ULONG uContext, 
  244.   ULONG cpicmExclude,
  245.   IOleComponentManager **rgpicmExclude,
  246.   DWORD dwReserved
  247. )
  248.   {
  249.   ASSERT(m_rgcomp[icomp].pcomp, "Bad icomp");
  250.   ASSERT(uStateID==cmgrstateModal,  "Not modal state");
  251.   ASSERT(!m_fInState, "Nested modal states");
  252.  
  253.   m_icompState = icomp;
  254.   m_fInState   = TRUE;
  255.   m_uStateID   = uStateID;
  256.   if (uStateID == cmgrstateModal)
  257.     EnableWindow(m_hwnd, FALSE);
  258.   }
  259.  
  260.  
  261. //---------------------------------------------------------------------------
  262. //
  263. //---------------------------------------------------------------------------
  264. STDMETHODIMP_(BOOL) CMsgLoop::FOnComponentExitState
  265. (
  266.   DWORD icomp,
  267.   ULONG uStateID,
  268.   ULONG uContext,
  269.   ULONG cpicmExclude,
  270.   IOleComponentManager **rgpicmExclude
  271. )
  272.   {
  273.   ASSERT(m_rgcomp[icomp].pcomp, "Bad icomp");
  274.   ASSERT(icomp==(DWORD)m_icompState, "icomp didn't own state");
  275.   ASSERT(uStateID==cmgrstateModal,  "Not modal state");
  276.   ASSERT(uStateID==m_uStateID, "non-matching modal states on pop");
  277.   ASSERT(m_fInState, "underflow of modal state");
  278.  
  279.   m_fInState   = FALSE;
  280.   m_icompState = icompNIL;
  281.   if (uStateID == cmgrstateModal)
  282.     EnableWindow(m_hwnd, TRUE);
  283.   return TRUE;
  284.   }
  285.  
  286.  
  287. //---------------------------------------------------------------------------
  288. //
  289. //---------------------------------------------------------------------------
  290. STDMETHODIMP_(BOOL) CMsgLoop::FInState
  291. (
  292.   ULONG uStateID,
  293.   void *pvoid
  294. )
  295.   {
  296.   return m_fInState && uStateID==m_uStateID;
  297.   }
  298.  
  299.  
  300. //---------------------------------------------------------------------------
  301. //
  302. //---------------------------------------------------------------------------
  303. STDMETHODIMP_(BOOL) CMsgLoop::FContinueIdle
  304. (
  305.   void
  306. )
  307.   {
  308.   return FALSE;
  309.   }
  310.  
  311.  
  312. //---------------------------------------------------------------------------
  313. //
  314. //---------------------------------------------------------------------------
  315. STDMETHODIMP_(BOOL) CMsgLoop::FPushMessageLoop
  316. (
  317.   DWORD icomp, 
  318.   ULONG uReason, 
  319.   void *pvLoopData
  320. )
  321.   {
  322.   MessageLoop(icomp, uReason, pvLoopData);
  323.   return TRUE;
  324.   }
  325.  
  326.  
  327. //---------------------------------------------------------------------------
  328. //
  329. //---------------------------------------------------------------------------
  330. STDMETHODIMP_(BOOL) CMsgLoop::FCreateSubComponentManager
  331. (
  332.   IUnknown *piunkOuter, 
  333.   IUnknown *piunkServProv,
  334.   REFIID    riid, 
  335.   void    **ppvObj
  336. )
  337.   {
  338.   ASSERT(!piunkOuter, "Don't support aggre. SubCompMgr");
  339.   HRESULT hr = this->QueryInterface(riid, ppvObj);
  340.   return !FAILED(hr);
  341.   }
  342.  
  343.  
  344. //---------------------------------------------------------------------------
  345. //
  346. //---------------------------------------------------------------------------
  347. STDMETHODIMP_(BOOL) CMsgLoop::FGetParentComponentManager
  348. (
  349.   IOleComponentManager **ppicm
  350. )
  351.   {
  352.   // UNDONE: Need to implement
  353.   return FALSE;
  354.   }
  355.  
  356.  
  357. //---------------------------------------------------------------------------
  358. //
  359. //---------------------------------------------------------------------------
  360. STDMETHODIMP_(BOOL) CMsgLoop::FGetActiveComponent
  361. (
  362.   DWORD           dwReserved,
  363.   IOleComponent **ppcompOut
  364. )
  365.   {
  366.   // Do we have an active component?
  367.   if (m_icompActive == icompNIL)
  368.     {
  369.     *ppcompOut = NULL;
  370.     return FALSE;
  371.     }
  372.  
  373.   // Yes, return it
  374.   *ppcompOut = m_rgcomp[m_icompActive].pcomp;
  375.   (*ppcompOut)->AddRef();       // for *ppcompOut
  376.   return TRUE;
  377.   }
  378.  
  379.  
  380.  
  381. //***************************************************************************
  382. // Message Loop Implementation
  383. //***************************************************************************
  384.  
  385. //---------------------------------------------------------------------------
  386. // This pushes a new message loop.
  387. //---------------------------------------------------------------------------
  388. void CMsgLoop::MessageLoop
  389. (
  390.   DWORD icomp,
  391.   ULONG uReason, 
  392.   void *pvLoopData
  393. )
  394.   {
  395.   BOOL  fExitLoop = FALSE;
  396.  
  397.   m_cMsgLoop++;
  398.  
  399.   while (!fExitLoop) 
  400.     fExitLoop = PumpMessage(icomp, uReason, pvLoopData);
  401.  
  402.   m_cMsgLoop--;
  403.  
  404.   if (!m_cMsgLoop)
  405.     m_fScrptReset = FALSE;
  406.   }
  407.  
  408.  
  409. //---------------------------------------------------------------------------
  410. // This processes one message.
  411. // Returns TRUE if it is time to exit the current message loop.
  412. //---------------------------------------------------------------------------
  413. BOOL CMsgLoop::PumpMessage
  414. (
  415.   DWORD icomp,
  416.   ULONG uReason, 
  417.   void *pvLoopData
  418. )
  419.   {
  420.   BOOL fExitLoop = FALSE;
  421.   BOOL fMsg;
  422.   MSG  msg;
  423.  
  424.   fMsg = PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE);
  425.   if (fMsg) 
  426.     {
  427.     if (msg.message == WM_QUIT)
  428.       {
  429.       // Since we're not really an app, re-post the WM_QUIT message, until
  430.       // we can pop any msgloops we've pushed.
  431.       if (m_cMsgLoop)
  432.            PostQuitMessage(msg.wParam);
  433.       return TRUE;
  434.       }
  435.     else
  436.       ProcessMessage(&msg);
  437.     }
  438.  
  439.   if (m_fScrptReset)
  440.     return TRUE;
  441.  
  442.   // A Component told us to push this message loop, and so we
  443.   // ask them whether it's time yet to exit the loop
  444.   fExitLoop = !m_rgcomp[icomp].pcomp->FContinueMessageLoop(uReason, pvLoopData);
  445.  
  446.   if (!fMsg && !fExitLoop) 
  447.     {
  448.     // There weren't any messages and we don't need to exit this message
  449.     // loop yet.  Therefore, now is the right time to do idle processing
  450.     DoIdleProcessing();
  451.     WaitMessage();
  452.     }
  453.  
  454.   return fExitLoop;
  455.   }
  456.  
  457.  
  458. //---------------------------------------------------------------------------
  459. // This processes one message.
  460. //---------------------------------------------------------------------------
  461. void CMsgLoop::ProcessMessage
  462. (
  463.   MSG  *pmsg
  464. )
  465.   {                            
  466.   // When a component is active give it a chance to translate
  467.   // its accelerators.
  468.   if (m_icompActive != icompNIL)
  469.     {
  470.     if (!m_rgcomp[m_icompActive].pcomp->FPreTranslateMessage(pmsg))
  471.       {
  472.       TranslateMessage(pmsg);        // Translates virtual key codes  
  473.       DispatchMessage(pmsg);        // Dispatches message to window 
  474.       }
  475.     } 
  476.   else 
  477.     {
  478.     if (!TranslateAccelerator(m_hwnd, m_haccel, pmsg))
  479.       {
  480.       TranslateMessage(pmsg); // Translates virtual key codes  
  481.       DispatchMessage(pmsg);  // Dispatches message to window 
  482.       }
  483.     }
  484.   }
  485.  
  486.  
  487. //---------------------------------------------------------------------------
  488. // This is called at idle time.
  489. //---------------------------------------------------------------------------
  490. void CMsgLoop::DoIdleProcessing
  491. (
  492.   void
  493. )
  494.   {
  495.   MSG  msg;
  496.   BOOL fContinue = TRUE;
  497.  
  498.   while (fContinue && !PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE))
  499.     {
  500.     fContinue = DoIdle();
  501.     }
  502.   }
  503.  
  504.  
  505. //---------------------------------------------------------------------------
  506. //
  507. //---------------------------------------------------------------------------
  508. BOOL CMsgLoop::DoIdle
  509. (
  510.   void
  511. )
  512.   {
  513.   int  i;
  514.   BOOL fDidWork = FALSE;
  515.  
  516.   // if we have periodic idle tasks that to be done, 
  517.   // do them and return TRUE.
  518.   for (i=0; i<cCOMP; i++)
  519.     {
  520.     if (m_rgcomp[i].pcomp)
  521.       if (m_rgcomp[i].pcomp->FDoIdle(cmgridlefPeriodic))
  522.         fDidWork = TRUE;
  523.     if (fDidWork)
  524.       return TRUE;
  525.     }
  526.     
  527.   // if any high priority idle tasks need to be done,
  528.   // do it, and return TRUE.
  529.   for (i=0; i<cCOMP; i++)
  530.     {
  531.     if (m_rgcomp[i].pcomp)
  532.       if (m_rgcomp[i].pcomp->FDoIdle(cmgridlefPriority))
  533.         fDidWork = TRUE;
  534.     if (fDidWork)
  535.       return TRUE;
  536.     }
  537.  
  538.   // if any lower priority idle tasks need to be done,
  539.   // do it, and return TRUE.
  540.   for (i=0; i<cCOMP; i++)
  541.     {
  542.     if (m_rgcomp[i].pcomp)
  543.       if (m_rgcomp[i].pcomp->FDoIdle(cmgridlefNonPeriodic))
  544.         fDidWork = TRUE;
  545.     if (fDidWork)
  546.       return TRUE;
  547.     }
  548.  
  549.   return FALSE;
  550.   }
  551.  
  552. //--- EOF -------------------------------------------------------------------
  553.