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.
- 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, whichBApplication
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()
, andGetAppInfo()
.
5 Automatic Assignment:
- The
BApplication
object is automatically assigned to the globalbe_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 forBApplication
.int main()
: Defines the main function of the program.BApplication* app = new BApplication("application/x-vnd.vendor-application");
: Initializes theBApplication
object with the specified signature.app->Run();
: Starts the message loop of the application.delete app;
: Deletes theBApplication
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.
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
- 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 + Z
to 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 theBWindow
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:
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;
}