Main structure
The main structure is below.
Main Workflow
When MotionBuilder starts, QtSample DLL is loaded, but no QtSample instance is created. Only when a plugin is run, the QtSample,
FBWidgeHolder and xxx instance are created like the below sequence:
Let’s see the track to the code to see details:
- DllMain (…) invokes FBModuleQtSample ().
- FBModuleQtSample () invokes FBObject_Register (…) (to register the QtSample class).
- FBObject_Register (…) invokes RegisterToolQTSAMPLE__CLASS (...)
- RegisterToolQTSAMPLE__CLASS (...) creates a QtSample instance, and invoke FBCreate() function.
- FBCreate () invokes UICreate () to create the UI.
- UICreate () invokes CreateQtTestWidget (…).
- CreateQtTestWidget (…) creates an xxx instance. (xxx is the UI class.)
- xxx constructor invoke ui.setupUi (this) to create the UI. setupUi () function can be found in ui_xxx.h file, which is generated
by xxx.ui file by uic command.
Until now the UI has been created and shown in screen. But how to respond to the button click event?
- When you click the button, xxx::qt_metacall(…) will be invoked.
- on_buttonCreateCube_clicked() will be invoked to response the button click event.
MOC & UIC Commands
Do you feel strange about xxx::qt_metacall(…)? You haven't created it. Actually it is created when compiler creates moc_xxx.cpp
files by MOC commands. Below graphic show you which file could generate which file by which command:
Each file’s responsibilities have been shown in below graphic:
You can find the use of UIC in xxx.ui file's property:
You can find the use of MOC in xxx.h file's property:
Where is DllMain?
You may get confused that you cannot find the DllMain(…) method, the DLL entry point. Actually it is generated by below MICRO
in qtsample_tool.cpp file.
// Library declaration.
FBLibraryDeclare( qtsample )
{
FBLibraryRegister( QtSample );
}
FBLibraryDeclareEnd;
After compiling the qtsample_tool.i file you can see it clearly:
static FBLibrary qtsampleGlobalFBLibrary;
extern "C"
{
__declspec(dllexport)
bool LIBRARY_INIT(HIError )
{
;
if (qtsampleGlobalFBLibrary.LibInit())
return true;
return false;
}
}
__declspec(dllexport) void EntryPointqtsample(kFBDllOperation Operation);
BOOL __stdcall DllMain(HINSTANCE hinstDLL,DWORD fdwReason, LPVOID lpvReserved )
{
switch (fdwReason)
{
case 1: EntryPointqtsample(kFBDllLoad); break;
case 0: EntryPointqtsample(kFBDllUnLoad); break;
}
return 1;
}
void EntryPointqtsample(kFBDllOperation Operation)
{
switch( Operation )
{
case kFBDllLoad:
{
{
extern void FBModuleQtSample( );
FBModuleQtSample( );;
}
} break;
default: break;
}
};
Something tricky
- If you ask ***.cpp to pre-compile a ***.i file, it will not generated a ***.obj file after compiling. You have two choices:
- easily turn off the pre-compile setting
- copy the ***.cpp's command line to VS 2008 command line to execute.
- If compiler say cannot find *** file in compiling or linking, you can try open property setting to delete or add “..\” to
make sure the directory is right.
- In Qt, slot name is combined by on_<control name>_<signal name> and shouldn’t be changed. For example, if you want to write
a slot to handle buttonCreateCube’s clicked signal, you must name the slot as on_buttonCreateCube_clicked(). Otherwise it
doesn’t work. Check the Qt documentation for more information.