windows 编程—— 使用函数笔记

时间:2022-05-15 09:42:31

 

目录:

  • 创建滚动条
  • 滚动条函数(新老版本)
  • 取得设备内容句柄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 是假想的点,用于与原点连接形成假想的线:

                                                  windows 编程—— 使用函数笔记

使用自定义的 画笔 和 画刷

画笔的定义以及使用

/** 使用现有的画笔*******************************/
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:
windows 编程—— 使用函数笔记

参数crColor以及其他这里出现的 颜色参数,都是用COLORREF值(只是一个32位的无正负号长整数)来表示一种色彩。COLORREF结构如下:

                                         windows 编程—— 使用函数笔记

颜色的定义和使用如下:

#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 如图:

                         windows 编程—— 使用函数笔记

[注意] 在画虚线和画影线模式的画刷时,空隙会默认使用 CreateWindow 时指定的 画刷,一般为白色画刷,要改变空隙的填充方式,可用

//指定空隙颜色
SetBkColor (hdc, crColor) ;   //可用GetBkColor 取当前颜色

//指定填充模式
SetBkMode (hdc, bkMode) ;  //GetBkMode来取得目前背景模式

//bkMode:
OPAQUE             //内定模式,Windows使用背景色来填入空隙,内定的背景色为白色
TRANSPARENT        //Windows将忽略背景色,并且不填入空隙

设备内容中定义的绘图方式也影响显示器上所画线的外观。绘图色彩由画笔色彩和画线区域原来的色彩共同决定。

设置不同的绘图方式:

SetROP2 (hdc, iDrawMode) ;
iDrawMode = GetROP2 (hdc) ;
//具体的 iDrawMode值如下表

                         windows 编程—— 使用函数笔记 

矩形、区域和剪裁

矩形函数:

//三种矩形绘制函数
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 如下表:

                        windows 编程—— 使用函数笔记

 

两个相关函数:

SetViewportOrgEx (hdc, cxClient / 2, cyClient / 2, NULL) ;
SetWindowOrgEx (hdc, -cxClient / 2, -cyClient / 2, NULL) ;

//此两句效果如下:

                        windows 编程—— 使用函数笔记   ==》windows 编程—— 使用函数笔记

 


其他常用的方便计算的函数

//获得显示区域的矩形
GetClientRect (hwnd, &rect) ;