window 绘图

目录


转载网址:http://www.cnblogs.com/kzloser/archive/2012/11/01/2747565.html#c0

GUI作图概述
描绘图形
位图
文本输出
设置画刷/画笔/字体
MFC 资源句柄的获得与释放

(本章节中例子都是用 VS2005 编译调试的)

GUI作图概述

作图步骤

  • 获得设备描述表资源句柄
  • 绘图操作
  • 释放设备描述表资源句柄

流程图如下:

window 绘图_第1张图片

获取/释放设备资源描述表

  • 获取设备资源描述表:   BeginPaint / GetDC
  • 释放设备资源描述表:  EndPaint / ReleaseDC

BeginPaint / GetDC 两种方式的区别:

             BeginPaint             GetDC            
使用环境         只用于图形刷新时获取设备环境   使用较为广泛
操作区域         无效区              特定窗口的客户区或者整个窗口
释放设备环境所用函数   EndPaint ()            ReleaseDC ()

代码示例:

在 WM_PAINT 添加 BeginPaint 事件,在 WM_LBUTTONDOWN 添加 GetDC 事件.

BeginPaint 使用:

复制代码
//获得资源DC
hdc=BeginPaint(hwnd,&ps);
//获得窗口大小
GetClientRect(hwnd,&rect);
//绘制文本
DrawText(hdc,"hellow my first windows program",strlen("hellow my first windows program"),&rect,
    DT_SINGLELINE | DT_CENTER | DT_VCENTER);
//释放资源DC
EndPaint(hwnd,&ps);
复制代码

 GetDC 使用: 

//获得设备资源描述表
hdc = GetDC(hwnd);
//绘制带圆角矩形
RoundRect(hdc,10,10,110,60,10,10);
//释放设备资源描述表
ReleaseDC(hwnd,hdc);

程序源码

运行结果:

单击鼠标右键和重绘窗口时

window 绘图_第2张图片

在单击鼠标右键后

window 绘图_第3张图片

绘图操作分类

  • 描绘图形
  • 位图
  • 文本输出

与设备描述表相关函数

  • 背景色:  GetBkColor / SetBkColor
  • 背景模式:  GetBkMode / SetBkMode
  • 位图:  CreateBitMap / CreateBitMapIndirect / CreateCompatibleBitmap / SelectObject
  • 画刷:  CreateBrushIndirect / CreateDIBPatternBrush  CreateHatchBrush / CreatePatternBrush / CreateSolidBrush / SelectObject
  • 画刷起始位置:  GetBrushOrg / SetBrushOrg / UnrealizeObject
  • 剪裁域:  ExcludeClipRect / IntersectClipRect / OffsetClipRgn / SelectClipPath / SelectObject / SelectClipRgn
  • 颜色调色板:  CreatePalette / RealizePalette / SelectPalette
  • 绘图方式:  GetROP2 / SetROP2
  • 字体:  CreateFont / CreateFontIndirect / SelectObject
  • 字符间距:  GetTextCharacterExtra / SetTextCharacterExtra
  • 映射方式:  GetMapMode / SetMapMode
  • 画笔:  CreatePen / CreatePenIndirect / SelectObject
  • 多边形填充方式:  GetPolyFillMode / SetPolyFillMode
  • 缩放模式:  SetStretchBltMode / GetStretchBltMode
  • 文本颜色:  GetTextColor / SetTextColor
  • 视图范围:  GetViewportExtEx / SetViewportExtEx / ScaleViewportExtEx
  • 视图原点:  GetViewportOrgEx / SetViewportOrgEx
  • 窗口范围:  GetWindowExtEx / SetWindowExtEx / ScaleWindowExtEx
  • 窗口原点:  GetWindowOrgEx / SetWindowOrgEx

描绘图形

常用绘图函数:

  • 画贝塞尔曲线:
    • PolyBezier
    • PolyDraw
  • 画点:  SetPixel
  • 画矩形:  Rectangle
  • 画带圆角的矩形:  RoundRect
      函数原型:  BOOL RoundRect( HDC hdc, int nLeftRect, int nTopRect,int nRightRect,int nBottomRect,int nWidth,int nHeight);
      参数说明:
            window 绘图_第4张图片
  • 画椭圆:  Ellipse
  • 画椭圆的一部分(即画一个弦):  Chord
  • 画一个扇形区并用当前画刷填充:  Pie
  • 画椭圆弧线:   Arc
      函数原型:  BOOL Arc(HDC hdc,int nLeftRect, int nTopRect,int nRightRect,int nBottomRect,int nXStartArc,int nYStartArc,int nXEndArc,int nYEndArc); 
      参数说明:

            window 绘图_第5张图片
  • 画椭圆弧线:   ArcTo
  • 画正圆弧线:  AngleArc
      函数原型:   BOOL AngleArc(HDC hdc,int X,int Y,DWORD dwRadius,FLOAT eStartAngle,FLOAT eSweepAngle);
      参数说明:

          window 绘图_第6张图片
  • 画一系列相连的直线:
    • Polyline
    • PolylineTo
    • PolyPolyline
  • 画线条:
    • 设置画笔起始位置:  MoveToEx
    • 设置画笔终止位置:  LineTo

位图

步骤:

  • 建立位图资源
  • 载入/创建位图资源
  • 获取设备内存
  • 选入内存设备
  • 贴图

流程图如下所示:

window 绘图_第7张图片

代码示例:

.rc 内容(位图资源):

IDB_BITMAP1             BITMAP                  "8c8a09f1gw1ds3qh4vtcyj.bmp"

位图(8c8a09f1gw1ds3qh4vtcyj.bmp 尺寸信息:440*622):

window 绘图_第8张图片

在鼠标左键单击事件中添加贴图操作:

加载位图:

hBmp = LoadBitmap(hinstance,MAKEINTRESOURCE(IDB_BITMAP1));

创建兼容 DC 并将位图选入兼容 DC 中:

hcmdc = CreateCompatibleDC(hdc);
SelectObject(hcmdc,hBmp);

 获得窗口大小(被显示的区域),获得位图信息(要显示的区域)

//获取窗口大小
GetClientRect(hwnd,&rect);
//获取位图信息(在 StretchBlt 时候有用到,而 BitBlt 没有)
GetObject(hBmp, sizeof(BITMAP), &bmp);

 显示位图:

//显示方式一,  按原图比例显示
BitBlt(hdc,0,0,rect.right-rect.left,rect.bottom-rect.top,hcmdc,0,0,SRCCOPY);

//显示方式二,  拉伸式显示
StretchBlt(hdc,0,0,rect.right-rect.left,rect.bottom-rect.top,hcmdc,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);

程序源码

运行结果:

  • 在未点击鼠标右键时候:

    window 绘图_第9张图片

  • 点击鼠标左键(用 BitBlt 方法):

    window 绘图_第10张图片

  • 点击鼠标左键(用 StretchBlt 方法):

    window 绘图_第11张图片

文本输出

文本输出操作

  • 文字输出:  TextOut
  • 显示字符串:  DrawText

有关文本操作:

  • 获取文字信息:  GetTextMetrics
  • 格式化文字:  GetTextExtentPoint32
  • 设置字体颜色和背景颜色:
    • 字体:  SetTextColor
    • 背景:  SetBkColor

设置画刷/画笔/字体

相关结构体:

字体结构体

TEXTMETRIC

作用:  记录基本的字体信息

结构体定义(MSDN 链接):

View Code

 图示:

window 绘图_第12张图片

步骤:

  • 创建资源句柄
  • 创建自定义资源/调用系统资源
  • 将资源选入系统

如下图所示:

window 绘图_第13张图片

代码示例:

在窗口重画的时候添加创建新画笔操作:

创建新画笔,并将画笔选入设备描述表中

pen = CreatePen(PS_DOT,3,RGB(255,100,100));
SelectObject(hdc,pen);

为了区别创建画笔前和创建画笔后的作图的区别

在创建画笔前绘制一条直线:

//rect 为记录窗口大小的 RECT 结构体
MoveToEx(hdc,(rect.left+rect.right)/2-130,(rect.top+rect.bottom)/2-50,NULL);
LineTo(hdc,(rect.left+rect.right)/2+130,(rect.top+rect.bottom)/2-50);

在创建画笔后绘制一条直线:

MoveToEx(hdc,(rect.left+rect.right)/2-130,(rect.top+rect.bottom)/2+50,NULL);
LineTo(hdc,(rect.left+rect.right)/2+130,(rect.top+rect.bottom)/2+50);

程序源码

运行结果:

window 绘图_第14张图片

程序源码

复制代码
#include<windows.h>
#include"resource.h"

HINSTANCE hinstance;

LRESULT CALLBACK textprom(
  HWND hwnd,      // handle to window
  UINT uMsg,      // message identifier
  WPARAM wParam,  // first message parameter
  LPARAM lParam   // second message parameter
);

int WINAPI WinMain(  HINSTANCE hInstance,  // handle to current instance
  HINSTANCE hPrevInstance,  // handle to previous instance
  LPSTR lpCmdLine,      // pointer to command line
  int nCmdShow          // show state of window
)
{
    WNDCLASS wndclass;
    HWND hwnd;
    MSG msg;

    //设计窗口类
    wndclass.cbClsExtra=0;
    wndclass.cbWndExtra=0;
    wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
    wndclass.hIcon=LoadIcon(NULL,IDI_ERROR);
    wndclass.hInstance=hInstance;
    wndclass.lpfnWndProc=textprom;
    wndclass.lpszClassName="text";
    wndclass.lpszMenuName=NULL;
    wndclass.style=CS_HREDRAW | CS_VREDRAW;
    
    //注册窗口类
    if(!RegisterClass(&wndclass))
    {
        MessageBox(NULL,"create windows error!","error",MB_OK | MB_ICONSTOP);
    }

    //创建无菜单资源的窗口窗口
    hwnd=CreateWindow("text","hellow world",WS_DLGFRAME | WS_MINIMIZEBOX | WS_SYSMENU,0,0,500,300,NULL,NULL,hInstance,NULL);


    //显示更新窗口
    ShowWindow(hwnd,nCmdShow);
    UpdateWindow(hwnd);

    hinstance = hInstance;

    //消息循环
    while(GetMessage(&msg,NULL,0,0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}

LRESULT CALLBACK textprom(
  HWND hwnd,      // handle to window
  UINT uMsg,      // message identifier
  WPARAM wParam,  // first message parameter
  LPARAM lParam   // second message parameter
)
{
    HDC hdc,hcmdc;
    PAINTSTRUCT ps;
    RECT rect;
    HBITMAP hBmp;
    SIZE   size;
    BITMAP bmp;
    HPEN pen;

    switch(uMsg)
    {
    //重绘事件
    case WM_PAINT:
        hdc=BeginPaint(hwnd,&ps);
        //显示文本
        GetClientRect(hwnd,&rect);
        DrawText(hdc,"hellow my first windows program",strlen("hellow my first windows program"),&rect,
            DT_SINGLELINE | DT_CENTER | DT_VCENTER);
        //画笔
        MoveToEx(hdc,(rect.left+rect.right)/2-130,(rect.top+rect.bottom)/2-50,NULL);
        LineTo(hdc,(rect.left+rect.right)/2+130,(rect.top+rect.bottom)/2-50);
        pen = CreatePen(PS_DOT,3,RGB(255,100,100));
        SelectObject(hdc,pen);
        MoveToEx(hdc,(rect.left+rect.right)/2-130,(rect.top+rect.bottom)/2+50,NULL);
        LineTo(hdc,(rect.left+rect.right)/2+130,(rect.top+rect.bottom)/2+50);
        EndPaint(hwnd,&ps);
        break;
    //绘制圆角矩形
    case WM_LBUTTONDOWN:
        hdc = GetDC(hwnd);
        RoundRect(hdc,10,10,110,60,10,10);
        ReleaseDC(hwnd,hdc);
        break;
    //贴图
    case WM_RBUTTONDOWN:
        hdc = GetDC(hwnd);
        hBmp = LoadBitmap(hinstance,MAKEINTRESOURCE(IDB_BITMAP1));
        hcmdc = CreateCompatibleDC(hdc);
        SelectObject(hcmdc,hBmp);    
        GetClientRect(hwnd,&rect);
        GetObject(hBmp, sizeof(BITMAP), &bmp);
        StretchBlt(hdc,0,0,rect.right-rect.left,rect.bottom-rect.top,hcmdc,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
        //BitBlt(hdc,0,0,rect.right-rect.left,rect.bottom-rect.top,hcmdc,0,0,SRCCOPY);
        ReleaseDC(hwnd,hdc);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    }
    return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
复制代码

MFC 资源句柄的获得与释放

绘图是选用GDI资源的说明

在程序中,当构造函数构造一个GDI对象后,该对象并不会立刻生效,必须选入设备描述表,它才会在以后的操作中生效,利用SelectObject函数可以实现把GDI对象选入设备描述表中,并且返回指向先前GDI设备对象的指针,一般情况下,在完成绘图操作后,都要利用SelectObject函数吧先前的GDI对象选入设备表,以便使恢复到先前状态

GDI绘图对象(CPen,CFont.CBitmap,CBrush)都派生于CGdiObject类对象,都有一个m_hObject记录与对应资源联系的关系,当其对象与对应的资源调用CreateXXXX建立联系后若想把对象关联上新的资源时候,必须先对旧的资源释放才能和新的资源建立上联系,可以用CGdiObject对象的DeleteObject函数去切断与旧资源的联系,并释放旧的资源

相关函数

获得资源设备表

函数原型

CDC* GetDC();

返回值:  如果调用成功,则返回CWnd客户区的设备环境;否则,返回NULL。这个指针可能是临时的,不能被保存以供将来使用

说明:   这个函数获得一个指针,指向一个客户区的公用的、属于类的或者私有的设备环境,依赖于为CWnd指定的类风格。对于公用的设备环境,GetDC每次获得设备环境时都给它赋予缺省值。对于属于类的或者私有的设备环境,GetDC保持原来的属性不变。在随后的图形设备接口(GDI)函数中可以使用设备环境以在客户区中绘图

释放资源设备表

函数原型

int ReleaseDC( CDC* pDC );

参数说明:   pDC 标识了要释放的设备环境
返回值:    如果成功,则返回非零值;否则返回0
说明:     释放设备环境,以供其它应用程序使用。ReleaseDC成员函数的效果依赖于设备环境的

CPainDC与CCleintDC的区别

  • CPaintDC
    • CPaintDC继承于CDC
    • 在构造函数中调用BeginPaint
    • 在析构函数调用EndPaint函数
    • 用于相应WM_PAINT消息的函数中
  • CClientDC
    • CClientDC继承于CDC
    • 在析构函数中调用GetDC
    • 在析构函数中调用ReleaseDC
    • 用于非WM_PAINT消息的GDI绘图函数中

获得设备资源描述表实现步骤

window 绘图_第15张图片

你可能感兴趣的:(window 绘图)