wxWidgets应用程序:代码结构与生命周期

  • 时间:2025-12-01 21:59 作者: 来源: 阅读:4
  • 扫一扫,手机访问
摘要:与传统c程序或Win32程序相比,wxWidgets最大的不同是贯彻了彻底的面向对象设计思想,所有的实体都被封装为类。应用程序本身也被定义为一个类进行管理。 一、应用程序示例 创建wxWidgets应用程序最基础的方式是创建一个wxApp或wxAppConsole的派生类,然后重写其中的OnInit()方法。 (一)控制台应用程序 以控制台程序为例,首先从wxAppConsole派生子类(

与传统c程序或Win32程序相比,wxWidgets最大的不同是贯彻了彻底的面向对象设计思想,所有的实体都被封装为类。应用程序本身也被定义为一个类进行管理。

一、应用程序示例

创建wxWidgets应用程序最基础的方式是创建一个wxApp或wxAppConsole的派生类,然后重写其中的OnInit()方法。

(一)控制台应用程序

以控制台程序为例,首先从wxAppConsole派生子类(如MyApp)。这个子类至少需要重写虚函数OnInit()。其返回参数是一个bool值,用于指示处理是否应继续(true)或直接退出(false)。

新建应用程序头文件myapp.h,声明wxAppConsole的派生子类MyApp,继承基本接口OnInit()和OnRun()。并调用宏wxDECLARE_APP()创建MyApp实例。



//MyApp.h
class MyApp : public wxAppConsole{
public:
    virtual bool OnInit(); //初始化函数
    virtual int OnRun(); //主程序函数
};
wxDECLARE_APP(MyApp);

新建应用程序实现文件myapp.cpp。使用wxIMPLEMENT_APP(MyApp)实现C程序运行相关的函数如main()等,并在main中对wxDECLARE_APP()创建的MyApp实例进行初始化等操作。



//MyApp.cpp
#include<iostream>
using namespace std;
//通过宏的方式创建MyApp全局对象和main()函数
wxIMPLEMENT_APP_CONSOLE(MyApp);
bool MyApp::OnInit(){   
    cout<<"Hello World"<<endl;
    return true; //返回false将直接退出,不会执行后面的OnRun函数
 }
int MyApp::OnRun(){
    //主程序函数 do nothing
    return 0;
}

至此,一个完整可运行的应用程序便诞生了。它会打开一个命令行窗口,然后输出字符串“Hello World”。

(二)GUI应用程序

与控制台程序不同的是,GUI应用程序需要从wxApp类继承,在通常情况下,子类成员函数OnInit()的任务是创建顶层窗口。

如创建控制台程序一样,先创建头文件myapp.h。



//MyApp.h
class MyApp : public wxApp{
public:
    virtual bool OnInit();
};
wxDECLARE_APP(MyApp);  

创建定义文件



//MyApp.cpp
//通过宏的方式创建MyApp全局对象表示当前的应用程序
wxIMPLEMENT_APP(MyApp);
bool MyApp::OnInit(){   
    wxFrame *the_frame = new wxFrame(NULL, wxID_ANY, "minpro");
    the_frame->Show(true);
    return true;
}

该代码将显示一个非常简单的窗口。

二、静态结构

wxAppConsole是wxApp的父类,成员函数bool OnInit()是入口函数,类似(但不等同)传统C/C++程序的main()。应用程序类存在于所有的wxWidgets应用程序中,是基于wxWidgets开发的起点,因此,对它进行深入地理解是必要而有意义的。其静态类结构如图 15所示。

图 15 wxApp类图

wxAppConsole继承至wxEventHandler(事件处理)和wxEvtFilter(事件过滤)。该类适用于编写控制台或wxUSE_GUI=0的混合应用程序,其作用为:设置和获取应用程序范围内的属性;实现窗口系统消息或事件循环,在控制台模式应用程序中也支持事件处理;通过OnInit()初始化应用程序;处理应用程序中其他模块未处理的事件等。

wxApp继承至wxAppConsole。适用于编写GUI应用程序。除了wxAppConsole提供的功能外,它还跟踪顶部窗口,添加了对视频模式的支持,并存储GUI应用程序的全局配置信息等。

wxEventHandler是用于处理事件。当接收到事件时,wxEvtHandler将调用事件表中的处理函数。当使用多重继承时,wxEvtHandler或其派生类类必须是继承的第一个类,以便整个对象的this指针与wxEvtHandler部分的this指针相同。

wxEvtFilter是一个全局事件过滤器,用于对程序中生成的所有事件进行预处理。这是一个非常简单的类,它只提供FilterEvent()虚拟方法,在启动任何事件处理之前先由wxEvtHandler处理。从这个类继承并重写FilterEvent()允许捕获所有事件,并可以决定处理或忽略这些事件。

三、生命周期

(一)启动流程

1、定义main()函数

应用程序入口类是一个派生至wxApp或wxAppConsole的C++类,如实例中的类MyApp。MyApp的创建由宏wxIMPLEMENT_APP(MyApp)完成,宏的参数为应用程序类的名称,创建过程如图 16所示。

图 16 wxIMPLEMENT_APP定义

wxIMPLEMENT_APP中的wxIMPLEMENT_APP_NO_THEMES负责实例化MyApp对象并创建全局变量wxTheApp;wxIMPLEMENT_APP_NO_THEMES主要完成两项工作:

一是根据平台类型创建main()。在不同的平台中,main的定义形式不尽相同,例如,wxMSW使用WinMain()替代main()。但它们最终都是由main()驱动。

二是创建2个全局函数wxCreateApp()和wxGetApp()以及1个全局wxAppInitializer变量wxTheAppInitializer。wxCreateApp()的功能是创建一个MyApp类型实例,wxGetApp()则返回这个实例。wxTheAppInitializer在构造函数将调用wxCreateApp()创建MyApp实例。

当wxWidgets创建MyApp实例时,会将实例的值赋给一个wxApp类型全局变量wxTheApp。您可以在程序中的任何位置引用这个变量,如(MyApp)wxTheApp。不过,使用wxGetApp()可以避免繁琐的类型转换,前提是需要通过wxDECLARE_APP(MyApp)来声明,其定义如下:



#define wxDECLARE_APP(appname)              
    extern appname& wxGetApp()

3、main()函数执行过程

wxIMPLEMENT_APP(MyApp)定义了MyApp实例,并创建了main()调用MyApp实例启动程序。图 17为main()函数执行过程中涉及的主要函数及相互调用关系。

图 17 wxMSW中main函数流程

OnInit()是您会需要重写的一个函数,用于应用程序的初始化,main()在调用wxTheApp->OnInit()之前,wxWidgets的主要工作是为程序的运行准备运行时环境;OnRun()最后执行,持续进行事件分发和处理,wxWidgets应用程序是由事件驱动的。

(二)命令参数

命令参数在程序启动前传入,用于动态修改程序配置,定义程序行为。与int main(int argc,char**argv)不同,wxWidgets程序不能从OnInit()函数中直接获取命令行参数。argc和argv参数存储在wxAppConsole的同名成员变量中,并在调用OnInit()之前完成初始化。您可以在wxApp子类中直接使用,也可以在wxApp类之外通过wxGetApp().argc或wxGetApp().argv访问。

(三)程序退出

应用程序退出前应销毁所有的窗口。删除父窗口时会自动删除子窗口,因此建议在创建新窗口时应当尽可能标识窗口之间的父子关系。也可以在父窗口的wxCloseEvent处理函数中的显式删除所有子窗口。

在紧急情况下,可以调用wxExit()函数来结束应用程序,函数会删除顶层窗口及其子窗口,然后退出程序,但应该尽量避免使用这种结束程序的方式。

应用程序通常在最后一个顶层窗口关闭时自动退出。如果您的程序有一个顶层窗口,那么响应“Exit”菜单命令就可以调用wxWindow::Close()。如果调用了wxApp的SetExitOnFrameDelete(false)将禁用该功能,即最后一个顶层窗口关闭时,应用程序将会继续运行。

应用程序关闭过程中,会在销毁之前调用OnExit(),所有清理内存的工作通常在该函数中进行。您需要重载它以删除创建的wxWidgets对象。值得注意的是,不要从应用程序类的析构函数中销毁它们!例如,此代码可能会崩溃:



class MyApp : public wxApp{
public:
    wxCHMHelpController m_helpCtrl;
    //...
};

原因是m_helpCtrl是栈上分配的对象,将在MyApp析构函数中销毁,当调用MyApp的析构函数时,wxWidgets内部结构已经清理,此时调用wxCHMHelpController的析构函数会因为缺少必要的wxWidgets内部依赖而使应用崩溃。解决办法是在堆上创建wxWidgets对象,在MyApp::OnExit()删除:



class MyApp : public wxApp{
public:
    wxCHMHelpController *m_helpCtrl;
    //...
};
bool MyApp::OnInit(){
    ...
    m_helpCtrl = new wxCHMHelpController;
    //...
}
int MyApp::OnExit(){
    delete m_helpCtrl;
    return 0;
}

四、总结

与MFC程序相比,wxWidgets贯彻了较为彻底的面向对象思想,程序结构简洁且易于理解。创建wxWidgets应用程序最基础的操作就是定义并创建一个wxApp的派生类即可。

  • 全部评论(0)
最新发布的资讯信息
【系统环境|】创建一个本地分支(2025-12-03 22:43)
【系统环境|】git 如何删除本地和远程分支?(2025-12-03 22:42)
【系统环境|】2019|阿里11面+EMC+网易+美团面经(2025-12-03 22:42)
【系统环境|】32位单片机定时器入门介绍(2025-12-03 22:42)
【系统环境|】从 10 月 19 日起,GitLab 将对所有免费用户强制实施存储限制(2025-12-03 22:42)
【系统环境|】价值驱动的产品交付-OKR、协作与持续优化实践(2025-12-03 22:42)
【系统环境|】IDEA 强行回滚已提交到Master上的代码(2025-12-03 22:42)
【系统环境|】GitLab 15.1发布,Python notebook图形渲染和SLSA 2级构建工件证明(2025-12-03 22:41)
【系统环境|】AI 代码审查 (Code Review) 清单 v1.0(2025-12-03 22:41)
【系统环境|】构建高效流水线:CI/CD工具如何提升软件交付速度(2025-12-03 22:41)
手机二维码手机访问领取大礼包
返回顶部