BApplication

Overview

In this article we will explore the working of main class which is responsible for creating application BApplication. Applications built using Haiku OS typically use BApplication as the base class to handle event processing, message passing, window management, and resource management.

What is BApplication?

BApplication is a fundamental class in Haiku OS, serving as a container object for an application. It establishes a connection between the application and the Application Server and handles messages sent to it.

image-111.png
  • BApplication is inherited from the BLooper class which provides the continues loop.

1 Event Loop:

  • BApplication provides a continuous event loop that processes system event and dispatches messages to the appropriate handlers.
  • The Event loop is managed by the BLooper class, which BApplication inherits from.
  • The message loop is started by calling the Run() method.
  • The Loop continues until the application is told to quit.

2 Message Handling:

  • BApplication manages the handling of message within the application, including messages from the system and user-defined messages.
  • Messages are dispatched to the appropriate handlers using the DispatchMessage() function.

3 Window Management:

  • BApplication manages the creation, destruction, and event handling of application windows.

4 Resource Management:

  • BApplication manages application resources such as settings, preferences, and global variables.
  • It provides function for managing resources, such as SetAppInfor(), and GetAppInfo().

5 Automatic Assignment:

  • The BApplication object is automatically assigned to the global be_app variables, allowing easy access from anywhere in the code.

Creating Application

BApplication Constructor:

You can create an simple application by using BApplication constructor.

The BApplication constructor is used to create an instance of the BApplicaiton class, which represents the application itself.

There are different constructor available for the BApplication:

1 BApplication()

BApplication::BApplication (const char * signature	)	
  • It initializes a BApplication with the passed in signature (string).
  • signature is a unique identifier for the application and is used by the system to identify the application. It typically follows the format "application/x-vnd.vendor-application_name".
  • The new BApplication is, by default, not running yet. After setting up everything we have to call Run() to start the application.

2 BApplication()

BApplication::BApplication(const char* signature, status_t* _error);
  • Initialize a BApplication with the passed in signature and a pointer to an error message.
  • Any error that occurs while constructing the BApplication will be set to the _error pointer. If _error points to a status_t error then you should not call Run().

3 BApplication()

BApplication::BApplication(BMessage* data);
  • Initialize a BApplication object from a message.
  • The message must contain the signature of the application you wish to initialize in the "mime_sig" variable.

Example:

Typically, we initialize the BApplication object in the programs main() function. As we all know that the main() is the entry point of the program.

A typical main() function looks something like this:

#include Application.h
 
main()
{
    /* Vendor is your vendor name, application is your application name */
    BApplication *app = new BApplication("application/x-vnd.vendor-application");
    app->Run();
    delete app;
 
    return 0;
}

Code Explanation:

  • #include <Application.h>: Includes the necessary header file for BApplication.
  • int main(): Defines the main function of the program.
  • BApplication* app = new BApplication("application/x-vnd.vendor-application");: Initializes the BApplication object with the specified signature.
  • app->Run();: Starts the message loop of the application.
  • delete app;: Deletes the BApplication object to free its memory usage.
  • return 0;: Indicates successful completion of the program.

Note: It is important to call delete app; to free the memory allocated for the BApplication object when the application exits.

Compiling it: I assume you are using Haiku OS for this:

Open a terminal and navigate to the directory where you saved MyApp.cpp. Then, use the following command to compile the code:

gcc -o MyApp MyApp.cpp -lbe
  • gcc: Command to invoke the GNU Compiler Collection.
  • -o MyApp: Specifies the output file name as MyApp.
  • MyApp.cpp: Name of the source file.
  • -lbe: Links the application with the libbe library, which is required for Haiku OS applications using the Haiku Application Kit.
image-110.png

Enough coding time to run it

Running the Application:

You can run the application by double clicking the generated output file or through the terminal as follows:

./MyApp

Did anything happen? Nope, right

bapplication-simple-long.gif
  • It is because it was a simple application that does nothing, just nothing. Later in the series we will create the window in the application.
  • Press ALT + Zto break this loop in terminal.

BApplication Functions

Let's have a look to the most common used functions of the BApplication class but before that create the window.

1 BWindow in BApplication:

In order to Create window in BApplication you need to use BWindow class constructor, as shown in the code below:

#include <Application.h>
#include <Window.h>

int main()
{
    // Create a BApplication object with a signature
    BApplication* app = new BApplication("application/x-vnd.MyApp");
    
    // Create a BWindow object
    BWindow* window = new BWindow(BRect(100, 100, 400, 300), "My Window",
                                  B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE);
    
    // Show the window
    window->Show();
    
    // Run the application (start the event loop)
    app->Run();
    
    // Delete the BApplication object to free its memory
    delete app;
 
    return 0;
}

Explanation:

  • The above code first create an instance of the BApplication class and initialize it with the specified signature.
  • After that, Create an instance of the BWindow class with the desired parameters which we look later on the BWindow section.
  • Parameters include window Frame (BRect), window title, window type, and flags.
  • After that we call the Show() method of the BWindow object to display the window on the screen.
  • Start the main event loop of the application by calling the Run() method.
  • Last but not the least is clean up, Delete the BApplication object to free its memory usage.

The Code will show the kind of output as shown in the screenshot below:

image-112.png

2 Message Loop:

status_t BApplication::Run();
  • This function is inherited from BLooper.
  • It starts the main event loop of the application.
  • Returns when the application is told to quit.

3 MessageReceived():

virtual void BApplication::MessageReceived(BMessage* message);

Called when a message is received by the application. Override this function to handle application-specific messages.

Example:

#include <Application.h>
#include <Window.h>
#include <Message.h>

class MyWindow : public BWindow {
public:
    MyWindow(BRect frame, const char* title)
        : BWindow(frame, title, B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE) {}

    void MessageReceived(BMessage* message) {
        switch (message->what) {
            case 'HELLO':
                printf("Hello Message Received!\n");
                break;
            default:
                BWindow::MessageReceived(message);
                break;
        }
    }
};

int main()
{
    // Create a BApplication object with a signature
    BApplication* app = new BApplication("application/x-vnd.MyApp");
    
    // Create a BWindow object
    MyWindow* window = new MyWindow(BRect(100, 100, 400, 300), "My Window");
    
    // Show the window
    window->Show();
    
    // Run the application (start the event loop)
    app->Run();
    
    // Delete the BApplication object to free its memory
    delete app;
 
    return 0;
}

This demo application does nothing separate than the last example as we have introduced just the MessageReceived function but didn't added the logic to send the message to this application.

4 Hook Methods

In software development, hook methods, also known as hook functions or callback methods, are functions that are called by a framework or library in response to specific events or conditions. These methods allow you to customize or extend the behavior of the framework or library without modifying its source code directly.

In the context of the Haiku OS BApplication class, hook methods are virtual functions that you can override in your custom application class to handle various events or conditions. Here are the hook methods provided by the BApplication class:

	virtual	thread_id			Run();
	virtual	void				Quit();
	virtual bool				QuitRequested();
	virtual	void				Pulse();
	virtual	void				ReadyToRun();
	virtual	void				MessageReceived(BMessage* message);
	virtual	void				ArgvReceived(int32 argc, char** argv);
	virtual	void				AppActivated(bool active);
	virtual	void				RefsReceived(BMessage* message);
	virtual	void				AboutRequested();

#1 ReadyToRun()

  • This method is called when the application is ready to run.
  • It is commonly used for initializing the application and creating its user interface.
  • We create and show a BWindow object within its method.

#2 MessageReceived(BMessage* message)

  • This method is called when a message is received by the application.
  • You can override this method to handle custom messages sent to your application.

#3 RefsReceived(BMessage* message)

  • This method is called when the application received file references messages.
  • It is used to handle file drops or file opening events.

#4 ArgvReceived(int32 argc, char** argv)

  • This method is called when the application receives command-line arguments.
  • It is used to handle command-line parameters passed to the application when it is launched.

Suppose you pass the command line with some arguments.

./myapp arg1 arg2 arg3

In order to receive these arguments we have to modify the main function of the application:

int main()
{
    // Create an instance of the custom application
    MyApp app;
    // Run the application
    app.Run();

    // Return the exit status of the application
    return 0;
}
// Called when the application receives command-line arguments
virtual void ArgvReceived(int32 argc, char** argv) {
    printf("Command-line arguments received!\n");
    for (int32 i = 0; i < argc; i++) {
        printf("Argument %d: %s\n", i, argv[i]);
    }
}

When you run ./myapp arg1 arg2 arg3 from the command line, the ArgvReceived() method will be automatically called, and you will see the output:

Command-line arguments received!
Argument 0: ./myapp
Argument 1: arg1
Argument 2: arg2
Argument 3: arg3

Note: We can call ArgvReceived manually as well from the main function of the app.

// Example of sending command-line arguments
    char* argv[] = {"MyApp", "-arg1", "-arg2"};
    app.ArgvReceived(3, argv);

#5 AboutRequested()

  • This method is called when the user requests information about the application.
  • It is used to display information about the application, such as version number, copyright, etc.

#6 Quit()

  • Quits the application.
  • Stops the main event loop and exists the application.

#7 QuitRequested()

  • Checks if a quit request has been made for the application.
  • Returns true if a quit request has been made, false otherwise.

#8 Pulse()

  • Called periodically by the application's message loop.
  • Can be overridden to perform periodic tasks or checks.

#9 AppActivated(bool active)

  • Called when the application's activation state changes.
  • Receives a boolean parameter indicating whether the application has been activated or deactivated.

Example of Hook Methods:

#include <Application.h>
#include <Window.h>
#include <Message.h>
#include <Alert.h>
#include <stdio.h> // Include for printf()

// Custom BWindow class
class MyWindow : public BWindow {
public:
    MyWindow(BRect frame, const char* title)
        : BWindow(frame, title, B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE) {}

    void MessageReceived(BMessage* message) {
        switch (message->what) {
            case 'HELLO':
                printf("Hello Message Received!\n");
                break;
            default:
                BWindow::MessageReceived(message);
                break;
        }
    }
};

// Custom BApplication class
class MyApp : public BApplication {
public:
    MyApp() : BApplication("application/x-vnd.MyApp") {}

    // Starts the main event loop of the application
    virtual thread_id Run() {
        printf("Application is running!\n");
        return BApplication::Run();
    }

    // Quits the application
    virtual void Quit() {
        printf("Quitting the application!\n");
        BApplication::Quit();
    }

    // Checks if a quit request has been made for the application
    virtual bool QuitRequested() {
        printf("Quit requested!\n");
        return true; // Always return true to allow quitting
    }

    // Called periodically by the application's message loop
    virtual void Pulse() {
        printf("Pulse!\n");
    }

    // Called when the application is ready to start running
    virtual void ReadyToRun() {
        printf("Application is ready to run!\n");

        // Create and show a BWindow object
        MyWindow* window = new MyWindow(BRect(100, 100, 400, 300), "My Window");
        window->Show();
    }

    // Called when a message is received by the application
    virtual void MessageReceived(BMessage* message) {
        switch (message->what) {
            case 'APP_MESSAGE':
                printf("Application Message Received!\n");
                break;
            default:
                BApplication::MessageReceived(message);
                break;
        }
    }

    // Called when the application receives command-line arguments
    virtual void ArgvReceived(int32 argc, char** argv) {
        printf("Command-line arguments received!\n");
        for (int32 i = 0; i < argc; i++) {
            printf("Argument %d: %s\n", i, argv[i]);
        }
    }

    // Called when the application's activation state changes
    virtual void AppActivated(bool active) {
        printf("Application Activated: %s\n", active ? "true" : "false");
    }

    // Called when the application receives file reference messages
    virtual void RefsReceived(BMessage* message) {
        printf("File references received!\n");
    }

    // Called when the user requests information about the application
    virtual void AboutRequested() {
        printf("About Requested!\n");
        BAlert* alert = new BAlert("About", "MyApp version 1.0", "OK");
        alert->Go();
    }
};

int main()
{
    // Create an instance of the custom application
    MyApp app;
    // Run the application
    app.Run();

    // Example of sending a custom message to the application
    BMessage* customMessage = new BMessage('APP_MESSAGE');
    app.PostMessage(customMessage);

    // Example of sending command-line arguments
    char* argv[] = {"MyApp", "-arg1", "-arg2"};
    app.ArgvReceived(3, argv);

    // Example of activating and deactivating the application
    app.AppActivated(true);
    app.AppActivated(false);

    // Example of receiving file references
    BMessage* fileMessage = new BMessage(B_REFS_RECEIVED);
    app.RefsReceived(fileMessage);

    // Example of requesting information about the application
    app.AboutRequested();

    return 0;
}
bapplication-hooksmethod-1.gif