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

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

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



#define AFX_WNDMCTLS_REG      (0x0010) 

#define AFX_WNDOLECONTROL_REG     (0x0020) 



出现在上述函数中的五个窗口类别名称,分别定义于WINCORE。CPP  中: 



const TCHAR _afxWnd'' = AFX_WND; 

const TCHAR _afxWndControlBar'' = AFX_WNDCONTROLBAR; 

const TCHAR _afxWndMDIFrame'' = AFX_WNDMDIFRAME; 

const TCHAR _afxWndFrameOrView'' = AFX_WNDFRAMEORVIEW; 

const TCHAR _afxWndOleControl'' = AFX_WNDOLECONTROL; 



而等号右手边的那些AFX_ 常数又定义于AFXIMPL。H  中: 



#ifndef _UNICODE 

#define _UNICODE_SUFFIX 

#else 

#define _UNICODE_SUFFIX _T(〃u〃) 

#endif 



#ifndef _DEBUG 

#define _DEBUG_SUFFIX 

#else 

#define _DEBUG_SUFFIX _T(〃d〃) 

#endif 



#ifdef _AFXDLL 

#define _STATIC_SUFFIX 

#else 

#define _STATIC_SUFFIX _T(〃s〃) 

#endif 



#define AFX_WNDCLASS(s)  

  _T(〃Afx〃) _T(s) _T(〃42〃) _STATIC_SUFFIX _UNICODE_SUFFIX _DEBUG_SUFFIX 



#define AFX_WND                   AFX_WNDCLASS(〃Wnd〃) 

#define AFX_WNDCONTROLBAR         AFX_WNDCLASS(〃ControlBar〃) 

#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 

           CWinApp* pApp = AfxGetApp();          m_pMainWnd…》UpdateWindow(); 

                                               8 

                                                 return TRUE; 

         2                                    } 

           AfxWinInit(。。。); 



         3                                    CMyFrameWnd::CMyFrameWnd() 

           pApp…》InitApplication(); 

           pApp…》InitInstance();              { 

         4 

                                               6 

           nReturnCode = pApp…》Run();            Create(NULL; 〃Hello MFC〃; 。。。; 

                                                        〃MainMenu〃); 

           AfxWinTerm();                      } 

        } 

                                              void CMyFrameWnd::OnPaint()  { 。。。 } 

                                              void CMyFrameWnd::OnAbout()  { 。。。 } 



                                              BEGIN_MESSAGE_MAP(CMyFrameWnd; CFrameWnd) 

                                                 ON_MAND(IDM_ABOUT; OnAbout) 

                                                 ON_WM_PAINT() 

                                              END_MESSAGE_MAP() 



       CMyFrameWnd::CMyFrameWnd 结束后, 窗口已经诞生出来; 程序流程又回到 



       CMyWinApp::InitInstance  , 于是调用ShowWindow  函数令窗口显示出来, 并调用 



       UpdateWindow 函数令Hello 程序送出WM_PAINT  消息。 



       我们很关心这个WM_PAINT  消息如何送到窗口函数的手中。而且,窗口函数又在哪里? 



       MFC 程序是不是也像SDK 程序一样,有一个GetMessage/DispatchMesage 循环?是否 



       每个窗口也都有一个窗口函数,并以某种方式进行消息的判断与处理? 



       两者都是肯定的。我们马上来寻找证据。 



                                                                                               389 


…………………………………………………………Page 452……………………………………………………………

                       第篇    湷觥 FC  程式設計 



              CWinApp::Run 程序生命的活水源头 



                                                                  HELLO。CPP 



                                                               1  CMyWinApp theApp;   // application object 

                       WINMAIN。CPP 



                                                                  BOOL CMyWinApp::InitInstance() 

                        int AFXAPI AfxWinMain (。。。) 

                                                                   { 

                        { 

                                                                   5 

                                                                     m_pMainWnd = new CMyFrameWnd(); 

                            CWinApp* pApp = AfxGetApp(); 

                                                                     m_pMainWnd…》ShowWindow(m_nCmdShow); 

                                                                   7 

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