友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
第三电子书 返回本书目录 加入书签 我的书架 我的书签 TXT全本下载 『收藏到我的浏览器』

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

快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!


#define AFX_WNDMDIFRAME           AFX_WNDCLASS(〃MDIFrame〃) 

#define AFX_WNDFRAMEORVIEW        AFX_WNDCLASS(〃FrameOrView〃) 

#define AFX_WNDOLECONTROL         AFX_WNDCLASS(〃OleControl〃) 



                                                                               383 


…………………………………………………………Page 446……………………………………………………………

                    第篇    湷觥 FC  程式設計 



                    所以,如果在Windows 95         (non…Unicode )中使用MFC 动态联结版和除错版,五个窗口 



                    类别的名称将是: 



                        〃AfxWnd42d〃 

                        〃AfxControlBar42d〃 

                        〃AfxMDIFrame42d〃 

                        〃AfxFrameOrView42d〃 

                        〃AfxOleControl42d〃 



                    如果在Windows NT      (Unicode 环境)中使用MFC 静态联结版和除错版,五个窗口类 



                    别的名称将是: 



                        〃AfxWnd42sud〃 

                        〃AfxControlBar42sud〃 

                        〃AfxMDIFrame42sud〃 

                        〃AfxFrameOrView42sud〃 

                        〃AfxOleControl42sud〃 



                    这五个窗口类别的使用时机为何?稍后再来一探究竟。 



                    让我们再回顾AfxEndDeferRegisterClass  的动作。它调用两个函数完成实际的窗口类别注 



                    册动作,一个是RegisterWithIcon ,一个是AfxRegisterClass : 



                    static BOOL AFXAPI RegisterWithIcon (WNDCLASS* pWndCls; 

                            LPCTSTR lpszClassName; UINT nIDIcon) 

                    { 

                        pWndCls…》lpszClassName = lpszClassName; 

                        HINSTANCE hInst = AfxFindResourceHandle( 

                                MAKEINTRESOURCE(nIDIcon); RT_GROUP_ICON); 

                        if ((pWndCls…》hIcon = ::LoadIcon(hInst; MAKEINTRESOURCE(nIDIcon))) == NULL) 

                        { 

                            // use default icon 

                            pWndCls…》hIcon = ::LoadIcon(NULL; IDI_APPLICATION); 

                        } 

                        return AfxRegisterClass (pWndCls); 

                    } 



                    BOOL AFXAPI AfxRegisterClass (WNDCLASS* lpWndClass) 

                    { 

                        WNDCLASS wndcls; 



384 


…………………………………………………………Page 447……………………………………………………………

                                                         第6章    MFC 程式的生死因果 



    if (GetClassInfo(lpWndClass…》hInstance; 

                         lpWndClass…》lpszClassName; &wndcls)) 

    { 

        // class already registered 

        return TRUE; 

    } 



    ::RegisterClass(lpWndClass); 

    。。。 

    return TRUE; 

} 



注意,不同类别的PreCreateWindow 成员函数都是在窗口产生之前一刻被调用,准备用 



来注册窗口类别。如果我们指定的窗口类别是NULL ,那么就使用系统预设类别。从CWnd 



及其各个衍生类别的PreCreateWindow 成员函数可以看出,整个Framework 针对不同功 



能的窗口使用了哪些窗口类别: 



// in WINCORE。CPP 

BOOL CWnd::PreCreateWindow(CREATESTRUCT& cs) 

{ 



    { 

        AfxDeferRegisterClass(AFX_WND_REG); 

        。。。 

        cs。lpszClass = _afxWnd;            (这表示CWnd 使用的窗口类别是_afxWnd) 

    } 

    return TRUE; 

} 



// in WINFRM。CPP 

BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs) 

{ 

    if (cs。lpszClass == NULL) 

    { 

        AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG); 

        。。。 

        cs。lpszClass = _afxWndFrameOrView;         (这表示CFrameWnd 使用的窗口 

    }                                           

                                               类别是_afxWndFrameOrView) 

    。。。 

} 



// in WINMDI。CPP 

BOOL CMDIFrameWnd::PreCreateWindow(CREATESTRUCT& cs) 



                                                                                         385 


…………………………………………………………Page 448……………………………………………………………

                    第篇    湷觥 FC  程式設計 



                    { 

                        if (cs。lpszClass == NULL) 

                        { 

                            AfxDeferRegisterClass(AFX_WNDMDIFRAME_REG); 

                            。。。 

                            cs。lpszClass = _afxWndMDIFrame;           (这表示CMDIFrameWnd 使用的窗口 

                                                                   类别是_afxWndMDIFrame) 

                        }                                         

                        return TRUE; 

                    } 



                    // in WINMDI。CPP 

                    BOOL CMDIChildWnd::PreCreateWindow(CREATESTRUCT& cs) 

                    { 

                        。。。 

                        return CFrameWnd::PreCreateWindow(cs);   (这表示CMDIChildWnd 使用的窗口 

                                                                     类别是    类别是    类别是_afxWndFrameOrView) 

                    }                                                 



                    // in VIEWCORE。CPP 

                    BOOL CView::PreCreateWindow(CREATESTRUCT & cs) 

                    { 

                        if (cs。lpszClass == NULL) 

                        { 

                            AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG); 

                            。。。                                             

                            cs。lpszClass = _afxWndFrameOrView;          (这表示CView 使用的窗口 

                        }                                                类别是_afxWndFrameOrView) 

                        。。。 

                    } 



                    题外话:「Create 是一个比较粗糙的函数,不提供我们对图标(icon )或鼠标光标的设定, 



                    所以在Create 函数中我们看不到相关参数」。这样的说法对吗?虽然「不能够让我们指 



                    定窗口图标以及鼠标光标」是事实,但这本来就与Create 无关。回忆SDK 程序,指定 



                    图标和光标形状实为RegisterClass  的责任而非CreateWindow 的责任! 



                     MFC 程序的RegisterClass 动作并非由程序员自己来做,因此似乎难以改变图标。不过, 



                     MFC 还是开放了一个窗口,我们可以在HELLO。RC 这么设定图标: 



                          AFX_IDI_STD_FRAME ICON DISCARDABLE 〃HELLO。ICO〃 



                     你可以从AfxEndDeferRegisterClass  的第55 行看出,当它调用RegisterWithIcon  时,指 



                     定的icon 正是AFX_IDI_STD_FRAME。 



386 


…………………………………………………………Page 449……………………………………………………………

                                                     第6章    MFC 程式的生死因果 



        鼠标光标的设定就比较麻烦了。要改变光标形状,我们必须调用AfxRegisterWndClass               (其 



        中有! ¨ Cursor! ¨  参数)注册自己的窗口类别;然后再将其传回值(一个字符串)做为Create 



        的第一个参数。 



奇怪的窗口类别名称 Afx:b:14ae:6:3e8f 



        当应用程序调用CFrameWnd::Create  (或CMDIFrameWnd::LoadFrame,第7章)准备产 



        生窗口时,MFC 才会在Create 或LoadFrame  内部所调用的PreCreateWindow 虚拟函 



        式中为你产生适当的窗口类别。你已经在上一节看到了,这些窗口类别的名称分别是(假 



        设在Win95  中使用MFC 4。2 动态联结版和除错版): 



             〃AfxWnd42d〃 



             〃AfxControlBar42d〃 



             〃AfxMDIFrame42d〃 



             〃AfxFrameOrView42d〃 



             〃AfxOleControl42d〃 



        然而,当我们以Spy++     (VC++ 所附的一个工具)观察窗口类别的名称,却发现: 



        窗口类别名称怎么会变成像Afx:b:14ae:6:3e8f 这副奇怪模样呢?原来是Application 



        Framework 玩了一些把戏,它把这些窗口类别名称转换为Afx:x:y:z:w  的型式,成为独一 



        无二的窗口类别名称: 



                                                                              387 


…………………………………………………………Page 450……………………………………………………………

                   第篇    湷觥 FC  程式設計 



                          x: 窗口风格(window style )的hex  



                          y: 窗口鼠标光标的hex 值         值 



                          z: 窗口背景颜色的hex 值 



                          w: 窗口图标(icon )的hex 值 



                    如果你要使用原来的(MFC 预设的)那些个窗口类别,但又希望拥有自己定义的一个有 



                    意义的类别名称,你可以改写PreCreateWindow 虚拟函数(因为Create 和LoadFrame 



                    的内部都会调用它),在其中先利用API  函数GetClassInfo 获得该类别的一个副本, 



                    更改其类别结构中的lpszClassName 字段( 甚至更改其hIcon 字段),再以 



                   AfxRegisterClass  重新注册之,例如: 



                   #0000  #define MY_CLASSNAME  〃MyClassName〃 

                   #0001 

                   #0002  BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) 

                   #0003  { 

                   #0004       static LPCSTR className = NULL; 

                   #0005 

                   #0006       if (!CFrameWnd::PreCreateWindow(cs)) 

                   #0007           return FALSE; 

                   #0008 

                   #0009       if (className==NULL) { 

                   #0010            // One…time class registration 

                   #0011            // The only purpose is to make the class name something 

                   #0012            // meaningful instead of 〃Afx:0x4d:27:32:hup1hup:hike!〃 

                   #0013            // 

                   #0014            WNDCLASS wndcls; 

                   #0015            ::GetClassInfo(AfxGetInstanceHandle(); cs。lpszClass; &wndcls); 

                   #0016            wndcls。lpszClassName = MY_CLASSNAME; 

                   #0017            wndcls。hIcon = AfxGetApp()…》LoadIcon(IDR_MAINFRAME); 

                   #0018            VERIFY(AfxRegisterClass(&wndcls)); 

                   #0019            className=TRACEWND_CLASSNAME; 

                   #0020       } 

                   #0021       cs。lpszClass = className; 

                   #0022 

                   #0023       return TRUE; 

                   #0024  } 



                    本书附录D「以MFC 重建Debug Window            (DBWIN )」会运用到这个技巧。 



388 


…………………………………………………………Page 451……………………………………………………………

                                                               第6章    MFC 程式的生死因果 



窗口显示与更新 



                                              HELLO。CPP 



                                           1  CMyWinApp theApp;   // application object 



                                              BOOL CMyWinApp::InitInstance() 

       WINMAIN。CPP 

                                              { 

                                               5 

        int AFXAPI AfxWinMain (。。。)              m_pMainWnd = new CMyFrameWnd(); 

        {                                        m_pMainWnd…》ShowWindow(m_nCmdShow); 

                                               7 

       
返回目录 上一页 下一页 回到顶部 0 0
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!