⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch18.htm

📁 visual c plus plus its a book for how to learn c plus plus in just 21 days its an easy way to lea
💻 HTM
📖 第 1 页 / 共 5 页
字号:
 2: { 3:     int i; 4:  5:     // Get the position of the view 6:     POSITION pos = GetFirstViewPosition(); 7:     // Did we get a valid position? 8:     if (pos != NULL) 9:     {10:         // Get a pointer to the view11:         CView* pView = GetNextView(pos);12: 13:         // Loop through the spinners14:         for (i = 0; i &lt; 4; i++)15:         {16:             // Set the pointer to the view17:             m_cSpin[i].SetViewWnd(pView);18:             // Initialize the pointer to the continuation indicator19:             m_cSpin[i].SetContinue(NULL);20:             switch (i)21:             {22:             case 1:    // Set the pointer to the first thread 23:                        // continuation indicator24:                 m_cSpin[i].SetContinue(&amp;((CTaskingView*)pView)-			&Acirc;&gt;m_bThread1);25:                 break;26:             case 3:    // Set the pointer to the second thread 27:                        // continuation indicator28:                 m_cSpin[i].SetContinue(&amp;((CTaskingView*)pView)-			&Acirc;&gt;m_bThread2);29:                 break;30:             }31:             // Calculate the location of the spinner32:             CalcPoint(i, &amp;m_cSpin[i]);33:         }34:     }35: }</PRE><P>In this function, you first went through the steps of getting a pointer to theview class from the document, as you did initially back on Day 10. Once you havea valid pointer to the view, start a loop to initialize each of the spinners in thearray. You call the SetViewWnd spinner function to set the spinner's pointer to theview window and then initialize the spinner's pointer to the check box variable toNULL for all spinners. If the spinner is either of the two that will be used by independentthreads, you pass a pointer to the appropriate check box variable. Once you set allof this, call the CalcPoint function that you created just a few minutes earlierto calculate the location of the spinner on the view window.</P><BLOCKQUOTE>	<P><HR><STRONG>NOTE:</STRONG> Although you've seen several examples of using pointers, the way	that you are passing a pointer to the check box variable to the spinner deserves	taking a closer look:	<PRE>m_cSpin[i].SetContinue(&amp;((CTaskingView*)pView)-&gt;m_bThread1);</PRE></BLOCKQUOTE><PRE></PRE><BLOCKQUOTE>	<P>In this statement, you take the pointer to the view object, pView, which is a	pointer for a CView object, and cast it as a pointer to the specific view class that	you have created in your application:	<PRE>(CTaskingView*)pView</PRE></BLOCKQUOTE><PRE></PRE><BLOCKQUOTE>	<P>Now that you can treat the pointer to the view object as a CTaskingView object,	you can get to the check box variable, m_bThread1, which is a public member of the	CTaskingView class:	<PRE>((CTaskingView*)pView)-&gt;m_bThread1</PRE></BLOCKQUOTE><PRE></PRE><BLOCKQUOTE>	<P>Once you access the m_bThread1 variable, get the address of this variable by placing	an ampersand in front of this whole string:	<PRE>&amp;((CTaskingView*)pView)-&gt;m_bThread1</PRE></BLOCKQUOTE><PRE></PRE><BLOCKQUOTE>	<P>Passing this address for the m_bThread1 variable to the SetContinue function,	you are, in effect, passing a pointer to the m_bThread1 variable, which can be used	to set the pointer to this variable that the spinner object contains.<HR></BLOCKQUOTE><P>Now that you've created the routines to initialize all the spinners, make surethat this routine is called when the application is started. The best place to putthis logic is the OnNewDocument function in the document class. This function willbe called when the application is started, so it is a logical place to trigger theinitialization of the spinner objects. To add this code to the OnNewDocument function,add the code in Listing 18.9 to the OnNewDocument function in the document class.</P><P><PRE><B>Listing 18.9. </B>The CTASKINGDOC ONNEWDOCUMENT function.  1: BOOL CTaskingDoc::OnNewDocument() 2: { 3:     if (!CDocument::OnNewDocument()) 4:         return FALSE; 5:  6:     // TODO: add reinitialization code here 7:     // (SDI documents will reuse this document) 8:  9:     ///////////////////////10:     // MY CODE STARTS HERE11:     ///////////////////////12: 13:     // Initialize the spinners14:     InitSpinners();15: 16:     ///////////////////////17:     // MY CODE ENDS HERE18:     ///////////////////////19: 20:     return TRUE;21: }</PRE><H4>Spinning the Spinner</H4><P>Once last thing that you'll add to the document class for now is a means of callingthe Draw function for a specific spinner from outside the document class. Becausethe array of spinners was declared as a private variable, no outside objects canget access to the spinners, so you need to add access for the outside objects. Youcan add a function to provide this access by adding a new member function to yourdocument class. Specify the function type as void, specify the function declarationwith a name and a single integer argument for the spinner number, such as DoSpin(intnIndex), and then specify the function's access as public. Once you have added thefunction, you can add the code in Listing 18.10 to the function to perform the actualcall to the specified spinner.</P><P><H4>LISTING 18.10. THE CTaskingDoc DoSpin FUNCTION.</H4><PRE>1: void CTaskingDoc::DoSpin(int nIndex)2: {3:     // Spin the Spinner4:     m_cSpin[nIndex].Draw();5: }</PRE><H3><A NAME="Heading9"></A>Adding the OnIdle Tasks</H3><P>Now that you have the supporting functionality in place, it's time to turn yourattention to adding the various threads that will turn the various spinners. Thefirst threads to add are the ones executing while the application is idle. You'lladd a clicked event handler for the two On Idle check boxes so that you can keepthe variables for these two check boxes in sync with the window. You'll also addthe code to the application's OnIdle function to run these two spinners when theapplication is idle and the check boxes for these two spinner threads are checked.</P><BLOCKQUOTE>	<P><HR><STRONG>NOTE:</STRONG> The use of the term <I>thread</I> in the preceding is slightly misleading.	Any functionality that you place in the OnIdle function is running in the main application	thread. All the OnIdle processing that you add to the sample application won't be	running as an independent thread, but will be just functions that can be called from	the main thread.<HR></BLOCKQUOTE><H4>Starting and Stopping the OnIdle Tasks</H4><P>The OnIdle function will check the values of the two check box variables thatspecify whether each should run, so all your application needs to do when eitherof these check boxes is clicked is make sure that the variables in the view objectare synchronized with the controls on the window. All that you need to do to accomplishthis is call the UpdateData function when either of these controls is clicked. Youneed to be able to start and stop the OnIdle tasks by adding a single event handlerfor both of the On Idle Thread check boxes and then calling the UpdateData functionin this event function.</P><P>To add this to your application, open the Class Wizard and select the view class(in this case, CTaskingView). Select one of the On Idle check boxes and add a functionfor the BN_CLICKED event. Change the name of the suggested function to OnCbonidleand click OK. Do the same thing for the other On Idle check box. Once you specifythat both of these events use the same code, click on the Edit Code button and addthe code in Listing 18.11.</P><P><H4>LISTING 18.11. THE CTaskingView OnCbonidle FUNCTION.</H4><PRE> 1: void CTaskingView::OnCbonidle() 2: { 3:     // TODO: Add your control notification handler code here 4:  5:     /////////////////////// 6:     // MY CODE STARTS HERE 7:     /////////////////////// 8:  9:     // Sync the variables with the dialog10:     UpdateData(TRUE);11: 12:     ///////////////////////13:     // MY CODE ENDS HERE14:     ///////////////////////15: }</PRE><H4>Building the OnIdle Threads</H4><P>If you examine the application class (CTaskingApp) source code, you'll find thatthe OnIdle function isn't there. All the functionality that the OnIdle function needsto perform by default is in the ancestor class of the application class that wascreated for your project. The only reason to have an OnIdle function in your applicationclass is that your application needs some specific functionality to be performedduring this event. As a result, you need to specifically add this event handler toyour application using the Class Wizard.</P><P>Once you add the OnIdle function to your application class, what does it needto do? First, it needs to get a pointer to the view so that it can check the statusof the check box variables. Next, it needs to get a pointer to the document classso that it can call the DoSpin function to trigger the appropriate spinner object.The key to both of these actions is getting pointers to each of these objects. Whenyou begin looking at what is necessary to get these pointers, you'll find that youhave to reverse the order in which you get the pointers. You need to get a pointerto the document object in order to get a pointer to the view. However, to get a pointerto the document, you have to go through the document template, getting a pointerto the template before you can get a pointer to the document. Each of these stepsrequires the same sequence of events, first getting the position of the first objectand then getting a pointer to the object in that position. What you'll do is getthe position of the first document template and then get a pointer to the documenttemplate in that position. Next, you'll use the document template to get the positionof the first document and then use the document template to get a pointer to thedocument in that first position. Finally, you'll use the document to get the positionof the first view and then use the document again to get a pointer to the view inthe position specified. Once you've got a pointer to the view, you can check thevalue of the check boxes and call the appropriate spinner.</P><P>To add this functionality to your application, use the Class Wizard to add a functionto the OnIdle event message for the application class (in this case, CTaskingApp).Once you add the function, click the Edit Code button and add the code in Listing18.12.</P><P><H4>LISTING 18.12. THE CTaskingApp OnIdle FUNCTION.</H4><PRE> 1: BOOL CTaskingApp::OnIdle(LONG lCount) 2: { 3:     // TODO: Add your specialized code here and/or call the base class 4: </PRE><PRE> 5:     // Get the position of the first document template</PRE><PRE> 6:     POSITION pos = GetFirstDocTemplatePosition(); 7:     // Do we have a valid template position? 8:     if (pos) 9:     {10:         // Get a pointer to the document template11:         CDocTemplate* pDocTemp = GetNextDocTemplate(pos);12:         // Do we have a valid pointer?13:         if (pDocTemp)14:         {15:             // Get the position of the first document16:             POSITION dPos = pDocTemp-&gt;GetFirstDocPosition();17:             // Do we have a valid document position?18:             if (dPos)19:             {20:                 // Get a pointer to the document21:                 CTaskingDoc* pDocWnd =22:                     (CTaskingDoc*)pDocTemp-&gt;GetNextDoc(dPos);23:                 // Do we have a valid pointer?24:                 if (pDocWnd)25:                 {26:                     // Get the position of the view27:                     POSITION vPos = pDocWnd-&gt;GetFirstViewPosition();28:                     // Do we have a valid view position?29:                     if (vPos)30:                     {31:                         // Get a pointer to the view32:                         CTaskingView* pView =      

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -