home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / internet / scripting / spruuids / msgloop.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-12  |  13.8 KB  |  556 lines

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