• win32 API编程之GDI绘图


    一、GDI简介

    二、获取DC的3种方法

    三、绘图函数

    四、双缓冲绘图技术

    五、绘制位图

    一、GDI简介

    1)什么是设备上下文

    2)设备上下文类型

    3)常见的GDI对象

    4)windows坐标系

    5)GDI绘图步骤

    二、获取DC的3种方法

    1)获取DC的3种方法

    2)PAINTSTRUCT结构

    3)BeginPaint函数

    4)EndPaint函数

    5)GetDC函数

    6)GetWindowDC函数

    7)三种方式的区别

    8)代码实例

    #include<windows.h> 
    
    
    //自定义的窗口过程
    LRESULT  CALLBACK    MyWindowProc(HWND hWnd, UINT Msg,
        WPARAM wParam, LPARAM lParam)
    {
        switch (Msg)
        {
        case WM_DESTROY:
            PostQuitMessage(0);//可以使GetMessage返回0    
            return 0;
    
        case WM_PAINT:
        { 
            //1.使用BeginPaint,它能将无效区域变成有效(如果存在无效区域,系统会一直发送WM_PAINT)
            /*PAINTSTRUCT  ps;
            HDC  hdc = BeginPaint(hWnd, &ps);
            TextOut(hdc, 0, 0, L"你好啊!", lstrlen(L"你好啊!"));
            EndPaint(hWnd, &ps);*/
    
            //2.使用GetDC获取客户区DC,它并不能将无效区域变成有效,所以WM_PAINT一直发送,文字一直闪烁
            /*
            HDC  hdc = GetDC(hWnd);
            TextOut(hdc, 0, 0, L"你好啊!", lstrlen(L"你好啊!"));
            ReleaseDC(hWnd, hdc);
            //return 0; //去掉之后交给默认DefWindowProc处理WM_PAINT消息,会调用BeginPaint,EndPaint
            */ 
    
        }
        break;
    
        case WM_NCPAINT:
        {
            //3.获取整个窗口的DC,包括标题栏,工具条等
            HDC  hdc = GetWindowDC(hWnd);
            RECT  r = {0,0,400,20};
            HBRUSH  brh = CreateSolidBrush(RGB(255, 0, 0));
            FillRect(hdc, &r, brh);
            DeleteObject(brh);
            ReleaseDC(hWnd, hdc);//释放掉DC
            return  true;
    
    
        }break;
    
        }
    
        return DefWindowProc(hWnd, Msg, wParam, lParam);
    }
    
    
    int  WINAPI   WinMain(HINSTANCE  hInstance, HINSTANCE  hPrevInstance,
        LPSTR lpCmdLine, int  nShowCmd)
    {
    
        //1.注册窗口类
        WNDCLASS  wnd;
        wnd.cbClsExtra = 0;
        wnd.cbWndExtra = 0;
        wnd.hbrBackground = (HBRUSH)(GetStockObject(GRAY_BRUSH));//背景色
        wnd.hCursor = LoadCursor(NULL, IDC_ARROW);//光标
        wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);//图标
                                                    //wnd.lpfnWndProc = DefWindowProc;//默认窗口过程函数,用于处理消息
        wnd.lpfnWndProc = MyWindowProc;//自定义的窗口过程函数
        wnd.lpszClassName = L"MrHuang";//窗口类名
        wnd.lpszMenuName = NULL;//菜单资源名称
        wnd.style = CS_HREDRAW | CS_DBLCLKS;//窗口类、样式
        wnd.hInstance = hInstance;//实例句柄
        RegisterClass(&wnd);
    
        //创建窗口(返回之前发送WM_CREATE)
        HWND    hWnd = CreateWindow(L"MrHuang", L"第一个窗口程序",
            WS_OVERLAPPEDWINDOW, 100, 100, 400, 400, NULL, NULL, hInstance, NULL);
    
        //显示窗口
        ShowWindow(hWnd, nShowCmd);
        //更新窗口(发送WM_PAINT)
        UpdateWindow(hWnd);
    
        //消息循环(收到WM_QUIT消息退出)
        MSG  msg;
        while (GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);//翻译消息
            DispatchMessage(&msg);//分发消息到窗口过程
        }
    }

    三、绘图函数

    1)创建画笔

    2)选择一个对象到数据上下文

    3)画直线

                                                

    4)画矩形

    5)创建画刷

    6)DeleteObject函数

    7)GetStockObject函数

    8)画椭圆

    9)画饼图

    10)写入字符串

    11)SetBkColor函数

    12)SetBkMode函数

    13)DrawText函数

    14)SetTextAlign函数

    15)代码实例

    ①绘制直线、矩形、椭圆、饼图

    #include<windows.h> 
    
    
    //自定义的窗口过程
    LRESULT  CALLBACK    MyWindowProc(HWND hWnd, UINT Msg,
        WPARAM wParam, LPARAM lParam)
    {
        switch (Msg)
        {
        case WM_DESTROY:
            PostQuitMessage(0);//可以使GetMessage返回0    
            return 0;
    
        case WM_PAINT: 
        {
            PAINTSTRUCT ps;
            //获取设备上下文句柄
            HDC   hdc = BeginPaint(hWnd, &ps);
     
            //创建画笔
            HPEN  hPen = CreatePen(PS_DASHDOT, 1, RGB(255, 0, 0));
            //将笔选入到设备上下文(使用这支笔)
            SelectObject(hdc, hPen);
    
            //1.画直线(两个点)
            MoveToEx(hdc, 100, 100, NULL);
            LineTo(hdc, 200, 100);
    
            //创建画刷
            HBRUSH hBsh = CreateSolidBrush(RGB(0, 255, 0));
            //将画刷选入到设备上下文(使用这支画刷)
            SelectObject(hdc, hBsh);
             
            //2.画矩形(正方形)
            Rectangle(hdc, 200, 200, 400, 400);
    
    
            //获取透明画刷
            HGDIOBJ hBsh2  =GetStockObject(NULL_BRUSH);
            SelectObject(hdc, hBsh2);
            Rectangle(hdc,  100, 100, 200, 150);
    
            //3.画椭圆(圆形)
            Ellipse(hdc, 200, 200, 400, 400);
            Ellipse(hdc, 100, 100, 200, 150);
    
    
            //4.画饼图 
    /*            
            //饼图产生的步骤分解
            Ellipse(hdc, 500, 100, 800, 400); 
             //从圆心到第一个点的连线
             MoveToEx(hdc, 650, 250, NULL);
             LineTo(hdc,1000, 300);  
             //从圆心到第二个点的连线
             MoveToEx(hdc, 650, 250, NULL);
             LineTo(hdc, 400, 400);
     */        
             Pie(hdc, 500, 100, 800, 400, 1000, 300,400, 400);
    
    
            //删除GDI对象
            DeleteObject(hPen);
            DeleteObject(hBsh);
    
            EndPaint(hWnd, &ps);
        }
        break;
    
        }
    
        return DefWindowProc(hWnd, Msg, wParam, lParam);
    }
    
    
    int  WINAPI   WinMain(HINSTANCE  hInstance, HINSTANCE  hPrevInstance,
        LPSTR lpCmdLine, int  nShowCmd)
    {
    
        //1.注册窗口类
        WNDCLASS  wnd;
        wnd.cbClsExtra = 0;
        wnd.cbWndExtra = 0;
        wnd.hbrBackground = (HBRUSH)(GetStockObject(GRAY_BRUSH));//背景色
        wnd.hCursor = LoadCursor(NULL, IDC_ARROW);//光标
        wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);//图标
                                                    //wnd.lpfnWndProc = DefWindowProc;//默认窗口过程函数,用于处理消息
        wnd.lpfnWndProc = MyWindowProc;//自定义的窗口过程函数
        wnd.lpszClassName = L"MrHuang";//窗口类名
        wnd.lpszMenuName = NULL;//菜单资源名称
        wnd.style = CS_HREDRAW | CS_DBLCLKS;//窗口类、样式
        wnd.hInstance = hInstance;//实例句柄
        RegisterClass(&wnd);
    
        //创建窗口(返回之前发送WM_CREATE)
        HWND    hWnd = CreateWindow(L"MrHuang", L"第一个窗口程序",
            WS_OVERLAPPEDWINDOW, 100, 100, 1000, 700, NULL, NULL, hInstance, NULL);
    
        //显示窗口
        ShowWindow(hWnd, nShowCmd);
        //更新窗口(发送WM_PAINT)
        UpdateWindow(hWnd);
    
        //消息循环(收到WM_QUIT消息退出)
        MSG  msg;
        while (GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);//翻译消息
            DispatchMessage(&msg);//分发消息到窗口过程
        }
    }

    ②写入字符串

    #include<windows.h> 
    
    
    //自定义的窗口过程
    LRESULT  CALLBACK    MyWindowProc(HWND hWnd, UINT Msg,
        WPARAM wParam, LPARAM lParam)
    {
        switch (Msg)
        {
        case WM_DESTROY:
            PostQuitMessage(0);//可以使GetMessage返回0    
            return 0;
    
        case WM_PAINT:
        {
            PAINTSTRUCT ps;
            //获取设备上下文句柄
            HDC   hdc = BeginPaint(hWnd, &ps);
    
            //改变文本的背景色
            SetBkColor(hdc, RGB(255, 0, 0));
            //设置文本背景模式 
            SetBkMode(hdc, TRANSPARENT);//透明
    
            //设置文本的颜色
            SetTextColor(hdc, RGB(255, 0, 0));
    
    
            //设置文本的参考点
            SetTextAlign(hdc, TA_TOP);
    
            //1.界面上画文本
            TextOut(hdc,250, 200, L"你好啊,这是画的文本!", lstrlen(L"你好啊,这是画的文本!"));
    
            //2.在矩形范围中画文本
            RECT  r = {250,400,300,500};
            Rectangle(hdc, r.left, r.top, r.right, r.bottom);
            DrawText(hdc, L"你好啊,这是画的文本!", lstrlen(L"你好啊,这是画的文本!")
                , &r,  DT_BOTTOM|DT_SINGLELINE);
    
    
    
    
            EndPaint(hWnd, &ps);
        }
        break;
    
        }
    
        return DefWindowProc(hWnd, Msg, wParam, lParam);
    }
    
    
    int  WINAPI   WinMain(HINSTANCE  hInstance, HINSTANCE  hPrevInstance,
        LPSTR lpCmdLine, int  nShowCmd)
    {
    
        //1.注册窗口类
        WNDCLASS  wnd;
        wnd.cbClsExtra = 0;
        wnd.cbWndExtra = 0;
        wnd.hbrBackground = (HBRUSH)(GetStockObject(GRAY_BRUSH));//背景色
        wnd.hCursor = LoadCursor(NULL, IDC_ARROW);//光标
        wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);//图标
                                                    //wnd.lpfnWndProc = DefWindowProc;//默认窗口过程函数,用于处理消息
        wnd.lpfnWndProc = MyWindowProc;//自定义的窗口过程函数
        wnd.lpszClassName = L"MrHuang";//窗口类名
        wnd.lpszMenuName = NULL;//菜单资源名称
        wnd.style = CS_HREDRAW | CS_DBLCLKS;//窗口类、样式
        wnd.hInstance = hInstance;//实例句柄
        RegisterClass(&wnd);
    
        //创建窗口(返回之前发送WM_CREATE)
        HWND    hWnd = CreateWindow(L"MrHuang", L"第一个窗口程序",
            WS_OVERLAPPEDWINDOW, 100, 100, 1000, 700, NULL, NULL, hInstance, NULL);
    
        //显示窗口
        ShowWindow(hWnd, nShowCmd);
        //更新窗口(发送WM_PAINT)
        UpdateWindow(hWnd);
    
        //消息循环(收到WM_QUIT消息退出)
        MSG  msg;
        while (GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);//翻译消息
            DispatchMessage(&msg);//分发消息到窗口过程
        }
    }

    四、双缓冲绘制技术

    1)什么是双缓冲绘制技术

    2)步骤

    3)CreateCompatiableDC函数

    4)CreateCompatiableBitmap函数

    5)BitBlt函数

    6)StretchBlt函数

    7)代码实例

    #include<windows.h>
    #include<CommCtrl.h> 
    
    
    //自定义的窗口过程
    LRESULT  CALLBACK    MyWindowProc(HWND hWnd, UINT Msg,
        WPARAM wParam, LPARAM lParam)
    {
        switch (Msg)
        {
        case WM_DESTROY:
            PostQuitMessage(0);//可以使GetMessage返回0    
            return 0;
    
        case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC   hdc = BeginPaint(hWnd, &ps);
     
             //1.创建兼容内存DC,此时它的大小时1X1,很小,不能绘制
            HDC  hMemDC=CreateCompatibleDC(hdc);
    
            //2.创建兼容位图,提供绘画区域
            HBITMAP hMemBmp = CreateCompatibleBitmap(hdc, 100, 100);
    
            //3.把兼容位图选到兼容内存DC中,此刻DC的大小与位图一致,可以绘制
            SelectObject(hMemDC, hMemBmp);
    
            //4.在兼容内存DC上进行绘图操作
            SetTextColor(hMemDC, RGB(255, 0, 0));
            TextOut(hMemDC, 0, 0, L"双缓冲技术绘制!", lstrlen(L"双缓冲技术绘制!")); 
            Rectangle(hMemDC, 30, 30, 80, 80);
    
            //5.把内存DC中的图像一次性画到窗口DC上
             //不拉伸
             BitBlt(hdc, 0, 0, 100, 100, hMemDC, 0, 0, SRCCOPY);
            
             //拉伸(目标矩形大于源矩形)
             StretchBlt(hdc, 0, 0, 400, 400, hMemDC, 0, 0,100,100, SRCCOPY);
             //压缩(目标矩形小于源矩形)
             StretchBlt(hdc, 0, 0, 50, 50, hMemDC, 0, 0, 100, 100, SRCCOPY);
    
    
             //释放资源
             DeleteDC(hMemDC);
             DeleteObject(hMemBmp);
    
    
            EndPaint(hWnd, &ps);
        }
        break;
    
        }
    
        return DefWindowProc(hWnd, Msg, wParam, lParam);
    }
    
    
    int  WINAPI   WinMain(HINSTANCE  hInstance, HINSTANCE  hPrevInstance,
        LPSTR lpCmdLine, int  nShowCmd)
    {
    
        //1.注册窗口类
        WNDCLASS  wnd;
        wnd.cbClsExtra = 0;
        wnd.cbWndExtra = 0;
        wnd.hbrBackground = (HBRUSH)(GetStockObject(GRAY_BRUSH));//背景色
        wnd.hCursor = LoadCursor(NULL, IDC_ARROW);//光标
        wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);//图标
                                                    //wnd.lpfnWndProc = DefWindowProc;//默认窗口过程函数,用于处理消息
        wnd.lpfnWndProc = MyWindowProc;//自定义的窗口过程函数
        wnd.lpszClassName = L"MrHuang";//窗口类名
        wnd.lpszMenuName = NULL;//菜单资源名称
        wnd.style = CS_HREDRAW | CS_DBLCLKS;//窗口类、样式
        wnd.hInstance = hInstance;//实例句柄
        RegisterClass(&wnd);
    
        //创建窗口(返回之前发送WM_CREATE)
        HWND    hWnd = CreateWindow(L"MrHuang", L"第一个窗口程序",
            WS_OVERLAPPEDWINDOW, 100, 100, 400, 400, NULL, NULL, hInstance, NULL);
    
        //显示窗口
        ShowWindow(hWnd, nShowCmd);
        //更新窗口(发送WM_PAINT)
        UpdateWindow(hWnd);
    
        //消息循环(收到WM_QUIT消息退出)
        MSG  msg;
        while (GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);//翻译消息
            DispatchMessage(&msg);//分发消息到窗口过程
        }
    }

    五、绘制位图

    1)什么是位图

    2)位图绘制的步骤

    3)LoadImage函数

    4)SetStrechBltMode函数

    5)代码实例

    #include<windows.h>
    #include<CommCtrl.h> 
    
    
    //自定义的窗口过程
    LRESULT  CALLBACK    MyWindowProc(HWND hWnd, UINT Msg,
        WPARAM wParam, LPARAM lParam)
    {
        switch (Msg)
        {
        case WM_DESTROY:
            PostQuitMessage(0);//可以使GetMessage返回0    
            return 0;
    
        case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC   hdc = BeginPaint(hWnd, &ps);
    
            //1.创建内存兼容DC(1px  X  1px)
            HDC  hMemDC = CreateCompatibleDC(hdc);
    
            //2.加载位图资源
            HBITMAP hBmp= (HBITMAP)LoadImage(NULL, L"bg.bmp", IMAGE_BITMAP, 800, 800, LR_LOADFROMFILE);
    
            //3.把位图选入到兼容内存DC
            SelectObject(hMemDC, hBmp);
    
            //添加水印
            TextOut(hMemDC, 100, 100, L"乱涂乱画", lstrlen(L"乱涂乱画"));
             
            //设置图像拉伸模式
            //SetStretchBltMode(hdc, COLORONCOLOR);//删除多余像素
            SetStretchBltMode(hdc, HALFTONE); 
    
            //4.将兼容DC中的图像一次性拷贝到窗口DC上
             //BitBlt(hdc, 0, 0, 800, 800, hMemDC, 0, 0, SRCCOPY);
            //完整显示
             StretchBlt(hdc, 0, 0, 400, 400, hMemDC, 0, 0, 800,800,SRCCOPY);
    
            //5.释放DC与位图资源
            DeleteObject(hBmp);
            DeleteDC(hMemDC);
          
            EndPaint(hWnd, &ps);
        }
        break;
    
        }
    
        return DefWindowProc(hWnd, Msg, wParam, lParam);
    }
    
    
    int  WINAPI   WinMain(HINSTANCE  hInstance, HINSTANCE  hPrevInstance,
        LPSTR lpCmdLine, int  nShowCmd)
    {
    
        //1.注册窗口类
        WNDCLASS  wnd;
        wnd.cbClsExtra = 0;
        wnd.cbWndExtra = 0;
        wnd.hbrBackground = (HBRUSH)(GetStockObject(GRAY_BRUSH));//背景色
        wnd.hCursor = LoadCursor(NULL, IDC_ARROW);//光标
        wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);//图标
                                                    //wnd.lpfnWndProc = DefWindowProc;//默认窗口过程函数,用于处理消息
        wnd.lpfnWndProc = MyWindowProc;//自定义的窗口过程函数
        wnd.lpszClassName = L"MrHuang";//窗口类名
        wnd.lpszMenuName = NULL;//菜单资源名称
        wnd.style = CS_HREDRAW | CS_DBLCLKS;//窗口类、样式
        wnd.hInstance = hInstance;//实例句柄
        RegisterClass(&wnd);
    
        //创建窗口(返回之前发送WM_CREATE)
        HWND    hWnd = CreateWindow(L"MrHuang", L"第一个窗口程序",
            WS_OVERLAPPEDWINDOW, 100, 100, 400, 400, NULL, NULL, hInstance, NULL);
    
        //显示窗口
        ShowWindow(hWnd, nShowCmd);
        //更新窗口(发送WM_PAINT)
        UpdateWindow(hWnd);
    
        //消息循环(收到WM_QUIT消息退出)
        MSG  msg;
        while (GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);//翻译消息
            DispatchMessage(&msg);//分发消息到窗口过程
        }
    }
  • 相关阅读:
    环境变量
    Python的简介和入门程序
    Mybatis的分页插件PageHelper的使用
    SQLyog 快捷键总结
    如何查看开发项目框架的版本信息
    Linux find命令示例 30
    转:数据库索引原理------MemCached
    array_merge 和 + 的区别
    [介绍]PHP设计模式:DAO(数据访问对象模式)
    PHP业务逻辑层和数据访问层设计
  • 原文地址:https://www.cnblogs.com/mango1997/p/14628463.html
Copyright © 2020-2023  润新知