Application Classes
SFL contains two application-level classes, CApp and CMTIApp. Both classes work fundamentally the same. CApp mixes together window creation and application initialization. CMTIApp supplies additional functionality for managing the multiple top-level windows on different threads.
CApp
CApp is the basic class that is responsible for creating a window, running the message loop, and handling termination issues (such as destroying the window). Example 101 shows the SFL’s declaration of CApp.
Example 101 – SFL’s CApp class
template<typename _Base = ATL::CComModule,
typename _MessageLoop,
typename _Initializer = CNoopInitializer>
CApp : public _Base {
public:
HRESULT Init(int nShowCmd,
_ATL_OBJMAP_ENTRY* p,
HINSTANCE h,
const GUID* plibid = NULL);
void Term();
int Run();
};
CApp is a template class taking three parameters: a CComModule-derived class, a class for handling the message loop, and a class for handling application initialization. CApp derives itself from whatever type is passed in as the _Base type. Notice the default is ATL’s CComModule class. SFL (and ATL) expects to see a single instance of a class of type CComModule within the application. To this end, SFL assumes CApp to derive ultimately from CComModule (which is why -CComModule is named as the default base class).
Also notice that CApp’s declaration has two other parameters in addition to the base class: the message loop and the initializer. The class passed in as the _MessageLoop class is responsible for providing the message pumping machinery. CApp declares a member variable of the type passed in through the _MessageLoop template parameter and uses that member variable to drive the message loop.
CApp’s final parameter is the initializer class. SFL expects the initializer class to implement static functions named Init() and Term() for initializing the application and terminating the class. SFL declares four initializer classes: CNoopInitializer, CComInitializer, and COleInitializer, and -CCommonControlsInitializer. You’ll cover each of the initializers shortly. Notice that CApp defaults to the CNoopInitializer.
CApp has three methods: Init(), Term(), and Run(). These methods are for initializing the application, running the message loop, and terminating. They are usually called within the application’s WinMain() function.
CMTIApp
In addition to the basic CApp type, SFL also includes a class named CMTIApp, which manages a user interface consisting of multiple top-level windows. CMTIApp is useful for writing applications that have multiple top-level windows. Example 102 shows SFL’s CMTIApp class.
Example 102 – SFL’s CMTIApp class
template <typename _Base = ATL::CComModule,
typename _MessageLoop,
typename _Initializer = CNoopInitializer >
class CMTIApp : public _Base
{
public:
HRESULT Init(int nShowCmd, _ATL_OBJMAP_ENTRY* p, HINSTANCE h,
const GUID* plibid = NULL)
void Term()
int Run()
bool RunTopLevelWindow(void* lpParam = NULL);
protected:
// methods for managing the multiple message queue threads…
};
The difference between the CApp class and the CMTIApp class is that the CMTIApp class supports multiple top-level windows. CMTIApp manages a collection of message loops, each living on a separate thread. CMTIApp has a function for opening a new top-level window. Applications based on CMTIApp normally respond to the File | New menu option by running a new top level window. Other than that, the programmatic interface is more or less the same. You declare an instance of CMTIApp providing the same template parameters as you would with CApp. That is, name the instance _Module and call the Init(), Run(), and Term() functions within WinMain(). Example 103 shows how to call RunTopLevelWindowInit() in response to the File | New menu option.
Example 103 – Calling the application’s RunTopLevelWindow() function
LRESULT OnFileNew(WORD, WORD, HWND, BOOL&)
{
_Module.RunTopLevelWindow();
return 0;
}
SFL’s application classes also have hooks for integrating the SFL Layout Manager. See Chapter 7, “Layout Manager,” for more information.
As part of examining how the application classes work, take a look at how SFL’s initializer classes work.