第11章View功能之加強與
重繪效率之提升
1. 基本上要使View 窗口具備滾動條,你必須做到下列事情:
A.定義Document 大小。如果沒有大小,Framework就沒有辦法計算滾動條尺寸,
以及捲動比例。這個大小可以是常數,也可以是個儲存在每一Document 中的
變量,隨着執行時期變動。
B. 以CScrollView 取代CView
C. 只要Document 的大小改變,就將尺寸傳給CScrollView的SetScrollSizes 函
式。如果程序設定Document 爲固定大小(本例就是如此),那麼當然只要一
開始做一次滾動條設定動作即可。
D. 注意裝置座標(窗口座標)與邏輯座標(Document 座標)的轉換。
2. 以下分四個步驟修改Scribble源代碼:
A.Document 的大小。我們的作法是設定一個變量,代表大小,並在Document 初
始化時設定其值,此後全程不再改變(以簡化問題)。這個成員變量在文件進行文件讀寫(Serialization)時也應該併入文件內容中。
B.將CScribbleView 的父類別由CView 改變爲CScrollView。同時準備改寫其虛擬函數
OnInitialUpdate,爲的是稍後我們要在其中,根據Document 的大小,設定捲動範圍
C. 改寫OnInitialUpdate,在其中設定滾動條範圍。這個函數的被調用時機是在View 第
一次附着到Document 但尚未顯現時,由Framework 調用之。
SetScrollSizes 總共有四個參數:
int nMapMode:代表映射模式(Mapping Mode)
SIZE sizeTotal:代表文件大小
const SIZE& sizePage:代表一頁大小(預設是文件大小的1/10)
const SIZE& sizeLine:代表一行大小(預設是文件大小的1/100)
D. 修正鼠標座標。雖說OnDraw 不必因爲座標原點的變化而有任何改變,但是幕後出
力的CScrollView::OnPrepareDC卻不知道什麼是Windows 消息.
Windows座標系分爲邏輯座標系和設備座標系兩種,GDI支持這兩種座標系。一般而言,GDI的文本和圖形輸出函數使用邏輯座標,而在客戶區移動或按下鼠標的鼠標位置是採用設備座標。
<1>邏輯座標系是面向DC的座標系,這種座標不考慮具體的設備類型,在繪圖時,Windows會根據當前設置的映射模式將邏輯座標轉換爲設備座標。
<2>設備座標系是面向物理設備的座標系,這種座標以像素或設備所能表示的最小長度單位爲單位,X軸方向向右,Y軸方向向下。設備座標系的原點位置(0, 0)不限定在設備顯示區域的左上角。
設備座標系分爲屏幕座標系、窗口座標系和客戶區座標系三種相互獨立的座標系。
屏幕座標系以屏幕左上角爲原點,一些與整個屏幕有關的函數均採用屏幕座標,如GetCursorPos()、SetCursorPos()、CreateWindow()、MoveWindow()。彈出式菜單使用的也是屏幕座標。窗口座標系以窗口左上角爲座標原點,它包括窗口標題欄、菜單欄和工具欄等範圍。客戶區座標系以窗口客戶區左上角爲原點,主要用於客戶區的繪圖輸出和窗口消息的處理。鼠標消息的座標參數使用客戶區座標,CDC類繪圖成員函數使用與客戶區座標對應的邏輯座標。2)座標之間的相互轉換編程時,有時需要根據當前的具體情況進行三種設備座標之間或與邏輯座標的相互轉換。MFC提供了兩個函數CDC::DPtoLP()和CDC:: LPtoDP()用於設備座標與邏輯座標之間的相互轉換。MFC提供了兩個函數CWnd::ScreenToClient()和CWnd::ClientToScreen()用於屏幕座標與客戶區座標的相互轉換。
3. 分裂窗口的程序概念
A.須有三個窗口通力合作完成顯示任務
1. Document Frame 窗口:負責一般性窗口行爲。其類別衍生自CMDIChildWnd。
2. Splitter 窗口:負責管理各窗口。通常直接使用CSplitterWnd類別。
3 .View 窗口:負責資料的顯示。其類別衍生自CView。
4.CSplitterWnd::Create 正是產生分裂窗口的關鍵,它有七個參數:
1. 表示父窗口。這裏的this代表的是CChildFrame窗口。
2. 分裂窗口的水平窗口數(row)
3. 分裂窗口的垂直窗口數(column)
4. 窗口的最小尺寸(應該是一個CSize對象)
5. 在窗口上使用哪一個View類別。此參數直接取用Framework交給
OnCreateClient 的第二個參數即可。
6. 指定分裂窗口的風格。默認值是:WS_CHILD|WS_VISIBLE|WS_HSCROLL|
WS_VSCROLL|SPLS_DYNAMIC_SPLIT,意思就是一個可見的子窗口,有着水平卷
軸和垂直滾動條,並支持動態分裂。關於動態分裂(以及所謂的靜態分裂),
7. 分裂窗口的ID。默認值是AFX_IDW_PANE_FIRST,這將成爲第一個窗口的ID。
默認ID:ID_WINDOW_SPLIT
在Resource View資源視圖中,打開Menu下的IDR_MAINFRAME菜單,在View下添加一個菜單項,Caption設爲Splitter Window,ID設爲(一定要設爲)ID_WINDOW_SPLIT。這樣在運行結果界面中點擊此菜單項時MFC會執行一些操作顯示動態分割窗口。
運行實例:
第12章打印預覽
本章只是一些關於打印與預覽的知識點,基本上依靠vs2008工具建起來的文檔都有打印和預覽的功能。
1. 程序流程
2. 在MFC 應用程序中,View 和applicationframework 分工合力完成打印工作
Application framework 的責任是:
顯示【Print】對話框
爲打印機產生一個CDC 對象。
調用CDC 對象的StartDoc 和EndDoc 兩函數。
持續不斷地調用CDC 對象的StartPage,通知View 應該輸出哪一頁;一頁打印
完畢則調用CDC 對象的EndPage。
我們(程序員)在View 對象上的責任是:
通知application framework 總共有多少頁要打印。
application framework 要求打印某特定頁時,我們必須將Document中對應的部
份輸出到打印機上。
配置或釋放任何GDI 資源,包括筆、刷、字形...等等。
如果需要,送出任何escape 碼改變打印機狀態,例如走紙、改變打印方向等等。
程序運行視例: