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

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

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



                                                                       〃MainMenu〃); 

                         AfxWinTerm();                       } 

                      } 

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

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



                                                             BEGIN_MESSAGE_MAP(CMyFrameWnd; CFrameWnd) 

                                                                ON_MAND(IDM_ABOUT; OnAbout) 

                                                                ON_WM_PAINT() 

                                                             END_MESSAGE_MAP() 



                    CMyWinApp ::InitInstance 一开始new  了一个CMyFrameWnd 对象,准备用作主框窗口 



                    的C++ 对象。new 会引发构造式: 



                        CMyFrameWnd::CMyFrameWnd 

                         { 

                            Create(NULL; 〃Hello MFC〃; WS_OVERLAPPEDWINDOW; rectDefault; NULL; 

                                    〃MainMenu〃); 

                         } 



                    其中Create 是CFrameWnd 的成员函数,它将产生一个窗口。但,使用哪一个窗口类别 



                    呢? 



                    这里所谓的「窗口类别」是由RegisterClass 所注册的一份数据结构,不是C++ 类别。 



                    根据CFrameWnd::Create 的规格: 



376 


…………………………………………………………Page 439……………………………………………………………

                                                    第6章    MFC 程式的生死因果 



BOOL Create( LPCTSTR lpszClassName; 

               LPCTSTR lpszWindowName; 

               DWORD dwStyle = WS_OVERLAPPEDWINDOW; 

               const RECT& rect = rectDefault; 

               CWnd* pParentWnd = NULL; 

               LPCTSTR lpszMenuName = NULL; 

               DWORD dwExStyle = 0; 

               CCreateContext* pContext = NULL ); 



  八个参数中的后六个参数都有默认值,只有前两个参数必须指定。第一个参数 



  lpszClassName 指定WNDCLASS 窗口类别,我们放置NULL  究竟代表什么意思?意思 



  是要以MFC  内建的窗口类别产生一个标准的外框窗口。但,此时此刻Hello 程序中根 



  本不存在任何窗口类别呀!噢,Create 函数在产生窗口之前会引发窗口类别的注册动 



  作,稍后再解释。 



  第二个参数 lpszWindowName 指定窗口标题,本例指定〃Hello MFC〃。第三个参数 



  dwStyle 指定窗口风格,预设是WS_OVERLAPPEDWINDOW,也正是最常用的一种,它 



  被定义为(在WINDOWS。H 之中): 



    #define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED | WS_CAPTION | 

                                      WS_SYSMENU | WS_THICKFRAME  | 

                                      WS_MINIMIZEBOX | WS_MAXIMIZEBOX) 



  因此如果你不想要窗口右上角的极大极小钮,就得这么做: 



    Create(NULL; 

            〃Hello MFC〃; 

            WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME 

            rectDefault; 

            NULL; 

            〃MainMenu〃); 



  如果你希望窗口有垂直滚动条,就得在第三个参数上再加增WS_ VSCROLL 风格。 



  除了上述标准的窗口风格,另有所谓的扩充风格,可以在Create  的第七个参数 



  dwExStyle 指定之。扩充风格唯有以::CreateWindowEx        (而非::CreateWindow)函数才能 



  完成。事实上稍后你就会发现,CFrameWnd::Create 最终调用的正是::CreateWindowEx。 



  Windows 3。1 提供五种窗口扩充风格: 



                                                                                 377 


…………………………………………………………Page 440……………………………………………………………

                  第篇    湷觥 FC  程式設計 



                     WS_EX_DLGMODALFRAME 

                     WS_EX_NOPARENTNOTIFY 

                     WS_EX_TOPMOST 

                     WS_EX_ACCEPTFILES 

                     WS_EX_TRANSPARENT 



                   Windows 95 有更多选择,包括WS_EX_WINDOWEDGE 和WS_EX_CLIENTEDGE,让 



                   窗口更具3D 立体感。Framework  已经自动为我们指定了这两个扩充风格。 



                   Create  的第四个参数rect 指定窗口的位置与大小。默认值rectDefault 是CFrameWnd 



                   的一个static 成员变量,告诉Windows  以预设方式指定窗口位置与大小,就好象在 



                   SDK 程序中以CW_ USEDEFAULT 指定给CreateWindow 函数一样。如果你很有主见, 



                   希望窗口在特定位置有特定大小,可以这么做: 



                     Create(NULL; 

                             〃Hello MFC〃; 

                             WS_OVERLAPPEDWINDOW; 

                                                        起始位置           ,寬      ,高    ) 

                             CRect(40; 60; 240; 460);  //       (40;60)    200    400 

                             NULL; 

                             〃MainMenu〃); 



                   第五个参数pParentWnd  指定父窗口。对于一个top…level 窗口而言,此值应为NULL , 



                   表示没有父窗口(其实是有的,父窗口就是desktop 窗口)。 



                   第六个参数lpszMenuName 指定菜单。本例使用一份在RC  中准备好的菜单 



                   ! § MainMenu! ¨  。第八个参数pContext  是一个指向CCreateContext 结构的指针,framework 



                   利用它,在具备Document/View 架构的程序中初始化外框窗口(第8章的「CDocTemplate 



                    管理CDocument / CView / CFrameWnd 」一节中将谈到此一主题)。本例不具备 



                    Document/View 架构,所以不必指定pContext  参数,默认值为NULL 。 



                    前面提过,CFrameWnd::Create 在产生窗口之前,会先引发窗口类别的注册动作。让我 



                    再扮一次MFC  向导,带你寻幽访胜。你会看到MFC 为我们注册的窗口类别名称,及 



                    注册动作。 



378 


…………………………………………………………Page 441……………………………………………………………

                                                             第6章    MFC 程式的生死因果 



 WINFRM。CPP 



BOOL CFrameWnd::Create(LPCTSTR lpszClassName; 

                           LPCTSTR lpszWindowName; 

                           DWORD dwStyle; 

                           const RECT& rect; 

                           CWnd* pParentWnd; 

                           LPCTSTR lpszMenuName; 

                           DWORD dwExStyle; 

                           CCreateContext* pContext) 

{ 

    HMENU hMenu = NULL; 

    if (lpszMenuName != NULL) 

    { 

        // load in a menu that will get destroyed when window gets destroyed 

        HINSTANCE hInst = AfxFindResourceHandle(lpszMenuName; RT_MENU); 

        hMenu = ::LoadMenu(hInst; lpszMenuName); 

    } 



    m_strTitle = lpszWindowName;    // save title for later 



    CreateEx(dwExStyle; lpszClassName; lpszWindowName; dwStyle; 

          rect。left; rect。top; rect。right rect。left; rect。bottom rect。top; 

          pParentWnd…》GetSafeHwnd(); hMenu; (LPVOID)pContext); 



    return TRUE; 

} 



函数中调用CreateEx。注意,CWnd 有成员函数CreateEx,但其衍生类别CFrameWnd 并 



无,所以这里虽然调用的是CFrameWnd::CreateEx,其实乃是从父类别继承下来的 



        :: 

CWnd   CreateEx。 



 WINCORE。CPP 



BOOL CWnd::CreateEx(DWORD dwExStyle; LPCTSTR lpszClassName; 

                        LPCTSTR lpszWindowName; DWORD dwStyle; 

                        int x; int y; int nWidth; int nHeight; 

                        HWND hWndParent; HMENU nIDorHMenu; LPVOID lpParam) 

{ 

    // allow modification of several mon create parameters 

    CREATESTRUCT cs; 

    cs。dwExStyle = dwExStyle; 

    cs。lpszClass = lpszClassName; 



                                                                                                379 


…………………………………………………………Page 442……………………………………………………………

                    第篇    湷觥 FC  程式設計 



                        cs。lpszName = lpszWindowName; 

                        cs。style = dwStyle; 

                        cs。x = x; 

                        cs。y = y; 

                        cs。cx = nWidth; 

                        cs。cy = nHeight; 

                        cs。hwndParent = hWndParent; 

                        cs。hMenu = nIDorHMenu; 

                        cs。hInstance = AfxGetInstanceHandle(); 

                        cs。lpCreateParams = lpParam; 



                        PreCreateWindow(cs); 

                        AfxHookWindowCreate(this);  // 此动作将在第9章探讨。 

                        HWND hWnd = ::CreateWindowEx(cs。dwExStyle; cs。lpszClass; 

                                        cs。lpszName; cs。style; cs。x; cs。y; cs。cx; cs。cy; 

                                        cs。hwndParent; cs。hMenu; cs。hInstance; cs。lpCreateParams); 

                        。。。 

                    } 



                    函数中调用的PreCreateWindow 是虚拟函数,CWnd 和CFrameWnd 之中都有定义。由 



                    于this 指针所指对象的缘故,这里应该调用的是CFrameWnd::PreCreateWindow                       (还记 



                    得第2章我说过虚拟函数常见的那种行为模式吗?) 



                     WINFRM。CPP 



                    // CFrameWnd second phase creation 

                    BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs) 

                    { 

                        if (cs。lpszClass == NULL) 

                        { 

                            AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG); 

                            cs。lpszClass = _afxWndFrameOrView;  // COLOR_WINDOW background 

                        } 

                        。。。 

                    } 



                    其中AfxDeferRegisterClass  是一个定义于AFXIMPL。H  中的宏。 



380 


…………………………………………………………Page 443……………………………………………………………

                                                       第6章    MFC 程式的生死因果 



 AFXIMPL。H 



#define AfxDeferRegisterClass (fClass)  

  ((afxRegisteredClasses & fClass) ? TRUE : AfxEndDeferRegisterClass (fClass)) 



这个宏表示,如果变量afxRegisteredClasses  的值显示系统已经注册了fClass  这种视 



窗类别,MFC 就啥也不做;否则就调用AfxEndDeferRegisterClass(fClass),准备注册之。 



afxRegisteredClasses 定义于AFXWIN。H ,是一个旗标变量,用来记录已经注册了哪些视 



窗类别: 



// in AFXWIN。H 

#define afxRegisteredClasses  AfxGetModuleState()…》m_fRegisteredClasses 



 WINCORE。CPP : 



#0001  BOOL AFXAPI AfxEndDeferRegisterClass (short fClass) 

#0002  { 

#0003      BOOL bResult = FALSE; 

#0004 

#0005      // mon initialization 

#0006      WNDCLASS wndcls; 

#0007      memset(&wndcls; 0; sizeof(WNDCLASS));   // start with NULL defaults 

#0008      wndcls。lpfnWndProc = DefWindowProc; 

#0009      wndcls。hInstance = AfxGetInstanceHandle(); 

#0010      wndcls。hCursor = afxData。hcurArrow; 

#0011 

#0012      AFX_MODULE_STATE* pModuleState = AfxGetModuleState(); 

#0013      if (fClass & AFX_WND_REG) 

#0014      { 

#0015          // Child windows no brush; no icon; safest default class styles 

#0016          wndcls。style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; 

#0017          wndcls。lpszClassName = _afxWnd; 

#0018          bResult =  AfxRegisterClass(&wndcls); 

#0019          if (bResult) 

#0020              pModuleState…》m_fRegisteredClasses |= AFX_WND_REG; 

#0021      } 

#0022      else if (fClass & AFX_WNDOLECONTROL_REG) 

#0023      { 

#0024          // OLE Control windows use parent DC for speed 

#0025          wndcls。style |= CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; 

#0026          wndcls。lpszClassName = _afxWndOleControl; 

#0027          bResult =  AfxRegisterClass(&wndcls); 

#0028          if (bResult) 



                                                                                      381 


…………………………………………………………Page 444……………………………………………………………

                    第篇    湷觥 FC  程式設計 



                    #0029              pModuleState…》m_fRegisteredClasses |= AFX_WNDOLECONTROL_REG; 

                    #0030      } 

                    #0031      else if (fClass & AFX_WNDCONTROLBAR_REG) 

                    #0032      { 

                    #0033          // Control bar windows 

                    #0034          wndcls。style = 0;   // control bars don't handle double click 

                    #0035          wndcls。lpszClassName = _afxWndControlBar; 

                    #0036          wndcls。hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); 

                    #0037          bResult =  AfxRegisterClass(&wndcls); 

                    #0038          if (bResult) 

                    #0039              pModuleState…》m_fRegisteredClasses |= AFX_WNDCONTROLBAR_REG; 

                    #0040      } 

                    #0041      else if (fClass & AFX_WNDMDIFRAME_REG) 

                    #0042      { 

                    #0043          // MDI Frame window (also used for splitter window) 

                    #0044          wndcls。style = CS_DBLCLKS; 

                    #0045          wndcls。hbrBackground = NULL; 

                    #0046          bResult = RegisterWithIcon(&wndcls; _afxWndMDIFrame; 

                                                                    AFX_IDI_STD_MDIFRAME); 

                    #0047          if (bResult) 

                    #0048              pModuleState…》m_fRegisteredClasses |= AFX_WNDMDIFRAME_REG; 

                    #0049      } 

                    #0050      else if (fClass & AFX_WNDFRAMEORVIEW_REG) 

                    #0051      { 

                    #0052          // SDI Frame or MDI Child windows or views normal colors 

                    #0053          wndcls。style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; 

                    #0054          wndcls。hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); 

                    #0055          bResult = RegisterWithIcon(&wndcls; _afxWndFrameOrView; 

                                                                    AFX_IDI_STD_FRAME); 

                    #0056          if (bResult) 

                    #0057              pModuleState…》m_fRegisteredClasses |= AFX_WNDFRAMEORVIEW_REG; 

                    #0058      } 

                    #0059      else if (fClass & AFX_WNDMCTLS_REG) 

                    #0060      { 

                    #0061          InitmonControls(); 

                    #0062          bResult = TRUE; 

                    #0063          pModuleState…》m_fRegisteredClasses |= AFX_WNDMCTLS_REG; 

                    #0064      } 

                    #0065 

                    #0066      return bResult; 

                    #0067  } 



382 


…………………………………………………………Page 445……………………………………………………………

                                                 第6章    MFC 程式的生死因果 



出现在上述函数中的六个窗口类别卷标代码,分别定义于AFXIMPL。H  中: 



#define AFX_WND_REG               (0x0001) 

#define AFX_WNDCONTROLBAR_REG    (0x0002) 

#define AFX_WNDMDIFRAME_REG      (0x0004) 

#define AFX_WNDFRAMEORVIEW_REG  (0x0008) 

#define AFX_WNDMCTLS_REG      (0x0010) 

#define AFX_WNDOLECONTROL_REG     (0x0020) 



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