A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://gammasoft71.github.io/xtd/docs/documentation/guides/xtd.forms/Overview/control_events below:

Control and events | xtd

Control and events

As in all GUI frameworks, an xtd application is event based.

Events are either generated by the system or by a user action (for example when a property changed).

The event system of xtd is based on the Windows event system. This means that native toolkits have to convert their events to match Windows events. This is not important for the end user of xtd but for the developers of xtd.

Basic Operation

The Operating System uses an event loop to send and receive events.

This is how the Windows event loop works.

In main we will create the different controls necessary for the application and then we will create an event loop that will send and receive events until we quit the application. For each created control we will assign a method (usually called WndProc) as well as a fallback method (usually called DefWndProc) to receive the events related to the control. The fallback method is necessary to be able to use the default event handling for

Some events like WM_COMMAND, WM_NOTIFY, ... are not sent to the control directly but to the parent control.

Here is a Win32 example of a basic application

In the example below, we will just create a window with two buttons and two static texts. We will associate a WndProc only to the window because pressing the button results in a WM_COMMAND event that is sent to the parent control (in this case the window). At the end of the main function we will execute the event loop until the window is closed by the user.

#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

#include <string>
#include <Windows.h>
#include <CommCtrl.h>

using namespace std;
using namespace std::literals;


HWND window = nullptr;
HWND button1 = nullptr;
HWND button2 = nullptr;
HWND staticText1 = nullptr;
HWND staticText2 = nullptr;
WNDPROC defWndProc = nullptr;


LRESULT OnWindowClose(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
PostQuitMessage(0);
return CallWindowProc(defWndProc, hwnd, message, wParam, lParam);
}


LRESULT OnButton1Click(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
static auto buttonClicked = 0;
auto result = L"button1 clicked "s + to_wstring(++buttonClicked) + L" times"s;
SendMessage(staticText1, WM_SETTEXT, 0, reinterpret_cast<LPARAM>(result.c_str()));
return CallWindowProc(defWndProc, hwnd, message, wParam, lParam);
}


LRESULT OnButton2Click(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
static auto buttonClicked = 0;
auto result = L"button2 clicked "s + to_wstring(++buttonClicked) + L" times"s;
SendMessage(staticText2, WM_SETTEXT, 0, reinterpret_cast<LPARAM>(result.c_str()));
return CallWindowProc(defWndProc, hwnd, message, wParam, lParam);
}


LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
if (message == WM_CLOSE && hwnd == window) return OnWindowClose(hwnd, message, wParam, lParam);
if (message == WM_COMMAND && HIWORD(wParam) == BN_CLICKED && reinterpret_cast<HWND>(lParam) == button1) return OnButton1Click(hwnd, message, wParam, lParam);
if (message == WM_COMMAND && HIWORD(wParam) == BN_CLICKED && reinterpret_cast<HWND>(lParam) == button2) return OnButton2Click(hwnd, message, wParam, lParam);
return CallWindowProc(defWndProc, hwnd, message, wParam, lParam);
}


auto main() -> int {

window = CreateWindowEx(0, WC_DIALOG, L"Button example", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, nullptr, nullptr, nullptr, nullptr);
button1 = CreateWindowEx(0, WC_BUTTON, L"button1", WS_CHILD | WS_VISIBLE, 50, 50, 75, 25, window, nullptr, nullptr, nullptr);
button2 = CreateWindowEx(0, WC_BUTTON, L"button2", WS_CHILD | WS_VISIBLE, 50, 100, 200, 75, window, nullptr, nullptr, nullptr);
staticText1 = CreateWindowEx(0, WC_STATIC, L"button1 clicked 0 times", WS_CHILD | WS_VISIBLE, 50, 200, 200, 23, window, nullptr, nullptr, nullptr);
staticText2 = CreateWindowEx(0, WC_STATIC, L"button2 clicked 0 times", WS_CHILD | WS_VISIBLE, 50, 230, 200, 23, window, nullptr, nullptr, nullptr);


defWndProc = reinterpret_cast<WNDPROC>(SetWindowLongPtr(window, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(WndProc)));


ShowWindow(window, SW_SHOW);


MSG message = {0};
while (GetMessage(&message, nullptr, 0, 0)) {
TranslateMessage(&message);
DispatchMessage(&message);
}
}

The following code show the same example with xtd

#include <xtd/xtd>

using namespace xtd;
using namespace xtd::forms;


auto main() -> int {

form form1;
form1.text("Button example");
button button1;
button1.parent(form1).text("button 1").bounds({50, 50, 75, 25});
button button2;
button2.parent(form1).text("button 2").bounds({50, 100, 200, 75});
label label1;
label1.parent(form1).text("button1 clicked 0 times").bounds({50, 200, 200, 20});
label label2;
label2.parent(form1).text("button2 clicked 0 times").bounds({50, 230, 200, 20});


button1.click += [&] {
static auto button_clicked = 0;
label1.text(string::format("button1 clicked {} times", ++button_clicked));
};


button2.click += [&] {
static auto button_clicked = 0;
label2.text(string::format("button2 clicked {} times", ++button_clicked));
};


application::run(form1);
}

What can we see apart from the verbosity and the c++ lambda functions?

The code is based on the same model. Indeed, even if you can't see it when reading the code, the application::run(const form& main_form) method actually hides the Windows message loop and the display of the form passed to it as a parameter.

The control::click events of xtd are also based on the control::wnd_proc and control::def_wnd_proc] functions which are protected member functions of the control class.

The form::form_closed event automatically closes the application because it is considered to be the main window when passed as a parameter to the application::run(const form& main_form) method.

How to respond to an event

Two possible methods:

event_handler

Let's take a simple example of a click on a button.

The following code shows how to associate an event_handler to the control::click event.

#include <xtd/xtd>

using namespace xtd::forms;

class form1 : public form {
public:
form1() {
button1.parent(*this);
button1.text("Button 1");
button1.location({10, 10});
button1.click += [&] {
message_box::show("Button clicked!");
};
}

private:
button button1;
};

auto main() -> int {
application::run(form1 {});
}

In this example we use a lambda function, but we could as well have associated an external function to the class form1 or an internal method. We could also have specified the arguments of the click event if we needed them.

The following example uses the form1::on_button_click member function with event click arguments. Even if we don't need the arguments it's just for the example.

#include <xtd/xtd>

using namespace xtd;
using namespace xtd::forms;

class form1 : public form {
public:
form1() {
button1.parent(*this);
button1.text("Button 1");
button1.location({10, 10});
button1.click += {*this, &form1::on_button1_click};
}

private:
void on_button1_click(object& sender, const event_args& e) {
message_box::show("Button clicked!");
}

button button1;
};

auto main() -> int {
application::run(form1 {});
}

See delegates and events for more information.

Overriding the protected method associated with the event

Let's take the previous example but overload the on_click method associated to the click event. To do this we need to create a class derived from the button class.

#include <xtd/xtd>

using namespace xtd;
using namespace xtd::forms;

class my_button : public button {
public:
my_button() = default;

protected:
void on_click(const event_args& e) override {
button::on_click(e);
message_box::show("Button clicked!");
}
};

class form1 : public form {
public:
form1() {
button1.parent(*this);
button1.text("Button 1");
button1.location({10, 10});
}

private:
my_button button1;
};

auto main() -> int {
application::run(form1 {});
}
See also

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4