• windows 编程—— 使用函数笔记


    目录:

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

     

     

  • 相关阅读:
    批处理文件双击运行成功,程序调用却运行失败解决方案
    前端安全之加解密种类与HTTPS加密原理(二)
    node包管理nvm与pnpm(一)
    React状态管理—reduxAPI原理分析(三)
    动态规划原理与算法实践(二)
    双指针算法基本原理和实践(一)
    分治算法基本原理和实践(三)
    编程范式(一)
    Java基础
    前端模块化CommonJS、AMD、CMD、ES6模块(二)
  • 原文地址:https://www.cnblogs.com/BensonLaur/p/5323177.html
Copyright © 2020-2023  润新知