主要討論映射模式:MM_ANISOTROPIC,MM_ISOTROPIC.及相關方法的應用。
1,先建立一個MFC單文檔,過程不再贅述。
2,在View類中找到CMainFrame::PreCreateWindow函數,在其中設置默認窗口大小為400 pixel*300 pixel:
1 BOOL CTestView::PreCreateWindow(CREATESTRUCT& cs) 2 { 3 // TODO: 在此處通過修改 4 // CREATESTRUCT cs 來修改窗口類或樣式 5 cs.cx=400; 6 cs.cy=300; 7 return CView::PreCreateWindow(cs); 8 }
3,給CTestView在類向導里面,給WM_PAINT添加OnPaint()處理程序:
void CCausalityInterfaceView::OnPaint() { CPaintDC dc(this); // device context for painting // TODO: 在此處添加消息處理程序代碼 // 不為繪圖消息調用 CView::OnPaint() OnPrepareDC(&dc); OnDraw(&dc); CRect cr;//矩形結構 GetClientRect(&cr);//獲得客戶區窗口 int cx=cr.right;//右 int cy=cr.bottom;//底 dc.SetMapMode(MM_ISOTROPIC);//X=Y dc.SetWindowExt(1000,1000);//設置邏輯窗口,默認窗口原點為(0,0) dc.SetViewportExt(cx,-cy);//定義輸出視口,X右Y上為正 dc.SetViewportOrg(cx/2,cy/2);//定義視口原點為客戶區中心 dc.Ellipse(-500,500,500,-500);//繪制橢圓與客戶區外切的橢圓 //繪制水平垂直的四條半徑 dc.MoveTo(0,0); dc.LineTo(500,0); dc.MoveTo(0,0); dc.LineTo(-500,0); dc.MoveTo(0,0); dc.LineTo(0,500); dc.MoveTo(0,0); dc.LineTo(0,-500); //執行F5進行Debug,在底端Output窗口中可以觀察ClientRect TRACE( "ClientRect.x = %d, ClientRect.y = %d\n", cx, cy ); }
MM_ISOTROPIC:邏輯單位被映射為具有等刻度軸的任意單位:x軸上的一個單位等於y軸上的一個單位。
SetWindowExt(int cx, int cy): cx表示水平方向邏輯坐標的范圍,cy表示垂直方向邏輯坐標的范圍,
當改變窗口的大小時,以窗口的寬度或高度較小的方向為標准,比較下面兩個圖
圖(1)
圖(2)
圖(1)和圖(2)為運行結果,改變窗口大小時的結果。無論怎么改變大小,客戶區內始終顯示的是一個圓,不會變成橢圓。
當寬度>高度時,高度(y方向)達到1000的邏輯范圍,所以寬度(x方向)的邏輯范圍超過1000,
當寬度<高度時,寬度(x方向)達到1000的邏輯范圍,所以高度(y方向)的邏輯范圍超過1000.
將dc.SetWindowExt(1000,1000);改為:dc.SetWindowExt(1000,500);會出現如下情況:
圖(3)
圖(4),原因得自己思考了。
將模式改為MM_ANISOTROPIC:邏輯單位被轉換為任意單位,其中軸可以被隨意縮放。客戶區的圓會根據窗口的大小變為橢圓:
圖(5),橢圓會始終和客戶區邊界相切。
4,當進行如下設置時:
dc.SetMapMode(MM_ISOTROPIC);//X=Y dc.SetWindowExt(1000,1000);//設置邏輯窗口,默認窗口原點為(0,0) dc.SetViewportExt(500,-600); dc.SetViewportOrg(cx/2,cy/2);//定義視口原點為客戶區中心
圖(6)
圖(7)
客戶區的圓的大小不會隨客戶區改變,原因是邏輯單位 與 像素的映射已經固定,根據圓的半徑的邏輯單位得出圓占多少像素,而像素是固定的,所以圓的大小不在改變。
設置為:
dc.SetMapMode(MM_ANISOTROPIC);//X!=Y dc.SetWindowExt(1000,1000);//設置邏輯窗口,默認窗口原點為(0,0) dc.SetViewportExt(500,-600); dc.SetViewportOrg(cx/2,cy/2);//定義視口原點為客戶區中心
圖(8),圓顯示為橢圓,且大小不改變。