START_JUCE_APPLICATION (PluginHostApp) 展开这个宏
#ifdef DOXYGEN
#define START_JUCE_APPLICATION(AppClass)
#elif JUCE_ANDROID
#define START_JUCE_APPLICATION(AppClass) \
juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); }
#else
#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
可以看到调用了main函数,同里还可以看到这里创建了应用程序的实例的创建函数指针,这个指针将在main函数中被调用
juce::JUCEApplicationBase::createInstance
这时一直找到了main函数
int JUCEApplicationBase::main()
{
ScopedJuceInitialiser_GUI libraryInitialiser;
jassert (createInstance != nullptr);
const ScopedPointer<JUCEApplicationBase> app (createInstance());
jassert (app != nullptr);
if (! app->initialiseApp())
return 0;
JUCE_TRY
{
// loop until a quit message is received..
MessageManager::getInstance()->runDispatchLoop();
}
JUCE_CATCH_EXCEPTION
return app->shutdownApp();
}
调用消息循环,同时这个地方还调用了app的初始化函数,这是个虚函数
void MessageManager::runDispatchLoop()
{
runDispatchLoopUntil (-1);
}
进入循环
bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor)
{
jassert (isThisTheMessageThread()); // must only be called by the message thread
const int64 endTime = Time::currentTimeMillis() + millisecondsToRunFor;
while (! quitMessageReceived)
{
JUCE_TRY
{
if (! dispatchNextMessageOnSystemQueue (millisecondsToRunFor >= 0))
Thread::sleep (1);
}
JUCE_CATCH_EXCEPTION
if (millisecondsToRunFor >= 0 && Time::currentTimeMillis() >= endTime)
break;
}
return ! quitMessageReceived;
}
//==============================================================================
bool MessageManager::dispatchNextMessageOnSystemQueue (const bool returnIfNoPendingMessages)
{
using namespace WindowsMessageHelpers;
MSG m;
if (returnIfNoPendingMessages && ! PeekMessage (&m, (HWND) 0, 0, 0, PM_NOREMOVE))
return false;
if (GetMessage (&m, (HWND) 0, 0, 0) >= 0)
{
if (m.message == specialId && m.hwnd == juce_messageWindowHandle)
{
dispatchMessageFromLParam (m.lParam);
}
else if (m.message == WM_QUIT)
{
if (JUCEApplicationBase* const app = JUCEApplicationBase::getInstance())
app->systemRequestedQuit();
}
else if (isEventBlockedByModalComps == nullptr || ! isEventBlockedByModalComps (m))
{
if ((m.message == WM_LBUTTONDOWN || m.message == WM_RBUTTONDOWN)
&& ! JuceWindowIdentifier::isJUCEWindow (m.hwnd))
{
// if it's someone else's window being clicked on, and the focus is
// currently on a juce window, pass the kb focus over..
HWND currentFocus = GetFocus();
if (currentFocus == 0 || JuceWindowIdentifier::isJUCEWindow (currentFocus))
SetFocus (m.hwnd);
}
TranslateMessage (&m);
DispatchMessage (&m);
}
}
return true;
}
这个边的代码看! PeekMessage (&m, (HWND) 0, 0, 0, PM_NOREMOVE) 这个用来检查是否有消息,然后使用
GetMessage
(&
m
,
(
HWND
)
0
,
0
,
0
) 来取出消息
这里的specialId 是发送消息的时候设置的。
const unsigned int specialId = WM_APP + 0x4400;
const unsigned int broadcastId = WM_APP + 0x4403;
同时,这里还处理了
if ((m.message == WM_LBUTTONDOWN || m.message == WM_RBUTTONDOWN)
&& ! JuceWindowIdentifier::isJUCEWindow (m.hwnd))
{
// if it's someone else's window being clicked on, and the focus is
// currently on a juce window, pass the kb focus over..
HWND currentFocus = GetFocus();
if (currentFocus == 0 || JuceWindowIdentifier::isJUCEWindow (currentFocus))
SetFocus (m.hwnd);
}
接边接着看两个分支语句是如何去处理的
void dispatchMessageFromLParam (LPARAM lParam)
{
MessageManager::MessageBase* const message = reinterpret_cast <MessageManager::MessageBase*> (lParam);
JUCE_TRY
{
message->messageCallback();
}
JUCE_CATCH_EXCEPTION
message->decReferenceCount();
}
message
->
decReferenceCount
(); 如果计数为零的话则销毁消息
特别说明,在app的初始中进行了一系列的初始化操作,包括创口的创建等,具体可以参见juce的示例代码,窗口的具体创建过程请参见后续文章。
void initialise (const String& commandLine)
{
// initialise our settings file..
PropertiesFile::Options options;
options.applicationName = "Juce Audio Plugin Host";
options.filenameSuffix = "settings";
options.osxLibrarySubFolder = "Preferences";
appProperties = new ApplicationProperties();
appProperties->setStorageParameters (options);
LookAndFeel::setDefaultLookAndFeel (&lookAndFeel);
mainWindow = new MainHostWindow();
mainWindow->setUsingNativeTitleBar (true);
commandManager.registerAllCommandsForTarget (this);
commandManager.registerAllCommandsForTarget (mainWindow);
mainWindow->menuItemsChanged();
if (commandLine.isNotEmpty()
&& ! commandLine.trimStart().startsWith ("-")
&& mainWindow->getGraphEditor() != nullptr)
mainWindow->getGraphEditor()->graph.loadFrom (File::getCurrentWorkingDirectory()
.getChildFile (commandLine), true);
}
说明:分析不一定正确,仅供参考。
juce群号:68016614