Начиная с версии 3.0, библиотека WxWidgets разрабатывалась для использования совместно с юникодными строками.
1. Создаем пустой C++ проект.
Запускаем MS VS 2022, выполняем: меню - File - New - Project - Windows Dectop Wizard - Windows Dectop Wizard.
Указываем имя проекта: WxEmpty, жмем кнопку ОК:
2. Настройка пустого проекта.
2.1 Настраиваем стандарт языка C++, кодировку строк и сбрасываем "бит консольности".
Во вкладке "Solution Explorer" выбираем проект WxEmpty, в свойствах проекта выбираем конфигурацию "All configurations", платформа - "All platforms", в разделе Configuration Properties выбираем подраздел General, задаем C++ Language Standard: ISO C++20 Standard (/std:c++20); в свойствах Advanced выбираем Character Set и указываем значение Use Unicode Character Set. В свойствах Linker-Sytem-SubSystem выбираем Windows (/SUBSYSTEM:WINDOWS).
2. Настройка пустого проекта.
2.1 Настраиваем стандарт языка C++, кодировку строк и сбрасываем "бит консольности".
Во вкладке "Solution Explorer" выбираем проект WxEmpty, в свойствах проекта выбираем конфигурацию "All configurations", платформа - "All platforms", в разделе Configuration Properties выбираем подраздел General, задаем C++ Language Standard: ISO C++20 Standard (/std:c++20); в свойствах Advanced выбираем Character Set и указываем значение Use Unicode Character Set. В свойствах Linker-Sytem-SubSystem выбираем Windows (/SUBSYSTEM:WINDOWS).
2.2 Добавляем страницу свойств wxwidgets.props
Во вкладке "Solution Explorer" выбираем проект WxEmpty, далее выполняем: меню - View - Property Manager, появляется окно Property Manager. Выбираем проект WxEmpty, разворачиваем его. Удерживая клавишу Ctrl, выделяем две конфигурации Win32 (Debug и Release), щелкаем по выделению правой кнопкой мыши, выбираем пункт Add Existing Project Propery Sheet. выбираем wxwidgets.props в директории D:\Cpp\Lib, жмем кнопку Открыть.
Во вкладке "Solution Explorer" выбираем проект WxEmpty, далее выполняем: меню - View - Property Manager, появляется окно Property Manager. Выбираем проект WxEmpty, разворачиваем его. Удерживая клавишу Ctrl, выделяем две конфигурации Win32 (Debug и Release), щелкаем по выделению правой кнопкой мыши, выбираем пункт Add Existing Project Propery Sheet. выбираем wxwidgets.props в директории D:\Cpp\Lib, жмем кнопку Открыть.
2.3 Добавляем файлы main.cpp и pch.h.
Добавляем упомянутые файлы, в pch.h вводим:
#pragma once
vc
В main.cpp вводим:
#include "pch.h"
class wx_main : public wxApp
{
public:
virtual bool OnInit() { return true; };
};
wxIMPLEMENT_APP(wx_main);
Для файла main.cpp определяем Precompiled Header как "Create/Yc", pch.h:
... в принципе, precompiled header можно задать и для всего проекта. И отключать данную опцию для файлов, где сие не нужно (например, с библиотечными утилитами).
3. Компилируем.
Данное приложение можно экспортировать как шаблон: Project - Export Template... Перед экспортом, в состав проекта следует включить файл страницы свойств D:\Cpp\Lib\wx\wxwidgets.props, создаваемые на основе приложения не будут ссылаться не страницу свойств.
4. Добавляем формы wxFormBuilder.
Файл проекта wxFormBuilder и сгенерированные им файлы разместим в подкаталоге gui.
Для того, чтобы файлы из этого каталога "видели" файл заголовочный файл pch.h, в путь дополнительных каталогов файлов включения (Additional Include Directories) проекта добавим переменную $(ProjectDir):
Запускаем wxFormBuilder, обзываем проект gui_(с подчеркиванием!) , сохраняем файл под именем gui.fbp (без подчеркивания).
Далее задаем имена файлов cpp и h , в которых будут помещаться базовые классы фреймов wxWidgets. Имя задается в свойстве file проекта fbp. Также включаем опцию use_microsoft_bom и задаем значение свойства precompiled_header как #include "pch.h".
На сайзере szrRight размещаем кнопку wxButton. Задаем свойства кнопки:
- wxButton.name: btn_addData;
- wxAnyButton.label: Добавление данных.
На сайзере szrLeft размещаем грид wxGrid, который именуем как grMain.
Настройка грида grMain.
Задаем свойства:
- name: grMain;
- Grid.rows: 0;
- Grid.cols: 1;
- Grid.editing: false;
- Columns.columns_sizes: 80, 330;
- Columns.col_label_values: "Время" "Событие";
- Columns.col_label_horiz_alignment: wxALIGN_LEFT;
- Rows.row_label_size: 0;
- sizeritem.proportion: 1:
- sizeritembase.flag: wxALL, wxExpand
Должна получиться вот такой фрейм:
Генерация базовых классов.
В wxFormBuilder жмем кнопку Generate Code (F8). В подкаталоге gui появляются два файла: gui.cpp и gui.h. При изменении fbp - проекта и последующей перегенерации кода, эти файлы всякий раз создаются заново, поэтому редактировать их не стоит: перегенерация похерит все изменения. Настройка фреймов будет выполняться в классах - наследниках. Выполним генерацию классов-наследников, нажав клавишу F6.
Следует установить "галку" возле имени фрейма и, если нужно, изменить имя самбкласса и/или имя файлов cpp/h. Для редактирования следует кликнуть мышкой справа от имени фрейма.
Видим, что имя формируется из имени fbp проекта "gui_" и имени базового класса "frmMain", то есть, символ подчеркивания в имени fbp проекта был нужен для отделения префикса "gui" от имени базового класса.
Проект cpp должен собираться без ошибок.
Отображаем фрейм.
Модифицируем main.cpp:
#include "pch.h"
#include "gui/gui_frmMain.h"
class wx_main : public wxApp
{
public:
virtual bool OnInit() {
auto * frmMain = new gui_frmMain((wxWindow *) nullptr);
frmMain->Show();
SetTopWindow(frmMain);
return true;
};
};
wxIMPLEMENT_APP(wx_main);
Наполнение грида.
В гриде будут отображаться различные сообщения.
Грид wsGrid может работать с различными источниками данных. Создадим собственный источник, реализовав наследник "почти абстрактного" класса (см. wxGridTableBase: https://docs.wxwidgets.org/3.1.5/classwx_grid_table_base.html).
Данные будут храниться в контейнере типа deque, элемент данных - пара "время, строка":
using data_row_type = std::pair<time_t, std::wstring>;
Добавляем в cpp-проект класс ds_logo.
ds_logo.h:
#pragma once
#include "pch.h"
#include "wx/generic/grid.h"
#include <deque>
using data_row_type = std::pair<time_t, std::wstring>;
class ds_logo :
public wxGridTableBase
{
public:
~ds_logo() { delete data; };
int GetNumberCols() override { return 2; }
int GetNumberRows() override { return data->size(); }
wxString GetValue(int row, int col) override;
void SetValue(int row, int col, const wxString& value) override {}; // Read-only
wxString GetColLabelValue(int col) override;
bool IsEmptyCell(int, int) override { return false; }
void Clear() override { data->clear(); }
void push_back(const std::wstring& text); // Дополнительный метод для заливки данных
private:
std::deque<data_row_type>* data = new std::deque<data_row_type>;
};
ds_logo.cpp:
#include "pch.h"
#include "ds_logo.h"
wxString ds_logo::GetValue(int row, int col)
{
wxString result;
auto& data_row = data->at(row);
switch (col)
{
case 0:
{
auto dt = data_row.first;
tm* ltm = std::localtime(&dt);
wchar_t mbstr[100];
std::wcsftime(mbstr, 100, L"%d-%m-%Y %T", ltm);
std::wstring dateAjoutSysteme(mbstr);
result = mbstr; // dateAjoutSysteme;
break;
}
case 1:
{
result = data_row.second;
break;
}
}
return result;
}
wxString ds_logo::GetColLabelValue(int col)
{
switch (col) {
case 0: return L"Время";
case 1: return L"Событие";
default: return L"";
}
}
void ds_logo::push_back(const std::wstring& text)
{
if (data->size() >= 11000)
data->erase(data->begin(), data->begin() + 1000);
data->push_back({ std::time(0) ,text });
auto grid = GetView();
wxGridTableMessage msg(this, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1);
grid->ProcessTableMessage(msg);
grid->SelectRow(data->size() - 1);
grid->ScrollLines(data->size());
grid->ShowRow(data->size() - 1);
grid->ForceRefresh();
}
В производном классе реализованы: деструктор ~ds_logo(), а также перекрыты методы GetNumberCols(), GetNumberRows(), GetValue(), SetValue(), IsEmptyCell(), GetColLabelValue( ) и Clear(), а также добавлен метод push_back(const std::wstring& text) - для заливки отображаемых данных.
Обработка события "Нажатие кнопки".
В дизайнере wxFormBuilder выбираем кнопку btn_addData, открываем закладку Events и для события wxButton.OnButtonClick задаем значение btn_addData_click. Жмем кнопку F8(генерация кода базовых классов).
В файле gui.h появились строки:
// Virtual event handlers, override them in your derived class
virtual void btn_addData_click( wxCommandEvent& event ) { event.Skip(); }
Т.е., в производном классе gui_frmMain следует переопределить виртуальный метод btn_addData_click. Сделаем это.
gui_frmMain.h:
#ifndef __gui_frmMain__
#define __gui_frmMain__
/**
@file
Subclass of frmMain, which is generated by wxFormBuilder.
*/
#include "gui.h"
//// end generated include
/** Implementing frmMain */
class gui_frmMain : public frmMain
{
public:
/** Constructor */
gui_frmMain( wxWindow* parent );
//// end generated class members
protected:
void btn_addData_click(wxCommandEvent& event) override;
};
#endif // __gui_frmMain__
gui_frmMain.cpp:
Комментариев нет:
Отправить комментарий