vc++之cwnd

既然窗口操作是Windows編程的核心內容,那麼窗口基類CWnd在MFC類結構中的核心地位就無可爭議了。它派生於CCmdTarget類,是最基本的GUI對象。我們在屏幕上看到的一切對象都與窗口有關,它們或者派生於CWnd,屬繼承關係,如對話框、工具欄、狀態欄、子控件;或者被CWnd合成,屬服務員與服務對象的關係,如圖標、菜單、顯示設備。

  窗口類CWnd與Windows操作系統管理是顯示(或隱藏)給用戶的,作爲應用程序的一種表現形式的窗口是兩個概念。前者通過一個窗口句柄操作後者,不同的操作被封裝爲不同的成員函數。而後者,操作系統爲其開闢了一個內存區,存儲一個數據結構,進行管理。後者包括窗口風格、窗口類、當前狀態等信息。

  其實我們可以理解,CWnd是MFC中所有組件對象的父類,GetDlgItem()可以通過組件的ID號得到組件對象的地址,這裏是以父類指針CWnd*返回,如果需要使用可以強轉,CWnd類封裝的窗口操作主要包括窗口的創建和銷燬、操作窗口風格、操作窗口狀態、窗口子類化、獲取指定窗口等。除窗口操作外,CWnd類還實現以下功能。

繪製窗口

  通過取得窗口的顯示設備上下文,控制窗口的繪製。主要成員函數如下。

  ■ GetDC():取得客戶區顯示設備上下文。

  ■ GetWindowDC():取得整個窗口的顯示設備上下文。

  ■ ReleaseDC(): 釋放設備上下文。

  ■ BeginPaint():準備繪製客戶區。

  ■ EndPaint():結束繪製客戶區。

  ■ PrintClient():繪製或打印客戶區。

  ■ RedrawWindow():重畫客戶區的某區域。

操作窗口子控件

  操作子控件的成員函數如下。

  ■ GetDlgItem():取得(臨時的)控件對象指針。

  ■ SetDlgItemText()和GetDlgItemText():設置(取得)控件標題。

  ■ SubclassDlgItem():將控件句柄與相應類對象關聯。

  ■ DlgDirList()和DlgDirListComboBox():以文件列表或目錄列表填充(組合框)列表框。

  ■ CheckDlgButton()和CheckRadioButton():設置複選框(單選按鈕)狀態。

  ■ GetNextDlgTabItem():取得下一個WS_TABSTOP風格的控件。

窗口定時器

  可以爲窗口定時器事件設置定時器或銷燬定時器。

  ■ SetTimer():設置定時器。

  ■ KillTimer():銷燬定時器。

窗口消息的相關函數

  進行窗口消息處理的函數如下。

  ■ GetCurrentMessage():取得當前被處理的消息。

  ■ PreTranslateMessage():可重載的虛函數。被UI線程的消息循環調用,可以過濾窗口收到的消息,過濾出的消息得以分發。

  ■ SendMessage() :向本窗口發送消息。不通過消息循環,直接調用窗口函數處理消息。窗口函數執行完畢,該函數才返回。

  ■ PostMessage():向本窗口寄送消息。將消息放入消息隊列,立即返回。

  ■ Default():爲所有的窗口消息提供默認處理。對無需處理的消息或希望默認處理的消息,可以使用Default()。

默認的消息處理函數

  前面介紹了消息的默認處理函數Default(),該函數一般要調用一個默認的窗口過程,對當前消息執行默認的系統級處理。例如對於窗口的WM_LBUTTONDOWN消息,默認處理函數要爲該窗口設置焦點。對於許多消息,執行這種默認的處理是完全必要的。這樣,程序員只需在消息到來之際執行相關的用戶級處理,對這些消息的系統級處理不必關心。所以,在一個消息處理函數中,如果允許當前消息正常執行,最終就應該調用默認處理函數Default()。例如,下面要控制一個CEdit控件的接收字符集,不允許輸入0~9的數字,並將輸入的小寫字母轉換爲大寫字母。程序如下:

  //class CEditnew :public CEdit

  void CEditnew::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)

  {

  TRACE("%c/n",nChar);

  if(nChar>=''0'' && nChar<=''9'')

  return; //過濾掉當前消息

  if(nChar>=''a'' && nChar<=''z'')

  {

  nChar-=32;

  LPARAM lpara=nFlags<<16|nRepCnt;

  //更改消息參數,重新執行該消息處理函數

  SendMessage(WM_CHAR,(WPARAM)nChar,lpara);

  return;

  }

  //執行默認的處理過程,將當前字符追加到控件的文本中

  Default();

  }

  然而,在實際的編程中,很少直接調用Default(),更多是調用基類的消息處理函數。例如在上例中,以 CEdit::OnChar(nChar, nRepCnt, nFlags);

  代替Default()要更合理。因爲針對大部分消息,CWnd類已經定義了相應的處理函數,封裝對Default()的調用。例如,針對WM_CHAR消息的處理函數這樣定義:

  void CWnd::OnChar(UINT, UINT, UINT)

  { Default(); }

  同時,對於一些特殊的消息,僅執行系統級的處理是不夠的,框架必須針對消息完成一些例行的操作。例如,收到WM_SYSCOLORCHANGE消息後,要將系統顏色的變化通知所有子窗口;收到WM_NCDESTROY消息,要做必要的清理工作,並使MFC窗口對象與已經關閉的窗口分離。針對這些消息,CWnd類也定義了相應的處理函數,封裝框架的例行處理。下面是針對WM_SYSCOLORCHANGE消息的處理函數。

  void CWnd::OnSysColorChange()

  {

  CWinApp* pApp = AfxGetApp();

  if (pApp != NULL && pApp->m_pMainWnd == this)

  {

  //調整主窗口的控制條(工具條、狀態條等)顏色

  afxData.UpdateSysColors();

  }

  #ifndef _AFX_NO_CTL3D_SUPPORT

  if (!afxContextIsDLL)

  {

  if (AfxGetThread() != NULL && AfxGetThread()->m_pMainWnd == this)

  {

  _AFX_CTL3D_STATE* pCtl3dState = _afxCtl3dState;

  //調整3D顯示

  if (pCtl3dState->m_pfnColorChange != NULL)

  (*pCtl3dState->m_pfnColorChange)();

  }

  }

  #endif

  //通知所有的子窗口

  if (!(GetStyle() & WS_CHILD))

  SendMessageToDescendants(WM_SYSCOLORCHANGE, 0, 0L, TRUE, TRUE);

  //最後執行默認處理

  Default();

  }

發佈了16 篇原創文章 · 獲贊 1 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章