Windows GDI繪圖基礎知識
一、Windows可以畫直線、橢圓線(橢圓圓周上的曲線)和貝塞爾曲線。
////////////7 個畫線函式是:
(1)畫直線LineTo BOOL LineTo(HDC hdc,int nXEnd,int nYEnd);結合MoveToEx函式使用BOOL MoveToEx(HDC hdc,int X,int Y,LPPOINT lpPoint)
Point記錄了舊的座標點(先前的當前位置)。///注意:GetCurrentPositionEx (hdc, &pt) ;獲得當前位置。
(2)畫一系列相連的直線。Polyline 把Point陣列的點連線成線。不用當前點做開始點,PolylineTo 使用當前點做開始點,並將當前的位置設定成最後一根線的終點。PolyPolyline 畫多組相連的線。
(3)填充矩形Rectangle 畫一個矩形,並用白色刷子填充、Rectangle(hdc,xleft,ytop,xright,ybottom)Ellipse 畫一橢圓,並用白色的刷子填充。Ellipse (hdc,xleft,ytop,xright,ybottom)RoundRect 畫圓角矩形。並用白色的刷子填充 RoundRect(hdc,xL,yT,xR,yB,xC,yC) xC,yC是圓角矩形的圓角。Arc 畫橢圓線。Arc (hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd,yEnd) Chord 畫弦弓形Chord(hdc,xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd) Pie 畫餅形圖 Pie(hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd);ArcTo 和AngleArc 畫橢圓線。
//////多邊形Polygon(hdc,apt,iCount); //畫一個多邊形,最後一點與第一點相連。PolyPolygon(hdc,apt,aiCount,iPolyCount); //畫多個多邊形。
(4)貝塞爾曲線,畫貝塞爾曲線POINY apt【4】=(起點,第一控制點,第二控制點,終點)需要注意的是::曲線是起點到終點的連線曲線,控制點(調整點)不在其中、PolyBezier (hdc,apt,icount)PolyBezierTo (hdc,apt,icount)。使用當前點為起點PolyDraw 畫一系列相連的線以及貝塞爾曲線。對於多條貝塞爾曲線,後一條的起點是前一條的終點。
(5)矩形函式FillRect(hdc,&rect,hBrush); //使用指定的畫刷來填充矩形,(不包含(Right,buttom)FrameRect(hdc,&rect,hBrush);//使用畫刷來填充矩形框,不填充矩形,InvertRect(hdc,&rect); //使畫素翻轉,白變黑,黑變白,綠變紅。
///////對Rect的操作SetRect(&rect,xLeft,yTop,xRight,yButtom);//賦值OffsetRect(&rect,x,y); //沿x,y移動InflateRect(&rect,x,y); //增減矩形的尺寸。SetRectEmpty(&rect); //置0CopyRect(&A,&B);把B複製到A.IntersectRect(&A,&B1,&B2);//把B1和B2的交集複製到A.UnionRect(&A,&B1,&B2); //取並集bEmpty=IsRectEmpty(&Rect);//判斷矩形是否為空。blnRect=PtlnRect(&Rect,point); //判斷點是否在矩形中。
二、映像座標
1)、視口:裝置座標(畫素)視窗:邏輯座標,畫素、mm、英寸視口(裝置)座標轉換為視窗(邏輯)座標:公式:一般不用記,有專門的函式。xWindow=(xViewport - xViewOrg) * xWinExt/xViewExt +xWinOrgyWindow=(yViewport - yViewOrg) * yWinExt/yViewExt +yWinOrg
(xWindow,yWindow) 轉換後的視窗座標(xViewport,yViewport)待轉換的視口座標(xWinExt,yWinExt)是邏輯座標的視窗範圍;(xViewExt,yViewExt)是裝置座標的視窗範圍。(xWinOrg,yWinOrg)是邏輯座標的視窗原點;(xViewOrg,yViewOrg)是裝置座標的視口原點
2)、裝置點轉化為邏輯點DPtoLP (hdc, pPoints, iNumber);pPoints 結構陣列的指標,而iNumber 是要轉換的點的個數例如:GetClientRect (hwnd, &rect) ;DPtoLP (hdc, (PPOINT) &rect, 2) ;
將邏輯點轉換為裝置點:LPtoDP (hdc, pPoints, iNumber) ;
3)、SetMapMode(hdc,iMapMode); //設定對映方式。預設:MM_TEXT:每個邏輯單位轉換為一個圖素,X正方向向右,Y正方向向下。原點可以改變,範圍不可改變SetWindowOrgEx(); //設定裝置環境的原點SetViewprocOrgEx(); //設定客戶區中心////原點和範圍都可以改變、MM_ANISOTROPIC:邏輯單位轉換成具有任意比例軸的任意單位,用SetWindowExtExSetViewportExtEx函式可指定單位、方向和比例。
//原點可以改變,範圍不可以改變,X的正方面向右,Y的正方向向上。MM_HIENGLISH:每個邏輯單位轉換為0.001英寸,X的正方面向右,Y的正方向向上。MM_HIMETRIC:每個邏輯單位轉換為0.01毫米,X正方向向右,Y的正方向向上。MM_ISOTROPIC:邏輯單位轉換成具有均等比例軸的任意單位,即沿X軸的一個單位等於沿Y軸的一個單位,用和函式可以指定該軸的單位和方向。圖形裝置介面(GDI)需要進行調整,以保證X和Y的單位保持相同大小(當設定視窗範圍時,視口將被調整以達到單位大小相同)。MM_LOENGLISH:每個邏輯單位轉換為0.01英寸,X正方向向右,Y正方向向上。MM_LOMETRIC:每個邏輯單位轉換為0.1毫米,X正方向向右,Y正方向向上。MM_TWIPS;每個邏輯單位轉換為列印點的1/20(即1/1400英寸),X正方向向右,Y方向向上。
三、GDI 物件
畫筆、刷子、點陣圖、區域、字型、調色盤是可以建立的6種GDI物件。GetStockObject(obj);獲取物件的控制代碼。DeleteObject(obj); 刪除物件。(注意不能在有效的裝置描述表中刪除。)除調色盤外,其他物件都是透過SelectObject(hdc,obj);選入裝置描述表中。GetObject(HOBJ,size,lpObj); lpObj可以是下列的結構體。獲取物件資訊、BITMAP //點陣圖DIBSECTION //點陣圖 EXTLOGPEN //畫筆LOGBRUSH //刷 LOGFONT //字型LOGPEN //畫筆(1)畫筆(Pen) windows的預設值:BLACK_PEN建立:方法一:hPen=CreatePen(iPenStyle,iWidth,crColor);iPenStyle的引數:PS_SOLID 實心畫筆 PS_DASH 破折號畫筆(在iWidth<1有效,否則系統會用實心筆替代) PS_DOT 虛線(在iWidth<1有效,否則系統會用實心筆替代) PS_DASHDOT 點劃線(在iWidth<1有效,否則系統會用實心筆替代) PS_DASHDOTDOT 雙重點劃線(在iWidth<1有效,否則系統會用實心筆替代) PS_NULL 空白筆 PS_INSIDEFRAME 粗實線,當iWidth>1可以使用抖動色(不只是純色)
方法二:LOGPEN logpen //指定筆顏色、大小、型別的結構體。同上。 hPen=CreatePenIndirect(&logpen);
(2)字型(Font) 預設值:SYSTEM_FONT建立:一:CreateFont只用到2個引數,其他都為0,例:CreateFont (0, 0, 0, 0, 0, 0, 0, 0, dwCharSet, 0, 0, 0, FIXED_PITCH, NULL)HFONT CreateFont( int nHeight, // 字元寬度,邏輯單位 int nWidth, // int nEscapement, // 斜放置字串 int nOrientation, // 字元傾斜的角度,影響單個字元 int fnWeight, // 粗體。0—400標準,700粗體 DWORD fdwItalic, // 斜體 DWORD fdwUnderline, // 下劃線 DWORD fdwStrikeOut, // 刪除線 DWORD fdwCharSet, // 1為預設值。指定字型字符集一個位元組的值(*不用理會) DWORD fdwOutputPrecision, // 輸出精度* DWORD fdwClipPrecision, // 裁剪精度* DWORD fdwQuality, // 期望匹配字型* DWORD fdwPitchAndFamily, // 字型族* LPCTSTR lpszFace // 字樣*); 字型:SYSTEM_FONT SYSTEM_FIXED_FONT OEM_FIXED_FONT
ANSI_FIXED_FONT、ANSI_VAR_FONT DEVICE_DEFAULT_FONT
其中: WM_INPUTLANGCHANGE: dwCharSet = wParam ;二:LOGFONT logfont; CreateFontIndirect(&logfont);
(3)刷子(Brush) 預設值::WHITE_BRUSH 系統的刷子: WHITE_BRUSH LTGRAY_BRUSH 亮灰 GRAY_BRUSH 灰 DKGRAY_BRUSH 黑灰 BLACK_BRUSH 建立:一:hBrush=CreateSolidBrush(crColor);二:hBrush=CreateHatchBrush(iHatchStyle,crColor);//建立有影線的刷子填充部分為陰影其中:iHatchStyle的引數如下: HS_BDIAGONAL 45度的斜線、 HS_CROSS 十字型的線、 HS_DIAGCROSS ×型 HS_FDIAGONAL 135度斜線 HS_HORIZONTAL 水平 HS_VERTICAL 垂直 三:LOGBRUSH logbrush CreateBrushIndirect(&logbrush);四: hBrush=CreatePatternBrush(HBITMAP hbmp);//建立點陣圖的刷子、五:hBrush=CreateDIBPatternBrushPt;//建立DIB點陣圖的刷子。 CreateDIBPatternBrush,
(4)點陣圖(Bitmap)預設值:None(無); CreateBitmap, CreateBitmapIndirect, CreateCompatibleBitmap, CreateDIBitmap, CreateDIBSection CreateSolidBrush第一種::HBITMAP CreateBitmap( int nWidth, // 寬 int nHeight, // 高 UINT cPlanes, // 顏色板的數目 UINT cBitsPerPel, // 沒畫素的位數。 CONST VOID *lpvBits // 指向顏色資料陣列指標。這些顏色資料用來設定矩形區域內畫素的顏色。矩形區域中的每一掃描線必須是雙位元組的整數倍(不足部分以0填充)。如果該引數為NULL,那麼就表示沒有定義新點陣圖。);
//簡化版HBITMAP CreateCompatibleBitmap( HDC hdc, int nWidth, int nHeight );
//第二種HBITMAP CreateBitmapIndirect(&bitmap);bitmap是BITMAP結構體
(5)區域(Region)區域是對顯示器上一個範圍的描述,這個範圍是矩形、多邊形和橢圓的組合,把區域選進裝置描述表,區域可以用於繪製和剪裁。作用:iRgnType=CombineRgn(hRgn,hRgn1,hRgn2,iCombine);iCombine的引數:RGN_AND 兩個源區域的公共部分RGN_OR 全部RGN_XOR 除去公共部分。RGN_DIFF hRgn1不在hRgn2的部分RGN_COPY hRgn1的全部。(忽略hRgn2);iRgnType的引數:NULLREGION 得到空區域SIMPLEREGION 得到簡單的矩形、橢圓或多邊形COMPLEXREGION 多個多邊形、矩形、橢圓的組合ERROR 出錯建立:一:建立矩形區域: hRgn = CreateRectRgn (xLeft, yTop, xRight, yBottom) ; hRgn = CreateRectRgnIndirect (&rect) ;二: 建立橢圓剪裁區域; hRgn = CreateEllipticRgn (xLeft, yTop, xRight, yBottom) ;// hRgn = CreateEllipticRgnIndirect (&rect) ;三;建立多邊形剪裁區域 hRgn = CreatePolygonRgn (&point, iCount, iPolyFillMode) ;
///////////////////////////////////////////////////////////矩形與區域的剪裁對於矩形;InvalidateRect (hwnd, NULL, TRUE) ;//使矩形無效GetUpdateRect 來取得失效矩形的座標或WM_PAINT中從PAINTSTRUCT結構中得到ValidateRect使有效對於區域:InvalidateRgn (hwnd, hRgn, bErase) ;ValidateRgn (hwnd, hRgn) ;
SelectObject(hdc,hRgn); 或SelectClipRgn(hdc,hRgn);選進裝置描述表ExcludeClipRect用於將一個矩形從剪裁區域裡排除掉,IntersectClipRect 用於建立一個新的剪裁區域,它是前一個剪裁區域與一個矩形的交,OffsetClipRgn 用於將剪裁區域移動到顯示區域的另一部分。
四、裝置描述表
理解1:裝置描述表中包含許多確定的GDI函式如何在裝置上工作的當前屬性。這些屬性允許傳遞給GDI函式的引數只包含其實座標或者尺寸資訊,而不包含Windows在裝置上顯示物件時需要的所以其他資訊、
理解2:一個裝置描述表通常指一個物理顯示裝置。如影片顯示器或印表機。
理解3:裝置描述表(簡稱DC)實際上是GDI內部儲存的資料結構。有些值是圖形化的“屬性”,這些屬性定義了一些GDI繪圖函式的工作,例如:文字顏色,文字的背景、TextOut函式的X座標,y座標對映到視窗客戶區的方式,還有windows顯示的字型、
//////////////////////////////////獲取控制代碼hdc
(1)注意這不能使無效區域變的有效hdc=GetDC(hwnd);//////ReleaseDC(hwnd,hdc);
(2)在處理WM_PAINT訊息時使用。能使無效區域變的有效、重繪。hdc=BeginPaint(hwnd,&ps);/////////EndPaint(hwnd,&ps);
(3)能獲得非客戶區的繪製訊息。包括視窗的標題欄,選單欄,和捲軸、框架等。在WM_NCPAINT中處理、hdc=GetWindowDC(hwnd);//////ReleaseDC(hwnd,hdc);
(4)通用獲得DC的方法。影片顯示器或者印表機上的DC.hdc=CreateDC(TEXT("DISPLAY"),NULL,NULL,NULL); //獲得整個螢幕的dc//////////////DeleteDC(hdc);
(5)獲得一個dc,其引數與CreateDC的引數相同。但是不能用這個資訊環境控制代碼往裝置描述表上寫東西。////特別 注意。hdc=CreateIC(TEXT("DISPLAY"),NULL,NULL,NULL);/////////DeleteDC (hdc);
(6)可以把點陣圖選進內部裝置描述表。然後用GDI 函式在點陣圖上繪畫。hdcMem=CreateCompatibleDC(hdc); //點陣圖選進內部裝置描述表///////////DeleteDC (hdcMem);
(7)獲取元檔案的裝置描述表來建立元檔案。hdcMeta=CreateMetaFile(pszFilename);//////////hmf=ColseMetaFile(hdcMeta)
/////////////////////獲取資訊(8)獲取影片顯示器的尺寸,色彩等資訊。int iValue=GetDeviceCaps(hdc,ilndex);
///////////////////儲存裝置描述表。(9) SaveDC(hdc);可以儲存多次、RestoreDC(hdc,-1);恢復DC五、裝置描述表屬性
1)一些空間隔的填充。如點和虛線之間的間隔填充。背景模式:使用SetBkMode(hdc,iBkMode)修改(1)OPAQUE(系統預設值),間隔使用背景顏色填充。 修改:SetBkColor(hdc,crColor); //修改背景色 GetBkColor(hdc); 獲取背景色(2)TRANSPARENT 不填充間隔 ,不擦除背景,透明模式
2)繪圖方式:用畫筆進行繪圖實際是畫筆畫素與目標位置處原來畫素之間的某種布林值運算。預設值::R2_COPYPEN;修改:SetROP2(hdc,iDrawMode);獲取:iDrawMode=GetROP2(hdc);