ObjectWindows encapsulates Windows applications and DLL modules using the TApplication and TModule classes, respectively.
TModule objects do the following:
TApplication objects build on the basic functionality provided by TModule. TApplication objects do the following:
Because TApplication is based on TModule, it also has all the functionality contained in TModule.
To use a TApplication object, you must:
TApplication is defined in the header file owl/applicat.h. You must include this header file to use TApplication. Because TApplication is derived from TModule, owl/applicat.h includes owl/module.h.
You can create a TApplication object using one of two constructors. The most commonly used constructor is this:
TApplication(const tstring& name);
This version of the TApplication constructor takes a string, which becomes the application's name. If you don't specify a name, by default the constructor names it the null string. TApplication uses this string as the application name.
The second version of the TApplication constructor lets you specify a number of parameters corresponding to the parameters normally passed to the WinMain function:
TApplication(const tstring& name, HINSTANCE instance, HINSTANCE prevInstance, const tstring& cmdLine, int cmdShow){}
You can use this constructor to pass command parameters to the TApplication object.
The most obvious thing that the TApplication::Run function does is to start your application running. But in doing so it performs a number of other important tasks, including
For the purposes of creating the basic application, it is sufficient to know that Run is the function you call to make your application go.
Here's the smallest application you can create. It includes the correct header file, creates a TApplication object, and calls that object's TApplication::Run() function.
#include <owl\applicat.h> int OwlMain(int argc, char* argv[]) { return owl::TApplication("Wow!").Run(); }
This example creates a Windows application having a main window with the caption "Wow!" You can resize, move, minimize, maximize, and close this window. In a real application, you would derive a new class for the application to add more functionality. Notice that the only function you have to call explicitly in this example is the Run function.
You might need to access an application object from outside that object's scope. For example, you might need to call one of the object's member functions from a function in a derived window class. But because the window object is not in the same scope as the application object, you have no way of accessing the application object. In this case, you must find the application object. You don't have to provide an explicit WinMain function for your ObjectWindows applications; you can instead use the function OwlMain. OwlMain lets you use int argc and char** argv parameters and return an int, just like a traditional C or C++ program with a main function.
To find the current application object from a window object, TWindow has a member function, TWindow::GetApplication(), that returns a pointer to the application object. You can use this pointer to call TApplication member functions and access TApplication data members. The following listing shows a possible use of GetApplication:
void TMyWindow::Error() { // display message box containing the application name MessageBox("An error occurred!", GetApplication()->Name, MB_OK); }
After your application is initialized, the application object's MessageLoop starts running. MessageLoop is responsible for processing incoming messages from Windows. There are two ways you can refine message processing in an ObjectWindows application:
TApplication has member functions that provide the message-handling functionality for any ObjectWindows application. These functions are TApplication::MessageLoop(), TApplication::IdleAction(), TApplication::PreProcessMenu(), and TApplication::ProcessAppMsg().
Idle processing lets your application take advantage of the idle time when there are no messages waiting (including user input). If there are no waiting messages, MessageLoop calls IdleAction.
To perform idle processing, override IdleAction to perform the actual idle processing. Since idle processing takes place while the user isn't doing anything, it should last only a short while. If you need to do anything that takes longer than a few tenths of a second, you should split it into several processes.
IdleAction's parameter idleCount is a long specifying the number of times IdleAction was called between messages. You can use idleCount to choose between low-priority and high-priority idle processing. If idleCount reaches a high value, you know that a long period without user input has passed, so it's safe to perform low-priority idle processing.
Return true from IdleAction to call IdleAction back sooner.
You should always call the base class IdleAction function in addition to performing your own processing. If you are writing applications for Windows NT, you can also use multiple threads for background processing.
Users usually close a Windows application by choosing File|Exit or pressing Alt+F4. To give the user a chance to save any open files, it's important that the application be able to intercept such an attempt.
TApplication lets you do that.
TApplication and all window classes have or inherit the member function CanClose. Whenever an application object tries to shut down, it queries the main window's and document manager's CanClose function. (The exception is when dialog boxes are canceled by the user's clicking the Cancel button or pressing the Esc key, in which case the dialog is simply destroyed, bypassing the CanClose function.) If either the main window or document manager object has children, it calls the CanClose function for each child. In turn, each child calls the CanClose function of each of its children, if any, and so on.
The CanClose function gives each object a chance to prepare to be shut down. It also gives the object a chance to abort to the shutdown if necessary. When the object has completed its clean-up procedure, its CanClose function should return true.
If any of the CanClose functions called returns false, the shut-down procedure is aborted.
The CanClose mechanism gives the application object, the main window, and any other windows a chance to either prepare for closing or prevent the closing from taking place. In the end, the application object approves the closing of the application. The normal closing sequence looks like this:
CanClose should rarely return false. Instead, CanClose should perform any actions necessary to return true. CanClose should return false only if it's unable to do something necessary for orderly shutdown, or if the user wants to keep the application running. For example, suppose you are creating a text editor. A possible procedure to follow in the CanClose member function would be to
Wiki: Initializing_the_application
Wiki: Knowledge_Base
Wiki: Running_the_application's_message_loop
Wiki: Using_WinMain_and_OwlMain