WxWidgets Hello World в Visual C++ и wxFormBuilder

Материал из Викиучебника — открытых книг для открытого мира
Перейти к навигации Перейти к поиску

Cоздаем приложение "Привет, Мир!" в VC++ 2015 и ФормБилдере[править]

Вступление[править]

Прежде чем начать этом урок, следует отметить, что он описывает один из наиболее простых способов знакомства с wxWidgets с нуля, при котором вы не просто открываете готовый (и часто непонятный) пример, а создаете свой код. Однако, дальнейшее использование wxFormBuilder предполагает наличие у вас знаний языка C++, в частности понимания наследования классов. Кроме того, рано или поздно вы столкнетесь со ограниченностью возможностей формбилдера и необходимостью написания части кода GUI вручную, либо использования более функциональных конструкторов GUI вроде wxSmith (Code::Blocks) или wxDev-C++.

В wxDev-C++ создать Hello World можно даже меньшими усилиями, однако проект не развивается с 2012 года. Пример создания приложения при помощи wxSmith в Code::Blocks можно найти здесь: Уроки wxSmith: Hello world. Code::Blocks тоже притормозил развитие и поддерживает компиляторы Visual C++ лишь до VS 2010. Это накладывает свои ограничения на применение вышеупомянутых конструкторов GUI и позволяет wxFormBuilder в некоторых случаях конкурировать с ними.

wxFormBuilder позволяет генерировать (и при правильном использовании дорабатывать) код графического интерфейса в проектах Visual Studio современных версий, что позволяет использовать всю мощь современных компиляторов, в частности: совместимость с новыми версиями библиотек, векторизацию и распараллеливание кода, одним словом дает возможность создания современных программ для многоядерных процессоров и гетерогенных вычислений, что "не по зубам" древним компиляторам.

Примечание:

Хорошей альтернативой описанному ниже способу создания графического интерфейса является использование в качестве библиотеки Qt и конструктора GUI Qt Creator, благо их развитие идет динамичнее, чем развитие wxWidgets, Qt имеет средства интеграции в Visual Studio, Qt активнее используют в коммерческих проектах. Однако wxWidgets более компактна (с проистекающими последствиями), а также более лояльна к коммерческому использованию, поэтому интереснее для небольших проектов, где разработчики не могут позволить себе приобретение дорогостоящих средств разработки, но хотели бы коммерциализировать свой проект, не обладая уверенностью, что он будет успешен в денежном выражении.

Итак, какой бы мотивацией вы не руководствовались, начнем наш урок.

Что потребуется:[править]

  • Visual Studio Community 2015 (далее VS), с установленными компонентами:
    • Visual C++
    • Windows SDK
  • wxFormBuilder
  • wxWidgets версии 3.0 или выше

Настройка среды разработки[править]

Можно использовать другую версию VS, но возникнут некоторые отличия в сборке библиотек wxWidgets. В VS 2015 это делается очень просто. Вместо VS можно также использовать компилятор Visual C++ с командной строки или свободный компилятор MinGW, однако это тоже усложнит задачу. Кроме того, если использовать wxWidgets версии 2.8 можно собрать проект даже на очень древних компиляторах (например от Borland) благо разработчики wxWindows позаботились об этом.

Вкратце об установке вышеуказанных программных продуктов:

  • VS нужно скачать c официального сайта и при установке указать необходимые компоненты;
  • wxFormBuilder последней версии можно найти на GitHub, жмем [Clone or download]->[Download ZIP]. Создаем каталог wxFormBuilder (например в корне диска C:) заливаем в него содержимое архива;
  • wxWidgets качаем с официального сайта в виде "Windows Installer", устанавливаем (лучше всего в место с не слишком длинным путем и обязательно без русских букв).

Далее нужно собрать библиотеки wxWidgets:

  • в подкаталоге библиотеки wxWigdets .\build\msw запускаем wx_vc14.sln
  • в открывшемся проекте открываем пункт меню [Build]->[Batch Build...]
  • выбираем всё [Select All], жмем [Build]
  • ждем завершения процесса сборки (достаточно долгого - можно вполне успеть приготовить и попить кофе с плюшками) и если всё завершится хорошо, то в логе будет что-то вроде "Build: 192 succeeded, 0 failed, 0 up-to-date, 0 skipped".

Если вы решили пойти более сложным путем и выбрали другой компилятор, то, возможно, вам поможет страничка Настройка wxWidgets в Code::Blocks, там описан процесс сборки wxWidgets c командной строки.

Создание приложения[править]

Итак, приступим к созданию нашего суперприложения. Открываем VS и создаем новый проект [File]->[New]->[Project...].

Visual Studio 2015 creating new project .png

В открывшемся окне выбираем [Installed]->[Templates]->[Visual С++]->[Win32]->[Win32 Project]. Даем проекту имя, например "wxHello".

Visual Studio 2015 new win32 project .png

В открывшемся окне мастера "Overview" жмем Next. Откроется окно настроек проекта "Application Settings". В окне ставим галочку Empty project" чтобы создать пустой проект. Остальные настройки - по умолчанию. Завершаем работу мастера нажатием [Finish].

Visual Studio 2015 new win32 empty project .png

В обозревателе созданного проекта делаем правый клик на название проекта (wxHello). В открывшемся меню жмем на [Add]->[New Filter]. Даем ему название GUI. Здесь будут ссылки на файлы wxFormBuilder.

Visual Studio 2015 adding new filter.png

Делаем правый клик на папке GUI. Далее [Add]->[Existing Item...].

Visual Studio 2015 adding existing item.png

В открывшемся окне создаем папку GUI. Здесь будет храниться проект GUI и код его элементов.

WxHello new folder.png

Далее нажимаем пока что [Отмена] и сворачиваем Visual Studio.

Создание пользовательского интерфейса[править]

Открываем wxFormBuilder, будет создан проект по умолчанию. Дадим ему имя (name) gui и такое же значение свойству file.

WxFormBuilder new project name.png

Теперь сохраним проект в папку GUI, которую мы создали в Visual Studio. Она находится в Документы->Visual Studio 2015->Projects->wxHello->wxHello ([User Directory]\Documents\Visual Studio 2015\Projects\wxHello\wxHello). Дадим файлу проекта название gui (gui.fbp). Сохраняем.

WxFormBuilder Save Project.png

В панели компонентов (Component Palette) выбираем вкладку Forms. На ней жмем иконку Frame. Будет создан фрейм (форма). Дадим ей имя frmMain

WxFormBuilder Add Frame.png

Теперь перейдем во вкладку Layout и нажмем на первую по счету иконку wxBoxSizer. Внутри проектируемой формы появится красная рамочка - это разместитель (sizer). Он будет управлять размещением вложенных в него компонентов на форме (друг над другом).

WxFormBuilder Add Sizer.png

Далее перейдем на вкладку Common и нажмем на иконку Static Text. Внутри разместителя в верхнем левом углу формы появится новый объект wxStaticText "MyLabel". Изменим его свойство label на "Hello World!".

WxFormBuilder Add Static Text.png

В разделе sizeritembase распахнем flags и поставим галочку у флага wxALIGN_CENTER. Теперь надпись будет в центре по горизонтали.

WxFormBuilder Align Center.png

Далее в разделе wxWindow распахнем font и увеличим размер шрифта до 30 (или можете ввести свое значение). Надпись изменит свой размер.

WxFormBuilder Change Font Size.png

Пока достаточно. Мы неплохо потрудились над дизайном. Попробуем сгенерировать C++ код GUI нашего приложения.

Откроем пункт меню [File]->[Generate Code].

WxFormBuilder Generate Code.png

Вроде бы ничего не произошло, но, уверяю вас, наш заветный код форм на C++ сформирован и лежит вместе с файлом проекта. Теперь нажмем [Tools]->[Generate Inherited Class].

WxFormBuilder Generate Inherited Class.png

Это формирует файлы отнаследованных классов, с которыми мы будем дальше работать. Обратите внимание, что эта процедура должна производиться только один раз! Иначе код который мы создадим в Visual Studio "затрется" заново сгенерированным.

"Но как же так? Как дальше работать с проектом если всё затирается новым кодом?" - наверняка спросите вы и будете абсолютно правы. Да, затирается, но нужно просто не генерировать в дальнейшем отнаследованные классы, а генеровать лишь код базовых (материнских) классов, при этом дочерние классы унаследуют весь дизайн базовых и наш код на С++, который "неимоверными усилиями" мы будем писать дальше никуда не пропадет.

Закончив с этим, не забудьте нажать [File]->[Save], чтобы сохранить проект. Всё, формбилдер можно закрыть.

Объединяем проекты[править]

Теперь давайте вернемся в Visual Studio.

Сделаем правый клик на нашей созданной с большой тщательностью и любовью папке GUI и вновь выберем в выскочившей менюшке [Add]->[Existing Item...]. (Если забыли как - ищите скриншот выше). Заходим в папку GUI в проекте на диске, выбираем файл gui.fbp и нажимаем [Add].

Visual Studio 2015 Add Existing Item .png

Теперь наш файл gui.fbp добавлен в проект VS. Попробуем его открыть. Делаем на нем правый клик и в выскочившем меню выбираем [Open With...].

Visual Studio 2015 Open With.png

В открывшемся окне жмем [Add] и добавляем наш любимый wxFormBuilder в качестве приложения для таких файлов. Выбираем его в предложенном списке (он будет последним). Нажмите [Set as default] чтобы он запускался автоматически.

Visual Studio Open With Default.png

Теперь закройте это окно с выбором приложения. Дважды кликните на gui.fbp. Должен открыться наш проект GUI в wxFormBuilder.

Далее аналогично добавлению в проект файла gui.fbp добавим все файлы с расширением .h в "Header Files", а с расширением .cpp в "Source Files". Результат должен выглядеть примерно так:

Visual Studio 2015 Files Added.png


Создаем код приложения[править]

Теперь нам нужно создать файлы приложения. Создаем в Header Files файл HelloApp.h - постарайтесь сами разобраться, как это сделать. Добавляем в него следующий код (объявление класса нашего приложения):


#ifndef HELLOAPP_H
#define HELLOAPP_H

#include <wx/wx.h>

class HelloApp : public wxApp {
public:
	HelloApp();
	virtual ~HelloApp();
	virtual bool OnInit();
};

DECLARE_APP(HelloApp)

#endif


Создаем в Source Files файл HelloApp.cpp , добавляем в него следующий код (определение класса нашего приложения):

#include "HelloApp.h"
#include "gui/guifrmMain.h"

IMPLEMENT_APP(HelloApp)

HelloApp::HelloApp() {
}

HelloApp::~HelloApp() {
}

bool HelloApp::OnInit() {
	guifrmMain* frame = new guifrmMain((wxWindow*)NULL);
	frame->Show();
	SetTopWindow(frame);
	return true;
}

Подключение wxWidgets к проекту и сборка приложения[править]

Теперь нужно настроить компилятор, чтобы он видел заголовки библиотеки wxWidgets. Открываем пункт меню [Project]->[wxHello Properties...]. Выбираем в списке Configuraton: "All Configurations". Ищем внизу VC Directories и добавляем в Include Directories пути "C:\wxWidgets-3.1.2\include;" и "C:\wxWidgets-3.1.2\include\msvc;" (или где там у вас на диске лежит библиотека wxWidgets - нужно "плясать" от нее)

Visual Studio 2015 VC++ Directories.png

Если вернуться к проекту и попробовать его собрать [Build]->[Build Solution], то можно увидеть, что красные волнистые линии (ошибок в коде) пропали, но он всё еще не собирается из-за ошибки линкера:"Error LNK1104 cannot open file 'wxbase31ud.lib' ". Нужно добавить ссылку на каталог с файлами .lib

Снова открываем пункт меню [Project]->[wxHello Properties...]. На этот раз добавляем в Library Directories путь "C:\wxWidgets-3.1.2\lib\vc_lib;" (с возможной поправкой на ваш путь к библиотеке wxWidgets). Теперь снова запускаем [Build]->[Build Solution] и программа должна собраться: "Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped".

Финал[править]

Жмем кнопку с зеленым треугольником или нажимаем [F5] на клавиатуре и видим работающее приложение:

WxFormBuilder Visual Studio 2015 Hello World.png

Всё, урок закончен. Надеюсь, вы удовлетворены проделанной работой.

Дополнение[править]

А давайте проверим, что будет если мы напишем какой-то код, а затем доработаем дизайн формы.

Откроем файл HelloApp.cpp и вставим в конструктор формы команду, которая изменит надпись на "Hello".

#include "guifrmMain.h"

guifrmMain::guifrmMain( wxWindow* parent )
:
frmMain( parent )
{
	m_staticText1->SetLabel(_("Hello"));
}

Запускаем программу и видим:

VS2015 wxHello form constructor result.png

Теперь дважды кликнем gui.fbp и будем редактировать интерфейс в wxFormBuilder. Для начала выберем в дереве проекта (Object Tree) разместитель bSizer1. Открываем панель Common добавим в наш разместитель кнопку (wxButton).

WxFormBuilder Add Button.png

Выделим на форме нашу кнопку. Далее в верхней панели инструментов кликаем кнопки [Expand] и [Stretch]. Видим, что свойство prortion стало равно 1, а wxExpand пометилось галочкой. Добавленная нами кнопка при этом стала занимать всё доступное оставшееся место внутри разместителя.

WxFormBuilder Resize Button.png

Сделаем в нашей программе обработчик какого-нибудь события, например нажатия добавленной нами кнопки. Зайдем в её свойствах на вкладку Events и зададим свойство OnButtonClick равным MyButtonClick. Сгенерируем код формы и перейдем в Visual Studio.

WxFormBuilder Add Handler.png

Попробуем запустить программу, она при этом заново пересоберется.

WxHello with button.png

Как мы видим, наш код в конструкторе формы (пишущий "Hello") продолжает работать, но появилась и кнопка, которую мы добавляли в разместитель. Нажмем на кнопку и убедимся, что пока ничего не происходит. Нужно создать код обработчика.

Закрываем наше чудо-приложение и вставляем в guifrmMain.h объявление обработчика MyButtonClick(). Теперь класс guifrmMain выглядит так:

class guifrmMain : public frmMain
{
	public:
		/** Constructor */
		guifrmMain( wxWindow* parent );
	//// end generated class members
		void MyButtonClick(wxCommandEvent& event);
};

Вставляем в guifrmMain.cpp определение обработчика MyButtonClick():

void guifrmMain::MyButtonClick(wxCommandEvent& event)
{
	m_staticText1->SetLabel(_("Hello!"));
}

Запускаем.

WxHello with working button handler.png

Теперь при нажатии на кнопку в конце надписи появляется восклицательный знак. Обработчик работает.

На этом всё.

См. также[править]