VC++技術內幕(第四版)筆記(第4章)

/******************************************/
第四章:基本事件處理、映射模式和滾動視圖


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消息(響應這個消息的時候,窗口已經消失但還沒有銷燬)。
(可以響應這個消息來做一些銷燬當前窗口後的一些事情,例如再彈出其它對話框發送其他的消息)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章