第四章:基本事件處理、映射模式和滾動視圖
1,消息映射:如在視窗中按下滑鼠做鍵,會自動發送WM_LBUTTONDOWN消息,如果要對這消息有所反應的話,需
//{{AFX_MSG(CEx04aView)
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);//頭檔案聲明消息響應函數原型。
//}}AFX_MSG
DECLARE_MESSAGE_MAP()//頭檔案
BEGIN_MESSAGE_MAP(CDrawView, CView)//代碼檔案
//{{AFX_MSG_MAP(CEx04aView)
ON_WM_LBUTTONDOWN()//該消息映射宏将OnLButtonDown函數和應用程式架構聯系在一起
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CDrawView::OnLButtonDown(UINT nFlags, CPoint point) //代碼檔案
{
//event processing code here
}
說明:
為了友善ClassWizard,AppWizard生成了一些注釋行。它把消息映射函數原型放在兩個AFX_MSG“刮弧對”之間,在AFX_MSG_MAP“刮弧對”之間添加消息映射入口,并在代碼檔案中給出完整的OnLButtonDown成員函數架構。
2,視圖中的OnDraw()是根據視圖目前狀态來繪制圖象的,使用者的操作可以改變這中狀态。在完整的MFC庫應用程式中,文檔的對象掌握在應用程式(視圖)的狀态。
3,如果用全程變量來儲存視圖狀态,這将在多視圖情況下會遇到麻煩;(待體會)
4,CWnd::InvalidateRect函數能夠觸發WM_PAINT消息,該消息被視窗類如CView映射後,引起對OnDraw函數調用,進而重繪無效矩形區域。
優化視窗的繪制過程:
1)設定的無效區域越小,重畫的速度就越快;
2)執行無效區域外的繪制純屬于浪費時間,OnDraw函數可以調用CDC的成員函數GetClipBox得到無效區域大小。
注意:
OnDraw函數不僅僅響應InValidate*之類的調用,它也會在視窗改變大小和視窗顯露時被調用。
5,本章重要介紹函數
PtInRect(..);//測試一個點是否落在某個矩形内。
PtInRegion(..);//判斷一個點是否落在橢圓(CRgn對象)内//A region is an elliptical or polygonal area within a window.
GetClientRect(..);//獲得客戶矩形坐标并保持在CRect對象中
SelectStockObject(..);//選擇the predefined stock pens, brushes, or fonts到DC中,函數傳回先前的CGdiObject 對象指針。
6,在構造函數中對類資料成員初始化。
CEx04aView::CEx04aView() : m_rectEllipse(0, 0, 200, 200)//注意這種初試化方式,m_rectEllipse是CEx04aView類資料成員CRect類對象
{
m_nColor = GRAY_BRUSH;
}
7,[緻WIN32程式員]:
标準的基于WINDOWS應用程式會首先登記一個視窗類(不同于C++類[補:實際是個_WNDCLASS結構體]),同時在處理過程中,還需要對每個類指定視窗過程(WINDOWS PROCEDURE)。每次應用程式調用CreateWindow建立一個視窗時候,都要指定一個視窗類做為參數,這樣就把建立立的視窗和視窗過程函數連接配接起來了。每次Windows給視窗發送消息時候,這個函數就會被調用(補:消息循環中DispatchMessage(&msg)分派消息到視窗的回調函數處理,OS調用視窗回調函數進行處理),以檢查用參數傳送進來的消息碼,并執行适當的代碼來處理該消息。
MFC庫應用程式架構有一個适用于大多數視窗類型的簡單視窗類和視窗過程函數。該視窗過程函數會根據參數傳進來的視窗句柄,在MFC的句柄映射表(handle map)中查找,進而得到對應的C++視窗對象指針。然後,該視窗過程函數用MFC運作時類(runtime class)系統來決定視窗對象的C++類。下一步,它從由消息分發映射函數生成的靜态表中找到消息處理函數,最後用正确的視窗對象調用消息處理函數。
8,映射模式:
1)MM_TEXT映射模式:坐标被映射到象素,X值向右遞增,Y值向下遞增。可用它來表示[裝置坐标]。
CDC::SetMapMode(..)//設定映射模式
CDC::GetMapMode(..)
CDC::SetViewportOrg(..)//設定視口原點
CDC::GetViewportOrg(..)
CDC::SetWindowOrg (..)//設定螢幕原點
CDC::GetWindowOrg(..)
2)固定比例映射模式(MM_HIENGLISH,MM_HIMETRIC ,MM_LOMETRIC ,MM_LOENGLISH,MM_TWIPS )
固定比例映射模式均X值向右遞增,Y值向下遞減,它們之間唯一差别是 實際的比例因子。如下:
MM_HIENGLISH Each logical unit is converted to 0.001 inch.
MM_HIMETRIC Each logical unit is converted to 0.01 millimeter.
MM_LOENGLISH Each logical unit is converted to 0.01 inch.
MM_LOMETRIC Each logical unit is converted to 0.1 millimeter.
MM_TWIPS Each logical unit is converted to 1/20 of a point(磅). (Because a point is 1/72 inch, a twip is 1/1440 inch.)
//MM_TWIPS常常用于列印機。
3)可變比例映射模式:(MM_ISOTROPIC ,MM_ANISOTROPIC )
這兩種模式用許我們改變它們的比例因子和坐标原點。
應用這兩中模式,如使用者改變視窗的尺寸,繪制的圖形大小也會發生響應的變化
具體如下:
The MM_HIENGLISH, MM_HIMETRIC, MM_LOENGLISH, MM_LOMETRIC, and MM_TWIPS modes are useful for applications that must draw in physically meaningful units (such as inches or millimeters). The MM_ISOTROPIC mode ensures a 1:1 aspect ratio, which is useful when it is important to preserve the exact shape of an image. The MM_ANISOTROPIC mode allows the x- and y-coordinates to be adjusted independently
常一起使用的函數:
SetWindowExt(..)//Sets the x- and y-extents of the window associated with the device context.
SetViewportExt(..)//Sets the x- and y-extents of the viewport of the device context.
注意:
When the following mapping modes are set, calls to SetWindowExt and SetViewportExt functions are ignored:
MM_HIENGLISH,MM_HIMETRIC,MM_LOENGLISH,MM_LOMETRIC,MM_TEXT,MM_TWIPS
When MM_ISOTROPIC mode is set, an application must call the SetWindowExt member function before calling SetViewportExt.
9,坐标變換:(具體參見P54)
許多MFC庫函數隻能在裝置坐标下工作(尤其CRect類成員函數)。可以認為CDC的所有成員函數都一邏輯坐标作參數。可以認為CWnd的成員函數都以裝置坐标做參數。(所有在實際視窗上點選獲得的坐标都是邏輯坐标)。在設定了裝置環境的映射模式及相應的參數以後,CDC的LPtoDP和DPtoLP函數可以用來在邏輯坐标系和裝置做表系之間進行轉換。
在CView的虛函數OnPrepareDC中設定映射模式要比在OnDraw函數中要好。
//*注意:
CView::OnPrepareDC
virtual void OnPrepareDC( CDC* pDC, CPrintInfo* pInfo = NULL );
應用程式将在調用OnDraw之前調用OnPrepareDC函數。
(OnPrepareDC在為螢幕顯示而調用OnDraw函數之前,或在為列印或列印預覽每一頁而調用OnPrint成員函數之前。)
10,CScrollView支援滾動條的滾動,但不支援鍵盤的滾動。通過使用CWnd的ScrollWindow和SetViewportOrg函數,CScrollView類允許将視口原點移到視窗中的任何一個位置,甚至包括視窗區域的上部或視窗的原點的左邊。
鍵盤輸入是分兩步處理的。OS向視窗發送類如WM_KEYDOWN和WM_KEYUP消息時用的是虛拟鍵盤碼,在消息到達視窗之前,被翻譯成WM_CHAR消息,該消息帶着正常的鍵碼。
利用對WM_KEYDOWN消息進行響應,對按鍵分别調用OnVScroll就可以使應用程式支援鍵盤的滾動。
CWnd::OnVScroll
afx_msg void OnVScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar );
nSBCode:
SB_BOTTOM Scroll to bottom.
SB_ENDSCROLL End scroll.
SB_LINEDOWN Scroll one line down.
SB_LINEUP Scroll one line up.
SB_PAGEDOWN Scroll one page down.
SB_PAGEUP Scroll one page up.
SB_THUMBPOSITION Scroll to the absolute position. The current position is provided in nPos.
SB_THUMBTRACK Drag scroll box to specified position. The current position is provided in nPos.
SB_TOP Scroll to top.
The framework calls this member function(OnVScroll) when the user clicks the window’s vertical scroll bar.
11,CView::OnInitialUpdate
virtual void OnInitialUpdate( );
說明:
OnInitialUpdate是視圖視窗完全建立後架構調用的第一個函數。架構在第一次調用OnDraw前會調用OnInitialUpdate。
具體參見下:
Called by the framework after the view is first attached to the document, but before the view is initially displayed. The default implementation of this function calls the OnUpdate member function with no hint information .
12,MFC對140種Windows消息直接直接提供了相應的消息控制函數,當然,我們還可以定義自己的消息和相應的消息控制函數。
五種特殊Windows消息:WM_CREATE,WM_CLOSE,WM_QUERYENDSESSION,WM_DESTROY,WM_NCDESTROY.(具體參見 p62-63頁。這兩頁強烈建議看看,這裡簡要筆記三個最常用最重要的)
1)WM_CREATE消息:
The WM_CREATE message is sent when an application requests that a window be created by calling the CreateWindowEx or CreateWindow function. The window procedure of the new window receives this message after the window is created, but before the window becomes visible. The message is sent before the CreateWindowEx or CreateWindow function returns.
2)WM_CLOSE消息:
當關閉視窗或父視窗被關閉時,Windows都會發送WM_CLOSE消息。可以重新定義該消息響應函數OnClose來完全控制關閉過程。
3)WM_DESTROY消息:
Windows在發送WM_CLOSE消息之後,緊接着就會發送WM_DESTROY消息(響應這個消息的時候,視窗已經消失但還沒有銷毀)。
(可以響應這個消息來做一些銷毀目前視窗後的一些事情,例如再彈出其它對話框發送其他的消息)