目录:
- 创建滚动条
- 滚动条函数(新老版本)
- 取得设备内容句柄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) ;