轉自:http://webbery.tianyablog.com
閱讀本文前,我們假設您已經:
1,知道如何創建一個單文檔的App Wizard
2,知道C++ 類、函數重載等簡單知識
3,知道如何給View類或者Doc文檔添加成員變量
4,會用MFC的IDE調試工具最好,那麼本文的程序您可以copy去調試
5,知道如何爲某個框架類添加虛函數或消息處理函數
1,透明畫刷
CClientDC dc(this);
CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
dc.SelectObject(pBrush);
2,保存繪製的圖像(窗口重繪時仍然存在)
CGraphView類中添加m_ptOrigin,m_ptEnd,m_nDrawType三個變量,分別用於保存圖像起始點、終止點和圖像類型
1)構造一個CGraph類,用於存放每個對象
頭文件Graph.h
#if !defined(AFX_GRAPH_H__)
#define AFX_GRAPH_H__
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CGraph
{
public:
UINT m_nDrawType;
CPoint m_ptOrigin;
CPoint m_ptEnd;
CGraph();
CGraph( UINT m_nDrawType,CPoint m_ptOrigin,CPoint m_ptEnd);
virtual ~CGraph();
};
2),因爲不知道將會繪製多少圖像對象,用集合類來替代複雜的鏈表結構。View類中定義,添加
CPtrArray m_ptArray;
3),在OnLButtonDown和OnLButtonUp中分別保存兩個點,並在OnLButtonUp中添加以下語句,用集合類來保存圖像元素
//CGraph graph(m_nDrawType,m_ptOrigin,m_ptEnd);這種方法是錯誤的,因爲局部變量將被銷燬
CGraph *pGraph;
pGraph = new CGraph(m_nDrawType,m_ptOrigin,m_ptEnd);//在堆中分配內存,不會被釋放,生命週期和進程一致,直至delete出現
m_ptArray.Add(&graph);
CPaintDC只能在WM_PAINT的消息相應中使用,其創建和析構調用BenginDC和EndDC
CClientDC創建時調用GetDC,析構時調用ReleaseDC
OnPrepareDC,對CScrollView調用OnPrepareDC會做調整,
OnPaint()函數爲WM_PAINT的相應函數,如果沒有重載OnPaint函數,那麼OnPaint基函數是直接調用OnDraw函數。如果重載了OnPaint()函數,那麼只有在子類中OnPaint()的調用OnDraw()
Win32應用程序接口(API)使用四種座標空間:世界座標系空間、頁面空間、設備空間、和物理設備空間。應用程序運用世界座標系空間對圖形輸出進行旋轉、斜切(扭曲)或者反射
Win32
API把世界座標系空間和頁面空間成爲邏輯空間;作後一種座標空間(物理設備空間)通常指應用程序窗口的客戶區;但是它也包括整個桌面、完整的窗口(包括
框架、標題欄和菜單欄)或打印機的一頁或繪圖儀的一頁紙。物理設備的尺寸隨顯示器、打印機或繪圖儀所設置的尺寸而變化。
如果要在物理設備上繪製輸出,windows把一個矩形區域從一個座標空間拷貝到(映射到)另一個座標空間,直至最終完整地輸出呈現在物理設備上(通常是屏幕或者打印機)
如果該應用程序調用了SetWorldTransform函數,那麼映射就從應用程序的世界座標系空間開始;否則,映射在頁面控件中進行。在
Windows把矩形區域的每一點從一個空間拷貝到另一個空間時,它採用了一種被稱爲轉換的算法,轉換是把對象從一個座標空間拷貝到另一個座標空間時改變
(轉變)這一對象的刀削、方位、和形態,儘管轉換把對象看成一個整體,但它也作用於對象中的每一點或每條線。
一個典型轉換的例子
圖形旋轉、斜切的例子在MSDN中using Coordinate spaces and transformations中有TransformAndDraw函數的實現,可以仿照之。例如AutoCAD中對圖像的切割、旋轉、局部放大等。
OnInitialUpdate,窗口創建完成後,第一個被調用的函數
SetMapMode函數
SetScrollSizes在窗口創建之後調用
滾動窗口中重繪圖像時出現的圖形移動問題
1,原因:重繪時調用了OnPrepareDC設置了視點座標
2,保存數據時先調用OnPrepareDC調整,再調用DPtoLP轉換後,再保存,就可以了。
另外兩種保存圖形數據的方法
CMetaFileDC
1,在View.h中添加定義
CMetaFileDC m_dcMetaFile;
2,在view的構造函數中初始化
m_dcMetaFile.Create();
3,在OnLButtonUp中將所有dc指針更換爲m_dcMetaFile
4,在OnDraw中以前的繪圖語句註釋掉,添加以下
HMETAFILE hmetaFile;
hmetaFile=m_dcMetaFile.Close();
pDC->PlayMetaFile(hmetaFile);//播放原文件
m_dcMetaFile.Create();//新創建原文件,準備原文件設備上下文
m_dcMetaFile.PlayMetaFile(hmetaFile);//把前面的原文件播放一遍,避免丟失。相當於保存以前的繪圖命令
DeleteMetaFile(hmetaFile);//播放結束,釋放原文件句柄
5,保存
copyMetaFile
1)保存語句
HMETAFILE hmetaFile;
hmetaFile=m_dcMetaFile.Close();
CopyMetaFile(hmetaFile,"meta.wmf");
m_dcMetaFile.Create();
DeleteMetaFile(hmetaFile);
2)打開圖形
HMETAFILE hmetaFile;
hmetaFile=GetMetaFile("meta.wmf");
m_dcMetaFile.PlayMetaFile(hmetaFile);
DeleteMetaFile(hmetaFile);
Invalidate();
利用兼容DC保存圖形
1,在View中定義變量
CDC m_dcCompatible;
2,在OnLButtonUp中添加
if(!m_dcCompatible.m_hDC)
{
m_dcCompatible.CreateCompatibleDC(&dc);
CRect rect;
GetClientRect(&rect);
CBitmap bitmap;
//用當前客戶區大小來創建兼容位圖
bitmap.CreateCompatibleBitmap(&dc,rect.Width(),rect.Height());
//把兼容位圖選入兼容DC中。此位圖bitmap可以是普通位圖,也可以是兼容位圖
m_dcCompatible.SelectObject(&bitmap);
m_dcCompatible.BitBlt(0,0,rect.Width(),rect.Height(),&dc,0,0,SRCCOPY);
m_dcCompatible.SelectObject(pBrush);
}
3,把OnLButtonUp中dc指針都換成m_dcCompatible
已經建立好的基類爲CView的視類,改變爲有滾動條的視類,即CScroolView步驟
1,將CXXXView的.h and .cpp文件中CView統統用CScrollView替換,注意類定義繼承的地方
2,添加OnInitialUpdate,在其中添加滾動條的初始化。不做這一步的話,將運行出錯
SetScrollSizes(MM_TEXT,CSize(800,600));