C语言编写图形界面

这篇具有很好参考价值的文章主要介绍了C语言编写图形界面。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

环境

使用的是VSCode + MinGW;

配置环境

VSCode配置C语言的环境就不讲了,具体可以看一下这篇文章:VSCode配置C语言环境
先说一下本篇文章编译的条件吧。
本篇文章需要编译器链接Windows GDI32库,所以如果你用的是VSCode+MinGW,就需要修改task.json文件,使其在链接的时候,链接Window GDI32库。
修改也比较简单,只需要为args数组加上一个字符串"-lgdi32",示例代码如下:

"args": [
    "-o",
    "${fileDirname}\\${fileBasenameNoExtension}",
    "${file}",
    "-lgdi32"
]

使用库

我们使用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结构体变量的lpszClassName成员。

wc.lpszClassName = "MyWinClass";

这里我们将窗口类的名称被设置为"MyWinClass"。

完整代码如下:

    // 定义窗口类
    WNDCLASS wc = {0};
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    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是窗口句柄,用于标识窗口。

窗口过程函数

窗口过程函数是核心部分之一。该函数是一个回调函数,它是Windows操作系统用来与应用程序交互的主要方式。每当有事件(如鼠标点击、键盘输入、窗口移动等)发生在应用程序的某个窗口上时,操作系统就会调用相应的窗口过程函数,并将事件信息传递给它。

基本的窗口过程函数的结构和组成部分如下所示:

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    // 处理各种 Windows 消息
    case WM_DESTROY:
    {
        // 当窗口被销毁时,发送一个退出消息
        PostQuitMessage(0);
        return 0;
    }
    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd, &ps);
        // 在这里添加你的绘画代码
        EndPaint(hWnd, &ps);
        return 0;
    }
    // 其他消息处理...
    default:
    {
        // 对于未处理的消息,返回默认处理结果
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    }
}

在窗口过程函数中,LRESULT 是返回值的数据类型,通常表示一个长整数,用于返回消息处理的结果。CALLBACK 是一个关键字,表示这是一个回调函数。

WndProc 是窗口过程函数的名字,你可以根据需要自定义这个名字。

HWND 前面我们说过了,是窗口句柄的数据类型,它标识了一个特定的窗口。

UINT、WPARAM 和 LPARAM 分别表示消息标识符、附加消息信息和额外消息信息。

在函数内部,我们使用 switch 语句来根据接收到的消息类型 (msg) 来执行不同的操作。例如,当接收到 WM_DESTROY 消息时,我们调用 PostQuitMessage 函数来通知操作系统我们希望退出程序。当接收到 WM_PAINT 消息时,我们进行窗口的重绘操作。当然还有许多其他的消息类型,后面我们会接触到。

对于没有特别处理的消息,我们可以选择传递给默认的窗口过程函数 DefWindowProc 进行处理。

在创建窗口时,我们需要将这个窗口过程函数的地址注册给操作系统,这样当与该窗口相关的事件发生时,操作系统就知道应该调用哪个函数来进行处理。注册的方法就像我们前面写的那样。

完整代码

#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.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语言编写图形界面,c语言,开发语言

修改窗口背景色

要修改窗口的背景色,我们就要用到WNDCLASS结构体变量的hbrBackground成员,该成员需要一个HBRUSH句柄。该句柄代表一个画刷对象。画刷对象用于指定绘制图形的背景色或填充颜色。

我们可以使用 CreateSolidBrush、CreateHatchBrush 或 CreatePatternBrush 等函数创建一个画刷对象,这些函数将返回HBRUSH 类型的句柄。

在使用上面的函数时,可以使用RGB(r, g, b)函数来指定颜色。

示例代码如下:

wc.hbrBackground = CreateSolidBrush(RGB(0, 255, 0)); // 将背景色设置为绿色

接下来,我们把这段代码插入我们的程序中,为了篇幅,这里就不复制所有的代码了:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    // 定义窗口类
    WNDCLASS wc = {0};
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    wc.hbrBackground = CreateSolidBrush(RGB(0, 255, 0)); // 将背景色设置为绿色
    wc.lpszClassName = "MyWinClass";
    // 其他代码......
}

运行程序后,我们可以发现,我们的程序绿了,如下图所示。
C语言编写图形界面,c语言,开发语言

一个简单的电子钟

#include <windows.h>
#include <time.h>
#include <stdio.h>
// 声明窗口过程函数
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
char *getCurrentTime();
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    // 定义窗口类
    WNDCLASS wc = {0};
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    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);
        HBRUSH hBrush = CreateSolidBrush(RGB(255, 255, 255)); // 创建白色背景刷
        SetTextColor(hdc, RGB(0, 0, 0));
        SetBkColor(hdc, RGB(255, 255, 255));

        RECT rect;
        GetClientRect(hWnd, &rect);
        FillRect(hdc, &rect, hBrush); // 使用白色背景刷填充客户区
        // 获取当前时间并绘制
        char *timeStr = getCurrentTime();
        DrawText(hdc, timeStr, -1, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);

        SelectObject(hdc, hOldFont);
        DeleteObject(hBrush); // 删除背景刷
        DeleteObject(hFont);

        EndPaint(hWnd, &ps);
        break;
    }
    case WM_CREATE:
    {
        SetTimer(hWnd, 1, 100, NULL); // 每100毫秒触发一次
        break;
    }
    case WM_TIMER:
    {
        if (wParam == 1)
        {
            InvalidateRect(hWnd, NULL, TRUE); // 引发窗口重绘
        }
        break;
    }
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    return 0;
}
// 获取当前时间并格式化为字符串
char *getCurrentTime()
{
    time_t rawtime;
    struct tm *timeinfo;

    time(&rawtime);
    timeinfo = localtime(&rawtime);

    // 存储格式化后的字符串
    static char currentTime[32];
    strftime(currentTime, sizeof(currentTime), "%H:%M:%S", timeinfo);

    return currentTime;
}

执行成功后,运行效果如下图所示:
C语言编写图形界面,c语言,开发语言

创建按钮

接下来我们学习一下创建按钮:
创建按钮文章来源地址https://www.toymoban.com/news/detail-668088.html

到了这里,关于C语言编写图形界面的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 图形化界面扫雷(C语言+easyx实现,多图教学)

    学了那么长时间的C语言,我们所有的一切似乎都被禁锢在黑框框(控制台)里,让人觉得很无趣,学习unity那样的平台又太过困难,那么有没有什么是适合我们这些新手使用的?答案是:有! EasyX 是针对 C/C++ 的图形库,可以帮助使用C/C++语言的程序员快速上手图形和游戏编程

    2024年02月06日
    浏览(46)
  • qt图形化界面开发DAY4

    2024年01月23日
    浏览(33)
  • Python图形界面开发:Tkinter与PyQt

    Python是一种非常流行的编程语言,它拥有丰富的图形用户界面(GUI)开发库。其中,Tkinter和PyQt是最常用的两个库。下面是对这两个库的简单介绍。 1. Tkinter Tkinter是Python的标准图形用户界面库。它提供了一组简单的工具和函数,可以用来创建各种类型的窗口、按钮、文本框等

    2024年01月25日
    浏览(43)
  • 基于PyQt5的图形化界面开发——队列动画演示

    本文使用PyQt5制作图形化界面演示数据结构中的 队列 操作,与上一节队列动画相对应 基于PyQt5的图形化界面开发——队列动画演示 操作系统:Windows10 专业版 开发环境:Pycahrm Comunity 2022.3 Python解释器版本:Python3.8 第三方库:PyQt5 队列(Queue)是一种常用的数据结构,类似于现

    2024年02月07日
    浏览(55)
  • 基于PyQt5的图形化界面开发——自制ssh工具

    本节我们使用PyQt5来制作一个简单的ssh小工具。 操作系统:Windows10 专业版 开发环境:Pycahrm Comunity 2022.3 Python解释器版本:Python3.8 第三方库: PyQt5 和 paramiko 本节需要安装第三方库PyQt5和paramiko,如果你并不熟悉第三方库的安装,你可以参考以下文章来学习: Python第三方库安装

    2024年02月06日
    浏览(43)
  • 在嵌入式Linux设备上使用Flutter开发图形界面(试水)

    链接: https://www.bilibili.com/video/BV1qE411N7aC/?spm_id_from=333.880.my_history.page.clickvd_source=0c443477abedebf2fdf7abecef55405d 我是跟着这个视频安装 Docker Desktop for Windows + 启用k8s k8s网址 https://github.com/AliyunContainerService/k8s-for-docker-desktop 主要步骤参照 https://www.toradex.com/zh-cn/blog/zai-qian-ru-shi-linux-sh

    2024年02月21日
    浏览(44)
  • 迅为RK3588开发板编译 Buildroot单独编译图形化界面三

    第三步:编译 Recovery 首先在 linux 源码目录下输入以下命令进入编译的 UI 界面,进入之后如下所示: ./build.sh 然后将光标移动到第四个 recovery,点击回车即可开始 recovery 的编译,编译过程如下所示: 编译完成如下图所示: 第四步:编译 buildroot 关注下一章节,迅为R

    2024年02月02日
    浏览(47)
  • 基于PyQt5的图形化界面开发——模拟医院管理系统

    本节以医院管理系统为例,使用PyQt5模拟医院系统的功能。 本次用到的数据结构思想为队列,使用队列能够更真实的反映医院排队等候的情况(先挂号者先就诊),事实上 操作系统:Windows10 专业版 开发环境:Pycahrm Comunity 2022.3 Python解释器版本:Python3.8 第三方库:PyQt5 如果你

    2024年02月02日
    浏览(116)
  • Python图形用户界面设计-Delphi For Python高级开发教程

    目录 简介........................................................................ 5 谁应该阅读这本教程........................................................ 5 第1章 Python与Delphi...................................................... 6 什么是Delphi4Python....................................................... 6 1.1 Python语言介绍....

    2024年02月07日
    浏览(77)
  • c语言练手项目【编写天天酷跑游戏2.0】EASYX图形库的运用。代码开源,素材已打包

    素材加Q群:723550115 项目是基于Windows,easyX图形库进行开发的, 开发环境:Visual Studio 2022 项目技术最低要求: 常量,变量,数组,循环,函数。 使用initgraph()初始化界面; 加载背景资源 写好游戏的图像化界面的框架 由于easyX不支持透明图片的的贴图,所以我们要自己写一个

    2024年02月15日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包