GDI 基本图形

GDI:Graphics Device Interface,图形设备接口

  • 设备环境 (Device Context)
    • 设备环境是Windows 内部使用的数据结构,,它定义了GDI 函数在显示设备特定区域的工作方式。
      • BeginPaint函数取得窗口客户区无效区域的设备环境句柄
      • GetWindowDC函数能够取得整个窗口的设备环境句柄
      • 如果不是在处理 WM_PAINT 消息,可以使用GetDC 函数取得窗口客户区的设备环境句柄,进而进行绘制操作
  • Windows 的颜色和像素点
    • 在Win32 编程中,统一使用32 位的整数(一个COLORREF 值)来表示深度为24 位的颜色。
    • 设置一个象素点的值可以用SetPixel 函数
      • COLORREF SetPixel(
      •   HDC hdc, // 设备环境句柄
      •   int X, // 象素的X 坐标
      •   int Y, // 象素的Y 坐标
      •   COLORREF crColor // 要设置的COLORREF 值
      • );
    • 如果需要获取DC 中某个像素点当前的颜色值,可以使用GetPixel 函数。
      • COLORREF GetPixel( HDC hdc, int nXPos, int nYPos);
  • 绘制线条
    • 绘制线条的函数有画单条直线的 LineTo,画多条直线的 Polyline 和PolylineTo,画贝塞儿曲线的PolyBezier 和PolyBezierTo,画弧线的 Arc 和 ArcTo。
    • 当前点的位置,可以使用MoveToEx 函数
      • BOOL MoveToEx(
      •   HDC hdc, // 设备环境句柄
      •   int X, // 新位置的X 坐标
      •   int Y, // 新位置的Y 坐标
      •   LPPOINT lpPoint // 用来返回原来的当前点位置,如果不需要的话,这个参数可以被设为NULL
      • )
      • 例如:
        • ::MoveToEx(hDC, 0, 0, NULL);
        • ::LineTo(hDC, 0, 500);
    • 绘制的是相连的多条直线,Polyline连接点;PolylineTo从当前点开始连接点
      • BOOL Polyline(HDC hdc, CONST POINT *lpPoint, int cPoints);  
      • BOOL PolylineTo(HDC hdc, CONST POINT *lpPoint, DWORD cPoints );
    • 画笔
      • 预定义画笔:BLACK_PEN、WHITE_PEN、NULL_PEN
        • // 获取预定义画笔的句柄。Stock 的中文含义是常备的、库存的
        • HPEN hPen = (HPEN)::GetStockObject(BLACK_PEN);
        • // 将画笔对象选入设备。SelectObject函数会根据句柄的种类自动替换掉原来的对象,并返回原对象句柄
        • HPEN hOldPen = (HPEN)::SelectObject(hdc, hPen);
      • 以创建自定义的画笔对象
        • HPEN CreatePen(
        •   int fnPenStyle, // 画笔的风格,取值有PS_SOLID、PS_DASH、PS_DOT、PS_DASHDOT 等
        •   int nWidth, // 画笔的宽度,单位是DC 坐标映射方法中定义的逻辑单位
        •   COLORREF crColor // 画笔的颜色
        • );
  • 绘制区域
    • 绘制边线的时候要使用画笔,填充区域就要使用画刷了。绘制区域的函数工作的时候以当前画笔绘制边线,并以当前画刷填充中间的区域。这些函数有画矩形的Rectangle,画椭圆的Ellipse,画多边形的Polygon,画弦的Chord 等,
      • Rectangle(hdc, x1, y1, x2, y2); // 画以(x1, y1)和(x2, y2)为对角坐标的填充矩形
      • Ellipse(hdc, x1, y1, x2, y2); // 以(x1, y1)和(x2, y2)为对角坐标定义一个矩形,然后画矩形相切的椭圆并填充
      • Polygon(hdc, lpPoint, 5)  // lpPoint 指向存放(x0, y0)到(x4, y4)的内存,函数从(x1, y1)到(x2, y2)...到(x4, y4),再回到(x1, y1),一共画5 条直线并填充
    • CreateSolidBrush函数创建了新的单色的画刷对象
      • HBRUSH CreateHatchBrush(
      •   int fnStyle, // 线条的风格
      •   COLORREF clrref // 图案线条的颜色
      • );
        • fnStyle 参数指定了不同风格的线条,这些图案线条实际上是由8×8 的位图重复铺开组成的。此参数取值可以是HS_BDIAGONAL、HS_FDIAGONAL、HS_CROSS、HS_HORIZONTAL、HS_DIAGCROSS 或HS_VERTICAL
    • 当然,Windows 也预定义了一些画刷对象,可以被GetStockObject 函数获取,并被选入DC 中。这些常用的预定义对象有BLACK_BRUSH(黑色画刷)、DKGRAY_BRUSH(深灰色画刷)、GRAY_BRUSH(灰色画刷)、LTGRAY_BRUSH(浅灰色画刷)、WHITE_BRUSH(白色画刷)、NULL_BRUSH(空画刷)等。
  • 坐标系统
    • 坐标映射方式是设备环境中一个很重要的属性。它的默认值是 MM_TEXT,即以左上角为坐标原点,以右方当做x 坐标的正方向,以下方当做y 坐标的正方向。可以用SetMapMode 函数改变DC 中的坐标映射方式。
      • int SetMapMode(
      •   HDC hdc, // 设备环境句柄
      •   int fnMapMode // 新的坐标映射方式
      • );
      • fnMapMode 映射方法可取:MM_TEXT (像素),MM_LOMETRIC (0.1mm),MM_HIMETRIC (0.01mm),MM_LOENGLISH 0.01 英寸,MM_HIENGLISH 0.001 英寸,MM_TWIPS 1/1440 英寸,M_ISOTROPIC 用户自定义(X=Y),MM_ANISOTROPIC 用户自定义(X!=Y)
    • 调用 SetWindowExtEx 函数设置坐标系的逻辑单位
      • BOOL SetWindowExtEx(
      •   HDC hdc, // 设备环境句柄
      •   int nXExtent, // 新的宽度(映射方式为MM_ISOTROPIC 时nXExtent 必须等于nYExtent)
      •   int nYExtent, // 新的高度
      •   LPSIZE lpSize // 用于返回原来的大小,不需要的话可以设它为NULL
      • );
    • 调用 SetViewportExtEx 函数设置x、y 坐标轴的方向和坐标系包含的范围,即定义域和值域。
      • BOOL SetViewportExtEx(
      •   HDC hdc, // 设备环境句柄
      •   int nXExtent, // 新的宽度(以像素为单位,定义域)
      •   int nYExtent, // 新的高度(以像素为单位,值域)
      •   LPSIZE lpSize // 用于返回原来的大小,不需要的话可以设它为NULL
      • );
    • 设置坐标系的原点坐标SetViewportOrgEx(
      • BOOL SetViewportOrgEx(
      •   HDC hdc, // 设备环境句柄
      •   int X, // 原点的横坐标
      •   int Y, // 原点的纵坐标
      •   LPPOINT lpPoint // 用于返回原来的坐标,不需要的话可以设它为 NULL
      • );
    • 例如:以整个客户区为边界画一个椭圆
    • void OnPaint(HWND hWnd) 
      { 
      	PAINTSTRUCT ps;
      	HDC hdc = ::BeginPaint(hWnd, &ps);
      	// 取得客户区的大小
      	RECT rt; ::GetClientRect(hWnd, &rt); 
      	int cx = rt.right;
      	int cy = rt.bottom;
      	// 设置客户区的逻辑大小为500 乘500,原点为(0,0)
      	::SetMapMode(hdc, MM_ANISOTROPIC);      // 设置坐标映射关系
      	::SetWindowExtEx(hdc, 500, 500, NULL);  // 不管真实窗口的大小是多少,程序已经告诉了Windows 该窗口的逻辑大小是500×500
      	::SetViewportExtEx(hdc, cx, cy, NULL);  // 设置x, y轴的区域
      	::SetViewportOrgEx(hdc, 0, 0, NULL);	// 设置坐标原点
      	::Ellipse(hdc, 0, 0, 500, 500);         // 以整个客服区为边界画一个椭圆
      	::EndPaint(hWnd, &ps);
      }
  • Windows 内存DC
    • 利用Windows 内存DC进行绘图,可以减少屏幕闪烁。把所要绘制的一切先在内存DC中进行绘制,之后全部搬到屏幕DC中。
    • 利用内存DC绘图的方法为:
      • 创建关于屏幕DC的内存DC
        • MemDC.CreateCompatibleDC(pDC);
      • 创建一个关于屏幕DC的图画
        • CRect rect;
        • this->GetClientRect(rect);  // 得到客户区的大小
        • CBitmap bmpFace;
        • bmpFace.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
      • 将这幅画选入内存DC中
        • CBitmap* pOldBmp = NULL:
        • pOldBmp = MemDC.SelectObject(&bmpFace);
      • 在内存DC中进行任何绘制动作
        • CBrush brush(RGB(255, 255, 255));
        • MemDC.FillRect(rect, &brush);
        • for (int i = 0; i < 500; i++)
        • {
        •   MemDC.MoveTo(22+i, 22);
        •   MemDC.LineTo(22+i, 222);
        • }
      • 绘制完后将内存DC中的这幅画会知道屏幕DC中
        • pDC->BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &MemDC, rect.left, rect.top, SRCCOPY);
      • 进行相关资源的回收动作
        • MemDC.SelectObject(pOldBmp);
        • bmpFace.DeleteObject();
      • 同事需要把系统的ON_WM_ERASEBKGND消息进行修改,否则也会出现闪烁情况
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值