C语言编写图形界面
文章目录
- 环境
- 使用库
- 基础概念
- 句柄
- 程序的入口
- 创建窗口
- 定义窗口类
- 注册窗口类
- 创建窗口
- 完整代码
- 运行效果
环境
使用的是VSCode + MinGW;
使用库
我们使用windows.h库来实现图形化界面。
头文件如下:
#include <windows.h>
windows.h是 Windows 操作系统的核心头文件,它提供了许多与 Windows API 相关的功能和宏定义。
基础概念
句柄
首先我们来了解一个概念,叫句柄。句柄是一种表示、访问或操作资源的引用或标识符。它可以被视为对象或数据结构的抽象表示。简单来说,句柄是指向资源的指针。
在不同的上下文中,句柄可以表示多种类型的资源,比如说:内存句柄、文件句柄、窗口句柄等等许多许多。
句柄通常由操作系统提供和管理,开发者使用句柄来引用和操作资源,而无需了解底层实现的具体细节。句柄的具体实现方式因操作系统而异,可能是一个整数、一个指针或其他形式的标识符。
使用句柄的好处之一是它提供了一种封装和抽象资源的方式,隐藏了底层实现细节,使得资源的使用更安全和高效。另外,句柄也使得多个程序或线程可以共享资源,提高了系统资源的利用率。
程序的入口
我们之前写的C程序控制台入口都是int main(void){},但是当我们使用windows.h库,想要创建图形界面的时候就不可以了,应该使用如下程序入口:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
}
int WINAPI WinMain是Windows程序的入口函数。下面对WinMain函数的参数进行解释:
- HINSTANCE hInstance:当前应用程序的实例句柄。实例是指正在运行的应用程序的唯一标识。这个参数在Windows程序中常常用来标识应用程序以及与其他应用程序进行交互。
- HINSTANCE hPrevInstance:前一个应用程序的实例句柄。在Windows中已经被弃用,现在始终为NULL。
- LPSTR lpCmdLime:命令行参数。在Windows程序中,可以通过命令行传递额外的参数。这个参数是一个指向以空字符终止的字符串的指针,其中包含了命令行参数的文本。
- int nCmdShow:窗口的显示状态。它指示窗口在初始化后应如何显示,比如是否最大化、最小化或正常显示。nCmdShow参数可以采用以下常用值:
- SW_SHOW:显示窗口。
- SW_HIDE:隐藏窗口。
- SW_MAXIMIZE:最大化窗口。
- SW_MINIMIZE:最小化窗口。
创建窗口
定义窗口类
通过窗口类,我们可以实现自定义的窗口行为和外观。
我们首先需要定义一个WNDCLASS结构体变量。
WNDCLASS wc = {0};
如上,我们定义了一个名为wc的WNDCLASS结构体变量,并初始化所有成员为0。使用{0}可以将结构体中的所有成员都设置为默认值。
然后我们需要将窗口过程函数的地址赋给WNDCLASS结构体变量的lpfnWndProc成员。窗口过程函数是窗口消息的处理函数,代码如下。
wc.lpfnWndProc = WndProc;
然后将当前应用程序的实例句柄赋给WNDCLASS结构体变量的hInstance成员。实例句柄用于标识当前运行的应用程序的实例。
wc.hInstance = hInstance;
接着将背景刷子的句柄赋给WNDCLASS结构体变量的hbrBackground成员。
wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
在这里,使用了预定义的COLOR_BACKGROUND作为背景颜色,通过强制类型转换将其转换为HBRUSH类型。
最后,我们将窗口名赋给WNDCLASS结构体变量的lpszClassName成员。
wc.lpszClassName = "MyWinClass";
这里我们将窗口类的名称被设置为"MyWinClass"。
完整代码如下:
// 定义窗口类WNDCLASS wc = {0};wc.lpfnWndProc = WndProc;wc.hInstance = hInstance;wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);wc.lpszClassName = "MyWinClass";
注册窗口类
我们需要使用RegisterClass函数来注册窗口类,该函数需要一个参数,该参数指向包含窗口类信息的WNDCLASS结构体的指针。将窗口类信息传递给函数,以便系统知道如何处理后续创建的窗口。
RegisterClass(&wc)
同时,我们应该检查RegisterClass函数的返回值是否为0,也就是是否注册窗口类失败。如果注册失败,返回值为0。
// 注册窗口类
if (!RegisterClass(&wc)) {MessageBox(NULL, "窗口注册失败!", "错误", MB_ICONERROR);return 1;
}
代码中,如果窗口类注册失败,则弹出一个消息框,显示错误信息。
MessageBox方法的第一个参数NULL表示没有父窗口,第二个参数是消息框的内容,第三个参数是消息框的标题,MB_ICONERROR表示使用错误图标。
最后return 1,作为程序的退出码。这个值将被返回给操作系统,表示程序的执行状态。
通过注册窗口类,我们告知操作系统如何处理后续创建的窗口。如果注册窗口类失败,这通常是因为系统资源不足或窗口类信息错误,导致无法创建窗口。
创建窗口
我们可以通过CreateWindow()方法创建一个窗口实例,并将其句柄保存在变量中。
// 创建窗口
HWND hWnd = CreateWindow("MyWinClass", "我的窗口", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600,NULL, NULL, hInstance, NULL);
HWND是窗口句柄,用于标识窗口。
完整代码
#include <windows.h>// 声明窗口过程函数
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {// 定义窗口类WNDCLASS wc = {0};wc.lpfnWndProc = WndProc;wc.hInstance = hInstance;wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);wc.lpszClassName = "MyWinClass";// 注册窗口类if (!RegisterClass(&wc)) {MessageBox(NULL, "窗口注册失败!", "错误", MB_ICONERROR);return 1;}// 创建窗口HWND hWnd = CreateWindow("MyWinClass", "我的窗口", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600,NULL, NULL, hInstance, NULL);if (!hWnd) {MessageBox(NULL, "窗口创建失败!", "错误", MB_ICONERROR);return 1;}// 显示窗口ShowWindow(hWnd, nCmdShow);UpdateWindow(hWnd);// 消息循环MSG msg;while (GetMessage(&msg, NULL, 0, 0)) {TranslateMessage(&msg);DispatchMessage(&msg);}return msg.wParam;
}// 窗口过程函数
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {switch (msg) {case WM_PAINT: {PAINTSTRUCT ps;HDC hdc = BeginPaint(hWnd, &ps);// 设置字体和背景颜色HFONT hFont = CreateFont(30, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, "Arial");HFONT hOldFont = (HFONT)SelectObject(hdc, hFont);SetTextColor(hdc, RGB(0, 0, 0));SetBkColor(hdc, RGB(255, 255, 255));// 绘制文本RECT rect;GetClientRect(hWnd, &rect);DrawText(hdc, "Hello World", -1, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);SelectObject(hdc, hOldFont);DeleteObject(hFont);EndPaint(hWnd, &ps);break;}case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hWnd, msg, wParam, lParam);}return 0;
}
运行效果
最终我们代码的完整运行效果如图所示。

相关文章:
C语言编写图形界面
文章目录 环境使用库基础概念句柄 程序的入口创建窗口定义窗口类注册窗口类创建窗口 完整代码运行效果 环境 使用的是VSCode MinGW; 使用库 我们使用windows.h库来实现图形化界面。 头文件如下: #include <windows.h>windows.h是 Windows 操作…...
K8s学习笔记3
Kubernetes功能: Kubernetes是一个轻便的可扩展的开源平台,用于管理容器化应用和服务。通过Kubernetes能够进行应用的自动化部署和扩缩容。在Kubernetes中,会将组成应用的容器组合成一个逻辑单元以更易管理和发现。Kubernetes积累了作为Goog…...
ceph集群的扩容缩容
文章目录 集群扩容添加osd使用ceph-deploy工具手动添加 添加节点新节点前期准备新节点安装ceph,出现版本冲突 ceph-deploy增加节点 集群缩容删除osd删除节点 添加monitor节点删除monitor节点使用ceph-deploy卸载集群 实验所用虚拟机均为Centos 7.6系统,8…...
gremlin安装使用 详细步骤
gremlin是一个图数据库查询工具,注意他只是一个工具类似于dbeaver,navicat,sqlyog,是专门来分析图数据库的一个工具。 下载 下载地址Apache Download Mirrors 省事的可以直接 wget https://www.apache.org/dyn/closer.lua/tin…...
Java语言怎么编写一个程序计算出租车的运输费用:出租车起步15公里以内20块钱,需要支付调头费用
下面是一个Java语言编写的计算出租车运输费用的程序: java import java.util.Scanner; public class TaxiFareCalculator { public static void main(String[] args) { Scanner input new Scanner(System.in); System.out.print("请输入出租车行驶的里程&…...
十、flume的安装
1.解压 2.改名 3.修改权限 4.编辑环境变量并source export FLUME_HOME/usr/local/flume export PATH$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$HIVE_HOME/bin:$HBASE_HOME/bin:$SQOOP_HOME/bin:$PIG_HOME/bin:$FLUME_HOME/bin 5.配置 6.查看版本 7.启动Hadoo…...
互联网广告及产品变现认知分析整理
深入学习互联网广告及产品,并且高效利用这一模式进行变现。 字节先是建立了一个非常强大的用户产品——抖音,通过各种渠道让抖音快速成长起来,收获了一大批初始用户。有了用户基础之后,字节开始打造它的广告产品,逐渐…...
item_search_img-按图搜索淘宝商品(拍立淘)
一、接口参数说明: item_search_img-按图搜索淘宝商品(拍立淘),点击更多API调试,请移步注册API账号点击获取测试key和secret 公共参数 请求地址: https://api-gw.onebound.cn/taobao/item_search_img 名称类型必须描…...
OWASP Top 10(2021)漏洞学习(最新)
A01:2021-权限控制失效 从第五位上升到第一位,94%的应用程序都接受了某种形式的针对“失效的访问控制”的测试,该事件的 平均发生率为 3.81%,该漏洞在提供的数据集中出现漏洞的应用数量最多,总发生漏洞应用数量超过31.8万多 次。 …...
mysql 、sql server 游标 cursor
游标 声明的位置 游标必须在声明处理程序之前被声明,并且变量和条件还必须在声明游标或处理程序之前被声明 游标的使用步骤 声明游标打开游标使用游标关闭游标 (sql server 关闭游标和释放游标) sql server 游标 declare my_cursor curs…...
dockers搭建基本服务
1、使用mysql:5.6和 owncloud 镜像,构建一个个人网盘。 拉取mysql-5.6和owncloud的镜像 docker run -d --name mdb --env MYSQL_ROOT_PASSWORD123 cytopia/mysql-5.6 docker run -d -p 90:80 --name webdcloud --link mdb:mdb owncloud 注册的时候,数据…...
微信小程序纯前端从阿里云OSS下载json数据-完整版
起因 因为云开发开始收费(貌似很久了),准备改造在以前的小程序,数据转到oss上,小程序使用原生,不算专业领域, 所以先百度.... 网上的教程真的是千篇一律,大部分开局就是require(ali-oss); 好点的npm install ali-oss --save开局,拼凑操作到最后发现要用云开发,因为云…...
【微服务实战】01-工程结构概览
文章目录 工程结构概览:定义应用分层及依赖关系1.应用分层2.定义Entity3.仓储层3.1 工作单元:事务管理3.2 仓储层 4.领域事件5.APIController最佳实践 工程结构概览:定义应用分层及依赖关系 1.应用分层 领域模型层基础设施层 ⇒ 仓储应用层 ⇒ Api、后台任务Job共…...
论文导读|European Journal of Operational Research近期文章精选:旅行商问题专题
推文作者:王松阁 编者按 在“European Journal of Operational Research近期论文精选”中,我们有主题、有针对性地选择了European Journal of Operational Research中一些有趣的文章,不仅对文章的内容进行了概括与点评,而且也对文…...
playwright迭代元素
DOM结构 <ul><li>apple</li><li>banana</li><li>orange</li> </ul>迭代元素操作 通过 page.get_by_role("listitem") 会匹配到 apple, banana, orange, 如果要对这一组数据中的每个元素进行操作&#…...
65 | 增长模型案例
增长模型代表了一种综合性的方法论,旨在通过深入了解用户行为、市场趋势和数据洞察,来指导企业制定有效的增长战略。这种方法突破了传统的经验主义,将决策过程建立在数据驱动和实验的基础之上。增长模型不仅仅是一种理论,更是一种实际操作的框架,帮助企业在各个层面实现业…...
Django视图-HttpRequest请求对象和HttpResponse响应对象
文章目录 HttpRequestHttpResponse实践request对象的属性和方法响应 def index(request): 这个request其实就是内部已经封装好的Http请求HttpRequest,它是一个请求对象Django中的视图主要用来接受Web请求,并做出响应。 视图的本质就是一个Python中的函数…...
原来Lambda表达式是这样写的
原来Lambda表达式是这样写的 lambda 是一个匿名函数,我们可以把 lambda 表达式理解为是一段可以传递的代码。 lambda 简明地将代码或方法作为参数传递进去执行。 函数式编程:核心是把函数作为值。 函数式接口 :只有一个抽象方法的接口称之…...
smartsofthelp 5.0 最专业的数据库优化工具,数据库配置优化,数据库高并发优化,SQL 语句优化...
下载地址:百度网盘 请输入提取码 SQL操作返回历史记录: 2023-08-21 20:42:08:220 输入:select version as 版本号 2023-08-21 20:42:08:223 输出:当前数据库实例版本号:Microsoft SQL Server 2012 - 11.0.2100.60 (X64) …...
智影 R100:首款三维Mesh建模的SLAM激光扫描仪
近年来,激光SLAM系统凭借其更加快速且准确获取更丰富信息的优势,迅速风靡测绘领域,让原本耗时耗力的外业测量变得更加高效。手持激光扫描仪作为基于激光SLAM技术衍生的众多产品之一,相较于架站式激光扫描仪更加轻巧便利࿰…...
大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会࿰…...
【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error
在前端开发中,JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作(如 Promise、async/await 等),开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝(r…...
jdbc查询mysql数据库时,出现id顺序错误的情况
我在repository中的查询语句如下所示,即传入一个List<intager>的数据,返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致,会导致返回的id是从小到大排列的,但我不希望这样。 Query("SELECT NEW com…...
第22节 Node.js JXcore 打包
Node.js是一个开放源代码、跨平台的、用于服务器端和网络应用的运行环境。 JXcore是一个支持多线程的 Node.js 发行版本,基本不需要对你现有的代码做任何改动就可以直接线程安全地以多线程运行。 本文主要介绍JXcore的打包功能。 JXcore 安装 下载JXcore安装包&a…...
