八宝书库 > 文学其他电子书 > 深入浅出MFC第2版(PDF格式) >

第83部分

深入浅出MFC第2版(PDF格式)-第83部分

小说: 深入浅出MFC第2版(PDF格式) 字数: 每页4000字

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!



                nCount = 0; 



                其实是: 



                this…》nCount = 0; 



                基于相同的道理,上例中的EnumObjectsProc  既然是一个成员函数,C++ 编译器也 



                会为它多准备一个隐藏参数。 



                好,问题就出在这个隐藏参数。callback 函数是给Windows 调用用的,Windows 并 



                不经由任何对象调用这个函数,也就无由传递this 指针给callback 函数,于是导至 



                堆栈中有一个随机变量会成为this 指针,而其结果当然是程序的崩溃了。 



                要把某个函数用作callback 函数,就必须告诉C++ 编译器,不要放this 指针作为 



                该函数的最后一个参数。两个方法可以做到这一点: 



                1。 不要使用类别的成员函数(也就是说,要使用全域函数)做为callback 函数。 



                2。 使用static 成员函数。也就是在函数前面加上static 修饰词。 



                第一种作法相当于在C 语言中使用callback 函数。第二种作法比较接近OO  的精神。 



                我想更进一步提醒你的是,C++  中的static 成员函数特性是,即使对象还没有产生, 



                static 成员也已经存在(函数或变量都如此) 。换句话说对象还没有产生之前你已经 



                可以调用类别的static 函数或使用类别的static 变量了。请参阅第二章。 



                也就是说,凡声明为static 的东西(不管函数或变量)都并不和对象结合在一起, 



                它们是类别的一部份,不属于对象。 



402 


…………………………………………………………Page 465……………………………………………………………

                                                            第6章    MFC 程式的生死因果 



空闲时间(idle time)的处理:OnIdle 



        为了让Hello 程序更具体而微地表现一个MFC 应用程序的水准,我打算为它加上空闲 



        时间(idle time )的处理。 



        我已经在第1章介绍过了空闲时间,也简介了Win32 程序如何以PeekMessage                       「偷闲」。 



        Microsoft 业已把这个观念落实到CWinApp  (不,应该是CWinThread)中。请你回头看 



        看本章的稍早的「CWinApp::Run 程序生命的活水源头」一节,那一节已经揭露了MFC 



        消息循环的秘密: 



        int CWinThread::Run() 

         { 

            。。。 

            for (;;) 

            { 

                while (bIdle && 

                        !::PeekMessage(&m_msgCur; NULL; NULL; NULL; PM_NOREMOVE)) 

                { 

                    // call OnIdle while in bIdle state 

                    if (!OnIdle(lIdleCount++)) 

                        bIdle = FALSE; // assume 〃no idle〃 state 

                } 

                。。。 // msg loop 

            } 

         } 



        CThread::OnIdle 做些什么事情呢?CWinApp 改写了OnIdle  函数,CWinApp::OnIdle 又 



       做些什么事情呢?你可以从THRDCORE。CPP 和APPCORE。CPP  中找到这两个函数的 



       源代码,源代码可以说明一切。当然基本上我们可以猜测OnIdle  函数中大概是做一些 



        系统(指的是MFC 本身)的维护工作。这一部份的功能可以说日趋式微,因为低优先 



       权的执行线程可以替代其角色。 



        如果你的MFC 程序也想处理idle time,只要改写CWinApp 衍生类别的OnIdle  函数即 



        可。这个函数的类型如下: 



              virtual BOOL OnIdle(LONG lCount); 



                                                                                         403 


…………………………………………………………Page 466……………………………………………………………

                  第篇    湷觥 FC  程式設計 



                   lCount 是系统传进来的一个值,表示自从上次有消息进来,到现在,OnIdle  已经被调用 



                   了多少次。稍后我将改写Hello 程序,把这个值输出到窗口上,你就可以知道空闲时间 



                   是多么地频繁。lCount 会持续累增,直到CWinThread::Run  的消息循环又获得了一个讯 



                   息,此值才重置为0 。 



                   注意:Jeff Prosise 在他的Programming Windows 95 with MFC 一书第7章谈到OnIdle 



                   函数时,曾经说过有几个消息并不会重置lCount 为0,包括鼠标消息、WM_SYSTIMER 、 



                   WM_PAINT 。不过根据我实测的结果,至少鼠标消息是会的。稍后你可在新版的Hello 程 



                   序移动鼠标,看看lCount 会不会重设为0 。 



                  我如何改写Hello 呢?下面是几个步骤: 



                  1。 在CMyWinApp 中增加OnIdle 函数的声明: 



                      class CMyWinApp : public CWinApp 

                      { 

                     public: 

                      virtual BOOL InitInstance(); // 每一个应用程序都应该改写此函数 



                      virtual BOOL OnIdle(LONG lCount); // OnIdle 用来处理空闲时间(idle time) 

                      }; 



                   2。 在CMyFrameWnd 中增加一个IdleTimeHandler  函数声明。这么做是因为我希 



                   望在窗口中显示lCount 值, 所以最好的作法就是在OnIdle 中调用 



                   CMyFrameWnd 成员函数,这样才容易获得绘图所需的DC 。 



                      class CMyFrameWnd : public CFrameWnd 

                      { 

                     public: 

                        CMyFrameWnd();            // constructor 

                        afx_msg void OnPaint();   // for WM_PAINT 

                        afx_msg void OnAbout();   // for WM_MAND  (IDM_ABOUT) 

                        void IdleTimeHandler(LONG lCount);  // we want it call by CMyWinApp::OnIdle 

                        。。。 

                      }; 



                    3。 在HELLO。CPP  中定义CMyWinApp::OnIdle 函数如下: 



404 


…………………………………………………………Page 467……………………………………………………………

                                                 第6章    MFC 程式的生死因果 



 BOOL CMyWinApp::OnIdle(LONG lCount) 

 { 

    CMyFrameWnd* pWnd = (CMyFrameWnd*)m_pMainWnd; 

    pWnd…》IdleTimeHandler(lCount); 



    return TRUE; 

 } 



4。 在HELLO。CPP  中定义CMyFrameWnd::IdleTimeHandler  函数如下: 



 void CMyFrameWnd::IdleTimeHandler(LONG lCount) 

 { 

   CString str; 

   CRect rect(10;10;200;30); 

   CDC* pDC = new CClientDC(this); 



   str。Format(〃%010d〃; lCount); 

   pDC…》DrawText(str; ▭ DT_LEFT | DT_TOP); 

 } 



为了输出lCount,我又动用了三个MFC 类别:CString、CRect 和CDC。前两者非常 



简单,只是字符串与四方形结构的一层C++ 包装而且,后者是在Windows 系统中绘图所 



必须的DC     (Device Context )的一个包装。 



新版Hello 执行结果如下。左上角的lCount  以飞快的速度更迭。移动鼠标看看,看 



lCount 会不会重置为0 。 



                                                                              405 


…………………………………………………………Page 468……………………………………………………………

                    第篇    湷觥 FC  程式設計 



              Dialog 与 Control 



                    回忆SDK 程序中的对话框作法:RC 文件中要准备一个对话框的Template,C 程序中要 



                   设计一个对话框函数。MFC 提供的CDialog 已经把对话框的窗口函数设计好了,因此 



                   在MFC 程序中使用对话框非常地简单: 



                                                                            WM_MAND 

                                                                            (IDM_ABOUT) 

                                                    HELLO。CPP 



                                                    void CMyFrameWnd::OnAbout() 

                                                    { 

                                                       CDialog about(〃AboutBox〃; this); 

                                                       about。DoModal(); 

                                                    } 



                                                                              HELLO。RC 



                     AboutBox DIALOG DISCARDABLE  34; 22; 147; 55 

                     STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU 

                     CAPTION 〃About Hello〃 

                     { 

                       ICON          〃JJHouRIcon〃;IDC_STATIC;11;17;18;20 

                       LTEXT         〃Hello MFC 4。0〃;IDC_STATIC;40;10;52;8 

                       LTEXT         〃Copyright 1996 Top Studio〃;IDC_STATIC;40;25;100;8 

                       LTEXT         〃J。J。Hou〃;IDC_STATIC;40;40;100;8 

                       DEFPUSHBUTTON 〃OK〃;IDOK;105;7;32;14;WS_GROUP 

                     } 



                    当使用者按下【File/About  】菜单, 根据Message Map 的设定,WM_MAND 



                     (IDM_ABOUT )被送到OnAbout 函数去。我们首先在OnAbout 中产生一个CDialog 物 



                   件,名为about 。CDialog 构造式容许两个参数,第一个参数是对话框的模板资源,第二 



                   个参数是about 对象的主人。由于我们的〃About〃 对话框是如此地简单,不需要改写 



                    CDialog 中的对话框函数,所以接下来直接调用CDialog::DoModal ,对话框就开始运作 



                    了。 



406 


…………………………………………………………Page 469……………………………………………………………

                                                                         第6章    MFC 程式的生死因果 



通用对话框(mon Dialogs) 



       有些对话框,例如【File Open 】或【Save As】对话框,出现在每一个程序中的频率是如 



       此之高,使微软公司不得不面对此一事实。于是,自从Windows 3。1 之后,Windows API 



        多了一组通用对话框( mon Dialogs  ) API  函数, 系统也多了一个对应的 



       MDLG。DLL          (32 位版则为DLG32。DLL )。 



        MFC 也支持通用对话框,下面是其类别与其类型: 



        类别                                     类型 



        CmonDialog                                          以下各类别的父类别 



        CFileDialog                                                 File 对话框(Open 或Save As ) 



        CPrintDialog                                               Print 对话框 



        CFindReplaceDialog                                    Find and Replace 对话框 



        CColorDialog                                               Color  对话框 



        CFontDialog                                                Font 对话框 



        CPageSetupDialog                                       Page Setup 对话框(MFC 4。0 新增) 



        COleDialog                                               

返回目录 上一页 下一页 回到顶部 0 0

你可能喜欢的