<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      loveday

      MFC繪圖(轉(zhuǎn)載)

      http://www.cppblog.com/bestcln/articles/83189.html

      1 幾何對象的結(jié)構(gòu)和類
      為了使用繪圖函數(shù),應(yīng)該先了解繪圖所用到的幾種表示幾何對象的結(jié)構(gòu)和類。這些結(jié)構(gòu)和類分別定義在頭文件windef.h和afxwin.h中。
      1.點
      1)點結(jié)構(gòu)POINT
      點數(shù)據(jù)結(jié)構(gòu)POINT用來表示一點的x、y坐標(biāo):
      typedef struct tagPOINT {

          LONG x;

          LONG y;

      } POINT;
      2)點類CPoint
      點類CPoint為一個沒有基類的獨立類,封裝了POINT結(jié)構(gòu),有成員變量x和y,其構(gòu)造函數(shù)有5種:
      CPoint( );
      CPoint( int initX, int initY );
      CPoint( POINT initPt );
      CPoint( SIZE initSize );
      CPoint( LPARAM dwPoint ); // 低字設(shè)為x、高字設(shè)為y
      CPoint類還定義了4個平移和設(shè)置函數(shù):
      void Offset(int xOffset, int yOffset);
      void Offset(POINT point);
      void Offset(SIZE size);
      void SetPoint(int X, int Y);
      CPoint類還重載了+、-、+=、-=、==、!=等運算符來支持CPoint對象和CPoint、POINT、SIZE對象之間的運算。
      2.大小
      1)大小結(jié)構(gòu)SIZE
      大小(size尺寸)結(jié)構(gòu)SIZE用來表示矩形的寬cx和高cy:
      typedef struct tagSIZE {
          LONG cx;
          LONG cy;
      } SIZE;
      2)大小類CSize
      大小類CSize也為一個沒有基類的獨立類,封裝了SIZE結(jié)構(gòu),有成員變量cx和cy,其構(gòu)造函數(shù)也有5種:
      CSize( );
      CSize( int initCX, int initCY );
      CSize( SIZE initSize );
      CSize( POINT initPt );
      CSize( DWORD dwSize ); // 低字設(shè)為cx、高字設(shè)為cy
      CSizet類也重載了+、-、+=、-=、==、!=等運算符來支持CSize對象和CSize、POINT、SIZE、RECT對象之間的運算。
      3.矩形
      1)矩形結(jié)構(gòu)RECT
      矩形結(jié)構(gòu)RECT定義了矩形的左上角與右下角的坐標(biāo):
      typedef struct tagRECT {

         LONG left;

         LONG top;

         LONG right;

         LONG bottom;

      } RECT;
      2)矩形類CRect
      矩形類CRect也為一個沒有基類的獨立類,封裝了RECT結(jié)構(gòu),有成員變量left、top、right和bottom,其構(gòu)造函數(shù)有6種:
      CRect( );

      CRect( int l, int t, int r, int b );

      CRect( const RECT& srcRect );

      CRect( LPCRECT lpSrcRect );

      CRect( POINT point, SIZE size );

      CRect( POINT topLeft, POINT bottomRight );

      CRect類重載了=,+、-,+=、-=,==、!=,&、|,& amp;=、|=等運算符來支持CRect對象和CRect、POINT、SIZE、RECT對象之間的運算。還定義了轉(zhuǎn)換符LPCRECT和 LPRECT來自動完成CRect對象到矩形結(jié)構(gòu)和類指針LPCRECT和LPRECT的轉(zhuǎn)換。
      CRect類中常用的屬性和成員函數(shù)有:
      int Width( ) const;
      int Height( ) const;
      CSize Size( ) const;
      CPoint& TopLeft( );
      CPoint& BottomRight( );
      CPoint CenterPoint( ) const;
      void SwapLeftRight();
      BOOL IsRectEmpty( ) const;
      BOOL PtInRect( POINT point ) const;
      void SetRect( int x1, int y1, int x2, int y2 );
      void SetRect(POINT topLeft, POINT bottomRight);
      void OffsetRect(int x, int y);
      void MoveToXY(int x, int y);
      3) 判斷點是否在矩形中
      有時需要判斷某點(如鼠標(biāo)位置)是否在某一矩形區(qū)域中,這可以調(diào)用CRect類的PtInRect函數(shù)來做:

      BOOL PtInRect( POINT point ) const;

      該函數(shù)當(dāng)點point在其矩形區(qū)域內(nèi)時,返回真。注意,該矩形區(qū)域不包括矩形的右邊界和底邊界。例如:

      CRect rect( 10, 10, 371, 267 );

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

      {

             // TODO: Add your message handler code here and/or call default

             if ( rect.PtInRect( point ) ) {
      ... ...
             }
      ... ...
             CView::OnLButtonUp(nFlags, point);
      }
       
      2 客戶區(qū)大小和DC
      在繪圖前,必須先得到客戶區(qū)大小和設(shè)備上下文DC。
      1.獲得客戶區(qū)
      繪圖一般都是在視圖窗口的客戶區(qū)進行,而客戶區(qū)的大小在運行時可由用戶改變,為了使繪制的圖形能隨窗口大小自動改變,必須先得到當(dāng)前客戶區(qū)大小的數(shù)據(jù)(寬w和高h)。
      獲取客戶區(qū)大小的方法有如下兩種:
      1)在消息響應(yīng)函數(shù)OnSize中獲得
      利用屬性窗口的信息頁,在視圖類中添加WM_SIZE消息的響應(yīng)函數(shù)OnSize。該函數(shù)在窗口第一次顯示或窗口大小被改變時會被Windows系統(tǒng)調(diào)用。其輸入?yún)?shù)中的cx和cy就是客戶區(qū)大小的寬和高,可將它們賦值給類變量(如m_iW和m_iH)供繪圖時使用。例如
      void CDrawView::OnSize(UINT nType, int cx, int cy) {

            CView::OnSize(nType, cx, cy);

       
            // TODO: 在此處添加消息處理程序代碼
            m_iW = cx;  m_iH = cy;
      }
      其中,nType的值為:

      <!--[if !supportLists]-->l         <!--[endif]-->SIZE_MAXIMIZED(窗口已被最大化)

      <!--[if !supportLists]-->l         <!--[endif]-->SIZE_MINIMIZED(窗口已被最小化)

      <!--[if !supportLists]-->l         <!--[endif]-->SIZE_RESTORED(窗口已被改變大?。?/p>

      <!--[if !supportLists]-->l         <!--[endif]-->SIZE_MAXHIDE(其他窗口被最大化)

      <!--[if !supportLists]-->l         <!--[endif]-->SIZE_MAXSHOW(其他窗口從最大化還原)

      2)調(diào)用成員函數(shù)GetClientRect得到
      可在繪圖前,定義一個矩形變量rect,然后再調(diào)用CWnd類的成員函數(shù)GetClientRect:

      void GetClientRect( LPRECT lpRect ) const;

      得到當(dāng)前客戶區(qū)矩形的數(shù)據(jù),其中的右(right)與底(bottom)就是客戶區(qū)的寬與高(其左left與頂top都為0)。例如:
             RECT rect;
             GetClientRect(&rect);
             int w = rect.right, h = rect.bottom;
      2.DC

      在Windows中,繪圖使用的是MFC的DC(Device-Context, 設(shè)備上下文)類CDC中各種繪圖函數(shù)。

      0)CDC類
      CDC是CObject的直接派生類,CDC類自己也有若干派生類,其中包括窗口客戶區(qū) DC所對應(yīng)的CClientDC類、OnPaint和OnDraw消息響應(yīng)函數(shù)的輸入?yún)?shù)中使用的CPaintDC類、圖元文件對應(yīng)的 CMetaFileDC類和整個窗口所對應(yīng)的CWindowDC類。
      CDC類中有許多成員函數(shù),可以用來設(shè)置各種繪圖環(huán)境、屬性和參數(shù),以及繪制各種圖形和圖像等,將在后面陸續(xù)加以介紹。
      1)獲得DC
      可以從OnDraw函數(shù)的輸入?yún)?shù)pDC或調(diào)用CWnd的成員函數(shù)GetDC:

      CDC* GetDC( );

      來獲得DC的指針。
      2)釋放DC
      因為Windows限制可用DC的數(shù)量,所以DC屬于稀缺的公用資源。因此,對每次獲得的DC,在使用完成后必須立即釋放。
      從OnDraw函數(shù)的輸入?yún)?shù)pDC獲得的DC,在該函數(shù)運行結(jié)束后,系統(tǒng)會自動釋放。但由GetDC所獲得的DC,必須自己來釋放,這可以通過調(diào)用CWnd的成員函數(shù)ReleaseDC來完成:

      int ReleaseDC( CDC* pDC ); // 成功返回非0

      例如:

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

      {
             ReleaseCapture();
             if (m_bLButtonDown) {
                    CDC* pDC = GetDC();

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

                    pDC->SelectStockObject(NULL_BRUSH);
                    pDC-> Ellipse (rect);
                    ReleaseDC(pDC);
                    m_bLButtonDown = FALSE;
             }
             CView::OnLButtonUp(nFlags, point);
      }
      3)類DC
      每次從OnDraw函數(shù)的輸入?yún)?shù)或調(diào)用GetDC所獲得的DC,都是一個全新的臨時缺省DC。它不能用類變量來長期保存,而且原來選入的各種GDI對象全都被作廢,必須從頭再來。
      為了使選入的各種GDI對象一直有效,必須在視圖類的PreCreateWindow函數(shù)中調(diào)用CWnd類的成員函數(shù)AfxRegisterWndClass:

      LPCTSTR AFXAPI AfxRegisterWndClass( UINT nClassStyle, HCURSOR hCursor = 0,

      HBRUSH hbrBackground = 0, HICON hIcon = 0 );

      來修改窗口類的風(fēng)格屬性中的DC為類DC:CS_CLASSDC。如
      BOOL CDrawView::PreCreateWindow(CREATESTRUCT& cs) {

          cs.lpszClass = AfxRegisterWndClass(CS_DBLCLKS | CS_HREDRAW |

      CS_VREDRAW | CS_CLASSDC, 0,

      ::CreateSolidBrush(RGB(255, 255, 255)));

             return CView::PreCreateWindow(cs);

      }
      4)安全DC句柄
      也可以用CDC類的成員函數(shù):

      HDC GetSafeHdc();

      來獲取CD所對應(yīng)窗口(如客戶區(qū))的安全DC句柄,該句柄在窗口存在期間一直是有效的。例如,可先定義類變量HDC m_hDC;,再在適當(dāng)?shù)牡胤浇o它賦值m_hDC = GetDC()->GetSafeHdc();,然后就可以放心地使用了。例如,可以使用CDC類的成員函數(shù)

      BOOL Attach(HDC hDC); // 成功返回非0

      來將CDC對象與DC句柄連接在一起。
      3 設(shè)置繪圖顏色
      1.顏色
      Windows中的顏色一般用4個字節(jié)表示(0BGR(整數(shù)) = R G B 0(字節(jié)序) [Intel CPU低位字節(jié)在前]),Win32 API中定義了一個專門表示顏色索引值的變量類型COLORREF:(windef.h)

      typedef DWORD COLORREF; // 0x00bbggrr

      和一個由紅綠藍三原色構(gòu)造顏色值的宏RGB:(wingdi.h)

      #define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16)))

      其中,r、g、b為字節(jié)變量,取值范圍為0~255。其函數(shù)說明為:
      COLORREF RGB(

       BYTE bRed,    // red component of color

       BYTE bGreen, // green component of color

       BYTE bBlue    // blue component of color

      );
      例如:

                    COLORREF red, gray;

                    red = RGB(255, 0, 0);

                    gray = RGB(128, 128,128);

      在API中還定義了由COLORREF變量獲取各個顏色分量的宏Get?Value:(wingdi.h)

      #define GetRValue(rgb) (LOBYTE(rgb))

      #define GetGValue(rgb) (LOBYTE(((WORD)(rgb)) >> 8))

      #define GetBValue(rgb) (LOBYTE((rgb)>>16))

      其中:
      typedef unsigned long ULONG_PTR;

      typedef ULONG_PTR DWORD_PTR;

      #define LOBYTE(w)  ((BYTE)((DWORD_PTR)(w) & 0xff))
      它們對應(yīng)的函數(shù)說明為:
      BYTE GetRValue(DWORD rgb); // DWORD rgb ~ COLORREF col
      BYTE GetGValue(DWORD rgb);
      BYTE GetBValue(DWORD rgb);
      2.點色(像素)
      在Windows中,像素(pixel)的顏色是直接由設(shè)備上下文類CDC的成員函數(shù)SetPixel來設(shè)置的,該函數(shù)的原型為:
      COLORREF SetPixel( int x, int y, COLORREF crColor );
      COLORREF SetPixel( POINT point, COLORREF crColor );
      其中,x與y分別為像素點的橫坐標(biāo)與縱坐標(biāo),crColor為像素的顏色值。例如:

      pDC->SetPixel(10, 10, RGB(0, 255, 0));

             另外,也可以用CDC的成員函數(shù)
      COLORREF GetPixel( int x, int y ) const;
      COLORREF GetPixel( POINT point ) const;
      來獲得指定點(x, y)或point的顏色。例如:
          COLORREF col;
          col = pDC->GetPixel(10, 10);
      3.線色(筆)
      在Windows中,線狀圖必須用筆(pen)來畫,所以線的顏色就由筆色來確定。在MFC中,筆的屬性和功能由CPen類提供(CPen是CGDIObject的派生類)。
      筆的創(chuàng)建與使用的步驟為:

      <!--[if !supportLists]-->l         <!--[endif]-->創(chuàng)建筆對象:創(chuàng)建筆類CPen對象的方法有如下兩種:

      <!--[if !supportLists]-->n         <!--[endif]-->使用構(gòu)造函數(shù)CPen

      CPen( int nPenStyle, int nWidth, COLORREF crColor );

      其中:

      <!--[if !supportLists]-->u       <!--[endif]-->nPenStyle為筆的風(fēng)格,可取值:

      PS_SOLID, PS_DASH, PS_DOT, PS_DASHDOT, PSDASHDOTDOT

       
      注意:1~4號筆風(fēng)格只是在筆寬=0或1時有效,筆寬>1時總為實心的。

      <!--[if !supportLists]-->u       <!--[endif]-->nWidth為筆寬,與映射模式有關(guān),使用缺省映射時為像素數(shù),若nWidth = 0,則不論什么映射模式,筆寬都為一個像素;

      <!--[if !supportLists]-->u       <!--[endif]-->crColor為筆的顏色值。

      例如
      CPen* pGrayPen = new CPen(PS_SOLID, 0, RGB(128, 128, 128));
      CPen grayPen(PS_SOLID, 0, RGB(128, 128, 128));

      <!--[if !supportLists]-->n         <!--[endif]-->使用成員函數(shù)CreatePen

      BOOL CreatePen( int nPenStyle, int nWidth, COLORREF crColor );

      如:
      CPen grayPen;
      grayPen.CreatePen(PS_SOLID, 0, RGB(128, 128, 128));

      <!--[if !supportLists]-->n         <!--[endif]-->缺省的筆為單像素寬的實心黑色筆

      <!--[if !supportLists]-->l         <!--[endif]-->將筆對象選入設(shè)備上下文:為了能使用我們所創(chuàng)建的筆對象,必須先將它選入設(shè)備上下文,這可以調(diào)用設(shè)備上下文類CDC的成員函數(shù)SelectObject來完成:

      CPen* SelectObject( CPen* pPen );
      返回值為指向原來筆對象的指針(一般將其保存下來,供下次再裝入時使用)。如
      pOldPen = pDC->SelectObject(&pen);
      另外,Windows中有一些預(yù)定義的筆對象,可用CDC的另一成員函數(shù)SelectStockObject將其選入DC,其函數(shù)原型為:
      virtual CGdiObject* SelectStockObject( int nIndex );
      預(yù)定義的筆對象有BLACK_PEN(黑色筆)、WHITE_PEN (白色筆)、NULL_PEN(空筆/無色筆)。例如:
      pDC->SelectStockObject(BLACK_PEN);

      <!--[if !supportLists]-->l         <!--[endif]-->使用設(shè)備上下文畫線狀圖:畫線狀圖以及面狀圖的邊線,所使用的是當(dāng)前設(shè)備上下文中的筆對象。線狀圖有直線、折線、矩形、(橢)圓(弧)等,詳見4)(2)

      <!--[if !supportLists]-->l         <!--[endif]-->將筆對象從設(shè)備上下文中放出:為了能刪除使用過的筆對象,必須先將它從設(shè)備上下文中釋放出來后,然后才能刪除。釋放的方法是裝入其他的筆對象(一般是重新裝入原來的筆對象)。例如

      pDC->SelectObject(pOldPen);

      <!--[if !supportLists]-->l         <!--[endif]-->刪除筆對象:為了能刪除筆對象,必須先將其從設(shè)備上下文中釋放。刪除方法有如下幾種:

      <!--[if !supportLists]-->n         <!--[endif]-->調(diào)用筆類CDC的成員函數(shù)DeleteObject刪除筆的當(dāng)前內(nèi)容(但是未刪除筆對象,以后可再用成員函數(shù)CreatePen在筆對象中繼續(xù)創(chuàng)建新的筆內(nèi)容)。如

      pen.DeleteObject();

      <!--[if !supportLists]-->n         <!--[endif]-->使用刪除運算符delete將筆對象徹底刪除,如delete pen;

      <!--[if !supportLists]-->n         <!--[endif]-->自動刪除:若筆對象為局部變量,則在離開其作用域時,會被系統(tǒng)自動刪除

      下面為一段較完整地創(chuàng)建與使用筆的例子代碼:
             CPen pen, *pOldPen;

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

                    HSLtoRGB(m_hue, m_sat, 255 - j, r, g, b); // 自定義的函數(shù)

                    pen.CreatePen(PS_SOLID, 0, RGB(r, g, b));

                    pOldPen = pDC->SelectObject(&pen);

                    pDC->MoveTo(0, j); pDC->LineTo(40, j);

                    pDC->SelectObject(pOldPen);
                    pen.DeleteObject();
             }
      4.面色(刷)
      在Windows中,面狀圖必須用刷(brush)來填充,所以面色是由刷色來確定的。MFC中的刷類為CBrush(它也是CGDIObject的派生類),刷的創(chuàng)建與使用的步驟與筆的相似。

      <!--[if !supportLists]-->l         <!--[endif]-->構(gòu)造函數(shù)有4個:

      <!--[if !supportLists]-->n         <!--[endif]-->CBrush( ); // 創(chuàng)建一個刷的空對象

      <!--[if !supportLists]-->n         <!--[endif]-->CBrush( COLORREF crColor ); // 創(chuàng)建顏色為crColor的實心刷

      <!--[if !supportLists]-->n         <!--[endif]-->CBrush( int nIndex, COLORREF crColor ); // 創(chuàng)建風(fēng)格由nIndex指定且顏色為crColor的條紋(hatch孵化)刷,其中nIndex可取條紋風(fēng)格(Hatch Styles)值:

      符號常量
      數(shù)字常量
      風(fēng)格
      HS_HORIZONTAL
      0
      水平線
      HS_VERTICAL
      1
      垂直線
      HS_FDIAGONAL
      2
      正斜線
      HS_BDIAGONAL
      3
      反斜線
      HS_CROSS
      4
      十字線(正網(wǎng)格)
      HS_DIAGCROSS
      5
      斜十字線(斜網(wǎng)格)
       

      <!--[if !supportLists]-->n         <!--[endif]-->CBrush( CBitmap* pBitmap ); // 創(chuàng)建位圖為pBitmap的圖案刷

      如:pDC->FillRect( &rect, new CBrush( RGB(r, g, b) ) );

      <!--[if !supportLists]-->l         <!--[endif]-->與構(gòu)造函數(shù)相對應(yīng),有多個創(chuàng)建不同類型刷的成員函數(shù):

      <!--[if !supportLists]-->n         <!--[endif]-->BOOL CreateSolidBrush( COLORREF crColor );

      <!--[if !supportLists]-->n         <!--[endif]-->BOOL CreateHatchBrush( int nIndex, COLORREF crColor );

      <!--[if !supportLists]-->n         <!--[endif]-->BOOL CreatePatternBrush( CBitmap* pBitmap );

      <!--[if !supportLists]-->n         <!--[endif]-->BOOL CreateDIBPatternBrush( HGLOBAL hPackedDIB, UINT nUsage );

      <!--[if !supportLists]-->n         <!--[endif]-->BOOL CreateDIBPatternBrush( const void* lpPackedDIB, UINT nUsage );

      <!--[if !supportLists]-->n         <!--[endif]-->BOOL CreateBrushIndirect( const LOGBRUSH* lpLogBrush );

      <!--[if !supportLists]-->n         <!--[endif]-->BOOL CreateSysColorBrush( int nIndex );

      <!--[if !supportLists]-->l         <!-- [endif]-->預(yù)定義的刷對象有BLACK_BRUSH(黑刷)、DKGRAY_BRUSH(暗灰刷)、GRAY_BRUSH(灰刷)、 HOLLOW_BRUSH(空刷)、LTGRAY_BRUSH(亮灰刷)、NULL_BRUSH(空刷)、WHITE_BRUSH(白刷)

      <!--[if !supportLists]-->l         <!--[endif]-->缺省的刷為空刷

      <!--[if !supportLists]-->l         <!--[endif]-->與筆一樣,可以用函數(shù)SelectObject或SelectStockObject將自定義的刷或預(yù)定義的刷選入DC中,供繪面狀圖時使用。

      5.文本色
      可使用CDC類的成員函數(shù)SetTextColor和SetBkColor來分別設(shè)置輸出文本的前景色和背景色:(缺省的前景色為黑色,背景色空)
      COLORREF GetTextColor( ) const;
      virtual COLORREF SetTextColor( COLORREF crColor );
      COLORREF GetBkColor( ) const;
      virtual COLORREF SetBkColor( COLORREF crColor );
      例如:

             pDC->TextOut(10, 10, "Test text");

             pDC->SetTextColor(RGB(0, 128, 0)); pDC->TextOut(10, 30, "Test text");

             pDC->SetBkColor(RGB(0, 0, 128));     pDC->TextOut(10, 50, "Test text");

      6.繪圖工具
      1)GDI對象

      Windows的圖形設(shè)備接口(GDI = graphics device interface)對象指各種繪圖工具,如筆、刷、位圖、字體、調(diào)色板、區(qū)域等,對應(yīng)的MFC類為CPen、CBrush、CBitmap、CFont等。這些圖形繪制對象類都是CGDIObject的派生類,而CGDIObject則是直接從CObject類派生的抽象基類。<!--[endif]-->其中,Windws CE不支持調(diào)色板類CPalette;CRgn為區(qū)域類,對應(yīng)于窗口中的一個矩形、多邊形或(橢)圓區(qū)域(region),可用于移動、拷貝、合并、判斷和裁剪。

      2)選入
      可用設(shè)備上下文類CDC的多態(tài)成員函數(shù)SelectObject,來將繪圖工具對象選入設(shè)備上下文,以供繪圖時使用:
      CPen* SelectObject( CPen* pPen );
      CBrush* SelectObject( CBrush* pBrush );
      virtual CFont* SelectObject( CFont* pFont );
      CBitmap* SelectObject( CBitmap* pBitmap );
      int SelectObject( CRgn* pRgn );
      CGdiObject* SelectObject( CGdiObject* pObject );
      3)獲取
      可用API函數(shù)GetCurrentObject來獲得當(dāng)前在DC中的指定類型的繪圖對象:
      HGDIOBJ GetCurrentObject(

       HDC hdc,           // handle to device context

       UINT uObjectType   // specifies the object-type

      );
      其中,參數(shù)uObjectType可取值:

      OBJ_PEN      // Returns the current selected pen.

      OBJ_BRUSH // Returns the current selected brush.

      OBJ_PAL       // Returns the current selected palette.

      OBJ_FONT  // Returns the current selected font.

      OBJ_BITMAP // Returns the current selected bitmap.
      也可分別調(diào)用CDC類的下列成員函數(shù)來做同樣的事:

      CPen* GetCurrentPen( ) const;

      CBrush* GetCurrentBrush( ) const;

      CFont* GetCurrentFont( ) const;

      CBitmap* GetCurrentBitmap( ) const;

      CPalette* GetCurrentPalette( ) const;

      如:

      HPEN hPen = (HPEN)GetCurrentObject(pDC->m_hDC, OBJ_PEN);

      CPen* pPen = CPen::FromHandle(hPen);

      等價于:

      CPen* pPen = pDC-> GetCurrentPen( );

      4 畫圖
      在Windows中,繪圖一般在視圖窗口的客戶區(qū)進行,使用的是設(shè)備上下文類CDC中各種繪圖函數(shù)。
      1. 映射模式與坐標(biāo)系
      1)默認(rèn)映射模式
      映射模式(map mode)影響所有的圖形和文本繪制函數(shù),它定義(將邏輯單位轉(zhuǎn)換為設(shè)備單位所使用的)度量單位和坐標(biāo)方向,Windows總是用邏輯單位來繪圖。

      缺省情況下,繪圖的默認(rèn)映射模式為MM_TEXT,其繪圖單位為像素(只要不打印輸出,屏幕繪圖使用該模式就夠了)。若窗口客戶區(qū)的寬和高分別為w和h像素,則其x坐標(biāo)是從左到右,范圍為0 ~ w-1;y坐標(biāo)是從上到下,范圍為0 ~ h-1。

      2)設(shè)置映射模式
      可以使用CDC類的成員函數(shù)GetMapMode和SetMapMode來獲得和設(shè)置當(dāng)前的映射模式:
      int GetMapMode( ) const; // 返回當(dāng)前的映射模式

      virtual int SetMapMode( int nMapMode ); // 返回先前的映射模式

       
      映射模式的nMapMode取值與含義
      符號常量
      數(shù)字常量
      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的向下, 其余的都是向上,與數(shù)學(xué)上一致。除了MM_ANISOTROPIC外,其他所有映射模式的x與y方向的單位都是相同的。所有映射模式的邏輯坐標(biāo)的原點 (0, 0)最初都是在窗口的左上角,但在CScrollView的派生類中,MFC會隨用戶滾動文檔而自動調(diào)整邏輯原點的相對位置(改變視點的原點屬性)。
      3)自定義映射模式
      自定義映射模式MM_ISOTROPIC(各向同性,x與y方向的單位必須相同)和 MM_ANISOTROPIC(各向異性,x與y方向的單位可以不同)的單位和方向,可以通過用CDC類的成員函數(shù)G/SetWindowExt和G /SetViewportExt來獲取/設(shè)置窗口和視口的大小來確定:
      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類的成員函數(shù)SetViewportOrg來設(shè)置坐標(biāo)原點的位置:
      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));

      }
      將當(dāng)前的映射模式設(shè)置為各向異性自定義映射模式,窗口大小為1000個邏輯單位寬和1000個邏輯單位高,視口大小同當(dāng)前客戶區(qū),視口的坐標(biāo)原點設(shè)置在當(dāng)前客戶區(qū)的中央。由于使用了負(fù)數(shù)作為SetViewportExt函數(shù)的第2個參數(shù),所以y軸方向是向上的。
       
      可見,圓被畫成了橢圓,x與y方向上的邏輯單位不相同。
      4)單位轉(zhuǎn)換
      對所有非MM_TEXT映射模式,有如下重要規(guī)則:

      <!--[if !supportLists]-->l         <!--[endif]-->CDC的成員函數(shù)(如各種繪圖函數(shù))具有邏輯坐標(biāo)參數(shù)

      <!--[if !supportLists]-->l         <!--[endif]-->CWnd的成員函數(shù)(如各種響應(yīng)函數(shù))具有設(shè)備坐標(biāo)參數(shù)(如鼠標(biāo)位置point)

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

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

       
      因此,為了使應(yīng)用程序能夠正確工作,除MM_TEXT映射模式外,其他映射模式都需要進行單位轉(zhuǎn)換。下面是邏輯單位到設(shè)備單位(如像素)的轉(zhuǎn)換公式:
      x比例因子 = 視口寬度 / 窗口寬度
      y比例因子 = 視口高度 / 窗口高度
      設(shè)備x = 邏輯x * x比例因子 + x原點偏移量
      設(shè)備y = 邏輯y * y比例因子 + y原點偏移量
      Windows的GDI負(fù)責(zé)邏輯坐標(biāo)和設(shè)備坐標(biāo)之間的轉(zhuǎn)換,這可以調(diào)用CDC類的成員函數(shù)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; // 邏輯坐標(biāo)

                    CClientDC dc(this);
                    dc.SetMapMode(MM_LOENGLISH);
                    dc.LPtoDP(rect); // 轉(zhuǎn)化成設(shè)備坐標(biāo)

             if (rect.PtInRect(point)) // 位置的測試操作只有使用設(shè)備坐標(biāo)時才有效

             ......
      }

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

             float t,y;

                    char buf[40];

             CDC* pDC = GetDC();

      pDC->SetMapMode(MM_HIMETRIC);
                    pDC->DPtoLP(&point); // 轉(zhuǎn)化成邏輯坐標(biāo)

      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. 畫像素點
      畫像素點就是設(shè)置像素點的顏色,從前面3)(2)已知道這可由CDC的成員函數(shù)SetPixel來做,該函數(shù)的原型為:

      COLORREF SetPixel( int x, int y, COLORREF crColor ); 或

      COLORREF SetPixel( POINT point, COLORREF crColor );

      其中,x與y分別為像素點的橫坐標(biāo)與縱坐標(biāo),crColor為像素的顏色值。例如

      pDC->SetPixel(i, j, RGB(r, g, b));

      3.畫線狀圖
      在Windows中,線狀圖必須用筆來畫(筆的創(chuàng)建與使用見前面的3)(3)),下面是CDC類中可以繪制線狀圖的常用成員函數(shù):

      <!--[if !supportLists]-->l         <!--[endif]-->當(dāng)前位置:設(shè)置當(dāng)前位置為(x, y)或point:(返回值為原當(dāng)前位置的坐標(biāo))

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

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

      BOOL LineTo( int x, int y ); 或BOOL LineTo( POINT point );

      <!--[if !supportLists]-->l         <!--[endif]-->畫折線:使用DC中的筆,依次將點數(shù)組lpPoints中的nCount(≥2)個點連接起來,形成一條折線:

      BOOL Polyline( LPPOINT lpPoints, int nCount );

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

      BOOL Polygon( LPPOINT lpPoints, int nCount );

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

      BOOL Rectangle( int x1, int y1, int x2, int y2 ); 或
      BOOL Rectangle( LPCRECT lpRect );
                    有時需要根據(jù)用戶給定的兩個任意點來重新構(gòu)造左上角和右下角的點,例如:

                    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矩形的內(nèi)接橢圓倒角,再用DC中的刷填充其內(nèi)部區(qū)域:

      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的矩形中畫內(nèi)接(橢)圓的邊線,并用DC中的刷填充其內(nèi)部區(qū)域:

      BOOL Ellipse( int x1, int y1, int x2, int y2 );
      BOOL Ellipse( LPCRECT lpRect );
      注意,CDC中沒有畫圓的專用函數(shù)。在這里,圓是作為橢圓的(寬高相等)特例來畫的。

      <!--[if !supportLists]-->l         <!--[endif]-->畫?。?x1, y1)與(x2, y2)或lpRect的含義同畫(橢)圓,(x3, y3)或ptStart為弧的起點,(x4, y4)或ptEnd為弧的終點:(逆時針方向旋轉(zhuǎn))

      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]-->畫弓弦:參數(shù)的含義同上,只是用一根弦連接弧的起點和終點,形成一個弓形,并用DC中的刷填充其內(nèi)部區(qū)域:

      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中,面狀圖必須用刷來填充(刷的創(chuàng)建與使用見前面的3)(4))。上面 (2)中的Polygon、Rectangle、Ellipse和Chord等畫閉合線狀圖的函數(shù),只要DC中的刷不是空刷,都可以用來畫對應(yīng)的面狀圖 (邊線用當(dāng)前筆畫,內(nèi)部用當(dāng)前刷填充)。下面介紹的是CDC類中只能繪制面狀圖的其他常用成員函數(shù):

      <!--[if !supportLists]-->l         <!--[endif]-->畫填充矩形:用指定的刷pBrush畫一個以lpRect為區(qū)域的填充矩形,無邊線,填充區(qū)域包括矩形的左邊界和上邊界,但不包括矩形的右邊界和下邊界:

      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]-->畫餅圖(扇形):參數(shù)含義同Arc,但將起點和終點都與外接矩形的中心相連接,形成一個扇形區(qū)域,用DC中的刷填充整個扇形區(qū)域,無另外的邊線:

      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]-->填充區(qū)域:

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

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

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

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

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

      <!--[if !supportLists]-->u <!--[endif]-->nFillType = FLOODFILLBORDER:填充到顏色為crColor的邊界(同F(xiàn)loodFill);(用于填充內(nèi)部顏色不同但邊界顏色相同的區(qū)域)
      <!--[if !supportLists]-->u <!--[endif]-->nFillType = FLOODFILLSURFACE:填充所有顏色為crColor的點,直到碰到非crColor顏色的點為止。(點(x, y)的顏色也必須為crColor),(用于填充內(nèi)部顏色相同但邊界顏色可以不同的區(qū)域)。例如:

      pDC->ExtFloodFill(point.x, point.y, pDC->GetPixel(point), FLOODFILLSURFACE);

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

         LPCRECT lpRectUpdate = NULL,

         CRgn* prgnUpdate = NULL,

         UINT flags = RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE

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

             pDC->FillSolidRect(&rect, RGB(255, 255, 255));

      6.在控件上繪圖
      可以在對話框資源中放置圖片控件,并對其類型屬性選Frame??稍趯υ捒虻睦L圖消息響應(yīng)函數(shù)OnPaint或其他函數(shù)中,用CWnd類的函數(shù)GetDlgItem:
      CWnd* GetDlgItem( int nID ) const;
      來獲得圖片控件的窗口對象,再用函數(shù)GetDC:

      CDC* GetDC( );

      由窗口對象得到DC,然后就可以用該DC在控件中畫圖。如(在ID為IDC_HUESAT的圖片控件上畫調(diào)色板)
      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); // 自定義函數(shù),見網(wǎng)絡(luò)硬盤的

      // res目錄中的ColTrans.cpp文件

                                  pDC->SetPixel(i, j, RGB(r, g, b));

                           }
                    ... ...
             }
      }
      在非Frame類靜態(tài)控件上繪圖,必須先按順序依次調(diào)用CWnd類的Invalidate和UpdateWindow函數(shù)后,再開始用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]-->除了基于對話框的程序外,其他對話框類都需要自己添加(重寫型)消息響應(yīng)函數(shù)OnInitDialog,來做一些必要的初始化 對話框的工作。添加方法是:先在項目區(qū)選中“類視圖”頁,再選中對應(yīng)的對話框類,然后在屬性窗口的“重寫”頁中添加該函數(shù);

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

      <!--[if !supportLists]-->l     <!--[endif]-->一般的對話框類,缺省時都沒有明寫出OnPaint函數(shù)??梢宰约涸趯υ捒蝾愔刑砑覹M_PAINT消息的響應(yīng)函數(shù)OnPaint來進行一些繪圖工作。

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

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

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

      //CDialog::OnPaint();

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

      DWORD GetSysColor( int nIndex);
      得到,其中的nIndex取為COLOR_BTNFACE。例如:
      dc.SetBkColor(GetSysColor(COLOR_BTNFACE));
       
      下面是部分例子代碼:(其中FillColor和ShowImg為自定義的成員函數(shù))
      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: 在此處添加消息處理程序代碼
             // 不為繪圖消息調(diào)用 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 設(shè)置繪圖屬性
      除了映射模式外,還有許多繪圖屬性可以設(shè)置,如背景、繪圖方式、多邊形填充方式、畫弧方向、刷原點等。
      1.背景
      1)背景色
      當(dāng)背景模式為不透明時,背景色決定線狀圖的空隙顏色(如虛線中的空隙、條紋刷的空隙和文字的空隙),可以使用CDC類的成員函數(shù)GetBkColor和SetBkColor來獲得和設(shè)置當(dāng)前的背景顏色:
      COLORREF GetBkColor( ) const; // 返回當(dāng)前的背景色
      virtual COLORREF SetBkColor( COLORREF crColor ); // 返回先前的背景色
                                                                                    // 若出錯返回0x80000000
      2)背景模式
      背景模式影響有空隙的線狀圖的空隙(如虛線中的空隙、條紋刷的空隙和文字的空隙)用什么辦法填充??梢允褂肅DC類的成員函數(shù)GetBkMode和SetBkMode來獲得和設(shè)置當(dāng)前的背景模式:
      int GetBkMode( ) const; // 返回當(dāng)前背景模式
      int SetBkMode( int nBkMode ); // 返回先前背景模式
      背景模式的取值
      nBkMode值
      名稱
      作用
      OPAQUE
      不透明的(缺省值)
      空隙用背景色填充
      TRANSPARENT
      透明的
      空隙處保持原背景圖不變
      2. 繪圖模式
      繪圖模式(drawing mode)指前景色的混合方式,它決定新畫圖的筆和刷的顏色(pbCol)如何與原有圖的顏色(scCol)相結(jié)合而得到結(jié)果像素色(pixel)。
      1)設(shè)置繪圖模式
      可使用CDC類的成員函數(shù)SetROP2 (ROP = Raster OPeration光柵操作)來設(shè)置繪圖模式:

      int SetROP2( int nDrawMode );

      其中,nDrawMode可取值:
      繪圖模式nDrawMode的取值
      符號常量
      作用
      運算結(jié)果
      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)畫移動圖形
      為了能畫移動的位置標(biāo)識(如十字、一字)和隨鼠標(biāo)移動畫動態(tài)圖形(如直線、矩形、橢圓),必須在不破壞原有背景圖形的基礎(chǔ)上移動這些圖形。
      移動圖形采用的是異或畫圖方法,移動圖形的過程為:異或畫圖、在原位置再異或化圖(擦除)、在新位置異或畫圖、……。

             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;
      較完整的拖放動態(tài)畫圖的例子,可參照下面的“3. 拖放畫動態(tài)直線”部分。
      3)其他屬性

      <!--[if !supportLists]-->l         <!--[endif]-->多邊形填充方式:可使用CDC類的成員函數(shù)GetPolyFillMode和SetPolyFillMode來確定多邊形的填充方式:

      int GetPolyFillMode( ) const;
      int SetPolyFillMode( int nPolyFillMode );
      其中nPolyFillMode 可取值A(chǔ)LTERNATE(交替——填充奇數(shù)邊和偶數(shù)邊之間的區(qū)域,缺省值)或WINDING(纏繞——根據(jù)多邊形邊的走向來確定是否填充一區(qū)域)

      <!--[if !supportLists]-->l         <!--[endif]-->畫弧方向:可使用CDC類的成員函數(shù)GetArcDirection和SetArcDirection來確定Arc、Chord、Pie等函數(shù)的畫弧方向:

      int GetArcDirection( ) const;
      int SetArcDirection( int nArcDirection );
      其中,nArcDirection可取值A(chǔ)D_COUNTERCLOCKWISE(逆時針方向,缺省值)和AD_CLOCKWISE(順時針方向)

      <!--[if !supportLists]-->l         <!--[endif]-->刷原點:可使用CDC類的成員函數(shù)GetBrushOrg和SetBrushOrg來確定可填充繪圖函數(shù)的條紋或圖案刷的起點:(缺省值為客戶區(qū)左上角的坐標(biāo)原點(0, 0))

      CPoint GetBrushOrg( ) const;
      CPoint SetBrushOrg( int x, int y );
      CPoint SetBrushOrg( POINT point );
      3.拖放畫動態(tài)直線
      下面是一個較完整的拖放動態(tài)畫直線的例子:
      // 類變量
      class CDrawView : public CView {
             //……
      protected:

             BOOL m_bLButtonDown, m_bErase; // 判斷是否按下左鼠標(biāo)鍵

      //和是否需要擦除圖形的類變量

             CPoint p0, pm; // 記錄直線起點和動態(tài)終點的類變量

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

             //……
      }
      // 構(gòu)造函數(shù)
      CDrawView::CDrawView() {

             m_bLButtonDown = FALSE; // 設(shè)左鼠標(biāo)鍵按下為假

             m_bErase = FALSE; // 設(shè)需要擦除為假

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

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

      }
      // 鼠標(biāo)消息響應(yīng)函數(shù)

      void CDrawView::OnLButtonDown(UINT nFlags, CPoint point) {

             m_bLButtonDown = TRUE; // 設(shè)左鼠標(biāo)鍵按下為真

             SetCapture(); // 設(shè)置鼠標(biāo)捕獲

             // SetCursor(LoadCursor(NULL, IDC_CROSS)); // 設(shè)置鼠標(biāo)為十字

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

             pm = p0; // 讓矩形右下角等于左上角

             CView::OnLButtonDown(nFlags, point);

      }

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

             SetCursor(LoadCursor(NULL, IDC_CROSS)); // 設(shè)置鼠標(biāo)為十字

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

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

                    pDC->SelectObject(pGrayPen);// 選取灰色筆
                    pDC->SetROP2(R2_XORPEN);// 設(shè)置為異或繪圖方式

                    if (m_bErase) { // 需要擦除為真

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

                    }

                    else // 需要擦除為假

                           m_bErase = TRUE; // 設(shè)需要擦除為真

                    pDC->MoveTo(p0); pDC->LineTo(point); // 繪制新直線

                    pm = point; // 記錄老終點

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

             }

             CView::OnMouseMove(nFlags, point);

      }

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

             ReleaseCapture(); // 釋放鼠標(biāo)捕獲

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

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

                    pDC->SelectObject(pGrayPen);// 選取灰色筆
                    pDC->SetROP2(R2_XORPEN); // 設(shè)置為異或繪圖方式

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

                    pDC->SelectObject(pLinePen); // 選擇直線筆
                    pDC->SetROP2(R2_COPYPEN);// 設(shè)置為覆蓋繪圖方式

                    pDC->MoveTo(p0); pDC->LineTo(point); // 繪制最終的直線

                    m_bLButtonDown = FALSE; // 重設(shè)左鼠標(biāo)鍵按下為假

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

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

             }

             CView::OnLButtonUp(nFlags, point);

      }

      posted on 2016-01-05 02:28  loveday  閱讀(953)  評論(0)    收藏  舉報

      主站蜘蛛池模板: 欧美国产日产一区二区| 日本三级理论久久人妻电影 | 天堂中文8资源在线8| 中文字幕日韩人妻一区| 中文字幕国产日韩精品| 国产一区二区三区麻豆视频| 香港日本三级亚洲三级| 饶平县| 久久综合综合久久高清免费| 无码毛片一区二区本码视频 | 国产乱码精品一区二区三| 久久精品国产一区二区三| 激情综合网激情激情五月天| 亚洲红杏AV无码专区首页| 午夜视频免费试看| 五月婷之久久综合丝袜美腿| 性色av无码久久一区二区三区| 毛片av在线尤物一区二区| 国产综合精品一区二区在线| 久久精品国产亚洲精品色婷婷| 国产99在线 | 欧美| 国产成人精彩在线视频| 忘忧草社区在线www| 男女无遮挡激情视频| 国产精品免费中文字幕| 无码天堂va亚洲va在线va| 四川丰满少妇无套内谢| 国产玩具酱一区二区三区| 中文人妻av高清一区二区| 国产不卡精品视频男人的天堂| 饥渴少妇高潮正在播放| 国产成人午夜福利院| 国产精品永久免费成人av| 国产a在视频线精品视频下载 | 国产三级精品三级在线看| 亚洲av日韩在线资源| 国产精品久久国产丁香花| 农村老熟妇乱子伦视频| 少妇伦子伦情品无吗| 亚洲男人AV天堂午夜在| 久久精品国产2020|