窗口的本质
2026/9/24 9:28:33 网站建设 项目流程

窗口的本质

  1. 前置基础
    1)虚拟内存
    ● 每个进程 4GB 虚拟地址:0x00000000 ~ 0xFFFFFFFF
    ● 用户空间:0x00000000 ~ 0x7FFFFFFF(低 2GB,进程私有)
    ● 内核空间:0x80000000 ~ 0xFFFFFFFF(高 2GB,所有进程共享)
    2)模块划分
    ● 内核模块(内核空间)
    ○ ntoskrnl.exe:进程、线程、内存管理核心
    ○ win32k.sys:图形界面、窗口消息、GDI 底层实现,所有进程共享
    ● 用户模块(用户空间,每个进程独立)
    ○ kernel32.dll:进程线程内存基础 API
    ○ user32.dll:窗口、控件、消息
    ○ gdi32.dll:图形设备接口
    3)API 调用链路
    用户程序 → DLL 接口 (kernel32/user32/gdi32) → 内核模块真正实现
  2. 句柄对比:HANDLE 与 HWND
类型维护者句柄表跨进程生命周期用途
HANDLE各个内核对象进程私有句柄表❌无效进程关闭自动销毁进程、线程、互斥体、事件等内核对象
HWNDwin32k.sys全局共享句柄表✅全系统有效窗口销毁才失效窗口、控件

重点:HWND 是全局的,A 进程拿到的窗口句柄,B 进程可以直接使用
4. GDI 绘图核心概念
1)设备对象 (HWND) 绘图目标,代表 “画在哪里”,可以是窗口、桌面;Spy++ 可以抓取 HWND
2)设备上下文 HDC(Device Context)
内存绘图缓冲区,所有 GDI 绘图必须依赖 HDC
● 获取:HDC GetDC(HWND hwnd)
● 释放:ReleaseDC(HWND hwnd, HDC hdc)
● 双缓冲:先内存绘图,再输出到屏幕
3)GDI 图形对象(选入 DC 使用)

对象作用创建函数
Pen 画笔线条颜色、粗细、线型CreatePen()
Brush 画刷区域填充颜色图案CreateSolidBrush() / GetStockObject()
Font 字体文字样式CreateFont()
Bitmap 位图图片CreateBitmap()

SelectObject(HDC hdc, HGDIOBJ hgdiobj)
● 将 GDI 对象选入 DC,返回旧对象句柄
● DC 同一时刻每类对象只能有一个生效
● 绘图完成要恢复旧对象,销毁自定义 GDI 对象,否则发生GDI 资源泄漏
5. 画笔 CreatePen

HPENCreatePen(intstyle,intwidth,COLORREF color);

线型:
○ PS_SOLID 实线
○ PS_DASH虚线、PS_DOT点线、PS_DASHDOT点划线
虚线 / 点线,宽度必须≤1
宽度:逻辑像素,填 0 代表强制 1 像素
颜色:COLORREF RGB(r,g,b),r/g/b 范围 0‑255(FF)
示例:CreatePen(PS_SOLID,5,RGB(255,0,0)); //5像素红色实线
6. GetStockObject 获取系统预置 GDI 对象

HGDIOBJGetStockObject(intnIndex);

常用参数:
● BLACK_BRUSH黑色画刷、WHITE_BRUSH白色画刷
● NULL_BRUSH / HOLLOW_BRUSH空心画刷
● DC_BRUSH可动态改色的画刷,配合SetDCBrushColor()
系统预置对象不需要必须 DeleteObject,写 DeleteObject 也无害
7. 关键绘图 API
1)画线

MoveToEx(hdc,x1,y1,NULL);//设置起点LineTo(hdc,x2,y2);//画到终点

2)绘制矩形

Rectangle(hdc,left,top,right,bottom);

● 边框:由当前 DC 的画笔控制
● 内部填充:由当前 DC 的画刷控制
坐标原点 (0,0):绘图目标窗口左上角

标准 GDI 绘图完整示例代码

#include<windows.h>voidDrawDemo(HWND hwnd){//1.获取DCHDC hdc=GetDC(hwnd);//2.创建5像素红色实线画笔HPEN hPen=CreatePen(PS_SOLID,5,RGB(255,0,0));//3.获取系统可变色画刷HBRUSH hBrush=(HBRUSH)GetStockObject(DC_BRUSH);//4.把对象选入DC,保存旧对象!HGDIOBJ oldPen=SelectObject(hdc,hPen);HGDIOBJ oldBrush=SelectObject(hdc,hBrush);//修改画刷颜色为黄色SetDCBrushColor(hdc,RGB(255,255,0));//绘制400*400矩形Rectangle(hdc,0,0,400,400);//========资源恢复与释放【重中之重】========//恢复DC原来的对象SelectObject(hdc,oldPen);SelectObject(hdc,oldBrush);//销毁自定义GDI对象DeleteObject(hPen);//GetStockObject获取的对象可不删除//DeleteObject(hBrush);//释放设备上下文ReleaseDC(hwnd,hdc);}

注意:直接在窗口外部调用绘图,窗口被遮挡、最小化再还原时,绘制内容会消失
原因:窗口内容是实时绘制,窗口重绘消息WM_PAINT到来会刷新界面,真正绘图要写在 WM_PAINT 消息内部

总结

  1. 窗口本质:窗口没有永久保存图像,所有像素都是 GDI 实时绘制出来。窗口被遮挡后内容丢失,需要响应WM_PAINT重绘
  2. HDC用完必须ReleaseDC;自己 Create 出来的 GDI 对象必须DeleteObject,否则 GDI 泄漏
  3. SelectObject一定要保存旧对象,结束前还原回 DC,不能直接选入新对象不管
  4. HWND全局有效;普通HANDLE只属于本进程
  5. 画笔控制线条边框;画刷控制填充,画矩形、椭圆这类闭合图形两者同时生效

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询