目录:
- 创建滚动条
- 滚动条函数(新老版本)
- 取得设备内容句柄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, ) ; // apt 是点结构体数组,5 是点的个数 //画连续线有另一个版本,以下两行相当于上面的Polyline
MoveToEx (hdc, apt[].x, apt[].y, NULL) ;
PolylineTo (hdc, apt + , ) ; //画弧线可用下面函数,其用法参考接下来的【画填充图形】
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)) << )) | \
(((DWORD)(BYTE)(b)) << )))
//故可以直接使用以下来设置参数
RGB(,,);
逻辑画笔 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 / , cyClient / , NULL) ;
SetWindowOrgEx (hdc, -cxClient / , -cyClient / , NULL) ; //此两句效果如下:
==》
其他常用的方便计算的函数
//获得显示区域的矩形
GetClientRect (hwnd, &rect) ;