Run an application inside of the previous application instance.
While writing software applications, software developers often face the problem of creating an application instance which can be reused by any new run of the application. This problem is not resolved by a standard means of Visual Basic, thus we had to remedy it in our application by employing the technique of windows superclassing and temporary files storage.
Two classes and two modules were introduced for solution of the problem. Their functionality was organized as follows:
1. Windows superclassing approach was encapsulated to the both clsAppsObject class and mdlAppsObjectMain module. We had to put some functionality out of the clsAppsObject class, because of the limitations upon the use of the AddressOf operator in class modules.
All these modules need not any changes for further customization and development.
2. Temporary files storage functionality, used for data interchange between different instances of the application , was encapsulated to the clsTempFile . This module also need not any changes for further customization and development.
3. The wrapper for a default Main() subroutine was defined as the AppsObjectStartUpWrapper() subroutine which is the only subject of customization and development processes. It is presented in the mdlAppsObjectStartUp module.
The windows superclassing technique approach puts some limitations on the application developer:
1. StartUp Object of the project must be Main() subroutine;
2. Developers must use the AppsObjectStartUpWrapper() subroutine as an entry point for adding needed customization to the project.
3. Developers must not change names of the both AppsObjectStartUpWrapper() subroutine and class modules since these names are hard coded in application.
4. There are some difficulties of debugging in IDE due to extensive use of Windows API calls while superclassing window.
There exist enough references which explain the windows superclassing(subclassing) technique and show its use in Visual Basic applications. So we will speak only about the suggested approach for the problem solution.
The clsAppsObject class defines three new custom defined message identificators :
The class substitutes a default Windows function with its own, custom defined Windows function.
This function handles above mentioned messages directly, and all other messages are passed to the existing default Windows function. Thus the clsAppsObject class allows creation of the VB executable application superclassing.
While opening application, an initialized application instance checks that there is no previous instances of the application and completes its initialization by direct call to AppsObjectStartUpWrapper() .
If the previous application instance exists then on the application initialization, the current application instance sends broadcast message #1 to all existing windows of the application.
The whole solution of the problem is described by the table below where you can see the messaging flow among any initialized instance and other instances of the application.
|1||WM_FILE_TMP_ASK_MAIN_MSG||Current App||All existing windows||[A]|
|2||WM_FILE_TMP_SET_MAIN_MSG||First App||Current App||[B]|
[A] is the response of the custom defined Windows function in the previous application instance.
It sends its main window handler backward to the current application instance with message #2;
[B] is the response of the custom defined Windows function in the current application instance.
It sets obtained handler as previous application handler, saves the current command line to a temporary file and then sends message #3 to the previous application instance with file name as one of the parameters. After that the current application instance is destroyed;
[C] is the response of the custom defined Windows function in the previous application instance.
It reads command line data from temporary file and runs AppsObjectExecute() subroutine with command line as its parameter, after that it deletes the temporary file.
The project attached to this article was created to demonstrate this technique. The code was tested for the both MDI and SDI applications in VB5/VB6 environment. Conditional compilation argument COMP_SDI was added into the body of Main() subroutine in order to allow compilation to branch the creation either SDI or MDI application example. In the both cases there is form type and common counter of started instances in the caption of the form. Additionally, in the case of MDI application, the instance number and its command line string is displayed as the caption text of the child form. There is no code in forms modules.