Juce源代码分析(九)应用程序基类ApplicationBase
在前面的几篇文章,分析的都是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)
假设你看过Juce里面的Demo的话,一定对这个类很熟悉了,没错。这个就是JuceDemo里的应用程序类。当你第一次见到它时,首先应该想到的是什么?这是我们应该能联想到,学完Win32时初学MFC时的场景,一个很蛋疼的问题是:这玩意怎么执行,它的WinMain函数在哪里?第一次找MFC的WinMain函数时的感觉。相信大家都体验过,不停的按F11,好像穿越了几个世纪一样,见到的都是一个一个的陌生”面孔“,上个厕所的功夫回来就能忘得一干二净,分析源代码的感觉让人感到彷徨,然而却很刺激。相比之下Juce的刺激性小多了,对着START_JUCE_APPLICATION按F11一次就看到了WinMain。
#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)
        MessageManager::getInstance()->registerBroadcastListener (multipleInstanceHandler);这一句是注冊进程通信的监听器。
这些操作完毕之后,就是消息循环了。
在ApplicationBase的成员函数main()中我们看到,作者巧妙地利用了栈对象的自己主动析构原理来管理MessageManager和ApplicationBase两个对象的生命周期,使之初始化时机合理。析构时机亦合理,这点值得借鉴。
Juce源代码分析(九)应用程序基类ApplicationBase的更多相关文章
- Juce源代码分析(一)Juce的优势
		
为什么学习Juce JUCE (Jules' Utility Class Extensions)是由Raw MaterialSoftware公布的一套基于c++的跨平台应用程序框架类库(Windows ...
 - cocos2d-x 源代码分析 : control 源代码分析 ( 控制类组件 controlButton)
		
源代码版本号来自3.1rc 转载请注明 cocos2d-x源代码分析总文件夹 http://blog.csdn.net/u011225840/article/details/31743129 1.继承 ...
 - Hadoop源代码分析
		
http://wenku.baidu.com/link?url=R-QoZXhc918qoO0BX6eXI9_uPU75whF62vFFUBIR-7c5XAYUVxDRX5Rs6QZR9hrBnUdM ...
 - Hadoop源代码分析(完整版)
		
Hadoop源代码分析(一) 关键字: 分布式云计算 Google的核心竞争技术是它的计算平台.Google的大牛们用了下面5篇文章,介绍了它们的计算设施. GoogleCluster:http:// ...
 - android(cm11)状态栏源代码分析(一)
		
(一):写在前面 近期因为工作须要,须要了解CM11中的有关于StatusBar相关的内容.总的来说,刚開始阅读其源代码的时候,是有点困难,只是通过构建相关代码的脑图和流程图,几天下来.我已经对其源代 ...
 - Cocos2d-X3.0 刨根问底(九)----- 场景切换(TransitionScene)源代码分析
		
上一章我们分析了Scene与Layer相关类的源代码,对Cocos2d-x的场景有了初步了解,这章我们来分析一下场景变换TransitionScene源代码. 直接看TransitionScene的定 ...
 - ffdshow 源代码分析 9: 编解码器有关类的总结
		
===================================================== ffdshow源代码分析系列文章列表: ffdshow 源代码分析 1: 整体结构 ffds ...
 - ffdshow 源代码分析 8: 视频解码器类(TvideoCodecDec)
		
===================================================== ffdshow源代码分析系列文章列表: ffdshow 源代码分析 1: 整体结构 ffds ...
 - ffdshow 源代码分析 7: libavcodec视频解码器类(TvideoCodecLibavcodec)
		
===================================================== ffdshow源代码分析系列文章列表: ffdshow 源代码分析 1: 整体结构 ffds ...
 
随机推荐
- 滑雪与时间胶囊(bzoj 2753)
			
Description a180285非常喜欢滑雪.他来到一座雪山,这里分布着M条供滑行的轨道和N个轨道之间的交点(同时也是景点),而且每个景点都有一编号i(1<=i<=N)和一高度Hi. ...
 - FZOJ  Problem 2103 Bin & Jing in wonderland
			
...
 - POJ1167 The Buses
			
Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 6234 Accepted: 1698 Description A man ...
 - 【Visual Studio】The project appears to be under source control, but the associated source control plug-in is not installed on this computer
			
[问题描述]用 Visual Studio 2013打开一个项目时,出现下面错误: [问题原因]参考 http://codeverge.com/asp.net.web-forms/the-projec ...
 - LeetCode OJ--Gray Code **
			
http://oj.leetcode.com/problems/gray-code/ 求格雷码的表示,主要应用递归. 递归生成码表 这种方法基于格雷码是反射码的事实,利用递归的如下规则来构造: 1位格 ...
 - 转载——Step by Step 创建一个 Web Service
			
原创地址:http://www.cnblogs.com/jfzhu/p/4022139.html 转载请注明出处 (一)创建Web Service 创建第一个项目,类型选择ASP.NET Empty ...
 - 计蒜客  UCloud 的安全秘钥(随机化+Hash)
			
题目链接 UCloud 的安全秘钥 对于简单的版本,我们直接枚举每个子序列,然后sort一下判断是否完全一样即可. #include <bits/stdc++.h> using names ...
 - HTTP/1.1标准请求方法和状态码
			
HTTP/1.1标准自从1999年制定以来至今仍然是一个应用广泛并且通行的标准 相关文档 RFC2616:Hypertext Transfer Protocol -- HTTP/1.1 在RFC658 ...
 - 浅谈APP的分享功能,有时候社交裂变形式比内容更“重要”
			
回顾2018年的移动互联网,“社交裂变”“下沉”等成为年度关键词.一方面我们可以看到社交裂变助推用户增长,另一方面我们也看到了以拼多多.趣头条为代表的互联网企业对于社交裂变模式表现出的空前关注度.作为 ...
 - hdu6219(最大空凸包)
			
题意: 给一些点,求出一个最大的空凸包,这个凸包里没有任何给定点且要求这个凸包面积最大 分析: 枚举凸包左下角的点,然后dp[i][j]表示凸包的最后两条边是j->i和i->O情况下凸包的 ...