Начало Работы


В этом небольшом уроке мы объясним обычный процесс создания приложений в Visual Studio 2017(Вы можете использовать другие версии однако весь процесс остается прежним) с помощью фреймверка Nitisa и Конструктора Форм. Он не займет больше 30 минут. После завершения этого урока Вы будете знать как использовать фреймверк и сможете легко создавать потрясающие приложения.



Настройка проекта

Этот параграф описывает создание проекта используя Nitisa установленный как расширение Visual Studio. Если Вы пользуетесь скачанным исходным кодом(Вы загрузили Nitisa со страницы загрузки нашего портала), Вы можете пропустить этот параграф и перейти к следующему.

С Nitisa, установленным как расширение Visual Studio, процесс создания проекта невероятно прост. Все что нужно, это запустить Visual Studio, выбрать Project... в меню File->New, перейти к элементам в Visual C++, выбрать один из доступных шаблонов проектов Nitisa, придумать имя и расположение для проекта и кликнуть на кнопке OK. Ниже Вы можете увидеть как создать проект Nitisa для операционной системы Windows.

Создание проекта в Visual Studio с установленным расширением Nitisa

Шаблоны проектов Nitisa создают проекты готовые к компиляции. Это означает, что проект сразу можно скомпилировать и запустить и в результате Вы увидите пустую форму. На скриншоте ниже Вы можете видеть как проект выглядит сразу после создания. Все необходимые файлы, которые создаются руками как описано в следующем параграфе, описывающим использование фреймверка в виде скачанного исходного кода, создаются автоматически.

Создание проекта расширением Nitisa

Настройка проекта при использовании скачанных исходных текстов фреймверка

Этот параграф описывает создание проекта в случае использования скачанного исходного кода фреймверка. Если Вы используете расширение Nitisa для Visual Studio, Вы можете пропустить чтение этого параграфа, однако мы рекомендуем прочитать его в любом случае, чтобы лучше понять что шаблоны проектов Nitisa в действительности делают, когда Вы создаете проекты используя установленное расширение.

В самом начале создайте новое консольное приложение Windows в Visual Studio. Почему консольное? В принципе, конечно же Ваше приложение будет иметь графический интерфейс, не консольный. Мы выбрали тип консольного приложения только в целях отладки. Так как у него есть консольное окно в которое можно легко выводить любую отладочную информацию. В дейтвительности у нас не будет никакого отладочного вывода в этом приложении и Вы можете спокойно использовать Windows Desktop Application. Для нас между ними нет разницы никакой кроме главной функции и даже более того Вы можете менять тип проекта в любое время. Например, Вы можете использовать консольное приложение в отлодочных сборках и десктопное в финальных сборках.

Создание проекта в Visual Studio

Замечание: Шаблон Nitisa project создает Windows Desktop Application.

Как только Вы создали проект, добавьте файл main.cpp. Вам нужно сначала удалить все файлы из проекта если он не пустой по умолчанию(не забудте так же удалить stdafx.h из настроек проекта если он там был).

Кдалите предкомпилированный заголовок(stdafx.h) из проекта Visual Studio

Так что теперь в Вашем проекте должен быть только один файл main.cpp со следующим содержимым.

#include <iostream>

int main()
{
    std::system("pause");
    return 0;
}

Мы добавили одну комманду в функцию main чтобы остановить выполнение перед закрытием приложения и его консоли. Полезно видеть отладочный вывод если он существует. Теперь добавим папки фреймверка в настройки нашего проекта.

Настройка папок в Visual Studio

Замечание: Часть пути с версией, показанная выше, может отличаться если Вы скачали другой выпуск.

Как Вы можете видеть, мы добавили два пути в Include Directories. Первый к папке, в которой находятся файлы фреймверка. Второй - к папке Packages внутри первой. Мы так же добавили путь в Library Directories. Этот путь указывает на папку, в которую компилируются статические библиотеки фреймверка. Если Вы еще не скомпилировали фреймверк, сделайте это сейчас(просто откройте файл решения, выберите Debug x86 режим и начните сборку). Этот шаг не является обязательным и Вы можете подключать файлы фреймверка любым, удобным Вам, способом. То же самое касается линковки со статическими библиотеками фреймверка. Однако мы в будущих пояснениях будем предполагать, что Вы сделали это способом описаным здесь. При сборке фреймверка нужно проверить какие Platform Toolset и Runtime Library используются. Они должны быть одинаковы как для всех проектов фреймверка так и для Вашего приложения.

Мы так же должны установить связывание Runtime Library в статическое как показано ниже.

Настройка связывания с библиотекой времени выполнения в Visual Studio

Дизайн формы

Если Вы используете Nitisa как расширение для Visual Studio, форма автоматически создается за Вас, когда Вы создаете проект приложения Nitisa, и она размещается в папке Forms\Main в Обозревателе Решения и обычно открывается сразу после создания проекта.

В случае использования отдельной версии фреймверка(скачанной с этого сайта), Вам нужно перейти в папку, в которую Вы его распаковали. Найдите там подпапку bin\Windows\x86\ReleaseRT (или bin\Windows\x86\DebugRT, или bin\Windows\x64\ReleaseRT, или bin\Windows\x64\DebugRT; зависит от конфигурации и платформы, которые Вы выбрали при сборке решения). Найдите там приложение FormBuilder.exe (если его нет ни в одной из указанных папок, это значит Вы еще не собрали решение; в этом случае нужно открыть решение проекта, выбрать любую *RT конфигурацию(мы рекомендуем использовать ReleaseRT и платформу x86) и запустить сборку) и запустите его.

Начиная в выпуска 9.0.0 Конструктор Форм так же доступен в не-RT конфигурациях. Это значит, что если Вы соберете решение Nitisa используя любую конфигурицию и платформу x86 или x64, Вы сможете найти FormBuilder.exe в соответствующей папке. Мы рекомендуем использовать RT конфигурацию потому что, если Вы решите создавать свои виджеты и делиться ими, то Вам она все равно понадобиться.

В окне Конструктора Форм Вы можете видеть набор доступных компонентов и элементов управления(которые так же называются виджетами(widgets)) вверху, пустой редактор иерархии слева, редактор свойств с доступными свойствами формы ниже него и пустую форму посредине.

Конструктор Форм

Картинка выше показывает Конструктор Форм скомпилированный как обычное отдельное приложение. Как часть Visual Studio он выглядит и работает так же. Есть только одно отличие. Кнопки New(новая форма), Open(открыть), Save(сохранить) и Save as(сохранить как) недоступны. Вместо них используйте стандартные кнопки и функции Visual Studio.

Кликните на иконке элемента управления Edit в списке виджетов вверху окна Конструктора Форм. После этого кликните на форме в центре. Вот как можно добавить любой элемент управления на Вашу форму.

Добавляем виджет на форму в Конструкторе Форм

После добавления элемента управления он становится выбранным. Вы можете видеть это по окружающей границе в виде небольших квадратиков, которые позволяют перемещать элемент управления, вращать его и изменять его размер.

Есть один небольшой, смещенный относительно других квадратик, как показано на картинке ниже, который используется для контроля вращения.

Элемент управления в Конструкторе Форм

Давайте создадим следующую форму. Вы уже знаете как добавлять элементы управления. Вы можете нажать на элемент управления левой кнопкой мышы и перетащить его в нужное положение. Чтобы изменить размер выбранного элемента управления просто потяните за один из небольших квадратиков окружающих выбранный элемент управления, кроме того, который немного смещен. Он используется для вращения. Вы также можете изменить размер формы перетянув правую или нижнюю ее границу или правый нижний угол. Чтобы удалить элемент управления просто нажмите клавишу Delete на клавиуатуре(сначала нужно кликнуть на элемент управления чтобы выбрать его если он еще не выбран или если Вы кликнули на какой-то другой части Конструктора Форм). Когда элемент управления выделен Вы можете видеть его свойства в редакторе свойств. Можно кликнуть по любому свойству и отредактировать его. Редактирование будет происходить либо прямо в редакторе свойств либо в новом модальном окне(в зависимости от типа свойства). Как Вы можете видеть размеры и положение элемента управления приклеены к сетке, показанной точками на форме. По умолчанию размер сетки составляет 8 на 8 точек для перемещения и размера и 10 градусов для вращения. Чтобы переместить элемент управления на 1 пиксель используйте стрелки на клавиатуре. Чтобы изменить размер на 1 пиксель так же используйте стрелки на клавиатуре и с зажатой клавишей Shift. Поместите на форму элемент управления Label и измените его свойство Caption на Name:(Имя:). Измените свойство Text элемента управления Edit на пустое значение. Добавьте элемент управления Button и измените его Caption на Say hello(Сказать привет). Кликните на пустом пространтсве на форме. Теперь ни один элемент управления не должен быть выбран и Вы можете редактировать свойства самой формы в редакторе свойств. Измените Caption на First Form(Первая Форма) или любое другое какое Вам нравится, измените Name на FirstForm. Хотя редактор свойств позволяет иметь в качестве имен совершенно любые строки(с пробелами и даже символами других языков), Вы должны использовать только правильные с точки срения C++ идентификаторы, так как они будут использоваться в коде.

Первая форма в Конструкторе Форм

Наше первое приложение будет брать имя введенное пользователем в элементе управления Edit и приветствовать его, когда он кликнет по кнопке. Вот почему наша форма выглядит как на картинке ниже. Теперь мы закончили с дизайном формы. Давайте создадим событие для клика по кнопке. Чтобы сделать это, сначала кликните на кнопке на форме, чтобы выбрать ее, после этого перейдите во вкладку Events в секции Properties & Events Конструктора Форм. Вы можете видеть там множество доступных событий. Найдите событие OnClick и сделайте двойной щелчек на пустом пространстве справа от названия события. Когда Вы совершаете двойной щелчек на пустом событии, Редактор Событий создает событие за Вас основанное на именах элемента управления и события. Вы можете отредактировать его если Вам не нравится сгенерированное.

Создание события в Конструкторе Форм

Если Вы создаете проект с помощью расширения Nitisa, тогда первая форма создается автоматически и размещается в подпапке Forms\Main и носит название FormMain. Так что в последующем повествовании Вам лишь нужно изменить пути чтобы справиться с этим различием. Так же можно оставить имя формы по умолчанию или переименовать файл FormMain.nfr в FirstForm, как описано далее, используя Обозреватель Решения Visual Studio.

Мы закончили с формой. Теперь сохраните файл формы в той же папке, где находится файл main.cpp. Чтобы сделать это, кликните на кнопке Save или Save as в левой верхней части окна Конструктора Форм. На этих кнопках изображения дискет. В качестве имени файла введите FirstForm. Когда Вы сохраняете форму, Конструктор Форм на самом деле создает два файла. Первый с указанным именем и расширением .nfr содержит форму в json формате. Вы в дальнейшем можете открыть этот файл и продожить работу над формой. Название второго файла производится из имени формы только содержит букву I в начале, а так же его расширение .h. Это файл с прототипом формы. Вы будете использовать его при создании Вашей формы в приложении.

Если Вы используете расширение Nitisa для Visual Studio и работаете с Конструктором Форм интегрированным в Visual Studio, Вы можете работать с файлами форм абсолютно таким же образом как Вы работаете с заголовочными файлами и файлами с кодом. При открытии такого файла в Обозревателе Решения он открывается в Конструкторе Форм. Чтобы добавить новую форму, просто воспользуйтесь стандартным способом: выберите добавление нового элемента в проект и выберите в диалоговом окне Nitisa Form в разделе Visual C++ как показано ниже.

Добавление формы Nitisa в Visual Studio

Добавляем форму к проекту

Как упоминалось ранее, теперь у Вас есть прототип Вашей формы в файле IFirstForm.h(помните правила именования файла для прототипа формы и имя, которое Вы дали файлу формы при сохранении). Конструктор Форм создает класс для прототипа формы с именем, которое Вы даете форме при редактировании и добавлением I к нему в начале. В нашем примере это будет IFirstForm. Этот класс так же помещается в пространство имен nitisa::app. Вы можете изменить имя внутреннего пространства имен на любое, какое Вам нужно в окне настроек Конструктора Форм. По умолчанию это пространство имен называется app. Первое пространство имен в примере - это глобальное пространство имен фреймверка. Все во фреймверке находится внутри этого пространства имен и в его дочерних пространствах имен. Давайте создадим заголовочный файл с именем FirstForm.h в нашем проекте и запишем в него следующее содержимое.

#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())
            {

            }
        };
    }
}

В самом начале мы включаем сгенерированный Конструктором Форм файл прототипа нашей формы. Последние два включения добавляют окно и рендер. Каждая форма нуждается в окне на котором она будет рисоваться и рендер, который собственно говоря и выполняет рисование. После этого создаем класс CFirstForm наследуемый от класса прототипа нашей формы IFirstForm. У него есть метод Button1_OnClick, который вызывается когда происходит клик на кнопке. Класс прототипа(IFirstForm в примере) будет содержать виртуальные объявления всех методов для событий так что Вы не забудете реализовать их потому что они все абстрактные и Вы попросту получите ошибку на этапе компиляции о невозможности создать экземпляр абстрактного класса. В нашем простом примере мы просто берем текст из элемента управления Edit и показываем простое модальное окно. Как Вы можете видеть имя элемента управления m_pEdit1, в то время как в Редакторе Свойств в Конструкторе Форм его имя было Edit1. Префикс m_p добавляется по умолчанию. Вы можете изменить это в окне конфигурации Конструктора Форм. На что еще следует обратить внимание, так это на использование строк в юникоде. Весь фреймверк построен на использовании юникода, так что все строковые свойства, аргументы и значения должны быть в виде юникод-строки(префикс L перед строкой). В конце мы добавляем конструктор для нашей формы. Window(окно) - это объект, ответственный за управление окном системы. И renderer(рендер) - это объект, отсветственный за операции рисования. В настоящее время есть несколько реализаций окон и рендеров в Пакете Platform. Существуют универсальные классы для создания окон и рендеров. Они называются CWindow и CRenderer. Итак, при создании формы, мы должны создать окно и рендер и передать их в конструктор родительского класса IFirstForm. Это все что нужно для создания формы. Просто создаете дизайн в Конструкторе Форм, создаете класс наследуемый от прототипа формы сгенерированного Конструктором Форм, реализуете события если существуют и добавляете конструктор, который вызывает родительский конструктор с созданными окном и рендером. Вы не обязаны использовать только те окна и рендеры, которые реализованы в Пакете Platform. Вы так же можете создавать Ваши собственные реализации. О том как реализовать собственные окна и рендеры мы опышем в будущем. Это все, форма готова.

Завершаем приложение

При использовании шаблона проекта расширения Nitisa, файл создается автоматически. Следуйте коментариям в нем, если Вам нужно сделать какие-то изменения.

Если Вы используете отдельно скачанный фреймверк, то осталось только подправить main.cpp. Давайте сделаем это.

#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;
}

Вначале добавляем подключения реализации Application(приложение) из Пакета Platform к реализации нашей формы. После этого добавляем библиотеки к проекту - ядро, Стандартный пакет, пакет Platform и библиотека OpenGL. Нужно линковать со всеми статическими библиотеками, которые используются в проекте. Если у Вас много пакетов, Вам нужно добавлять только библиотеки тех из них, которые содержат используемые в Вашем приложении элементы управления. После этого мы добавили использование пространств имен. Это не обязательно однако упрощает код немного. Это была подготовка и теперь, наконец, реализация функции main. Во первых, нужно объявить переменную для нашей формы. После мы должны создать экземпляр приложения. После этого просто вызываем метод CreateForm() приложения, передаем ему адрес переменной нашей формы и приложение создает саму форму. Далее указываем, что наша форма является главной формой приложения. Указание главной формы приводит к следующему поведению. Все формы, созданные после указания главной, могут быть модальными относительно главной формы. Это означает, что когда Вы вызываете метод ShowModal() формы, которая была создана после указания главной формы, главная форма и остальные зависимые формы станут недоступными и только форма, чей метод ShowModal() Вы вызвали, будет доступна. Другое важное поведение заключается в том, что когда Вы закрываете главную форму, остальные формы уничтожаются автоматически и приложение завершает работу. Последний шаг - это запустить приложение методом Run(). На этом все(последняя строчка просто предотвращает автоматическое закрытие окна консоли после завершения работы приложения). Вкратце, Вам нужно обявить переменную для Вашей формы(или несколько, если у Вас несколько форм), объявить(что равносильно созданию) переменную приложения, создать главную форму, указать что она является главной, создать остальные формы если имеются и запустить приложение. Теперь скомпилируйте проект и запустите его. Вы увидете форму наподобие этой.

Работающее приложение

Если ввести имя в элементе управления Edit и потом нажать на Button(кнопку), Вы увидете приветствие.

Работающее приложение с модальным сообщением