目录:
- 创建滚动条
- 滚动条函数(新老版本)
- 取得设备内容句柄hdc
- 设置 hdc 中的属性
- 画点画线
- 画填充图形
- 使用自定义的 画笔 和 画刷
- 矩形、区域和剪裁
- 关于GDI映像模式
- 其他常用的方便计算的函数
创建滚动条:在CreateWindow函数中window style 参数设置WS_VSCROLL | WS_HSCROLL
产生的消息:WM_VSCROLL / WM_HSCROLL
滚动条函数(老的API——滑块大小固定)
SetScrollRange (hwnd, iBar, iMin, iMax, bRedraw) ;
SetScrollPos (hwnd, iBar, iPos, bRedraw) ;
GetScrollRange 和 GetScrollPos
新的函数win32滚动条函数
SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ;
GetScrollInfo (hwnd, SB_HORZ, &si) ;
第三个参数是一种结构体:
typedef struct tagSCROLLINFO { UINT cbSize ;// set to sizeof (SCROLLINFO) UINT fMask ; // values to set or get int nMin ; // minimum range value int nMax ; // maximum range value UINT nPage ; // page size int nPos ; // current position int nTrackPos ;// current tracking position } SCROLLINFO, * PSCROLLINFO ;
【注意】 使用是是si时必须先初始化 si.cbSize = sizeof (si) ;
然后 fMask 必须制定操作类型:SIF_RANGE | SIF_PAGE|SIF_POS|SIF_TRACKPOS|SIF_DISABLENOSCROLL|
SIF_ALL ( =SIF_RANGE|SIF_POS|SIF_PAGE|SIF_TRACKPOS)
滚动窗口时重画策略有二:
一、在滚动消息MS_VERT或MS_HORZ里调用InvalidateRect 函数,使其产生WM_PAINT 消息,并在重画消息中重画所有
二、在每次处理MS_VERT时,当LOWORD(wParam)里的通知 SB_THUMBTRACK等改变 position值,并在最后SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ;后,不调用InvalidateRect 函数,而是调用非GDI函数 ScrollWindow(HWND hWnd,int XAmount,int YAmount,CONST RECT *IpRect, CONST RECT *lpClipRect); ; 来挪动windows内容.最后两个参数设定为NULL,这指出了要卷动整个显示区域. (两个RECT,第一个为Client Area ,第二个为Clipping Rectangle),该函数会将新卷出的内容所在矩形设置为无效矩形,一边在其之后自身发出PAINT消息时减少重画的部分。
(第二种比较用户友好,不会有太明显的闪刷)
取得设备内容句柄:
1、在MS_PAINT中,
hdc = BeginPaint (hwnd, &ps) ; //其它行程序 EndPaint (hwnd, &ps) ;
2、在其他非 MS_PAINT中,
hdc = GetDC (hwnd) ; //其它行程序 ReleaseDC (hwnd, hdc) ;
3、或使用下面函数取得包括标题菜单在内的区域进行操作,使用时相应的处理消息 WM_NCPAINT
hdc = GetWindowDC (hwnd) ; //其它行程序 ReleaseDC (hwnd, hdc) ;
设置 设备内容句柄hdc 中的属性:
设备内容属性 | 默认值 | 修改该值的函数 | 取得该值的函数 |
Mapping Mode | MM_TEXT | SetMapMode | GetMapMode |
Window Origin | (0, 0) | SetWindowOrgEx OffsetWindowOrgEx | GetWindowOrgEx |
Viewport Origin | (0, 0) | SetViewportOrgEx OffsetViewportOrgEx | GetViewportOrgEx |
Window Extents | (1, 1) | SetWindowExtEx SetMapMode ScaleWindowExtEx | GetWindowExtEx |
Viewport Extents | (1, 1) | SetViewportExtEx SetMapMode ScaleViewportExtEx | GetViewportExtEx |
Pen | BLACK_PEN | SelectObject | SelectObject |
Brush | WHITE_BRUSH | SelectObject | SelectObject |
Font | SYSTEM_FONT | SelectObject | SelectObject |
Bitmap | None | SelectObject | SelectObject |
Current Position | (0, 0) | MoveToEx LineTo PolylineTo PolyBezierTo | GetCurrentPositionEx |
Background Mode | OPAQUE | SetBkMode | GetBkMode |
Background Color | White | SetBkColor | GetBkColor |
Text Color | Black | SetTextColor | GetTextColor |
Drawing Mode | R2_COPYPEN | SetROP2 | GetROP2 |
Stretching Mode | BLACKONWHITE | SetStretchBltMode | GetStretchBltMode |
Polygon Fill Mode | ALTERNATE | SetPolyFillMode | GetPolyFillMode |
Intercharacter Spacing | 0 | SetTextCharacterExtra | GetTextCharacterExtra |
Brush Origin | (0, 0) | SetBrushOrgEx | GetBrushOrgEx |
Clipping Region | None | SelectObject SelectClipRgn IntersectClipRgn OffsetClipRgn ExcludeClipRect SelectClipPath | GetClipBox |
画点画线
画点的相关函数有如下,不过比较少用
SetPixel (hdc, x, y, crColor) ;
crColor = GetPixel (hdc, x, y) ;
画线函数:
//画直线 MoveToEx (hdc, xBeg, yBeg, NULL) ; //不画点,指定[当前位置];最后一个参数POINT设置时取回上一次的[当前位置] LineTo (hdc, xEnd, yEnd) ; //获取当前位置的另一种方法 GetCurrentPositionEx (hdc, &pt) ; //画连续的线段可用Polyline函数,Polyline函数是在设备驱动程序层次上实作的,速度相对快些 Polyline (hdc, apt, 5) ; // apt 是点结构体数组,5 是点的个数 //画连续线有另一个版本,以下两行相当于上面的Polyline MoveToEx (hdc, apt[0].x, apt[0].y, NULL) ; PolylineTo (hdc, apt + 1, 4) ; //画弧线可用下面函数,其用法参考接下来的【画填充图形】 Arc(hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd) ; //画 贝塞尔曲线:两种 PolyBezier (hdc, apt, iCount) ; PolyBezierTo (hdc, apt, iCount) ;
画填充图形
//画填充 矩形 Rectangle (hdc, xLeft, yTop, xRight, yBottom) ; //画填充 圆角矩形 RoundRect (hdc, xLeft, yTop, xRight, yBottom, xCornerEllipse, yCornerEllipse) ; // 圆角所在圆的尺寸,一般x=y //画填充 椭圆 Ellipse (hdc, xLeft, yTop, xRight, yBottom) ; //画填充 饼和弓 Pie(hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd) ; Chord (hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd) ; //画填充 多边形 Polygon (hdc, apt, iCount) ; //apt为点的数组,iCount 为点的个数 PolyPolygon (hdc, apt, aiCounts, iPolyCount) ;// aiCounts 为数组,每个值表示多边形的顶点数, iPolyCount 为多边形的个数,apt包括所有构成的点 //于填入内部的方式,则取决于多边形填入方式,您可以用SetPolyFillMode函数来设定: SetPolyFillMode (hdc, iMode) ; // iMode : ALTERNATE 或 WINDING (区别略)
其中,Arc Pie Chord 三个函数xStart, yStart, xEnd, yEnd 是假想的点,用于与原点连接形成假想的线:
使用自定义的 画笔 和 画刷
画笔的定义以及使用
/** 使用现有的画笔*******************************/ HPEN hPen ; hPen = GetStockObject (WHITE_PEN) ; //系统还定义了另外两种 WHITE_PEN和NULL_PEN SelectObject (hdc, hPen) ; //现在必须将画笔选进设备内容 //也可以不定义,直接用 SelectObject (hdc, GetStockObject (WHITE_PEN)) ; //使用时传回的事 上一个画笔的句柄,可用于删除(避免生成太多对象) hPen = SelectObject (hdc, GetStockobject (WHITE_PEN)) ; //使用或删除 SelectObject (hdc, hPen) ; DeleteObject(hdc, hPen) ; /** 创建画笔*************************************/ hPen = CreatePen (iPenStyle, iWidth, crColor) ; //或 LOGPEN logpen ; hPen = CreatePenIndirect (&logpen) ;
iPenStyle:
参数crColor以及其他这里出现的 颜色参数,都是用COLORREF值(只是一个32位的无正负号长整数)来表示一种色彩。COLORREF结构如下:
颜色的定义和使用如下:
#define RGB(r,g,b) ((COLORREF)(((BYTE)(r) | \ ((WORD)((BYTE)(g)) << 8)) | \ (((DWORD)(BYTE)(b)) << 16))) //故可以直接使用以下来设置参数 RGB(255,0,0);
逻辑画笔 LOGPEN 和 逻辑画刷 LOGBRUSH 定义
// <WINGDI.h> 中定义的 LOGPEN typedef struct tagLOGPEN { UINT lopnStyle; //同为上面 iPenStyle 的7种,其中PS_INSIDEFRAME 和 PS_SOLID 都是画实线,区别是前者不管线多粗都在逻辑矩形内 POINT lopnWidth; //当Width>1 时,不连续线的画笔样式将不起作用 COLORREF lopnColor; } LOGPEN, *PLOGPEN, NEAR *NPLOGPEN, FAR *LPLOGPEN; //<WINGDI.h> 中定义的 LOGBRUSH typedef struct tagLOGBRUSH { UINT lbStyle; COLORREF lbColor; LONG lbHatch; } LOGBRUSH, *PLOGBRUSH, NEAR *NPLOGBRUSH, FAR *LPLOGBRUSH;
LOGBRUSH 中 lbStyle 以及对另外两个参数的影响
lbStyle (UINT) | lbColor (COLORREF) | lbHatch (LONG) |
BS_SOLID | 画刷的色彩 | 忽略 |
BS_HOLLOW | 忽略 | 忽略 |
BS_HATCHED | 影线的色彩 | 影线画刷风格 |
BS_PATTERN | 忽略 | 位图的句柄 |
BS_DIBPATTERNPT | 忽略 | 指向DIB的指标 |
要了解其中成员 lbHatch,还得介绍一下创建画刷的方式和 具体参数:
//使用以上LOGBRUSH 的函数是 hBrush = CreateBrushIndirect (&logbrush) ; //它可以看做是以下几个函数的集合函数 hBrush = CreateSolidBrush (crColor) ; hBrush = CreateHatchBrush (iHatchStyle, crColor) ; //影线填充,具体如下 //使用画刷同样需要选进设备内容,如同画笔选进的方式 SelectObject (hdc, hBrush) ; DeleteObject (hBrush) ;
iHatchStyle 如图:
[注意] 在画虚线和画影线模式的画刷时,空隙会默认使用 CreateWindow 时指定的 画刷,一般为白色画刷,要改变空隙的填充方式,可用
//指定空隙颜色 SetBkColor (hdc, crColor) ; //可用GetBkColor 取当前颜色 //指定填充模式 SetBkMode (hdc, bkMode) ; //GetBkMode来取得目前背景模式 //bkMode: OPAQUE //内定模式,Windows使用背景色来填入空隙,内定的背景色为白色 TRANSPARENT //Windows将忽略背景色,并且不填入空隙
设备内容中定义的绘图方式也影响显示器上所画线的外观。绘图色彩由画笔色彩和画线区域原来的色彩共同决定。
设置不同的绘图方式:
SetROP2 (hdc, iDrawMode) ; iDrawMode = GetROP2 (hdc) ; //具体的 iDrawMode值如下表
矩形、区域和剪裁
矩形函数:
//三种矩形绘制函数 FillRect (hdc, &rect, hBrush) ; FrameRect (hdc, &rect, hBrush) ; //FrameRect允许使用者画一个不一定为纯色的矩形框。该边界框为一个逻辑单位元宽。如果逻辑单位大于设备单位,则边界框将会为2个图素宽或者更宽。 InvertRect (hdc, &rect) ; //取反色绘制
//快速设置RECT的函数 SetRect (&rect, xLeft, yTop, xRight, yBottom) ; //可用的改变矩形属性的函数 OffsetRect (&rect, x, y) ; //将矩形沿x轴和y轴移动几个单元: InflateRect (&rect, x, y) ; //增减矩形的尺寸: SetRectEmpty (&rect) ; //矩形各字段设定为0: CopyRect (&DestRect, &SrcRect) ; //将矩形复制给另一个矩形:(相当于 DestRect = SrcRect) IntersectRect (&DestRect, &SrcRect1, &SrcRect2) ;//取得两个矩形的交集: UnionRect (&DestRect, &SrcRect1, &SrcRect2) ; //取得两个矩形的联集: bEmpty = IsRectEmpty (&rect) ; //确定矩形是否为空: bInRect = PtInRect (&rect, point) ; //确定点是否在矩形内:
建立和绘制裁剪区域:
HRGN hRgn; //创建矩形裁剪区域 hRgn = CreateRectRgn (xLeft, yTop, xRight, yBottom) ; //或 hRgn = CreateRectRgnIndirect (&rect) ; //创建椭圆裁剪区域 hRgn = CreateEllipticRgn (xLeft, yTop, xRight, yBottom) ; //或 hRgn = CreateEllipticRgnIndirect (&rect) ; //穿件圆角矩形同理 CreateRoundRectRgn //类似 Plygon函数 hRgn = CreatePolygonRgn (&point, iCount, iPolyFillMode) ; //point参数是一个POINT型态的结构数组,iCount是点的数目,iPolyFillMode是ALTERNATE或者WINDING /********** 组合裁剪区域函数 ****************/ iRgnType = CombineRgn (hDestRgn, hSrcRgn1, hSrcRgn2, iCombine) ; //这一函数将两个剪裁区域(hSrcRgn1和hSrcRgn2)组合起来并用句柄hDestRgn指向组合成的剪裁区域。这三个剪裁区域句柄都必须是有效的, //但是hDestRgn原来所指向的剪裁区域被破坏掉了(当您使用这个函数时,您可能要让hDestRgn在初始时指向一个小的矩形剪裁区域)。
CombineRgn 的最后一个参数 iCombine 如下:
iCombine值 新剪裁区域
___________________________________________
RGN_AND 两个剪裁区域的公共部分
RGN_OR 两个剪裁区域的全部
RGN_XOR 两个剪裁区域的全部除去公共部分
RGN_DIFF hSrcRgn1不在hSrcRgn2中的部分
RGN_COPY hSrcRgn1的全部(忽略hSrcRgn2)
CombineRgn 的返回值 iRgnType 包括如下情况:
NULLREGION, 表示得到一个空剪裁区域;
SIMPLEREGION, 表示得到一个简单的矩形、椭圆或者多边形;
COMPLEXREGION, 表示多个矩形、椭圆或多边形的组合;
ERROR, 表示出错了。
那么如何在程序使用区域,并起到什么效果呢?
区域和画笔画刷一样,是可以选进设备内容的对象,使用的方式与 其类似:
//选进设备内容 SelectObject (hdc, hRgn) ; //或 SelectClipRgn (hdc, hRgn) ; //类似的,删除 DeleteObject (hRgn) ; //另外,设定具体画刷属性,类似于矩形的函数,区域也有如下函数 FillRgn (hdc, hRgn, hBrush) ; FrameRgn (hdc, hRgn, hBrush, xFrame, yFrame) ; //xFrame和yFrame参数是画在区域周围的边框的宽度和高度 InvertRgn (hdc, hRgn) ; PaintRgn (hdc, hRgn) ; // 用设备内容中目前画刷填入所指定的区域
当接收到 WM_PAINT 无效区域除了是矩形,还可以是区域,相关函数:
//类似矩形的InvalidateRect (hwnd, NULL, TRUE) ; InvalidateRgn (hwnd, hRgn, bErase) ; ValidateRgn (hwnd, hRgn) ;
关于GDI映像模式
设置映像模式:
SetMapMode (hdc, iMapMode) ;
iMapMode = GetMapMode (hdc) ;
iMapMode 如下表:
两个相关函数:
SetViewportOrgEx (hdc, cxClient / 2, cyClient / 2, NULL) ; SetWindowOrgEx (hdc, -cxClient / 2, -cyClient / 2, NULL) ; //此两句效果如下:
==》
其他常用的方便计算的函数
//获得显示区域的矩形 GetClientRect (hwnd, &rect) ;