In this small tutorial we explain the usual application creating flow with Visual Studio 2017 (you may use a different version but the entire process remains the same), the Nitisa framework and the Form Builder. It shouldn't take more than 30 minutes. After finishing this tutorial you will know how to use the framework and will be able to create amazing applications easily.
This paragraph describes creating a project using Nitisa installed as a Visual Studio extension. If you use standalone installation (you downloaded Nitisa from downloads page of our portal) you may skip this paragraph and go to the next one.
With Nitisa installed as Visual Studio extension the process of creation a project is really simple. All you need is to run Visual Studio, select Project... in the File->New menu, go to the Visual C++ items, select one of the available Nitisa project templates, select name and location for the project and click on OK. Below you can see how to create Nitisa application project for Windows.
Nitisa project templates create projects ready for compilation. It means you can compile and run it and you will see blank form as a result. On the screenshot below you may see how the project looks after creation. All necessary files, which should be created manually as described in the following paragraph explaining usage the framework in standalone installation, are created automatically.
This paragraph describes creation a project in standalone mode. If you are using Nitisa extension for Visual Studio you may skip reading this paragraph but we recommend to read it anyway to better understand what Nitisa project templates actually do when you create project using installed extension.
First of all create a new Windows console project in Visual Studio. Why console? Well, of course your applications will be graphical, not console ones. We chose console type application for debugging purposes only. It have a console where you can easy output any debug information. Actually there won't be any debug output in this application and you can freely use the Windows Desktop Application type project. There is no any difference except for main function and moreover you can change the project type to console or to desktop when you want. For example, you may use console type in debug builds and desktop type in release builds.
Note: Nitisa project extension creates Windows Desktop Application.
Once you've created a project, add a main.cpp file. You have to remove all files if the project isn't empty by default (don't forget to remove stdafx.h from project settings if it is in the project).
So now your project should only have one file called main.cpp and should have the following content.
#include <iostream>
int main()
{
std::system("pause");
return 0;
}
We have added one command in main function to pause execution before closing the application and its console. It is useful to see debug output if it exists. Now we will add the framework directories to our solution.
Note: Version part of the path shown above can be different if you downloaded another release.
As you can see we have added two directories in Include Directories setting. The first one is to the folder where the framework files are. The second one is the folder Packages inside it. We have also added a path to the Library Directories. This path is pointed to directory where built static libraries of the framework are. If you haven't built it yet, do it now (just open the framework solution, choose Debug x86 mode and start building). This step isn't required and you may include the framework files in you own way, as well as add static libraries to it. But we assume in future explanations you do it in the way described here. When building the framework solution you have to check which Platform Toolset and Runtime Library you use. They should be the same for all the framework projects and your application.
We also have to set Runtime Library linking to static as shown below.
If you are using Nitisa as a Visual Studio extension, a form is created for you when you created Nitisa project application and it is located in the Forms\Main folder in the Solution Explorer and usually is opened right after project creation.
In case of using standalone installation you need to go to the framework installation directory. Find the bin\Windows\x86\ReleaseRT subdirectory there (or bin\Windows\x86\DebugRT, or bin\Windows\x64\ReleaseRT, or bin\Windows\x64\DebugRT; it depends on which configuration and platform you chose when building solution). Find inside FormBuilder.exe application (if there is none in any of the folders it means you didn't build it yet; you have to open the framework solution, choose any *RT configuration (we recommend to use ReleaseRT and x86 platform) and build it) and run it.
Since the release 9.0.0 the Form Builder is also available in non-RT configurations. It means if you built Nitisa solution using any configuration and x86 or x64 platform, you can find FormBuilder.exe in the corresponding folder. We recommend to use RT configuration because if you decide to created and publish your widgets you will need them anyway.
In the Form Builder window you can see a set of available controls and components (which are also called widgets) at the top, an empty hierarchy editor at left, a property editor with available form properties below it and an empty form in the center.
Image above shows Form Builder built as standalone application. As a part of Visual Studio it looks and works the same. There is but one difference. New, Open, Save, and Save as buttons are disabled. Use Visual Studio's corresponding buttons and features instead.
Click on the Edit widget icon at the controls list at the top of the Form Builder window. Then click on the form in center. This is how an any widget could be added to your form.
After you added a widget it becomes selected. You can see some kind of bounding box around it with small squares which allow you to transform the widget and change its position.
There is additional small box shifted a little of others, as shown on the picture below. It's being used for widget rotation.
Lets create a form like following. You already know how to add controls (widgets). You may click on a widget and drag it to the position you want. To change a size of the selected widget just drag one of the bounding squares except for the one which is a little bit shifted from others. This one is for rotation. You can change the form size as well by dragging its right or bottom border or right-bottom corner. To delete a widget just press a Delete key on your keyboard (you should click on the widget first to select it if it's not selected yet or if you have clicked on another parts of the Form Builder). When a widget is selected you see its properties at property editor. You may click on any property and edit it. The editing will be either inline or in a new window (depending on the property type). As you see widget positions and sizes are stuck to the grid shown by dots at the form. By default, grid size is 8x8 pixels for moving and size change and 10 degrees for rotation. To move a widget by 1 pixel instead use a keyboard arrows. To change size by 1 pixel use arrows and hold Shift key. Place on the form a widget called Label and change its Caption property to Name:
. Change the Edit widget property Text to empty. Add a Button widget and change its Caption to Say hello
. Click on the empty space of the form. Now no widget should be selected, and you can edit form's properties in the property editor. Change Caption to First Form
or anyone you like, change Name to FirstForm
. You should use only valid C++ names as they will be in your code.
Our first application will take a name typed by user in Edit widget and great him when he clicks on the button. That is why our form looks like on the picture above. Now we have finished form layout. Let's create an event for clicking on the button. To do this, first of all click on the button on the form to select it, than go to Events tab of Properties & Events section of the Form Builder. You can see a lot of available events there. Find an event called OnClick and double click on empty area at the right of the event name. When you double-click on empty event, the Event Editor creates an event for you based on widget and event names. You may edit the value if you don't like the generated one.
If you created the project using Nitisa extension then the form is placed inside Forms\Main subfolder and called FormMain. So in the following narration you only need to change paths to deal with this difference. You can also leave the form name by default or rename the file FormMain.nfr to the FirstForm as stated below using Solution Explorer of the Visual Studio.
We have finished with the form. Now save the form file in the same folder where you have your main.cpp file. To do it click on Save or Save as button at the left top part of the window of the Form Builder. It has a diskette picture on it. For the file name use FirstForm. When you save a form, the Form Builder actually creates two files. The first one with the name you specified and .nfr extension is the json representation of your form. You can later open such a file and continue working on it. The second file is called the same name you gave the form but with letter I at the beginning and has an extension .h. This file is a prototype of your form. You will use it to create your form in your application.
If you are using Nitisa extension for Visual Studio and work with Form Builder integrated into it, you can work with form files in the same way you work with header/source code files. When you open the file in solution explorer it will be opened in Form Builder. To add a new form, do it in standard way: choose adding new item and Nitisa Form in the dialog under Visual C++ option as shown below.
As mentioned before, now you have your form prototype in IFirstForm.h file (remember the rules of naming the file of form prototype and the name you gave to the form file while saving). The Form Builder creates a class for the form prototype with the name you gave to form in Form Builder and started with I. In our example it's IFirstForm
. It is also placed inside namespace nitisa::app
. You may configure internal namespace to whatever name you like in Form Builder configuration. By default, the namespace is app
. The first namespace is a global namespace of the framework. Everything is placed inside this namespace and namespaces inside it. Let's create a header file called FirstForm.h in our project and put following content in it.
#pragma once
#include "IFirstForm.h"
#include "Platform/Core/Window.h"
#include "Platform/Core/Renderer.h"
namespace nitisa
{
namespace app
{
class CFirstForm : public IFirstForm
{
protected:
void Button1_OnClick(IControl *sender) override
{
Application->Dialogs->Message(L"Hello " + m_pEdit1->getText() + L"!");
}
public:
CFirstForm() : IFirstForm(CWindow::Create(), CRenderer::Create())
{
}
};
}
}
First of all we include a generated by the Form Builder our form prototype file. The last two includes add window and renderer. Each form require window to be drawn on and renderer to perform drawing operations. Then we create a class called CFirstForm
derived from our prototype class IFirstForm
. It has a method called Button1_OnClick
which is called when a click event occurs at button. The prototype class (IFirstForm
in the example) will have virtual declarations of all events so, you won't forget to implement any of them because in the case you miss to add implementation of any event you will get a compile time error about impossibility to instantiate abstract class. In our simple example we just take a text from Edit control and show a simple modal message. As you can see the control name is m_pEdit1
while in Property Editor of the Form Builder its name was Edit1
. The prefix m_p is added by default. You may configure it in the Form Builder configuration window. The other note is about using unicode strings. The framework is unicode based, so every string properties, arguments and values should be in unicode (prefix L before string). At last, we add the constructor to our form. Window is an object which is responsible for managing platform specific window. And the renderer is an object which is responsible for drawing operations. Currently, there are several implementations of windows and renderers in Platform Package. There are universal classes for creating windows and renderers. The names of these two classes are CWindow and CRenderer. So when creating a form we create window and renderer for it and pass it to parent IFirstForm
constructor. That is all you require to create a form. Just design it in the Form Builder, create a class derived from form prototype generated by the Form Builder, implement events if there are, and add a constructor supplying it with a window and a renderer. You shouldn't use the only windows and renderers existing in Platform Package. You may create your own. How to implement your own window and renderer will be discussed in other articles. That is all, the form is ready.
When using Nitisa extension project template, the file is created automatically. Follow comments in it if you want to do some changes.
If you use the framework standalone the only adjusting main.cpp is remained. Let's do it.
#include <iostream>
#include "Platform/Core/Application.h"
#include "FirstForm.h"
#pragma comment(lib, "Nitisa.lib")
#pragma comment(lib, "Standard.lib")
#pragma comment(lib, "Platform.lib")
#pragma comment(lib, "opengl32.lib")
using namespace nitisa;
using namespace nitisa::standard;
using namespace nitisa::app;
int main()
{
CFirstForm *form;
CApplication application;
application.CreateForm(&form);
application.setMainForm(form);
application.Run();
std::system("pause");
return 0;
}
First, add an inclusion of the Application implementation from the Platform Package and our form implementation. Then add the libraries to the project - core, Standard and Platform packages and OpenGL as the Platform package renderers use OpenGL for drawing. You need to link with all static libraries you used in the project. If you have a lot of packages you have to add only those libraries which contains controls you use in your application. After it, we have added usage of namespaces. It is not necessary, but it simplifies a code a little. This was a preparation and now, finally, the main function implementation. First of all we need to declare a variable for our form. Then we must declare and create application instance. After it, just call the application method CreateForm()
supplying it with the form variable to application create our form. Then assign a main form of the application. Assigning main form results in following behaviour. All forms created after assigning a main one could be modal regarding the main one. It means when you call ShowModal()
method of the form, which was created after assigning the main form, the main form and other dependent forms will be disabled and only the form which ShowModal()
you called will be accessible. The other important behaviour is when you close the main form, the other forms will be destroyed automatically and application will shut down. The last step is to run by calling a Run()
method of the application. That's all (the last line just prevent closing the console window after application finish its work). Shortly, you have to declare a variable for your form(s), declare an application and create it, create your main form, set it as main, create other forms if exists, run the application. Now compile and run it. You will see a form like this.
If you type a name into Edit control and then click on Button, you will see a greeting.