home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / MTGDI.PAK / MTGDIVW.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  8.3 KB  |  350 lines

  1. // mtgdivw.cpp : implementation of the CThreadView class
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1992-1995 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Microsoft Foundation Classes Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Microsoft Foundation Classes product.
  12.  
  13. #include "stdafx.h"
  14. #include "mtgdi.h"
  15.  
  16. #include "mtgdidoc.h"
  17. #include "mtgdivw.h"
  18.  
  19. #ifdef _DEBUG
  20. #undef THIS_FILE
  21. static char BASED_CODE THIS_FILE[] = __FILE__;
  22. #endif
  23.  
  24. /////////////////////////////////////////////////////////////////////////////
  25. // CThreadView
  26.  
  27. IMPLEMENT_DYNCREATE(CThreadView, CView)
  28.  
  29. BEGIN_MESSAGE_MAP(CThreadView, CView)
  30.     //{{AFX_MSG_MAP(CThreadView)
  31.     ON_COMMAND(ID_THREAD_NEWBALL, OnNewball)
  32.     ON_COMMAND(ID_THREAD_KILLTHREADS, OnKillThreads)
  33.     ON_WM_DESTROY()
  34.     ON_COMMAND(ID_THREAD_NEWLINE, OnNewline)
  35.     ON_COMMAND(ID_THREAD_NEWRECTANGLE, OnNewrectangle)
  36.     ON_COMMAND(ID_THREAD_10NEWBALLS, On10newballs)
  37.     ON_COMMAND(ID_THREAD_10NEWLINES, On10newlines)
  38.     ON_COMMAND(ID_THREAD_10NEWRECTANGLES, On10newrectangles)
  39.     ON_WM_CREATE()
  40.     ON_WM_SIZE()
  41.     ON_COMMAND(ID_THREAD_25NEWBALLS, On25newballs)
  42.     ON_COMMAND(ID_THREAD_25NEWLINES, On25newlines)
  43.     ON_COMMAND(ID_THREAD_25NEWRECTANGLES, On25newrectangles)
  44.     ON_COMMAND(ID_THREAD_KILLTHREADSSLOW, OnThreadKillThreadsSlow)
  45.     //}}AFX_MSG_MAP
  46. END_MESSAGE_MAP()
  47.  
  48. /////////////////////////////////////////////////////////////////////////////
  49. // CThreadView construction/destruction
  50.  
  51. CThreadView::CThreadView()
  52. {
  53.     m_pDC = NULL;
  54. }
  55.  
  56. CThreadView::~CThreadView()
  57. {
  58. }
  59.  
  60. void CThreadView::UpdateTitle(int nThreads)
  61. {
  62.     if (nThreads == -1)
  63.         nThreads = m_threadList.GetCount();
  64.  
  65.     CString strCaption;
  66.     if (nThreads != 0)
  67.     {
  68.         CString strFormat; strFormat.LoadString(IDS_CAPTION_FORMAT);
  69.         strCaption.Format(strFormat, nThreads);
  70.     }
  71.     else
  72.          strCaption.LoadString(IDS_CAPTION_NOTHREADS);
  73.  
  74.     GetParentFrame()->SetWindowText(strCaption);
  75. }
  76.  
  77. void CThreadView::StartThread(int ThreadID)
  78. {
  79.     CGDIThread* pThread;
  80.     CPoint Pos(rand()%100,rand()%100);
  81.     CPoint Vel1((rand()%10)+2,(rand()%10)+2); 
  82.     CPoint Vel2((rand()%5)+2,(rand()%5)+2);
  83.     CSize Size(((rand()%60)+20),((rand()%60)+20));
  84.     COLORREF Color;
  85.     
  86.     //BLOCK: calculate random color
  87.     {
  88.         int r,g,b;
  89.  
  90.         do 
  91.         {
  92.             r = (rand()%3);
  93.             r = (r!=0) ? (r==2) ? 255 : 127 : 0;
  94.             
  95.             g = (rand()%3);
  96.             g = (g!=0) ? (g==2) ? 255 : 127 : 0;
  97.             
  98.             b = (rand()%3);
  99.             b = (b!=0) ? (b==2) ? 255 : 127 : 0;
  100.         }
  101.         while ((r==g) && (g==b)); 
  102.         // No white(255,255,255), gray(127,127,127), or black(0,0,0) allowed
  103.  
  104.         Color = RGB(r,g,b);
  105.     }
  106.  
  107.     if (rand()%1) Vel1.x*=-1;
  108.     if (rand()%1) Vel1.y*=-1;
  109.     if (rand()%1) Vel2.x*=-1;
  110.     if (rand()%1) Vel2.y*=-1;
  111.  
  112.     switch(ThreadID)
  113.     {
  114.     case 1:
  115.         pThread = new CBallThread(this, 
  116.             m_pDC->GetSafeHdc(), Pos, Vel1, Size, Color);
  117.         break;
  118.     case 2:
  119.         pThread = new CRectThread(this, 
  120.             m_pDC->GetSafeHdc(), Pos, Vel1, Size, Color);
  121.         break;
  122.     case 3:
  123.         pThread = new CLineThread(this, 
  124.             m_pDC->GetSafeHdc(), Pos, Vel1, Vel2, Size, Color);
  125.         break;
  126.     }
  127.  
  128.     if (pThread == NULL)
  129.         return;
  130.  
  131.     ASSERT_VALID(pThread);
  132.     pThread->m_pThreadParams = NULL;
  133.  
  134.     // Create Thread in a suspended state so we can set the Priority 
  135.     // before it starts getting away from us
  136.     if (!pThread->CreateThread(CREATE_SUSPENDED))
  137.     {
  138.         delete pThread;
  139.         return;
  140.     }
  141.  
  142.     // since everything is successful, add the thread to our list
  143.     m_threadList.AddTail(pThread);
  144.  
  145.     // If you want to make the sample more sprightly, set the thread priority here 
  146.     // a little higher. It has been set at idle priority to keep from bogging down 
  147.     // other apps that may also be running.
  148.     VERIFY(pThread->SetThreadPriority(THREAD_PRIORITY_IDLE));
  149.     // Now the thread can run wild
  150.     pThread->ResumeThread();
  151. }
  152.  
  153. void CThreadView::OnDraw(CDC*)
  154. {
  155. }
  156.  
  157. /////////////////////////////////////////////////////////////////////////////
  158. // CThreadView diagnostics
  159.  
  160. #ifdef _DEBUG
  161. void CThreadView::AssertValid() const
  162. {
  163.     CView::AssertValid();
  164. }
  165.  
  166. void CThreadView::Dump(CDumpContext& dc) const
  167. {
  168.     CView::Dump(dc);
  169. }
  170.  
  171. CThreadDoc* CThreadView::GetDocument() // non-debug version is inline
  172. {
  173.     return STATIC_DOWNCAST(CThreadDoc, m_pDocument);
  174. }
  175. #endif //_DEBUG
  176.  
  177. /////////////////////////////////////////////////////////////////////////////
  178. // CThreadView message handlers
  179.  
  180. void CThreadView::OnNewball() 
  181. {
  182.     StartThread(1);
  183.     UpdateTitle();
  184. }
  185.  
  186. void CThreadView::On10newballs() 
  187. {
  188.     for (int i = 0; i < 10; i++) 
  189.     {
  190.         StartThread(1);
  191.         UpdateTitle();
  192.     }
  193. }
  194.  
  195. void CThreadView::On25newballs() 
  196. {
  197.     for (int i = 0; i < 25; i++) 
  198.     {
  199.         StartThread(1);
  200.         UpdateTitle();
  201.     }
  202. }
  203.  
  204. void CThreadView::OnNewrectangle() 
  205. {
  206.     StartThread(2);
  207.     UpdateTitle();
  208. }
  209.  
  210. void CThreadView::On10newrectangles() 
  211. {
  212.     for (int i = 0; i < 10; i++) 
  213.     {
  214.         StartThread(2);
  215.         UpdateTitle();
  216.     }
  217. }
  218.  
  219. void CThreadView::On25newrectangles() 
  220. {
  221.     for (int i = 0; i < 25; i++) 
  222.     {
  223.         StartThread(2);
  224.         UpdateTitle();
  225.     }
  226. }
  227.  
  228. void CThreadView::OnNewline() 
  229. {
  230.     StartThread(3);
  231.     UpdateTitle();
  232. }
  233.  
  234. void CThreadView::On10newlines() 
  235. {
  236.     for (int i = 0 ;i < 10; i++) 
  237.     {
  238.         StartThread(3);
  239.         UpdateTitle();
  240.     }
  241. }    
  242.     
  243. void CThreadView::On25newlines() 
  244. {
  245.     for (int i = 0; i < 25; i++) 
  246.     {
  247.         StartThread(3);
  248.         UpdateTitle();
  249.     }
  250. }
  251.  
  252. // A preferred method for killing many threads.  Tell them to go away all
  253. // at once, then wait for them all to be scheduled and to terminate
  254. // themselves.  This is much, much faster than the more straight forward
  255. // way of asking just one to terminate, then waiting for it to do so.
  256. // It is also a little bit more complex.
  257.  
  258. void CThreadView::OnKillThreads()
  259. {
  260.     // tell all threads to shutdown
  261.     for (POSITION pos = m_threadList.GetHeadPosition(); pos != NULL; )
  262.     {
  263.         CGDIThread* pThread = m_threadList.GetNext(pos);
  264.         VERIFY(SetEvent(pThread->m_hEventKill));
  265.     }
  266.  
  267.     // wait for all threads to finish shutdown
  268.     for (int nThreadsLeft = m_threadList.GetCount(); nThreadsLeft != 0; )
  269.     {
  270.         WaitForSingleObject(CGDIThread::m_hAnotherDead, INFINITE);
  271.         Sleep(nThreadsLeft*2);// 200ms for every 100 threads
  272.         nThreadsLeft = 0;
  273.         for (pos = m_threadList.GetHeadPosition(); pos != NULL; )
  274.         {
  275.             CGDIThread* pThread = m_threadList.GetNext(pos);
  276.             if (WaitForSingleObject(pThread->m_hEventDead, 0) == WAIT_TIMEOUT)
  277.                 ++nThreadsLeft;
  278.         }
  279.         UpdateTitle(nThreadsLeft);
  280.     }
  281.  
  282.     // delete all thread objects
  283.     while (!m_threadList.IsEmpty())
  284.     {
  285.         CGDIThread* pThread = m_threadList.RemoveHead();
  286.                 /* Don't use the assertion check here since it's likely that the
  287.                    thread has already terminates, causing WaitForSingleObject
  288.                    to fail with an invalid thread handle. */
  289.         /*VERIFY*/(WaitForSingleObject(pThread->m_hThread, INFINITE) /*== WAIT_OBJECT_0*/);
  290.         delete pThread;
  291.     }
  292.     UpdateTitle();
  293.  
  294.     // invalidate the window since all threads are now gone
  295.     Invalidate();
  296. }
  297.  
  298. // KillThreadsSlow is much easier to understand since the process of
  299. // killing a thread is encapsulated in KillThread.  If you get more
  300. // than 50 threads running, however, you'll notice quite a difference
  301. // between this method and the one above.
  302.  
  303. void CThreadView::OnThreadKillThreadsSlow()
  304. {
  305.     // Iterate through the threads killing each
  306.     // KillThread doesn't return until the Thread is dead
  307.     while (!m_threadList.IsEmpty())
  308.     {
  309.         m_threadList.RemoveHead()->KillThread();
  310.         UpdateTitle();
  311.     }
  312.  
  313.     // Invalidate the window so it blanks the window
  314.     Invalidate();
  315. }
  316.  
  317. void CThreadView::OnDestroy()
  318. {
  319.     OnKillThreads();
  320.  
  321.     delete m_pDC;
  322.     m_pDC = NULL;
  323.  
  324.     CView::OnDestroy();
  325. }
  326.  
  327. int CThreadView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
  328. {
  329.     if (CView::OnCreate(lpCreateStruct) == -1)
  330.         return -1;
  331.     
  332.     // m_pDC must be initialized here instead of the constructor
  333.     // because the HWND isn't created until Create is called.
  334.     m_pDC = new CClientDC(this);
  335.     UpdateTitle();
  336.  
  337.     return 0;
  338. }
  339.  
  340. void CThreadView::OnSize(UINT nType, int cx, int cy) 
  341. {
  342.     CView::OnSize(nType, cx, cy);
  343.     
  344.     // Instead of getting the client rect every time we draw, we only
  345.     // update it when it changes.
  346.     for (POSITION pos = m_threadList.GetHeadPosition(); pos != NULL; )
  347.         m_threadList.GetNext(pos)->UpdateBorder();
  348. }
  349.  
  350.