C++.Windows图形
Windows图形
- 1. 基础知识
- 1.1 Windows图形编程基础
- 1.2 GDI与GDI+
- 1.3 窗口消息处理
- 2.1 注册窗口类
- 2.2 创建窗口
- 2.3 显示窗口
- 3.1 创建按钮
- 3.2 按钮消息处理
- 4.1 设置窗口透明度
- 4.2 透明窗口示例
- 5.1 使用区域创建异形窗口
- 5.2 异形窗口示例
- 6.1 GDI+抗锯齿设置
- 6.2 抗锯齿绘图示例
- 7.1 DirectX基础
- 7.2 Direct2D硬件加速
- Direct2D 的优势
- Direct2D 的基本使用
- 8.1 Direct2D矢量图形基础
- Direct2D 矢量图形的优势
- Direct2D 矢量图形的基本概念
- Direct2D 矢量图形的绘制流程
- 8.2 矢量图形绘制示例
- 9.1 窗口布局管理
- 静态布局
- 动态布局
- 使用布局管理器
- 水平布局
- 垂直布局
- 网格布局
- 9.2 控件排序与定位
- 设置控件的 Z 顺序
- 控件的定位
- 动态调整控件位置
- 使用布局管理器简化定位
- 9.3 布局管理器的高级应用
- 自适应布局
- 弹性布局
- 响应式布局
- 9.4 布局管理的注意事项
1. 基础知识
1.1 Windows图形编程基础
Windows图形编程主要基于Windows API,它提供了丰富的函数来创建和管理图形界面。以下是几个关键概念:
- 窗口(Window):是用户界面的基本元素,可以包含菜单、按钮、文本框等控件。每个窗口都有一个唯一的句柄(HWND)。
- 设备上下文(DC):是与设备相关的数据结构,用于存储绘图属性,如画笔、画刷等。通过设备上下文可以对窗口进行绘图操作。
- 消息(Message):是Windows操作系统与应用程序之间通信的方式,包括鼠标点击、键盘输入等事件。应用程序需要通过消息循环来处理这些消息。
- 坐标系统:Windows使用像素作为单位,坐标原点在窗口的左上角,水平向右为x轴正方向,垂直向下为y轴正方向。
1.2 GDI与GDI+
GDI(Graphics Device Interface)是Windows提供的图形设备接口,用于基本的绘图操作,如绘制线条、矩形、文本等。GDI+是GDI的升级版本,提供了更强大的功能,如抗锯齿、透明度、矢量图形等。
- GDI:使用设备上下文(HDC)进行绘图,例如:
HDC hdc = GetDC(hwnd); HPEN hPen = CreatePen(PS_SOLID, 2, RGB(255, 0, 0)); SelectObject(hdc, hPen); MoveToEx(hdc, 10, 10, NULL); LineTo(hdc, 100, 100); DeleteObject(hPen); ReleaseDC(hwnd, hdc);
- GDI+:使用GDI+对象进行绘图,例如:
Gdiplus::Graphics graphics(hdc); Gdiplus::Pen pen(Gdiplus::Color(255, 255, 0, 0), 2); graphics.DrawLine(&pen, 10, 10, 100, 100);
1.3 窗口消息处理
窗口消息处理是Windows图形编程的核心,应用程序通过消息循环来接收和处理消息。以下是基本的消息循环代码:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {TranslateMessage(&msg);DispatchMessage(&msg);
}
在窗口过程函数中,可以处理各种消息,例如:
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {switch (uMsg) {case WM_PAINT:// 绘图操作break;case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hwnd, uMsg, wParam, lParam);}return 0;
}
窗口消息处理是实现图形界面交互的基础,通过处理不同的消息,可以实现按钮点击、窗口移动等功能。# 2. 创建简单窗口
2.1 注册窗口类
在Windows编程中,注册窗口类是创建窗口的第一步。窗口类定义了窗口的外观和行为,包括窗口的标题、样式、图标、背景色等。以下是注册窗口类的代码示例:
WNDCLASS wc = {0};
wc.lpfnWndProc = WindowProc; // 指定窗口过程函数
wc.hInstance = hInstance; // 当前实例句柄
wc.lpszClassName = L"MyWindowClass"; // 窗口类名
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); // 背景色
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // 鼠标光标样式
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); // 窗口图标
if (!RegisterClass(&wc)) {MessageBox(NULL, L"Failed to register window class", L"Error", MB_OK | MB_ICONERROR);return 0;
}
在上述代码中,WNDCLASS
结构体用于描述窗口类的属性。lpfnWndProc
字段指定了窗口过程函数,用于处理窗口消息;hInstance
是当前程序实例的句柄;lpszClassName
是窗口类的名称,用于后续创建窗口时引用;hbrBackground
定义了窗口的背景颜色;hCursor
和hIcon
分别指定了鼠标光标样式和窗口图标。
2.2 创建窗口
注册窗口类后,可以使用CreateWindow
函数创建窗口。该函数需要指定窗口类名、窗口标题、窗口样式、窗口位置和大小等参数。以下是创建窗口的代码示例:
HWND hwnd = CreateWindow(L"MyWindowClass", // 窗口类名L"My Simple Window", // 窗口标题WS_OVERLAPPEDWINDOW, // 窗口样式CW_USEDEFAULT, CW_USEDEFAULT, // 窗口位置640, 480, // 窗口大小NULL, // 父窗口句柄NULL, // 菜单句柄hInstance, // 当前实例句柄NULL // 创建参数
);
if (!hwnd) {MessageBox(NULL, L"Failed to create window", L"Error", MB_OK | MB_ICONERROR);return 0;
}
在上述代码中,CreateWindow
函数的第一个参数是窗口类名,必须与注册窗口类时指定的类名一致;第二个参数是窗口标题,显示在窗口的标题栏上;第三个参数是窗口样式,WS_OVERLAPPEDWINDOW
表示创建一个具有标题栏、边框和最大化/最小化按钮的窗口;接下来的四个参数分别指定窗口的左上角坐标和宽度、高度;NULL
表示该窗口没有父窗口;NULL
表示该窗口没有菜单;hInstance
是当前程序实例的句柄;最后一个参数通常用于传递额外的创建参数。
2.3 显示窗口
创建窗口后,需要使用ShowWindow
函数来显示窗口。此外,通常还会调用UpdateWindow
函数来刷新窗口内容。以下是显示窗口的代码示例:
ShowWindow(hwnd, nCmdShow); // 显示窗口
UpdateWindow(hwnd); // 刷新窗口内容
在上述代码中,ShowWindow
函数的第一个参数是窗口句柄,nCmdShow
是命令行参数,通常在程序入口处由WinMain
函数传递。nCmdShow
的值可以是SW_SHOWNORMAL
、SW_SHOWMAXIMIZED
等,用于指定窗口的显示状态。UpdateWindow
函数会发送WM_PAINT
消息给窗口,触发窗口的绘制操作。
通过以上三个步骤,就可以创建并显示一个简单的窗口。这是Windows图形编程的基础,后续可以在此基础上添加更多的控件和功能。# 3. 按钮控件
3.1 创建按钮
在Windows编程中,按钮是一种常见的控件,用于接收用户的点击操作。按钮可以通过CreateWindow
函数创建,指定按钮的类型、位置、大小等属性。以下是创建按钮的代码示例:
// 创建一个普通按钮
HWND hwndButton = CreateWindow(L"BUTTON", // 按钮控件类名L"Click Me", // 按钮显示的文本WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, // 按钮样式100, 100, // 按钮左上角坐标100, 30, // 按钮宽度和高度hwnd, // 父窗口句柄(HMENU)1, // 按钮的ID,用于消息处理hInstance, // 当前实例句柄NULL // 创建参数
);
if (!hwndButton) {MessageBox(hwnd, L"Failed to create button", L"Error", MB_OK | MB_ICONERROR);
}
在上述代码中,CreateWindow
函数的第一个参数是按钮控件的类名,固定为L"BUTTON"
;第二个参数是按钮上显示的文本;第三个参数是按钮的样式,WS_CHILD
表示按钮是子窗口,WS_VISIBLE
表示按钮可见,BS_PUSHBUTTON
表示创建一个普通按钮;接下来的四个参数分别指定按钮的左上角坐标和宽度、高度;hwnd
是父窗口句柄;(HMENU)1
是按钮的ID,用于在消息处理中区分不同的按钮;hInstance
是当前程序实例的句柄;最后一个参数通常为NULL
。
除了普通按钮,还可以创建其他类型的按钮,例如单选按钮和复选按钮。单选按钮和复选按钮的创建方式与普通按钮类似,只是需要指定不同的样式。以下是创建单选按钮和复选按钮的代码示例:
// 创建一个单选按钮
HWND hwndRadioButton1 = CreateWindow(L"BUTTON", // 单选按钮控件类名L"Option 1", // 单选按钮显示的文本WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON, // 单选按钮样式100, 150, // 单选按钮左上角坐标100, 30, // 单选按钮宽度和高度hwnd, // 父窗口句柄(HMENU)2, // 单选按钮的IDhInstance, // 当前实例句柄NULL // 创建参数
);
if (!hwndRadioButton1) {MessageBox(hwnd, L"Failed to create radio button 1", L"Error", MB_OK | MB_ICONERROR);
}// 创建另一个单选按钮
HWND hwndRadioButton2 = CreateWindow(L"BUTTON", // 单选按钮控件类名L"Option 2", // 单选按钮显示的文本WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON, // 单选按钮样式100, 200, // 单选按钮左上角坐标100, 30, // 单选按钮宽度和高度hwnd, // 父窗口句柄(HMENU)3, // 单选按钮的IDhInstance, // 当前实例句柄NULL // 创建参数
);
if (!hwndRadioButton2) {MessageBox(hwnd, L"Failed to create radio button 2", L"Error", MB_OK | MB_ICONERROR);
}// 创建一个复选按钮
HWND hwndCheckBox = CreateWindow(L"BUTTON", // 复选按钮控件类名L"Check Me", // 复选按钮显示的文本WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, // 复选按钮样式100, 250, // 复选按钮左上角坐标100, 30, // 复选按钮宽度和高度hwnd, // 父窗口句柄(HMENU)4, // 复选按钮的IDhInstance, // 当前实例句柄NULL // 创建参数
);
if (!hwndCheckBox) {MessageBox(hwnd, L"Failed to create check box", L"Error", MB_OK | MB_ICONERROR);
}
在上述代码中,BS_AUTORADIOBUTTON
是单选按钮的样式,BS_AUTOCHECKBOX
是复选按钮的样式。单选按钮通常用于一组互斥的选项,用户只能选择其中一个;复选按钮则允许用户选择多个选项。
3.2 按钮消息处理
按钮的主要功能是接收用户的点击操作,并触发相应的事件。在Windows编程中,按钮的点击事件通过WM_COMMAND
消息来处理。当用户点击按钮时,系统会向父窗口发送WM_COMMAND
消息,父窗口可以通过检查消息的参数来确定是哪个按钮被点击,并执行相应的操作。以下是处理按钮点击事件的代码示例:
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {switch (uMsg) {case WM_COMMAND:// 检查是哪个按钮被点击switch (LOWORD(wParam)) {case 1: // 普通按钮被点击MessageBox(hwnd, L"Button clicked", L"Message", MB_OK);break;case 2: // 单选按钮1被选中if (IsDlgButtonChecked(hwnd, 2) == BST_CHECKED) {MessageBox(hwnd, L"Radio button 1 selected", L"Message", MB_OK);}break;case 3: // 单选按钮2被选中if (IsDlgButtonChecked(hwnd, 3) == BST_CHECKED) {MessageBox(hwnd, L"Radio button 2 selected", L"Message", MB_OK);}break;case 4: // 复选按钮被点击if (IsDlgButtonChecked(hwnd, 4) == BST_CHECKED) {MessageBox(hwnd, L"Check box checked", L"Message", MB_OK);} else {MessageBox(hwnd, L"Check box unchecked", L"Message", MB_OK);}break;}break;case WM_PAINT:// 绘图操作break;case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hwnd, uMsg, wParam, lParam);}return 0;
}
在上述代码中,WM_COMMAND
消息的wParam
参数包含了按钮的ID和通知代码。通过检查LOWORD(wParam)
的值,可以确定是哪个按钮被点击。对于普通按钮,当按钮被点击时,会触发BN_CLICKED
通知代码,父窗口可以直接执行相应的操作。对于单选按钮和复选按钮,需要使用IsDlgButtonChecked
函数来检查按钮的状态。如果按钮被选中,IsDlgButtonChecked
函数返回BST_CHECKED
;否则返回BST_UNCHECKED
。
通过上述代码,可以实现按钮的基本功能,如接收点击事件并触发相应的操作。按钮是Windows图形界面中非常重要的控件之一,通过合理使用按钮,可以为用户提供
相关文章:
C++.Windows图形
Windows图形 1. 基础知识1.1 Windows图形编程基础1.2 GDI与GDI+1.3 窗口消息处理2.1 注册窗口类2.2 创建窗口2.3 显示窗口3.1 创建按钮3.2 按钮消息处理4.1 设置窗口透明度4.2 透明窗口示例5.1 使用区域创建异形窗口5.2 异形窗口示例6.1 GDI+抗锯齿设置6.2 抗锯齿绘图示例7.1 D…...

vue实现与后台springboot传递数据【传值/取值 Axios 】
vue实现与后台springboot传递数据【传值/取值】 提示:帮帮志会陆续更新非常多的IT技术知识,希望分享的内容对您有用。本章分享的是node.js和vue的使用。前后每一小节的内容是存在的有:学习and理解的关联性。【帮帮志系列文章】:每…...

【英语笔记(三)】介绍谓语动词的分类,初步讲解四种基本状态:一般、进行、完成、完成进行
1. 五大类谓语动词 2. 谓语动词分类 3. 动词时间 过去--------------------------现在-----------------------未来 3. 动词状态 3.1 进行状态 3.2 完成状态 3.3 完成进行状态 3.4 一般状态 4. 时间 状态 名称说明例句现在现在现在现在进行时态现在某物正在做什么事情一只…...

【Python】让Selenium 像Beautifulsoup一样,用解析HTML 结构的方式提取元素!
我在使用selenium的find_element的方式去获取网页元素,一般通过xpath、css_selector、class_name的方式去获取元素的绝对位置。 但是有时候如果网页多了一些弹窗或者啥之类的,绝对位置会发生变化,使用xpath等方法,需要经常变动。…...

2025 后端自学UNIAPP【项目实战:旅游项目】3、API接口请求封装,封装后的简单测试以及实际使用
一、创建请求封装目录 选中自己的项目,右键鼠标---->新建---->目录---->名字自定义【我的是api】 二、创建两个js封装文件 选中封装的目录,右键鼠标---->新建---->js文件---->名字自定义【我的两个js文件分别是my_http和my_api】 三…...
Mysql--基础知识点--91.2--processlist
在 MySQL 中,SHOW PROCESSLIST 是一个常用命令,用于查看当前数据库服务器上所有正在运行的线程(进程)信息。以下是关键点说明: 1. 命令用法 SHOW FULL PROCESSLIST;输出字段: 列名含义Id线程唯一标识符&am…...
C#中程序集的详解一
程序集(Assembly)是 .NET 平台中的一个重要概念,它是代码和资源的逻辑单元,也是应用程序的部署、版本控制和安全权限的最小单位。下面详细介绍其定义和常见用法: 1. 程序集的定义 程序集是 .NET 应用程序的构建块&am…...
解决LangChain4j报错HTTP/1.1 header parser received no bytes
问题描述 当使用langchain4j-open-ai调用自己部署的大模型服务时报错: public static void main(String[] args) {OpenAiChatModel model OpenAiChatModel.builder().apiKey("none").modelName("qwen2.5-instruct").baseUrl("http://19…...

Ascend的aclgraph(二)_npu_backend中还有些什么秘密?
1 _npu_backend 文章还是从代码开始 import torch_npu, torchair config torchair.CompilerConfig() # 设置图下沉执行模式 config.mode "reduce-overhead" npu_backend torchair.get_npu_backend(compiler_configconfig) opt_model torch.compile(model, back…...

ventoy安全启动怎么选_ventoy安全启动支持是开还是关
ventoy安全启动怎么选?Ventoy新一代多系统启动U盘解决方案。国产开源U盘启动制作工具,支持Legacy BIOS和UEFI模式,理论上几乎支持任何ISO镜像文件,支持加载多个不同类型的ISO文件启动,无需反复地格式化U盘,…...
MySQL文章总结,简单整理和详细整理
这篇博客文章《MySQL 有这一篇就够(呕心狂敲37k字,只为博君一点赞!!!)》是一篇非常全面的MySQL基础教程,适合初学者和需要复习MySQL知识的开发者。以下是文章的核心内容整理: 一、SQ…...

CC53.【C++ Cont】二分查找的普通模版
目录 1.知识回顾 2.关键点 特点 三个模版 普通的模版(有局限) 以LeetCode上的一道题为例:704. 二分查找 分析 引入二段性:分两段,舍一段,操作另一段(这个是二分查找的本质!) 代码 提交结果 当然也可以使用随机数来分两段 普通模版总结 1.知识回顾 之前在C语言专栏…...
泛型加持的策略模式:打造高扩展的通用策略工具类
一、传统策略模式的痛点与突破 1.1 传统策略实现回顾 // 传统支付策略接口 public interface PaymentStrategy {void pay(BigDecimal amount); }// 具体策略实现 public class AlipayStrategy implements PaymentStrategy {public void pay(BigDecimal amount) { /* 支付宝支…...

【优选算法 | 链表】链表操作技巧:常见算法
算法相关知识点可以通过点击以下链接进行学习一起加油!双指针滑动窗口二分查找前缀和位运算模拟 链表是一种灵活的数据结构,广泛用于需要频繁插入和删除的场景。掌握链表的常见操作技巧,如插入、删除、翻转和合并等,能帮助开发者更…...
HTTP:十三.HTTP日志
日志记录 日志记录了跟踪使用情况、安全性、计费、错误检验。记录事务的基本信息。通常会记录下来的几个字段示例为: HTTP方法:主要记录事务用了什么方法客户端和服务器的HTTP版本:给出客户端和服务器有关的提示,比如兼容性提示什么的所请求资源的URL:记录Web站点某个资源…...
web 自动化之 selenium 元素四大操作三大切换等待
文章目录 一、元素的四大操作二、三大切换&等待1、切换窗口:当定位的元素不在当前窗口,则需要切换窗口2、切换iframe:当定位的元素在frame/iframe,则需要切换3、切换弹出窗口 一、元素的四大操作 1、输入 2、点击 3、获取文本 4、获取属…...
FEKO许可证的安全与合规性
在电磁仿真领域,FEKO软件因其出类拔萃的性能和广泛的应用场景,赢得了全球用户的广泛赞誉。但在这背后,是什么让FEKO在众多竞争者中脱颖而出?答案是其许可证的安全与合规性。它们不仅为用户提供了坚固的保障,更确保了用…...

w~大模型~合集30
我自己的原文哦~ https://blog.51cto.com/whaosoft/13284996 #VideoMamba 视频理解因大量时空冗余和复杂时空依赖,同时克服两个问题难度巨大,CNN 和 Transformer 及 Uniformer 都难以胜任,Mamba 是个好思路,让我们看看本文是…...

PBR材质-Unity/Blender/UE
目录 前言: 一、Unity: 二、Blender: 三、UE: 四、全家福: 五、后记: 前言: PBR流程作为表达物理效果的经典方式,很值得一学。纹理贴图使用的是上一期的Textures | cgbookcas…...

websocketpp 安装及使用
介绍 WebSocket 是从 HTML5 开始支持的一种网页端和服务端保持长连接的消息推送机制。 传统的 web 程序都是属于 "一问一答" 的形式,即客户端给服务器发送了一个 HTTP 请求,服务器给客户端返回一个 HTTP 响应。这种情况下服务器是属于被动…...
web:InfiniteScroll 无限滚动
InfiniteScroll 无限滚动 分页加载 <div class"data-box" v-infinite-scroll"loadMore"> <li v-fori in dataList></li> </div>form: {current: 1,size: 10,}loadMore(){console.log(this.dataList.length, this.total ,8888)if…...
LeetCode[101]对称二叉树
思路: 对称二叉树是左右子树对称,而不是左右子树相等,所以假设一个树只有3个节点,那么判断这个数是否是对称二叉树,肯定是先判断左右两个树,然后再看根节点,这样递归顺序我们就确认了࿰…...
c/c++爬虫总结
GitHub 开源 C/C 网页爬虫探究:协议、实现与测试 网页爬虫,作为一种自动化获取网络信息的强大工具,在搜索引擎、数据挖掘、市场分析等领域扮演着至关重要的角色。对于希望深入理解网络工作原理和数据提取技术的 C/C 开发者,尤其是…...
js fetch流式请求 AI动态生成文本,实现逐字生成渲染效果
开启流式请求:向后端接口发起普通的 fetch,它会返回一个包含 ReadableStream 的 Response 对象获取流式读取器:调用 response.body.getReader() 获取一个 ReadableStreamDefaultReader 实例循环读取数据块:在 while(true) 循环或 …...

第8章-2 查询执行的基础
上一篇:《第8章-1 查询性能优化-优化数据访问》,接着来了解查询执行的过程,这个对sql执行有个更直观的了解。 查询执行的基础 当希望MySQL能够以更高的性能运行查询时,最好的办法就是弄清楚MySQL是如何优化和执行查询的。一旦理解…...

java面试OOM汇总
在正式 Minor GC 前,JVM 会先检查新生代中对象,是比老年代中剩余空间大还是小。假如 Minor GC之后 Survivor 区放不下剩余对象,这些对象就要进入老年代 老年代剩余空间大于新生代中的对象大小,那就直接 Minor GC, GC 完…...
Java面试全记录:Spring Cloud+Kafka+Redis实战解析
Java面试全记录:Spring CloudKafkaRedis实战解析 人物设定 面试官:来自某互联网大厂资深架构师,着深灰色西装,手持MacBook Pro 候选人:张伟(随机生成),28岁,硕士&…...
com.fasterxml.jackson.dataformat.xml.XmlMapper把对象转换xml格式,属性放到标签<>里边
之前从没用过xml和对象相互转换,最近项目接了政府相关的。需要用xml格式数据进行相互转换。有些小问题,困扰了我一下下。 1.有些属性需要放到标签里边,有的需要放到标签子集。 2.xml需要加<?xml version"1.0" encoding"…...
LiveData:Android响应式编程的核心利器
LiveData是一种可观察的数据持有类,用于在Android应用中实现数据的响应式编程。它具有以下特点和作用: 特点 生命周期感知:LiveData能够感知与其关联的组件(如Activity、Fragment)的生命周期状态。只有当组件处于活跃状态(如Activity处于RESUMED状态)时,LiveData才会将…...
Browserless 快速上手
要将你提供的 HTML 模板和数据结构转换为可以用于 Browserless /pdf 接口的 JSON 请求体(且能正确渲染为 PDF),需要满足以下几点: ✅ 最终目标格式(这是能用的格式): json 复制编辑 { "h…...