• 绘图(VC_Win32)


    目录

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

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


    GUI作图概述

    作图步骤

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

    流程图如下:

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

    • 获取设备资源描述表:   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);

    程序源码

    运行结果:

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

    在单击鼠标右键后

    绘图操作分类

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

    与设备描述表相关函数


    描绘图形

    常用绘图函数:

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

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

            
    • 画一系列相连的直线:
    • 画线条:
      • 设置画笔起始位置:  MoveToEx
      • 设置画笔终止位置:  LineTo

    位图

    步骤:

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

    流程图如下所示:

    代码示例:

    .rc 内容(位图资源):

    IDB_BITMAP1             BITMAP                  "8c8a09f1gw1ds3qh4vtcyj.bmp"

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

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

    加载位图:

    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);

    程序源码

    运行结果:

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

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

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


    文本输出

    文本输出操作

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

    有关文本操作:

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

    设置画刷/画笔/字体

    相关结构体:

    字体结构体

    TEXTMETRIC

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

    结构体定义(MSDN 链接):

    View Code
    typedef struct tagTEXTMETRIC {
      LONG  tmHeight; // Specifies the height (ascent descent) of characters.
      LONG  tmAscent; // Specifies the ascent (units above the base line) of characters.
      LONG  tmDescent; // Specifies the descent (units below the base line) of characters.
      LONG  tmInternalLeading; // Specifies the amount of leading (space) inside the bounds set by the tmHeight member. 
      LONG  tmExternalLeading; // Specifies the amount of extra leading (space) that the application adds between rows. 
      LONG  tmAveCharWidth; // Specifies the average width of characters in the font.
      LONG  tmMaxCharWidth; // Specifies the width of the widest character in the font.
      LONG  tmWeight; // Specifies the weight of the font.
      LONG  tmOverhang; // Specifies the extra width per string that may be added to some synthesized fonts
      LONG  tmDigitizedAspectX; // Specifies the horizontal aspect of the device for which the font was designed.
      LONG  tmDigitizedAspectY; // Specifies the vertical aspect of the device for which the font was designed. 
      TCHAR tmFirstChar; // Specifies the value of the first character defined in the font.
      TCHAR tmLastChar; // Specifies the value of the last character defined in the font.
      TCHAR tmDefaultChar; // Specifies the value of the character to be substituted for characters not in the font.
      TCHAR tmBreakChar; // Specifies the value of the character that will be used to define word breaks for text justification.
      BYTE  tmItalic; // Specifies an italic font if it is nonzero.
      BYTE  tmUnderlined; // Specifies an underlined font if it is nonzero.
      BYTE  tmStruckOut; // Specifies a strikeout font if it is nonzero.
      BYTE  tmPitchAndFamily; // Specifies information about the pitch, the technology, and the family of a physical font.
      BYTE  tmCharSet; // Specifies the character set of the font. 
    } TEXTMETRIC, *PTEXTMETRIC;

     图示:

    步骤:

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

    如下图所示:

    代码示例:

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

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

    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);

    程序源码

    运行结果:


    程序源码

    View Code
    #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绘图函数中

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

  • 相关阅读:
    XPath中的text()和string()区别(转)
    (转)Ubuntu 16.04 安裝Docker(PS:本文适用amd64位的ubuntu系统)
    python 爬取世纪佳缘,经过js渲染过的网页的爬取
    Python中的join()函数的用法
    Ubuntu下修改ubuntu源,完成Redis Desktop Manager的安装
    Ubuntu16.04安装Redis
    Scrapy爬虫实例教程(二)---数据存入MySQL
    Ubuntu16.04安装mongodb 及使用
    关闭和启动网卡
    网络之端口的作用
  • 原文地址:https://www.cnblogs.com/kzang/p/2747565.html
Copyright © 2020-2023  润新知