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;
}

运行效果

最终我们代码的完整运行效果如图所示。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/99668.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis中的分布式锁及其延生的问题

前言 本文将着重介绍Redis中的分布式锁及其与出现的死锁和锁误删问题 什么是分布式锁 首先问题就是什么是分布式锁&#xff0c;分布式锁就是分布式系统中实现并发控制的一种锁机制&#xff0c;它可以保证多个节点在同一个时间只有有一个能成功竞争到系统资源&#xff08;共享…

微软Win11 Dev预览版Build23526发布

近日&#xff0c;微软Win11 Dev预览版Build23526发布&#xff0c;修复了不少问题。牛比如斯Microsoft&#xff0c;也有这么多bug&#xff0c;所以你写再多bug也不作为奇啊。 主要更新问题 [开始菜单&#xff3d; 修复了在高对比度主题下&#xff0c;打开开始菜单中的“所有应…

【LeetCode-中等题】128. 最长连续序列

题目 题解一&#xff1a;HeshSet枚举 思路&#xff1a;先对数组进行set去重&#xff0c;核心就是&#xff0c;先找出临界值&#xff08;假设以最小临界为例&#xff0c;那么这个临界值自己就是最小值&#xff0c;&#xff09;&#xff0c;以临界值不断做加1操作&#xff0c;看…

使用拦截器+Redis实现接口幂等

文章目录 使用拦截器Redis实现接口幂等1.思路分析2.具体实现2.1 创建redis工具类2.2 自定义幂等注解2.2 自定义幂等拦截器2.3 注入拦截器到容器 3.测试 使用拦截器Redis实现接口幂等 1.思路分析 接口幂等有很多种实现方式&#xff0c;拦截器/AOPRedis&#xff0c;拦截器/AOP本…

Linux —— 进程间通信(管道)

目录 一&#xff0c;进程间通信 二&#xff0c;管道 匿名管道 命名管道 一&#xff0c;进程间通信 进程间通信&#xff08;IPC&#xff0c;InterProcess Communication&#xff09;&#xff0c;即在不同进程之间进行信息的传播或交换&#xff1b;由于一般进程用户地址空间是…

JavaScript 中常用简写技巧总结

平时我们写代码时最高级的境界是自己写的东西别人看不懂&#xff01;哈哈哈&#xff01;分享一些自己常用的js简写技巧&#xff0c;长期更新&#xff0c;会着重挑选一些实用的简写技巧&#xff0c;使自己的代码更简洁优雅~ 这里只会收集一些大多数人不知道的用法&#xff0c;但…

PHP实现轻量级WEB服务器接收HTTP提交的RFID刷卡信息并回应驱动读卡器显示播报语音

本示例使用的读卡器&#xff1a;RFID网络WIFI无线TCP/UDP/HTTP可编程二次开发读卡器POE供电语音-淘宝网 (taobao.com) <?php mb_http_output(utf-8); $port88; $socket socket_create(AF_INET, SOCK_STREAM, SOL_TCP); $bool socket_bind($socket, "0.0.0.0",…

宇宙原理:黑洞基础。

宇宙原理&#xff1a;黑洞基础TOC 黑洞的数理基础&#xff1a;一个由满数组成的数盘&#xff0c;经过自然演进&#xff0c;将会逐步稀疏化、最终会向纯数方案发展&#xff1b;纯数方案虽然只有{2}、无数&#xff08;虚拟&#xff09;、{0,1,2,3}&#xff08;虚拟&#xff09;、…

如何在 Ubuntu 中安装最新的 Python 版本

动动发财的小手&#xff0c;点个赞吧&#xff01; Python 是增长最快的主要通用编程语言。其原因有很多&#xff0c;例如其可读性和灵活性、易于学习和使用、可靠性和效率。 目前使用的 Python 有两个主要版本 – 2 和 3&#xff08;Python 的现在和未来&#xff09;&#xff1…

LeetCode--HOT100题(36)

目录 题目描述&#xff1a;146. LRU 缓存&#xff08;中等&#xff09;题目接口解题思路代码 PS: 题目描述&#xff1a;146. LRU 缓存&#xff08;中等&#xff09; 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类&#xff1a; LRUCache…

AQS源码解读

文章目录 前言一、AQS是什么&#xff1f;二、解读重点属性statehead、tail 同步变量竞争acquire 同步变量释放 总结 前言 AQS是AbstractQueuedSynchronizer的缩写&#xff0c;也是大神Doug Lea的得意之作。今天我们来进行尽量简化的分析和理解性的代码阅读。 一、AQS是什么&a…

回归预测 | MATLAB实现WOA-SVM鲸鱼算法优化支持向量机多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现WOA-SVM鲸鱼算法优化支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现WOA-SVM鲸鱼算法优化支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09;效果一览基本介绍程…

PostgreSQL中的密码验证方法

假设您想在客户端/服务器协议中实现密码身份验证方法。 您将如何做到这一点以及可能出现的问题是什么&#xff1f; 以下是 PostgreSQL 中如何完成此操作的故事。 password 一开始&#xff0c;PostgreSQL 只有 pg_hba.conf 中现在称为“password”的方法。 这是你能想象到的最…

CloudQuery:更好地管理你的 OceanBase 数据库

前言&#xff1a;作为 OceanBase 的生态合作伙伴&#xff0c;CloudQuery&#xff08;简称“CQ”&#xff09; 最新发布的社区版 2.2.0 新增了 OceanBase 数据库&#xff0c;为企业使用 OceanBase 数据库提供全面的支持。包括连接与认证、查询与分析、数据安全与权限管理&#x…

【仿写tomcat】三、通过socket读取http请求信息

仿写tomcat 建立Socket连接获取连接信息查看HTTP信息 建立Socket连接 这里我们也是创建一个专门管理socket的类 package com.tomcatServer.socket;import java.io.*; import java.net.ServerSocket;/*** 套接字存储** author ez4sterben* date 2023/08/15*/ public class Soc…

【校招VIP】java语言考点之List和扩容

考点介绍&#xff1a; List是最基础的考点&#xff0c;但是很多同学拿不到满分。本专题从两种实现子类的比较&#xff0c;到比较复杂的数组扩容进行分析。 『java语言考点之List和扩容』相关题目及解析内容可点击文章末尾链接查看&#xff01;一、考点题目 1、以下关于集合类…

操作系统练习:在Linux上创建进程,及查看进程状态

说明 进程在执行过程中可以创建多个新的进程。创建进程称为“父进程”&#xff0c;新的进程称为“子进程”。每个新的进程可以再创建其他进程&#xff0c;从而形成进程树。 每个进程都有一个唯一的进程标识符&#xff08;process identifier&#xff0c;pid&#xff09;。在L…

通过远程访问解决家人的电脑难题

家里老人使用电脑、手机等设备遇到问题&#xff0c;子女在其他城市没法现场解决&#xff0c;远程沟通很困难。有没有一种方法可以随时远程帮助家人解决电脑、手机相关问题&#xff1f; 通过远程桌面软件&#xff0c;你可以与父母一起实时解决问题。这样他们就不会一遍遍给你打…

Linux系统的目录结构

file system hierarchy standard文件系统层级标准&#xff0c;定义了在类Unix系统中的目录结构和目录内容。 即让用户了解到已安装软件通常放置于哪个目录下。 Linux目录结构的特点 使用树形目录结构来组织和管理文件。 整个系统只有一个根目录&#xff08;树根&#xff09;&a…

Java虚拟机(JVM):垃圾收集算法

目录 一、分代收集理论 二、标记-清除算法 三、标记-复制算法 四、标记-整理算法 一、分代收集理论 分代收集理论建立在两个分代假说之上&#xff1a; 1、弱分代假说&#xff1a;绝大多数对象都是朝生夕灭的。 2、强分代假说&#xff1a;熬过越多次垃圾收集过程的对象就…