标签:而且 let exit 设计 ram broadcast 生命周期 getc ica
在前面的几篇文章,分析的都是Juce库里面Core模块的内存部分,除了骨灰级C++爱好者之外,貌似大家对这些都不是非常感兴趣。相信大家更想知道Juce是怎么用于产品开发,而对于它的构成不是非常感兴趣。天天写一些内存、指针、线程之类的文章。Skilla也厌倦了。这次来分析一下Juce的上层应用程序框架。
以下上一段Demo里的代码片段
class JuceDemoApplication : public JUCEApplication { public: JuceDemoApplication() {} //============================================================================== void initialise (const String& commandLine) override { if (invokeChildProcessDemo (commandLine)) return; Desktop::getInstance().setOrientationsEnabled (Desktop::allOrientations); // Do your application‘s initialisation code here.. mainWindow = new MainAppWindow(); } void shutdown() override { // Do your application‘s shutdown code here.. mainWindow = nullptr; } //============================================================================== void systemRequestedQuit() override { // This gets called when the OS wants our app to quit. You may want to // ask the user to save documents, close windows, etc here, but in this // case we‘ll just call quit(), which tells the message loop to stop and // allows the app to (asynchronously) exit. quit(); } //============================================================================== const String getApplicationName() override { return "JuceDemo"; } const String getApplicationVersion() override { return ProjectInfo::versionString; } bool moreThanOneInstanceAllowed() override { return true; } void anotherInstanceStarted (const String& /*commandLine*/) override { } private: ScopedPointer<MainAppWindow> mainWindow; }; //============================================================================== // This macro generates the main() routine that starts the app. START_JUCE_APPLICATION(JuceDemoApplication)
#if JUCE_WINDOWS && ! defined (_CONSOLE) #define JUCE_MAIN_FUNCTION int __stdcall WinMain (struct HINSTANCE__*, struct HINSTANCE__*, char*, int) #define JUCE_MAIN_FUNCTION_ARGS #else #define JUCE_MAIN_FUNCTION int main (int argc, char* argv[]) #define JUCE_MAIN_FUNCTION_ARGS argc, (const char**) argv #endif #define START_JUCE_APPLICATION(AppClass) static juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); } extern "C" JUCE_MAIN_FUNCTION { juce::JUCEApplicationBase::createInstance = &juce_CreateApplication; return juce::JUCEApplicationBase::main (JUCE_MAIN_FUNCTION_ARGS); } #endif
忽略其它平台,单纯看Windows部分,START_JUCE_APPLICATION等价于以下的代码
static juce::JUCEApplicationBase* juce_CreateApplication() { return new JuceDemoApplication(); } extern "C" int __stdcall WinMain (struct HINSTANCE__*, struct HINSTANCE__*, char*, int) { juce::JUCEApplicationBase::createInstance = &juce_CreateApplication; return juce::JUCEApplicationBase::main (); }
WinMain函数真正执行的是里面的静态成员函数main()
int JUCEApplicationBase::main() { ScopedJuceInitialiser_GUI libraryInitialiser; jassert (createInstance != nullptr); const ScopedPointer<JUCEApplicationBase> app (createInstance()); jassert (app != nullptr); if (! app->initialiseApp()) return app->getApplicationReturnValue(); JUCE_TRY { // loop until a quit message is received.. MessageManager::getInstance()->runDispatchLoop(); } JUCE_CATCH_EXCEPTION return app->shutdownApp(); }ScopedJuceInitialiser_GUI用于创建MessageManager(消息管理器的)单例,但同一时候也肩负着将它析构的重任,在ScopedPointer的管理下。里面的局部对象app相同也是自生自灭。app->initialiseApp()用于应用程序的初始化,一般应用层的初始化和窗体的创建都在这里实现。
再以下一句代码是MessageManager::getInstance()->runDispatchLoop();。这句代码是写的最短的。然而却是执行时间最长的,它就是我们最为熟知的消息循环。最后的shutdownApp则是善后处理并调用子类的shutdown成员函数,作为应用程序结束的通知,ShutdownApp返回以后WinMain函数就结束了。继而MessageManage的单例和app对象被作用域析构掉。由此可见,这样设计是合情合理的。这一章我们主要分析initialiseApp()看一下应用程序是怎么初始化的。
bool JUCEApplicationBase::initialiseApp() { #if JUCE_HANDLE_MULTIPLE_INSTANCES if ((! moreThanOneInstanceAllowed()) && sendCommandLineToPreexistingInstance()) { DBG ("Another instance is running - quitting..."); return false; } #endif // let the app do its setting-up.. initialise (getCommandLineParameters()); stillInitialising = false; if (MessageManager::getInstance()->hasStopMessageBeenSent()) return false; #if JUCE_HANDLE_MULTIPLE_INSTANCES if (multipleInstanceHandler != nullptr) MessageManager::getInstance()->registerBroadcastListener (multipleInstanceHandler); #endif return true; }最開始的if推断语句的目的是,推断应用程序是否同意多个实例同一时候进行而且查看是否当前有实例正在执行,由于有的软件是不同意”双开“或”多开“,这里能够依据须要重载moreThanOneInstanceAllowed()方法。 initialise (getCommandLineParameters());的功能是获取命令行參数,传给子类并完毕子类的初始化操作。 if (MessageManager::getInstance()->hasStopMessageBeenSent()) return false; 这一句是推断消息管理器是否收到了退出消息。 if (multipleInstanceHandler != nullptr)
这些操作完毕之后,就是消息循环了。
在ApplicationBase的成员函数main()中我们看到,作者巧妙地利用了栈对象的自己主动析构原理来管理MessageManager和ApplicationBase两个对象的生命周期,使之初始化时机合理。析构时机亦合理,这点值得借鉴。
Juce源代码分析(九)应用程序基类ApplicationBase
标签:而且 let exit 设计 ram broadcast 生命周期 getc ica
原文地址:http://www.cnblogs.com/wzzkaifa/p/6863237.html