Menu

Application_and_module_objects

ObjectWindows encapsulates Windows applications and DLL modules using the TApplication and TModule classes, respectively.

TModule

TModule objects do the following:

  • Encapsulate the initialization and closing functions of a Windows DLL.
  • Contain the hInstance and lpCmdLine parameters, which are equivalent to the parameters of the same name that are passed to the WinMain function in a non-ObjectWindows application. Note that both WinMain and LibMain have these two parameters in common. Unless you're working with a DLL, you do not need to create a TModule object yourself.

TApplication

TApplication objects build on the basic functionality provided by TModule. TApplication objects do the following:

  • Encapsulate the initialization, run-time management, and closing functions of a Windows application
  • Contain the values of the hPrevInstance and nCmdShow parameters, which are equivalent to the parameters of the same name that are passed to the WinMain function in a non-ObjectWindows application.

Because TApplication is based on TModule, it also has all the functionality contained in TModule.

Minimum requirements

To use a TApplication object, you must:

Include the right header file

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.

Create an application object

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.

Call the Run function

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

  1. [Initializing_the_application]
  2. Creating and displaying the main window
  3. [Running_the_application's_message_loop]

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.

Creating a small application

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.

Accessing application objects

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.

Finding the object

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);
}

Application message handling

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:

Extra message processing

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

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.

Closing applications

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.

Changing Closing Behavior

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.

Closing the Application

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:

  1. Windows sends a WM_CLOSE message to the main window.
  2. The main window object's EvClose member function calls the application object's CanClose member function.
  3. The application object's CanClose member function calls the main window object's CanClose member function.
  4. The main window and document manager objects call CanClose for each of their child windows. The main window and document manager objects' CanClose functions return true only if all child windows' CanClose member functions return true.
  5. If both the main window and document manager objects' CanClose functions return true, the application object's CanClose function returns true.
  6. If the application object's CanClose function returns true, the EvClose function shuts down the main window and ends the application.

Modifying CanClose

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

  1. Check to see if the editor text had changed
  2. If so, prompt the user to ask whether the text should be saved before closing, using a message box with Yes, No, and Cancel buttons
  3. Check the return value from the message box:
    • If the user clicks Yes, save the file, return true from the CanClose function.
    • If the user clicks No, simply return true from the CanClose function without saving the file.
    • If the user clicks Cancel indicating that the user does not want to close the application yet, return false from the CanClose function without saving the file.

Related

Wiki: Initializing_the_application
Wiki: Knowledge_Base
Wiki: Running_the_application's_message_loop
Wiki: Using_WinMain_and_OwlMain

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.