• Win32知识之窗口绘制.窗口第一讲


          Win32知识之窗口本质

    一丶摘要

      在学习Win32的时候. 很多操作都是窗口进行操作的.那么今天就说一下窗口的本质是什么. 

    窗口的本质是不断绘制.是windows通过消息机制进行绘制的.

    我们知道.内存分为高低2G 低2G是给应用程序使用的. 高2G是给操作系统使用的.而我们画图形的操作都是操作系统通过底层的 win32k.sys这个驱动来提供的.

    进程跟线程管理是通过notokerner.exe这个程序来管理的.但是三环不能使用.所以提供接口给三环. 分别是kerner32.dll 跟user32.dll gdi.dll

    那么他们之间的区别是什么.

    1.kerner32.dll  管理进程线程跟内存的一个dll

    2.user32.dll   窗口管理.图形界面管理.

    3.gdi.dll         自己绘制的的管理.

    而我们要认识一下窗口的创建.那么需要了解几个基础的只是.

    1.设备对象.

    2.DC设备上下文.

    3.图形对象.

    1.设备对象是什么.

      简而言之设备对象的意思就是你要画图形要往哪里画. 每一个窗口都有一个窗口句柄.而且是存放在全局窗口句柄表中的. 我们可以获取一下.使用Spy++获取.

    2.DC设备上下文.

      DC设备上下文其实就是这个窗口有一块内存是绘制用的. 我们想要往这个窗口绘制.需要先绘制到这个内存中才可以.这块内存就称为DC上下文.

    3.图形对象.

      图形对象就是指画笔 画刷 位图. 等等这些对象.因为我们要往内存中画的时候.可以画默认的.但是一般我们想改变一下形式.所以创建图形对象跟DC相关联.那么我们绘制就可以使用图形对象了.

    二丶绘制窗口步骤

      绘制窗口免不了使用API.但是使用之前.需要知道我们要操作的步骤.

    1.获取窗口句柄.也就是设备对象.

    2.获取窗口中的DC上下文.可以理解为获取指定窗口的绘图的那块内存.

    3.创建图形对象. 要想绘制.那么首先就需要你自定义的一个绘制的东西才可以.

    4.关联图形对象跟DC. 只要关联了.那么绘制的时候自动就使用你的图形对象了.

    5.进行你的绘图操作. 这里就是你写的绘图代码了.

    6.释放资源. 不管是窗口句柄也好. DC也好.图形对象也好.都是内核对象.所以我们需要进行释放.

    具体API:

     1.获取指定窗口句柄.     FindWindowA/FindWindowW

    HWND FindWindowA(
      LPCSTR lpClassName,              窗口类名.字符串. 可以用Spy++获取
      LPCSTR lpWindowName           窗口名称
    );
    返回窗口句柄.                          

     2.获取DC设备上下文.   GetDc()

    HDC GetDC(
      HWND hWnd                    传入设备对象.也就是窗口句柄
    );

    3.创建图形对象.

     PS: 创建图形对象.图形对象有很多. 有画笔. 画刷. 等等.

    复制代码
    HPEN CreatePen(
      int      iStyle,                创建笔的风格, 意思就是你的画笔是实心的 还是虚线 还是其他.
      int      cWidth,              笔的宽度.如果实心的.笔的宽度则自定义设置.如果其他.不能超过1
      COLORREF color            RGB的颜色.  你的画笔是什么颜色的.是一串16进制可以在线取色
    );
    返回图形对象
    复制代码

    还有常用的.创建矩形区域.

    复制代码
    HRGN CreateRectRgn(
      int x1,
      int y1,                             坐标
      int x2,
      int y2
    );
    复制代码

    具体使用可以查询MSDN: https://docs.microsoft.com/zh-cn/windows/desktop/gdi/windows-gdi  代码使用例子

    如果你安装了MSDN 2001版本.搜索SelectObject可以看到. 图形对象有很多.并且告诉你相应的API

    Bitmap  位图. 后面是操作的API

    Brush     画刷

    字体

    矩形

    4.关联DC跟图形对象.

    HGDIOBJ SelectObject(  HDC hdc,          // handle to DC
      HGDIOBJ hgdiobj   // handle to object);

     5.写你想要绘制的代码.

    这里如果是画线. 则用 LineTo(Hdc,x,y) 这个API  给定一个DC.给个x y坐标.则可以绘制.

    当然如果指定在哪里开始绘制则用MoveToEx指定起始位置.

    复制代码
    BOOL MoveToEx(
      HDC     hdc,
      int     x,
      int     y,
      LPPOINT lppt
    );
    复制代码

    6.释放资源.

    释放资源很简单了. 如果是图形对象.同一使用DeleteObject(对象) 进行删除.

    如果是DC. 如果是创建的Dc.则用DeleteDc(DC对象)来进行删除.

    如果是获取的DC.则用ReleaseDc(Dc对象) 来进行删除.

    题外话. windows程序中还有一个API.可以获取DC中默认的图形对象.

    HGDIOBJ GetStockObject(
      int i                                  对象的类型.你想从DC中获取什么对象类型.
    );

    图像类型如果是 DC_BRUSH 则是获取纯色刷.就不用自己创建色刷了.可以通过操作色刷的API进行操作.

    COLORREF SetDCBrushColor(
      HDC      hdc,
      COLORREF color                   RGB颜色
    );

    三丶绘制图形.

    1.绘制直线的代码例子.

    复制代码
    #include "stdafx.h"
    #include <Windows.h>
    
    int main(int argc, char *argv[])
    {
        
        //1.获取窗口句柄
        HWND hwnd = ::FindWindow(NULL, TEXT("计算器"));
    
        //2.获取DC.
        HDC hdc = ::GetDC(hwnd);
    
        //3.创建图形对象.
        HPEN hPen = CreatePen(PS_SOLID, 10, RGB(0xFF, 0, 0)); //设置为红色画笔
    
        //4.关联图形对象跟DC
        HPEN oldPen = (HPEN)::SelectObject(hdc, hPen); //返回旧的画笔
        
        //5.绘制直线.
        MoveToEx(hdc, 0, 0, NULL);
        LineTo(hdc, 600, 100);
    
        //6.释放资源.
        ::SelectObject(hdc, oldPen); //首先还原旧画笔
        DeleteObject(hPen);          //删除图形对象.
        ReleaseDC(hwnd,hdc);              //释放Dc
    
        system("pause");
        return 0;
    }
    复制代码

    运行之后图片.注意不要遮挡计算器.

     2.绘制矩形.获取默认画刷.设置画刷区域颜色.

     绘制代码

    复制代码
    #include "stdafx.h"
    #include <Windows.h>
    
    int main(int argc, char *argv[])
    {
        
        //1.获取窗口句柄
        HWND hwnd = ::FindWindow(NULL, TEXT("计算器"));
    
        //2.获取DC.
        HDC hdc = ::GetDC(hwnd);
    
        //3.创建图形对象.
        HPEN hPen = CreatePen(PS_SOLID, 10, RGB(0xFF, 0, 0)); //设置为红色画笔
        HBRUSH hBru = (HBRUSH)::GetStockObject(DC_BRUSH);
        //4.关联图形对象跟DC
        HPEN oldPen = (HPEN)::SelectObject(hdc, hPen); //返回旧的画笔
        SetDCBrushColor(hdc, RGB(0, 0xFF, 0)); //设置画刷颜色
        HBRUSH oldBrush = (HBRUSH)::SelectObject(hdc, hBru);
        //5.绘制句柄
        Rectangle(hdc, 0, 0, 100, 100);
    
        //6.释放资源.
        ::SelectObject(hdc, oldPen); //首先还原旧画笔
        DeleteObject(hPen);          //删除图形对象.
        ReleaseDC(hwnd,hdc);              //释放Dc
    
        system("pause");
        return 0;
    }
    复制代码

    其中新用到的API就是绘制矩形的API. 

    绘制完毕结果

    作者:IBinary


    坚持两字,简单,轻便,但是真正的执行起来确实需要很长很长时间.当你把坚持两字当做你要走的路,那么你总会成功. 想学习,有问题请加群.群号:725864912(收费)群名称: 逆向学习小分队 群里有大量学习资源. 以及定期直播答疑.有一个良好的学习氛围. 涉及到外挂反外挂病毒 司法取证加解密 驱动过保护 VT 等技术,期待你的进入。
  • 相关阅读:
    043_生成随机密码
    042_提示用户输入年份后测试判断是否为闰年
    041_查找 Linux 系统中的僵尸进程
    040_删除某个目录下大小为 0 的文件
    039_显示 CPU 厂商信息
    038_使用脚本自动创建逻辑卷
    037_自动添加防火墙规则,开启某些服务或端口(适用于 RHEL7)
    bzoj1537
    bzoj2466
    bzoj1047
  • 原文地址:https://www.cnblogs.com/bruce1992/p/14337837.html
Copyright © 2020-2023  润新知