程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> vc教程 >> VC++深入詳解:MFC框架窗口(2)

VC++深入詳解:MFC框架窗口(2)

編輯:vc教程

  2.創建窗口

  按照Win32程序編寫步驟,設計窗口類並注冊窗口類之後,應該是創建窗口了。在MFC程序中,窗口的創建功能是由CWnd類的CreateEx函數實現的,該函數的聲明位於AFXWin.h文件中,具體代碼如下所示。

  BOOL CreateEx(DWord dwExStyle, LPCTSTR lpszClassName,
    LPCTSTR lpszWindowName, DWord dwStyle,
    int x, int y, int nWidth, int nHeight,
    HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam = NULL);

  其實現代碼位於WINCORE.CPP文件中,部分代碼如例3-14所示。

  例3-14

  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 common create parameters
    CREATESTRUCT cs;
    cs.dwExStyle = dwExStyle;
    cs.lpszClass = lpszClassName;
    cs.lpszName = lpszWindowName;
    cs.style = dwStyle;
  ……
    if (!PreCreateWindow(cs))
    {
      PostNcDestroy();
      return FALSE;
    }
   
    AfxHookWindowCreate(this);
    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);
  ……
  }

  CFrameWnd類的Create函數的聲明也位於AFXWin.h文件中,具體代碼如下所示。
  BOOL Create(LPCTSTR lpszClassName,
        LPCTSTR lpszWindowName,
        DWord dwStyle = WS_OVERLAPPEDWINDOW,

const RECT& rect = rectDefault,
        CWnd* pParentWnd = NULL,    // != NULL for popups
        LPCTSTR lpszMenuName = NULL,
        DWord dwExStyle = 0,
        CCreateContext* pContext = NULL);

  其定義位於在WINFRM.CPP文件中,部分代碼如例3-15所示。

  例3-15

  BOOL CFrameWnd::Create(LPCTSTR lpszClassName,
    LPCTSTR lpszWindowName,
    DWord dwStyle,
    const RECT& rect,
    CWnd* pParentWnd,
    LPCTSTR lpszMenuName,
    DWord dwExStyle,
    CCreateContext* pContext)
  {
  ……
    if (!CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,
      rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
      pParentWnd->GetSafeHwnd(), hMenu, (LPVOID)pContext))
    {
      TRACE0("Warning: failed to create CFrameWnd.n");
      if (hMenu != NULL)
        DestroyMenu(hMenu);
      return FALSE;
    }
  ……
  }

  CFrameWnd類派生於CWnd類。從上述聲明代碼可知,CWnd類的CreateEx函數不是虛函數。另外,CFrameWnd類中也沒有重寫這個函數。根據類的繼承性原理,CFrameWnd類就繼承了CWnd類的CreateEx函數。因此,例3-15所示CFrameWnd類的Create函數內調用的實際上就是CWnd類的CreateEx函數。讀者可以在這兩個函數的定義處都設置斷點,然後調試運行Test程序以驗證這一點。

  再回到例3-14所示CWnd類的CreateEx函數實現代碼中,可以發現該函數中又調用了PreCreateWindow函數,後者是一個虛函數。因此,這裡實際上調用的是子類,即CMainFrame類的PreCreateWindow函數。之所以在這裡再次調用這個函數,主要是為了在產生窗口之前讓程序員有機會修改窗口外觀,例如,去掉窗口的最大化按鈕等,PreCreateWindow函數的參數就是為了實現這個功能而提供的。該參數的類型是CREATETRUCT結構,我們可以把這個結構體與CreateWindowEx函數的參數作一個比較,圖3.19是CREATETRUCT結構和CreateWindowEx函數聲明的一個對比,注意左邊結構體成員與右邊函數參數的對應關系。

  

圖3.19 CREATETRUCT結構和CreateWindowEx函數定義的對比

  可以發現,CREATETRUCT結構體中的字段與CreateWindowEx函數的參數是一致的,只是先後順序相反而已。同時,可以看到PreCreateWindow函數的這個參數是引用類型。這樣,在子類中對此參數所做的修改,在其基類中是可以體現出來的。再看看前面例3-14所示CWnd類的CreateEx函數代碼,如果在子類的PreCreateWindow函數中修改了CREATESTRUCT結構體的值,那麼,接下來調用CreateWindowEx函數時,其參數就會發生相應的改變,從而就會創建一個符合我們要求的窗口。


  知識點 MFC中後綴名為Ex的函數都是擴展函數。

  3.顯示窗口和更新窗口

  在Test程序的應用程序類(CTestApp)中有一個名為m_pMainWnd的成員變量。該變量是一個CWnd類型的指針,它保存了應用程序框架窗口對象的指針。也就是說,是指向CMainFrame對象的指針。在CTestApp類的InitInstance函數實現內部有如下兩句代碼。

  // The one and only window has been initialized, so show and update it.
  m_pMainWnd->ShowWindow(SW_SHOW);
  m_pMainWnd->UpdateWindow();

  這兩行代碼的功能是顯示應用程序框架窗口和更新這個窗口。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved