C++跨平台开发之基于wxWidgets开发GUI程序简介-001

1.引言

C++跨平台开发好处就是一次编写多处运行,对于服务端程序来随着C++语言版本的迭代演进,语言本身跨平台特性支撑了与操作系统无关的业务逻辑设计实现,对于操作系统密切相对的特性可以通过封装适配层来适应不同平台的编译和部署运行,例如互斥锁、多线程、SOCKET、进程间通信机制等,当然多线程也可以使用C++11以后的线程。

但对于GUI程序来说,因为支撑软件的人机交互业务,不同操作系统GUI实现机制差异非常大,当然开发者也可以对不同平台的图形库SDK进行封装设计,但对开发人员的要求非常高,必须熟悉多种操作系统的GUI及其实现机制,并且随着操作系统的升级还需要相应改动。因此对研发团队来说技术门槛和投入是必须考虑的问题,选择合适的跨平台GUI库对于加快开发进度,缩短交付周期都是非常重要的。

本文首先对wxWidget进行简要介绍,包括下载、部署以及开发简单应用程序。不同GUI库的优劣对比不在本文讲述之列,大家感兴趣可以自行查找资料。

2.wxWidgets简介

2.1遵循的许可协议

wxWidgets是一套跨平台的 C++ 图形界面(GUI)库,最早命名为wxWindows,后修改为wxWidget,基于这套图形库开发者可以编写一套代码,就能在 Windows、macOS、Linux 上直接编译运行。

wxWidgets采用的是 wxWindows Library Licence(wxWidgets Licence),当前版本为 3.1 版:

(1)主体是 **LGPL 2.0+ 协议**,带商用友好例外;

(2)基于 wxWidgets 开发软件,**可以闭源、可以商用、可以不开放自己的源码**;

(3) 只需要开源你**对 wxWidgets 库本身做的修改部分**,自己写的业务代码不用开源;

(4)可以直接编译成二进制库链接到自己项目,无强制开源约束。

因此纯粹的LGPL协议不允许使用者静态链接,如果静态链接就必须开放上层业务源代码,而开发者基于wxWidget协议则可以随便静态链接wxWidget库使用而不必开源自己的业务代码。

开发者需要声明使用了wxWidget库:

cpp 复制代码
//本软件使用 wxWidgets 库开发,基于wxWindows 库许可协议 3.1 版

2.2下载地址

wxWidgets库的下载地址为https://wxwidgets.org/downloads/,当前最新开发版本为3.3.2,当前最新稳定版本为3.2.10 。

2.3 安装过程(Windows系统)

下载Windows系统的"wxMSW-3.2.10-Setup.exe"文件后,双击运行可执行程序。

选择"I accept the agreement",然后点击"Next"。

阅读完wxWidget 3.2.10 Release Notes后,点击"Next"。

选择安装目录C:\wxWidgets-3.2.10或其它目录,然后点击"Next",开始安装。

安装完成后,在C:\wxWidgets-3.2.10目录下可以看到已安装完毕。

2.4编译过程

首先Windows系统已安装完毕vs2026,笔者使用的是Windows11,已经安装了VisualStudio2026 Community版本。

打开C:\wxWidgets-3.2.10\build\msw目录,找到vs2026的解决方案文件wx_vc18.slnx(对应vs2026),可以根据需要编译debug和release版本的动态库或静态库。

编译完成后,在C:\wxWidgets-3.2.10\lib可以看到vc_x64_dll和vc_x64_lib两个子目录,开发者可以根据各自需要采用动态或静态链接方式使用wxWidgets库。

3.开发案例

3.1创建项目类型

(1)打开vs2026,选择新建项目,项目类型选择"空项目",如下图:

(2)选择项目的代码目录,如下图:

(3)点击"创建"成功创建空的项目文件。

3.2配置wxWidgets库

(1)点击3.1中创建的项目属性,点击进入子属性"C/++"设置对话框,输入wxWidgets库的头文件目录,如下图:

(2)点击项目属性的"链接"->"常规",设置wxWidgets库的lib文件目录,如下图:

(2)点击项目属性的"链接"->"输入",分别设置Debug和Release配置下wxWidgets库的lib文件列表,如下图:

(3)点击项目属性的"链接"->"系统",将"所有配置"下的子系统选择为"窗口/SUBSYSTEM:WINDOWS",如果默认类型"控制台 (/SUBSYSTEM:CONSOLE)",则编译时会出现如下的链接错误"。

复制代码
1>------ 已启动生成: 项目: MyApp, 配置: Debug x64 ------
1>MSVCRTD.lib(exe_main.obj) : error LNK2019: 无法解析的外部符号 main,函数 "int __cdecl invoke_main(void)" (?invoke_main@@YAHXZ) 中引用了该符号
1>D:\shg_example\x64\Debug\MyApp.exe : fatal error LNK1120: 1 个无法解析的外部命令
========== 生成: 0 成功,1 失败,0 最新,0 已跳过 ==========”

"链接"->"系统"属性设置参数,如下图:

3.3案例简介

基于wxWidgets的案例为设计了一个基本的wxFrame窗体,并添加了一个wxButton按钮,点击该按钮弹出对话框,并弹出在对话框编辑控件中输入的字符串文本内容。案例非常简单,演示了wxWidgets窗体和对话框应用,并展示了在wxApp中显示出窗体。以下为该案例的代码:

3.3.1 MyDialog.h

cpp 复制代码
#ifndef MYDIALOG_H
#define MYDIALOG_H

#include <wx/wx.h>
#include <wx/dialog.h>

class CMyDialog : public wxDialog
{
public:
    CMyDialog(wxWindow* parent);

    wxString GetInputText(void) const;

private:
    void OnOK(wxCommandEvent& event);
    void OnCancel(wxCommandEvent& event);

    wxTextCtrl* m_textCtrl;
    wxString         m_inputValue;

    DECLARE_EVENT_TABLE()
};

#endif

3.3.2 MyDialog.cpp

cpp 复制代码
#include "MyDialog.h"

BEGIN_EVENT_TABLE(CMyDialog, wxDialog)
EVT_BUTTON(wxID_OK, CMyDialog::OnOK)
EVT_BUTTON(wxID_CANCEL, CMyDialog::OnCancel)
END_EVENT_TABLE()

CMyDialog::CMyDialog(wxWindow* parent)
    : wxDialog(parent, wxID_ANY, wxT("输入对话框"),
        wxDefaultPosition, wxSize(350, 180))
{
    wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);

    mainSizer->Add(new wxStaticText(this, wxID_ANY, wxT("请输入内容:")),
        0, wxALL | wxALIGN_LEFT, 10);

    m_textCtrl = new wxTextCtrl(this, wxID_ANY);
    mainSizer->Add(m_textCtrl, 1, wxALL | wxEXPAND, 10);

    wxBoxSizer* btnSizer = new wxBoxSizer(wxHORIZONTAL);
    btnSizer->Add(new wxButton(this, wxID_OK, wxT("确定")), 0, wxRIGHT, 5);
    btnSizer->Add(new wxButton(this, wxID_CANCEL, wxT("取消")), 0);

    mainSizer->Add(btnSizer, 0, wxALL | wxALIGN_CENTER, 10);

    SetSizer(mainSizer);
    Layout();
    m_textCtrl->SetFocus();
}

void CMyDialog::OnOK(wxCommandEvent& event)
{
    m_inputValue = m_textCtrl->GetValue();
    EndModal(wxID_OK);
}

void CMyDialog::OnCancel(wxCommandEvent& event)
{
    EndModal(wxID_CANCEL);
}

wxString CMyDialog::GetInputText(void) const
{
    return m_inputValue;
}

3.3.3 MyFrame.h

cpp 复制代码
#ifndef MAINFRAME_H
#define MAINFRAME_H

#include <wx/frame.h>

class CMainFrame : public wxFrame
{
public:
    CMainFrame(void);

private:
    void OnOpenDialog(wxCommandEvent& event);
};

#endif

3.3.4 MyFrame.cpp

cpp 复制代码
#include <wx/button.h>
#include <wx/msgdlg.h>
#include "MainFrame.h"
#include "MyDialog.h"

CMainFrame::CMainFrame(void)
    : wxFrame(NULL, wxID_ANY, wxT("主窗口 - 对话框演示"),
        wxDefaultPosition, wxSize(400, 250))
{
    wxPanel* panel = new wxPanel(this);
    wxButton* btn = new wxButton(panel, wxID_ANY, wxT("打开输入对话框"),
        wxPoint(100, 80), wxSize(180, 40));

    btn->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
        wxCommandEventHandler(CMainFrame::OnOpenDialog),
        NULL, this);
}

void CMainFrame::OnOpenDialog(wxCommandEvent& event)
{
    CMyDialog dlg(this);
    if (dlg.ShowModal() == wxID_OK)
    {
        wxString text = dlg.GetInputText();
        wxMessageBox(wxT("你输入的内容:\n") + text, wxT("提示"));
    }
}

3.3.5 MyApp.h

cpp 复制代码
#ifndef MYAPP_H
#define MYAPP_H

#include <wx/app.h>

class CMyApp : public wxApp
{
public:
    virtual bool OnInit(void);
};

#endif

3.3.6 MyApp.cpp

cpp 复制代码
#include "MyApp.h"
#include "MainFrame.h"

IMPLEMENT_APP(CMyApp)

bool CMyApp::OnInit(void)
{
    CMainFrame* frame = new CMainFrame();
    frame->Show(true);

    return true;
}

3.4运行界面

该案例逻辑简单,具体功能可参与源代码,此处不再赘述。

4.结语

本文简要介绍了wxWidgets跨平台GUI库及其下载安装过程,详细介绍了Windows系统和vs2026集成开发环境中的项目配置情况,并引入一个简单的wxWidgets开发案例,欢迎大家提出宝贵意见。

相关推荐
csbysj202010 小时前
C# 文件的输入与输出
开发语言
故事和你9110 小时前
洛谷-【动态规划1】动态规划的引入4
开发语言·数据结构·c++·算法·动态规划·图论
吃好睡好便好10 小时前
创建全0矩阵和全1矩阵
开发语言·学习·线性代数·算法·matlab·信息可视化·矩阵
我还记得那天10 小时前
数组的2个应用举例
c语言·开发语言·二分查找·数组
wunaiqiezixin10 小时前
5.16周测
c++
学困昇10 小时前
Linux IPC 详解:匿名管道、命名管道、共享内存与信号量
linux·运维·服务器·c语言·c++·人工智能
biter down10 小时前
10:GUI的 pytest 框架
开发语言·python
计算机安禾11 小时前
【c++面向对象编程】第39篇:简单工厂模式与工厂方法模式:C++实现
c++·简单工厂模式·工厂方法模式
Simon5231411 小时前
mybatis执行流程、关联映射、注解开发
java·开发语言·mybatis