青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

mfc繪圖(轉載)

4 畫圖
在Windows中,繪圖一般在視圖窗口的客戶區進行,使用的是設備上下文類CDC中各種繪圖函數。
1. 映射模式與坐標系
1)默認映射模式
映射模式(map mode)影響所有的圖形和文本繪制函數,它定義(將邏輯單位轉換為設備單位所使用的)度量單位和坐標方向,Windows總是用邏輯單位來繪圖。
缺省情況下,繪圖的默認映射模式為MM_TEXT,其繪圖單位為像素(只要不打印輸出,屏幕繪圖使用該模式就夠了)。若窗口客戶區的寬和高分別為w和h像素,則其x坐標是從左到右,范圍為0 ~ w-1;y坐標是從上到下,范圍為0 ~ h-1。

2)設置映射模式
可以使用CDC類的成員函數GetMapMode和SetMapMode來獲得和設置當前的映射模式:
int GetMapMode( ) const; // 返回當前的映射模式
virtual int SetMapMode( int nMapMode ); // 返回先前的映射模式


映射模式的nMapMode取值與含義
符號常量 數字常量 x方向 y方向 邏輯單位的大小 
MM_TEXT 1 向右 向下 像素 
MM_LOMETRIC 2 向右 向上 0.1 mm 
MM_HIMETRIC 3 向右 向上 0.01 mm 
MM_LOENGLISH 4 向右 向上 0.01 in 
MM_HIENGLISH 5 向右 向上 0.001 in 
MM_TWIPS 6 向右 向上 1/1440 in 
MM_ISOTROPIC 7 自定義 自定義 自定義 
MM_ANISOTROPIC 8 自定義 自定義 自定義


可見,除了兩種自定義映射模式外,x方向都是向右,y方向也只有MM_TEXT的向下,其余的都是向上,與數學上一致。除了MM_ANISOTROPIC外,其他所有映射模式的x與y方向的單位都是相同的。所有映射模式的邏輯坐標的原點(0, 0)最初都是在窗口的左上角,但在CScrollView的派生類中,MFC會隨用戶滾動文檔而自動調整邏輯原點的相對位置(改變視點的原點屬性)。
3)自定義映射模式
自定義映射模式MM_ISOTROPIC(各向同性,x與y方向的單位必須相同)和MM_ANISOTROPIC(各向異性,x與y方向的單位可以不同)的單位和方向,可以通過用CDC類的成員函數G/SetWindowExt和G/SetViewportExt來獲取/設置窗口和視口的大小來確定:
CSize GetWindowExt( ) const;
virtual CSize SetWindowExt( int cx, int cy );

virtual CSize SetWindowExt( SIZE size );
CSize GetViewportExt( ) const;
virtual CSize SetViewportExt( int cx, int cy );

virtual CSize SetViewportExt( SIZE size );
其中,cx或size.cx和cy或size.cy分別為窗口/視口的寬度與高度(邏輯單位)。
還可以用CDC類的成員函數SetViewportOrg來設置坐標原點的位置:
virtual CPoint SetViewportOrg( int x, int y );
CPoint SetViewportOrg( POINT point );
例如
void CDrawView::OnDraw(CDC* pDC) {
       CRect rect;
       GetClientRect(rect);
       pDC->SetMapMode(MM_ANISOTROPIC);
       pDC->SetWindowExt(1000,1000);
       pDC->SetViewportExt(rect.right, -rect.bottom);

       pDC->SetViewportOrg(rect.right / 2, rect.bottom /2);

       pDC->Ellipse(CRect(-500, -500, 500, 500));

}
將當前的映射模式設置為各向異性自定義映射模式,窗口大小為1000個邏輯單位寬和1000個邏輯單位高,視口大小同當前客戶區,視口的坐標原點設置在當前客戶區的中央。由于使用了負數作為SetViewportExt函數的第2個參數,所以y軸方向是向上的。

可見,圓被畫成了橢圓,x與y方向上的邏輯單位不相同。
4)單位轉換
對所有非MM_TEXT映射模式,有如下重要規則:
<!--[if !supportLists]-->l         <!--[endif]-->CDC的成員函數(如各種繪圖函數)具有邏輯坐標參數

<!--[if !supportLists]-->l         <!--[endif]-->CWnd的成員函數(如各種響應函數)具有設備坐標參數(如鼠標位置point)

<!--[if !supportLists]-->l         <!--[endif]-->位置的測試操作(如CRect的PtInRect函數)只有使用設備坐標時才有效

<!--[if !supportLists]-->l         <!--[endif]-->長期使用的值應該用邏輯坐標保存(如窗口滾動后保存的設備坐標就無效了)


因此,為了使應用程序能夠正確工作,除MM_TEXT映射模式外,其他映射模式都需要進行單位轉換。下面是邏輯單位到設備單位(如像素)的轉換公式:
x比例因子 = 視口寬度 / 窗口寬度
y比例因子 = 視口高度 / 窗口高度
設備x = 邏輯x * x比例因子 + x原點偏移量
設備y = 邏輯y * y比例因子 + y原點偏移量
Windows的GDI負責邏輯坐標和設備坐標之間的轉換,這可以調用CDC類的成員函數LPtoDP和DPtoLP來進行:
void LPtoDP( LPPOINT lpPoints, int nCount = 1 ) const;

void LPtoDP( LPRECT lpRect ) const;
void LPtoDP( LPSIZE lpSize ) const;
void DPtoLP( LPPOINT lpPoints, int nCount = 1 ) const;

void DPtoLP( LPRECT lpRect ) const;
void DPtoLP( LPSIZE lpSize ) const;
例如:
void CDrawView::OnLButtonDown(UINT nFlags, CPoint point) {

              CRect rect = m_rect; // 邏輯坐標

              CClientDC dc(this);
              dc.SetMapMode(MM_LOENGLISH);
              dc.LPtoDP(rect); // 轉化成設備坐標
       if (rect.PtInRect(point)) // 位置的測試操作只有使用設備坐標時才有效

       ......
}
void CDrawView:: OnMouseMove (UINT nFlags, CPoint point) {

       float t,y;

              char buf[40];
       CDC* pDC = GetDC();

pDC->SetMapMode(MM_HIMETRIC);
              pDC->DPtoLP(&point); // 轉化成邏輯坐標
t = t1 + (point.x * dt) / w; sprintf(buf, "%.4fs", t); pSB->SetPaneText(xV, buf);

y = (y0 - point.y) / dy; sprintf(buf, "%.4f", y); pSB->SetPaneText(yV, buf);
       ......
}
2. 畫像素點
畫像素點就是設置像素點的顏色,從前面3)(2)已知道這可由CDC的成員函數SetPixel來做,該函數的原型為:
COLORREF SetPixel( int x, int y, COLORREF crColor ); 或

COLORREF SetPixel( POINT point, COLORREF crColor );

其中,x與y分別為像素點的橫坐標與縱坐標,crColor為像素的顏色值。例如
pDC->SetPixel(i, j, RGB(r, g, b));

3.畫線狀圖
在Windows中,線狀圖必須用筆來畫(筆的創建與使用見前面的3)(3)),下面是CDC類中可以繪制線狀圖的常用成員函數:
<!--[if !supportLists]-->l         <!--[endif]-->當前位置:設置當前位置為(x, y)或point:(返回值為原當前位置的坐標)

CPoint MoveTo( int x, int y ); 或 CPoint MoveTo( POINT point );

<!--[if !supportLists]-->l         <!--[endif]-->畫線:使用DC中的筆從當前位置畫線到點(x, y)或point:(若成功返回非0值):

BOOL LineTo( int x, int y ); 或BOOL LineTo( POINT point );
<!--[if !supportLists]-->l         <!--[endif]-->畫折線:使用DC中的筆,依次將點數組lpPoints中的nCount(≥2)個點連接起來,形成一條折線:

BOOL Polyline( LPPOINT lpPoints, int nCount );
<!--[if !supportLists]-->l         <!--[endif]-->畫多邊形:似畫折線,但還會將最后的點與第一個點相連形成多邊形,并用DC中的刷填充其內部區域:

BOOL Polygon( LPPOINT lpPoints, int nCount );
<!--[if !supportLists]-->l         <!--[endif]-->畫矩形:使用DC中的筆畫左上角為(x1, y1)、右下角為(x2, y2)或范圍為*lpRect的矩形的邊線,并用DC中的刷填充其內部區域:

BOOL Rectangle( int x1, int y1, int x2, int y2 ); 或
BOOL Rectangle( LPCRECT lpRect );
              有時需要根據用戶給定的兩個任意點來重新構造左上角和右下角的點,例如:
              rect = CRect(min(p0.x, point.x), min(p0.y, point.y), max(p0.x, point.x), max(p0.y, point.y));

<!--[if !supportLists]-->l         <!--[endif]-->畫圓角矩形:使用DC中的筆畫左上角為(x1, y1)、右下角為(x2, y2)或范圍為*lpRect的矩形的邊線,并用寬x3或point.x高y3或point.y矩形的內接橢圓倒角,再用DC中的刷填充其內部區域:

BOOL RoundRect( int x1, int y1, int x2, int y2, int x3, int y3 );
BOOL RoundRect( LPCRECT lpRect, POINT point );
例如:
int d = min(rect.Width(), rect.Height()) / 4;

pDC-> RoundRect(rect, CPoint(d, d));
<!--[if !supportLists]-->l         <!--[endif]-->畫(橢)圓:使用DC中的筆在左上角為(x1, y1)、右下角為(x2, y2)或范圍為*lpRect的矩形中畫內接(橢)圓的邊線,并用DC中的刷填充其內部區域:

BOOL Ellipse( int x1, int y1, int x2, int y2 );
BOOL Ellipse( LPCRECT lpRect );
注意,CDC中沒有畫圓的專用函數。在這里,圓是作為橢圓的(寬高相等)特例來畫的。
<!--[if !supportLists]-->l         <!--[endif]-->畫弧:(x1, y1)與(x2, y2)或lpRect的含義同畫(橢)圓,(x3, y3)或ptStart為弧的起點,(x4, y4)或ptEnd為弧的終點:(逆時針方向旋轉)

BOOL Arc( int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4 );

BOOL Arc( LPCRECT lpRect, POINT ptStart, POINT ptEnd );
BOOL ArcTo(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);

BOOL ArcTo(LPCRECT lpRect, POINT ptStart, POINT ptEnd);
畫圓弧:(其中(x, y)為圓心、nRadius為半徑、fStartAngle為起始角、fSweepAngle為弧段跨角)
BOOL AngleArc(int x, int y, int nRadius, float fStartAngle, float fSweepAngle);

<!--[if !supportLists]-->l         <!--[endif]-->畫弓弦:參數的含義同上,只是用一根弦連接弧的起點和終點,形成一個弓形,并用DC中的刷填充其內部區域:

BOOL Chord( int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4 );

BOOL Chord( LPCRECT lpRect, POINT ptStart, POINT ptEnd );
4.畫填充圖
在Windows中,面狀圖必須用刷來填充(刷的創建與使用見前面的3)(4))。上面(2)中的Polygon、Rectangle、Ellipse和Chord等畫閉合線狀圖的函數,只要DC中的刷不是空刷,都可以用來畫對應的面狀圖(邊線用當前筆畫,內部用當前刷填充)。下面介紹的是CDC類中只能繪制面狀圖的其他常用成員函數:
<!--[if !supportLists]-->l         <!--[endif]-->畫填充矩形:用指定的刷pBrush畫一個以lpRect為區域的填充矩形,無邊線,填充區域包括矩形的左邊界和上邊界,但不包括矩形的右邊界和下邊界:

void FillRect( LPCRECT lpRect, CBrush* pBrush );
<!--[if !supportLists]-->l         <!--[endif]-->畫單色填充矩形:似FillRect,但只能填充單色,不能填充條紋和圖案:

void FillSolidRect( LPCRECT lpRect, COLORREF clr );
void FillSolidRect( int x, int y, int cx, int cy, COLORREF clr );
<!--[if !supportLists]-->l         <!--[endif]-->畫餅圖(扇形):參數含義同Arc,但將起點和終點都與外接矩形的中心相連接,形成一個扇形區域,用DC中的刷填充整個扇形區域,無另外的邊線:

BOOL Pie( int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4 );

BOOL Pie( LPCRECT lpRect, POINT ptStart, POINT ptEnd );
<!--[if !supportLists]-->l         <!--[endif]-->畫拖動的矩形:先擦除線寬為sizeLast、填充刷為pBrushLast的原矩形lpRectLast,然后再以線寬為size、填充刷為pBrush畫新矩形lpRectLast。矩形的邊框用灰色的點虛線畫,缺省的填充刷為空刷:

void DrawDragRect( LPCRECT lpRect, SIZE size, LPCRECT lpRectLast,

SIZE sizeLast, CBrush* pBrush = NULL, CBrush* pBrushLast = NULL );

如:pDC->DrawDragRect(rect, size, rect0, size);

<!--[if !supportLists]-->l         <!--[endif]-->填充區域:

<!--[if !supportLists]-->n     <!--[endif]-->用當前刷從點(x, y)開始向四周填充到顏色為crColor的邊界:

BOOL FloodFill(int x, int y, COLORREF crColor); // 成功返回非0

<!--[if !supportLists]-->n     <!--[endif]-->用當前刷從點(x, y)開始向四周填充:

BOOL ExtFloodFill(int x, int y, COLORREF crColor,

UINT nFillType); // 成功返回非0

<!--[if !supportLists]-->u <!--[endif]-->nFillType = FLOODFILLBORDER:填充到顏色為crColor的邊界(同FloodFill);(用于填充內部顏色不同但邊界顏色相同的區域)
<!--[if !supportLists]-->u <!--[endif]-->nFillType = FLOODFILLSURFACE:填充所有顏色為crColor的點,直到碰到非crColor顏色的點為止。(點(x, y)的顏色也必須為crColor),(用于填充內部顏色相同但邊界顏色可以不同的區域)。例如:
pDC->ExtFloodFill(point.x, point.y, pDC->GetPixel(point), FLOODFILLSURFACE);

5.清屏
Windows沒有提供專門的清屏函數,可以調用CWnd的下面兩個函數調用來完成該功能:
void Invalidate(BOOL bErase = TRUE);
void UpdateWindow( );
或調用CWnd的函數
BOOL RedrawWindow(
   LPCRECT lpRectUpdate = NULL,

   CRgn* prgnUpdate = NULL,
   UINT flags = RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE

);
來完成。
例如(菜單項ID_CLEAR的事件處理函數):
CDrawView::OnClear() { // 調用OnDraw來清屏
       //Invalidate();
       //UpdateWindow( );
       RedrawWindow( );
}
也可以用畫填充背景色矩形的方法來清屏,如:
       RECT rect;
       GetClientRect(&rect);
       pDC->FillSolidRect(&rect, RGB(255, 255, 255));

6.在控件上繪圖
可以在對話框資源中放置圖片控件,并對其類型屬性選Frame。可在對話框的繪圖消息響應函數OnPaint或其他函數中,用CWnd類的函數GetDlgItem:
CWnd* GetDlgItem( int nID ) const;
來獲得圖片控件的窗口對象,再用函數GetDC:
CDC* GetDC( );

由窗口對象得到DC,然后就可以用該DC在控件中畫圖。如(在ID為IDC_HUESAT的圖片控件上畫調色板)
void CColorDlg::OnPaint() 
{
       if (IsIconic()) {
              ... ...
       }
       else {
              CDialog::OnPaint();
              int i, j;
              BYTE r, g, b;
              // get control window and DC of Hue&Saturation

              CWnd *pWin = GetDlgItem(IDC_HUESAT);

              CDC *pDC = pWin->GetDC();

              // draw hue-saturation palette

              for (i = 0; i < 360; i++)

                     for (j = 0; j <= 255; j++) {

                            HSLtoRGB(i, 255 - j, 128, r, g, b); // 自定義函數,見網絡硬盤的

// res目錄中的ColTrans.cpp文件
                            pDC->SetPixel(i, j, RGB(r, g, b));

                     }
              ... ...
       }
}
在非Frame類靜態控件上繪圖,必須先按順序依次調用CWnd類的Invalidate和UpdateWindow函數后,再開始用DC畫圖。如在一個ID為IDC_COLOR的按鈕上繪圖:
void CComDlgDlg::DrawColor()
{
       CWnd* pWnd = GetDlgItem(IDC_COLOR);

       CDC* pDC = pWnd->GetDC();

       CRect rect;

       pWnd->GetClientRect(&rect);
       pWnd->Invalidate();
       pWnd->UpdateWindow();
       pDC->FillRect(&rect, new CBrush(m_crCol));
}

若干說明:
<!--[if !supportLists]-->l     <!--[endif]-->除了基于對話框的程序外,其他對話框類都需要自己添加(重寫型)消息響應函數OnInitDialog,來做一些必要的初始化對話框的工作。添加方法是:先在項目區選中“類視圖”頁,再選中對應的對話框類,然后在屬性窗口的“重寫”頁中添加該函數;

<!--[if !supportLists]-->l     <!--[endif]-->為了使在運行時能夠不斷及時更新控件的顯示(主要是自己加的顯式代碼),可以將自己繪制控件的所有代碼都全部加入對話框類的消息響應函數OnPaint中。在需要時(例如在繪圖參數修改后),自己調用CWnd的Invalidate和UpdateWindow函數,請求系統刷新對話框和控件的顯示。因為控件也是窗口,控件類都是CWnd的派生類。所以在對話框和控件中,可以像在視圖類中一樣,調用各種CWnd的成員函數。

<!--[if !supportLists]-->l     <!--[endif]-->一般的對話框類,缺省時都沒有明寫出OnPaint函數。可以自己在對話框類中添加WM_PAINT消息的響應函數OnPaint來進行一些繪圖工作。

<!--[if !supportLists]-->l     <!--[endif]-->為了在鼠標指向按鈕時,讓按鈕上自己繪制的圖形不被消去,可以設置按鈕控件的“Owner Draw”屬性為“True”。

<!--[if !supportLists]-->l     <!--[endif]-->如果希望非按鈕控件(如圖片控件和靜態文本等),也可以響應鼠標消息(如單擊、雙擊等),需要設置控件的“Notify”屬性為“True”。

<!--[if !supportLists]-->l     <!--[endif]-->使用OnPaint函數在對話框客戶區的空白處(無控件的地方)繪制自己的圖形,必須屏蔽掉其中缺省的對對話框基類的OnPaint函數的調用:

//CDialog::OnPaint();
<!--[if !supportLists]-->l     <!--[endif]-->對話框的背景色,可以用CWnd類的成員函數:

DWORD GetSysColor( int nIndex);
得到,其中的nIndex取為COLOR_BTNFACE。例如:
dc.SetBkColor(GetSysColor(COLOR_BTNFACE));

下面是部分例子代碼:(其中FillColor和ShowImg為自定義的成員函數)
void CSetDlg::OnBnClickedPenColor()
{
       // TODO: 在此添加控件通知處理程序代碼
       CColorDialog colDlg(m_crLineColor);

       if (colDlg.DoModal() == IDOK) {

              m_crLineColor = colDlg.GetColor();

              Invalidate();
              UpdateWindow();
       }
}
// ……
void CSetDlg::OnPaint()
{
       CPaintDC dc(this); // device context for painting

       // TODO: 在此處添加消息處理程序代碼
       // 不為繪圖消息調用 CDialog::OnPaint()
       FillColor(IDC_PEN_COLOR, m_crLineColor);

       FillColor(IDC_BRUSH_COLOR, m_crBrushColor);

       if(m_pBitmap0 != NULL) ShowImg(IDC_BRUSH_IMG, m_hBmp0);

       else if(m_pBitmap != NULL) ShowImg(IDC_BRUSH_IMG, m_hBmp);

}
void CSetDlg::FillColor(UINT id, COLORREF col)

{
       CWnd* pWnd = GetDlgItem(id);

       CDC* pDC = pWnd->GetDC();

       pDC->SelectObject(new CPen(PS_SOLID, 1, RGB(0, 0, 0)));

       pDC->SelectObject(new CBrush(col));

       CRect rect; 
       pWnd->GetClientRect(&rect);
       pWnd->Invalidate();
       pWnd->UpdateWindow();
       pDC->RoundRect(&rect, CPoint(8, 8));

}
void CSetDlg::ShowImg(UINT ID, HBITMAP hBmp)

{
       CWnd* pWnd = GetDlgItem(ID);

       CDC* pDC = pWnd->GetDC();

       CRect rect; 
       pWnd->GetClientRect(&rect);
       pWnd->Invalidate();
       pWnd->UpdateWindow();
       BITMAP bs;
       GetObject(hBmp, sizeof(bs), &bs);

       CDC dc;
       if(dc.CreateCompatibleDC(pDC)) {

              int x0, y0, w, h;
              float rx = (float)bs.bmWidth / rect.right,

                     ry = (float)bs.bmHeight / rect.bottom;

              if (rx >= ry) {

                     x0 = 0; w = rect.right;

                     h = (int)(bs.bmHeight / rx + 0.5);

                     y0 = (rect.bottom - h) / 2;

              }
              else {
                     y0 = 0; h = rect.bottom;

                     w = (int)(bs.bmWidth / ry + 0.5);

                     x0 = (rect.right - w) / 2;

              }
              ::SelectObject(dc.GetSafeHdc(), hBmp);

              pDC->SetStretchBltMode(HALFTONE);
              pDC->StretchBlt(x0, y0, w, h, &dc, 0, 0, bs.bmWidth, bs.bmHeight, SRCCOPY);

              SetDlgItemInt(IDC_W, bs.bmWidth);

              SetDlgItemInt(IDC_H, bs.bmHeight);

       }
}
//……
5 設置繪圖屬性
除了映射模式外,還有許多繪圖屬性可以設置,如背景、繪圖方式、多邊形填充方式、畫弧方向、刷原點等。
1.背景
1)背景色
當背景模式為不透明時,背景色決定線狀圖的空隙顏色(如虛線中的空隙、條紋刷的空隙和文字的空隙),可以使用CDC類的成員函數GetBkColor和SetBkColor來獲得和設置當前的背景顏色:
COLORREF GetBkColor( ) const; // 返回當前的背景色
virtual COLORREF SetBkColor( COLORREF crColor ); // 返回先前的背景色
                                                                              // 若出錯返回0x80000000
2)背景模式
背景模式影響有空隙的線狀圖的空隙(如虛線中的空隙、條紋刷的空隙和文字的空隙)用什么辦法填充。可以使用CDC類的成員函數GetBkMode和SetBkMode來獲得和設置當前的背景模式:
int GetBkMode( ) const; // 返回當前背景模式
int SetBkMode( int nBkMode ); // 返回先前背景模式
背景模式的取值
nBkMode值 名稱 作用 
OPAQUE 不透明的(缺省值) 空隙用背景色填充 
TRANSPARENT 透明的 空隙處保持原背景圖不變

2. 繪圖模式
繪圖模式(drawing mode)指前景色的混合方式,它決定新畫圖的筆和刷的顏色(pbCol)如何與原有圖的顏色(scCol)相結合而得到結果像素色(pixel)。
1)設置繪圖模式
可使用CDC類的成員函數SetROP2 (ROP = Raster OPeration光柵操作)來設置繪圖模式:
int SetROP2( int nDrawMode );

其中,nDrawMode可取值:
繪圖模式nDrawMode的取值
符號常量 作用 運算結果 
R2_BLACK 黑色 pixel = black 
R2_WHITE 白色 pixel = white 
R2_NOP 不變 pixel = scCol 
R2_NOT 反色 pixel = ~scCol 
R2_COPYPEN 覆蓋 pixel = pbCol 
R2_NOTCOPYPEN 反色覆蓋 pixel = ~pbCol 
R2_MERGEPENNOT 反色或 pixel = ~scCol | pbCol 
R2_MERGENOTPEN 或反色 pixel = scCol | ~pbCol 
R2_MASKNOTPEN 與反色 pixel = scCol & ~pbCol 
R2_MERGEPEN 或 pixel = scCol | pbCol 
R2_NOTMERGEPEN 或非 pixel = ~(scCol | pbCol) 
R2_MASKPEN 與 pixel = scCol & pbCol 
R2_NOTMASKPEN 與非 pixel = ~(scCol & pbCol) 
R2_XORPEN 異或 pixel = scCol ^ pbCol 
R2_NOTXORPEN 異或非 pixel = ~(scCol ^ pbCol)

其中,R2_COPYPEN(覆蓋)為缺省繪圖模式,R2_XORPEN(異或)較常用。
2)畫移動圖形
為了能畫移動的位置標識(如十字、一字)和隨鼠標移動畫動態圖形(如直線、矩形、橢圓),必須在不破壞原有背景圖形的基礎上移動這些圖形。
移動圖形采用的是異或畫圖方法,移動圖形的過程為:異或畫圖、在原位置再異或化圖(擦除)、在新位置異或畫圖、……。

       pGrayPen = new CPen(PS_DOT, 0, RGB(128, 128, 128));

pDC->SetBkMode(TRANSPARENT);
       pOldPen = pDC->SelectObject(pGrayPen);
pDC->SelectStockObject(NULL_BRUSH);
       pDC->SetROP2(R2_XORPEN);
       if (m_bErase) pDC->Ellipse(rect0);
       pDC->Ellipse(rect);
       pDC->SetROP2(R2_COPYPEN);
       pDC->SelectObject(pOldPen);
       rect0 = rect;
較完整的拖放動態畫圖的例子,可參照下面的“3. 拖放畫動態直線”部分。
3)其他屬性
<!--[if !supportLists]-->l         <!--[endif]-->多邊形填充方式:可使用CDC類的成員函數GetPolyFillMode和SetPolyFillMode來確定多邊形的填充方式:

int GetPolyFillMode( ) const;
int SetPolyFillMode( int nPolyFillMode );
其中nPolyFillMode 可取值ALTERNATE(交替——填充奇數邊和偶數邊之間的區域,缺省值)或WINDING(纏繞——根據多邊形邊的走向來確定是否填充一區域)
<!--[if !supportLists]-->l         <!--[endif]-->畫弧方向:可使用CDC類的成員函數GetArcDirection和SetArcDirection來確定Arc、Chord、Pie等函數的畫弧方向:

int GetArcDirection( ) const;
int SetArcDirection( int nArcDirection );
其中,nArcDirection可取值AD_COUNTERCLOCKWISE(逆時針方向,缺省值)和AD_CLOCKWISE(順時針方向)
<!--[if !supportLists]-->l         <!--[endif]-->刷原點:可使用CDC類的成員函數GetBrushOrg和SetBrushOrg來確定可填充繪圖函數的條紋或圖案刷的起點:(缺省值為客戶區左上角的坐標原點(0, 0))

CPoint GetBrushOrg( ) const;
CPoint SetBrushOrg( int x, int y );
CPoint SetBrushOrg( POINT point );
3.拖放畫動態直線
下面是一個較完整的拖放動態畫直線的例子:
// 類變量
class CDrawView : public CView { 
       //……
protected:
       BOOL m_bLButtonDown, m_bErase; // 判斷是否按下左鼠標鍵

//和是否需要擦除圖形的類變量
       CPoint p0, pm; // 記錄直線起點和動態終點的類變量

       CPen * pGrayPen, * pLinePen; // 定義灰色和直線筆

       //……
}
// 構造函數
CDrawView::CDrawView() {
       m_bLButtonDown = FALSE; // 設左鼠標鍵按下為假

       m_bErase = FALSE; // 設需要擦除為假

       pGrayPen = new CPen(PS_SOLID, 0, RGB(128, 128, 128));// 創建灰色筆

       pLinePen = new CPen(PS_SOLID, 0, RGB(255, 0, 0));// 創建紅色的直線筆

}
// 鼠標消息響應函數
void CDrawView::OnLButtonDown(UINT nFlags, CPoint point) {

       m_bLButtonDown = TRUE; // 設左鼠標鍵按下為真

       SetCapture(); // 設置鼠標捕獲

       // SetCursor(LoadCursor(NULL, IDC_CROSS)); // 設置鼠標為十字

       p0 = point; // 保存矩形左上角

       pm = p0; // 讓矩形右下角等于左上角
       CView::OnLButtonDown(nFlags, point);

}
void CDrawView::OnMouseMove(UINT nFlags, CPoint point) {

       SetCursor(LoadCursor(NULL, IDC_CROSS)); // 設置鼠標為十字

       if (m_bLButtonDown) { // 左鼠標鍵按下為真

              CDC* pDC = GetDC(); // 獲取設備上下文

              pDC->SelectObject(pGrayPen);// 選取灰色筆
              pDC->SetROP2(R2_XORPEN);// 設置為異或繪圖方式
              if (m_bErase) { // 需要擦除為真

                     pDC->MoveTo(p0); pDC->LineTo(pm); // 擦除原直線

              }
              else // 需要擦除為假

                     m_bErase = TRUE; // 設需要擦除為真
              pDC->MoveTo(p0); pDC->LineTo(point); // 繪制新直線

              pm = point; // 記錄老終點

              ReleaseDC(pDC); // 釋放設備上下文

       }
       CView::OnMouseMove(nFlags, point);

}
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point) {

       ReleaseCapture(); // 釋放鼠標捕獲

       if (m_bLButtonDown) { // 左鼠標鍵按下為真

              CDC* pDC = GetDC(); // 獲取設備上下文

              pDC->SelectObject(pGrayPen);// 選取灰色筆
              pDC->SetROP2(R2_XORPEN); // 設置為異或繪圖方式
              pDC->MoveTo(p0); pDC->LineTo(pm); // 擦除原直線

              pDC->SelectObject(pLinePen); // 選擇直線筆
              pDC->SetROP2(R2_COPYPEN);// 設置為覆蓋繪圖方式
              pDC->MoveTo(p0); pDC->LineTo(point); // 繪制最終的直線

              m_bLButtonDown = FALSE; // 重設左鼠標鍵按下為假

              m_bErase = FALSE; // 重需要擦除為假

              ReleaseDC(pDC); // 釋放設備上下文

       }
       CView::OnLButtonUp(nFlags, point);

}

posted on 2011-03-01 14:03 wrh 閱讀(2457) 評論(0)  編輯 收藏 引用

導航

<2008年11月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

統計

常用鏈接

留言簿(19)

隨筆檔案

文章檔案

收藏夾

搜索

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产精品分类| 香蕉av777xxx色综合一区| 亚洲欧美日韩国产另类专区| 一区二区三区高清在线观看| 一区二区三区欧美在线| 一区二区三区 在线观看视频| 亚洲精品一区中文| 亚洲一区二区三区在线| 欧美在线影院| 欧美高清视频一区二区三区在线观看 | 日韩一二三在线视频播| 国产伦精品一区二区三区高清| 99热在这里有精品免费| 亚洲精品你懂的| 亚洲电影自拍| 一本久久综合| 久久久久国产精品一区三寸| 免费欧美日韩国产三级电影| 欧美日韩精品一本二本三本| 国产精品日韩电影| 影音欧美亚洲| 亚洲在线观看免费| 欧美成人首页| 亚洲欧美国产一区二区三区| 老司机午夜精品| 国产精品久久久久毛片大屁完整版| 国产一区二区三区在线观看免费视频| 亚洲国产婷婷综合在线精品 | 亚洲国产精品欧美一二99| 夜夜嗨av色一区二区不卡| 久久国产精品毛片| 99re6热只有精品免费观看| 午夜精品久久久久久久久久久| 欧美大胆成人| 一区在线视频观看| 欧美一区二区黄色| 亚洲免费观看在线观看| 米奇777超碰欧美日韩亚洲| 国产在线播放一区二区三区| 亚洲欧美视频一区| 夜夜嗨一区二区| 欧美日韩成人一区二区| 亚洲精品欧美日韩| 欧美国产日本在线| 久久在线免费观看视频| 精品1区2区| 久久综合伊人77777蜜臀| 性欧美精品高清| 国产日韩欧美亚洲一区| 欧美一区国产在线| 亚洲欧美日韩高清| 国产精品一区一区三区| 亚洲亚洲精品三区日韩精品在线视频 | 在线播放亚洲| 久久国产精品99精品国产| 亚洲视频第一页| 欧美日韩一区二区视频在线| 一区二区三区免费观看| 日韩视频不卡| 在线日韩成人| 久久亚洲午夜电影| 韩国欧美一区| 久久精品成人欧美大片古装| 亚洲欧美日韩成人| 国产一区二区视频在线观看 | 亚洲欧美三级伦理| 亚洲综合色激情五月| 国产情侣一区| 久久久久久久一区二区| 久久久午夜电影| 亚洲精品国产精品乱码不99| 91久久精品国产91久久| 欧美日韩视频免费播放| 亚洲欧美日韩国产一区| 午夜欧美大片免费观看| 国产一区二区三区奇米久涩 | 亚洲国产日韩综合一区| 欧美猛交免费看| 午夜精品久久久久久久白皮肤| 欧美一区深夜视频| 亚洲第一福利社区| 一本色道88久久加勒比精品| 国产毛片久久| 欧美激情精品久久久六区热门 | 国产精品jizz在线观看美国| 欧美在线一区二区三区| 美国十次了思思久久精品导航| 一区二区日韩欧美| 久久久91精品国产一区二区精品| 亚洲国产成人在线播放| 一区二区三区精品| 亚洲第一综合天堂另类专| 99精品久久久| 尤妮丝一区二区裸体视频| 夜夜嗨av一区二区三区网站四季av| 国产日韩亚洲欧美综合| 亚洲国产精品成人综合| 国产一区91| 99在线热播精品免费99热| 国产综合网站| 一区二区三区久久精品| 亚洲国产一区二区精品专区| 亚洲欧美欧美一区二区三区| 亚洲精品乱码久久久久久日本蜜臀 | 国产婷婷97碰碰久久人人蜜臀| 亚洲高清三级视频| 国产一区二区精品| 一区二区三区欧美在线| 伊大人香蕉综合8在线视| 亚洲永久网站| 一区二区三区久久网| 亚洲欧美成人综合| 国产精品一区久久久| 亚洲欧洲日本在线| 狠狠色丁香久久婷婷综合丁香| 99成人精品| 亚洲人成网站精品片在线观看| 欧美一区二区高清在线观看| 亚洲视频欧美在线| 欧美女激情福利| 亚洲激情一区| 亚洲精品日韩一| 欧美激情综合色| 91久久精品一区二区三区| 亚洲国产成人久久| 老司机成人在线视频| 欧美96在线丨欧| 在线看国产日韩| 久久久噜噜噜久久中文字免| 欧美在线播放一区二区| 国产精品观看| 亚洲在线国产日韩欧美| 欧美在线免费视屏| 国产一区在线看| 久久精品国产欧美亚洲人人爽 | 亚洲国产精品电影| 亚洲精品久久久久久下一站| 欧美成人69av| 亚洲精品国产品国语在线app | 亚洲午夜精品一区二区| 欧美人与禽猛交乱配| 日韩一级大片在线| 亚洲午夜视频| 国产女主播在线一区二区| 亚洲免费视频观看| 久久久国产成人精品| 在线电影院国产精品| 欧美成人激情视频免费观看| 亚洲国语精品自产拍在线观看| 在线一区二区日韩| 国产精品久久久999| 性xx色xx综合久久久xx| 免费毛片一区二区三区久久久| 亚洲精品乱码久久久久久久久| 欧美日韩免费一区二区三区| 亚洲欧美综合国产精品一区| 久久深夜福利| 一本色道久久综合亚洲91| 国产精品久久久久一区二区三区| 欧美伊人久久久久久午夜久久久久| 麻豆久久婷婷| 国产精品99久久久久久久久| 国产欧美日韩在线| 毛片精品免费在线观看| 亚洲无线视频| 欧美黄色成人网| 亚洲欧美伊人| 亚洲黄色高清| 国产欧美精品日韩精品| 欧美激情成人在线视频| 午夜久久电影网| 91久久久亚洲精品| 久久精品视频va| 一区二区三区高清不卡| 一区久久精品| 国产精品日本一区二区| 毛片基地黄久久久久久天堂| 亚洲在线黄色| 亚洲人屁股眼子交8| 久久久www成人免费毛片麻豆| 国产精品扒开腿做爽爽爽视频| 欧美专区18| 一个人看的www久久| 欧美成人综合| 久久黄色网页| 在线亚洲高清视频| 亚洲第一天堂av| 国产人久久人人人人爽| 欧美日韩国产一区二区| 久久这里有精品15一区二区三区| 在线亚洲欧美视频| 亚洲国产天堂久久综合| 久久性天堂网| 久久电影一区| 午夜电影亚洲| 99re这里只有精品6| 亚洲国产日韩美| 樱花yy私人影院亚洲| 国产综合香蕉五月婷在线| 国产日韩成人精品|