zoukankan      html  css  js  c++  java
  • wxWidgets初始化分析应用定义和初始化

    1. 一个wxWidgets的基本结构是:一个App类+一个Frame类,代码如:

    class MyApp: public wxApp
    {
    public:
        bool OnInit();
    };
    IMPLEMENT_APP(MyApp)


    2. IMPLEMENT_APP(MyApp) 这个宏包含了入口,抽象了不同平台入口的差异,分析如下:

    IMPLEMENT_APP展开如下:

    #define IMPLEMENT_APP(appname)              \
        IMPLEMENT_APP_NO_THEMES(appname)        \
        IMPLEMENT_WX_THEME_SUPPORT

    IMPLEMENT_APP_NO_THEMES展开如下:

    #define IMPLEMENT_APP_NO_THEMES(appname)    \
        IMPLEMENT_APP_NO_MAIN(appname)          \
        IMPLEMENT_WXWIN_MAIN

    IMPLEMENT_APP_NO_MAIN展开如下:

    #define IMPLEMENT_APP_NO_MAIN(appname)                                      \
        wxAppConsole *wxCreateApp()                                             \
        {                                                                       \
            wxAppConsole::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE,         \
                                            "your program");                    \
            return new appname;                                                 \
        }                                                                       \
        wxAppInitializer                                                        \
            wxTheAppInitializer((wxAppInitializerFunction) wxCreateApp);        \
        DECLARE_APP(appname)                                                    \
        appname& wxGetApp() { return *wx_static_cast(appname*, wxApp::GetInstance()); }

    实际上IMPLEMENT_APP_NO_MAIN定义了wxCreateApp函数new appname创建出应用类的实例.   

    wxAppInitializer  wxTheAppInitializer((wxAppInitializerFunction) wxCreateApp);实际上把创建函数wxCreateApp用接口wxApp::SetInitializerFunction(fn);设置进了系统,都静态变量保存的.

    appname& wxGetApp() { return *wx_static_cast(appname*, wxApp::GetInstance()); }这个获取App实例的接口也在此定义.

    IMPLEMENT_WXWIN_MAIN展开如下:

    #define IMPLEMENT_WXWIN_MAIN \
        extern "C" int WINAPI WinMain(HINSTANCE hInstance,                    \
                                      HINSTANCE hPrevInstance,                \
                                      wxCmdLineArgType lpCmdLine,             \
                                      int nCmdShow)                           \
        {                                                                     \
            return wxEntry(hInstance, hPrevInstance, lpCmdLine, nCmdShow);    \
        }                                                                     \
        IMPLEMENT_WXWIN_MAIN_BORLAND_NONSTANDARD

    WinMain是Windows平台Win32应用的入口函数,WinMain包含了C/C++的main函数实现.

    多参WXDLLEXPORT int wxEntry(HINSTANCE hInstance,HINSTANCE WXUNUSED(hPrevInstance),wxCmdLineArgType WXUNUSED(pCmdLine),int nCmdShow),会在最后调用2参的int wxEntry(int& argc, char **argv),此函数实现有3处,Unicode版本的也是要转换成非Unicode版本的函数调用,最终会调用到wxEntryReal,此接口是真正的库初始化入口:分析如下

    wxEntryReal定义如下:

    int wxEntryReal(int& argc, wxChar **argv)
    {
        // library initialization
        wxInitializer initializer(argc, argv);

        if ( !initializer.IsOk() )
        {
    #if wxUSE_LOG
            // flush any log messages explaining why we failed
            delete wxLog::SetActiveTarget(NULL);
    #endif
            return -1;
        }

        wxTRY
        {

            // app initialization
            if ( !wxTheApp->CallOnInit() )
            {
                // don't call OnExit() if OnInit() failed
                return -1;
            }

            // ensure that OnExit() is called if OnInit() had succeeded
            class CallOnExit
            {
            public:
                ~CallOnExit() { wxTheApp->OnExit(); }
            } callOnExit;

            WX_SUPPRESS_UNUSED_WARN(callOnExit);

            // app execution
            return wxTheApp->OnRun();
        }
        wxCATCH_ALL( wxTheApp->OnUnhandledException(); return -1; )
    }

    wxInitializer initializer(argc, argv);这句隐含了库的初始化过程,wxInitializer类的构造函数进行了初始化:

        wxInitializer(int argc, char **argv) //构造函数
        {
            m_ok = wxInitialize(argc, argv);  //调用了初始化wxInitialize
        }

    wxInitialize调用了wxEntryStart,此函数也2个版本,unicode的版本也是经过转换调用的非unicode版本,如下:

        wxAppPtr app(wxTheApp);
        if ( !app.get() )
        {
            // if not, he might have used IMPLEMENT_APP() to give us a function to
            // create it
            wxAppInitializerFunction fnCreate = wxApp::GetInitializerFunction(); // 注意此句取得了上边设置的创建App的函数

            if ( fnCreate )
            {
                // he did, try to create the custom wxApp object
                app.Set((*fnCreate)()); // 此处构造了应用App类,app变量保存了此指针,这个赋值实际调用wxApp::SetInstance(ptr);赋值了ms_appInstance,

                                                  //通过wxTheApp宏访问,上边定义的wxGetApp接口,也是获取此变量.
        }

        if ( !app.get() )
        {
            // either IMPLEMENT_APP() was not used at all or it failed -- in any
            // case we still need something
            app.Set(new wxDummyConsoleApp);
        }


        // wxApp initialization: this can be customized
        // --------------------------------------------

        if ( !app->Initialize(argc, argv) ) // 调用app初始化接口,bool wxApp::Initialize(int& argc, wxChar **argv)此接口被调用,进而初始化了系统

        {
            return false;
        }

    wxEntryReal调用了系统初始化后,又调用了应用App的OnInit接口,给App初始化的时机:

            // app initialization
            if ( !wxTheApp->CallOnInit() )
            {
                // don't call OnExit() if OnInit() failed
                return -1;
            }
    此调用会多态到应用的OnInit接口,应用在此接口中初始化了Frame主窗口之类的窗口组件.wxTheApp宏用的比较多.CallOnInit接口调用了 CallOnInit() { return OnInit(); }接口。

    -----------------------------------------------------------------------

    以上基本完成了库和用户的App初始化过程,在wxEntryReal接口的最后,return wxTheApp->OnRun();进入:

    int wxAppBase::OnRun()
    {
        // see the comment in ctor: if the initial value hasn't been changed, use
        // the default Yes from now on
        if ( m_exitOnFrameDelete == Later )
        {
            m_exitOnFrameDelete = Yes;
        }
        //else: it has been changed, assume the user knows what he is doing

        return MainLoop();
    }
    //进入了程序主循环,开始了事件接收、分发、处理的过程,指导程序结束.

    本文完.

  • 相关阅读:
    关于使用AJAX获取数据时,由于IE缓存而导致数据不更新,串数据的问题!
    优化PHP代码的40条建议(转)
    这么晚了!难得今天看了几个小时的JAVA
    WEB开发,路漫漫其修远兮,个人的求索思考
    (转)高效的MySQL分页
    20121108随笔,关于代码严谨性、编写的优雅性
    Ubuntu 12.04LTS 安装PHP扩展pdo_oci.so支持ORACLE数据库
    程序员应该具备的11项基本技能
    Windows下配置使用MemCached
    PHP浮点数比较
  • 原文地址:https://www.cnblogs.com/linucos/p/2646543.html
Copyright © 2011-2022 走看看