• 0
Axbor

Собственный TListBoxItem на C++

Вопросы

Очень не хватает примеров на C++. Решил поделится опытом.

Рассмотрим создание собственного "ListBoxItem"а на C++.

И так начнем.

Для начало создадим стиль для нашего "ListItem"а. В моем случае оно выглядит так:

post-1434-0-35990000-1454700951.png

Структура выглядеть следующим образом:

post-1434-0-95824600-1454700965.png

А вы сразу можете создать собственный стиль.

Создадим класс для нашего "Item"а. Я назвал его TMyListBoxItem.

Нужно знать следующие вещи:

ApplyStyle() вызывается когда стиль загружен.

FreeStyle() когда стиль выгружен.

GetDefaultStyleLookupName() когда стиль не задано берется названые стиля по умолчанию.

FindStyleResource("стиль") ищет в стиле ресурс с заданным названием.

 

ListBox автоматически очищает из невидимых "Item"ов стиль что бы избежать от расходы на память. И заново загружает когда оно видимо. При этом вызывается соответствующие функции приведенные выше

 

я приведу только некоторые кусочки кода. Остальное всё можете посмотреть в прикреплённых файлах.

class TMyListBoxItem : public TListBoxItem
{
private:
        // Переменные для хранения данных
	System::UnicodeString FTimeTo;
	System::UnicodeString FTimeFrom;
        //....

        // Визуальные компоненты
	TText* FTextTimeTo;
	TText* FTextTimeFrom;
        //...

        // Функции для присваивания данных, это нужно при написании "properties"
	void __fastcall SetTimeTo(const System::UnicodeString Value);
	void __fastcall SetTimeFrom(const System::UnicodeString Value);
protected:
	void __fastcall ApplyStyle();
	void __fastcall FreeStyle();
	System::UnicodeString __fastcall GetDefaultStyleLookupName();
	virtual void UpdateStyleData();
__published:
	__property System::UnicodeString TimeTo = {read=FTimeTo, write=SetTimeTo};
	__property System::UnicodeString TimeFrom = {read=FTimeFrom, write=SetTimeFrom};
public:
	__fastcall TMyListBoxItem(System::Classes::TComponent* AOwner);
};

Теперь напишем сами функции.

void __fastcall TMyListBoxItem::ApplyStyle()
{
       // Вызов метода предка
	TListBoxItem::ApplyStyle();
	TFmxObject *StyleObject;
    // Поиск ресурса из стиля. Посмотрите в скрине, там есть ресурс с названием "timeto" типа TText
	StyleObject = FindStyleResource("timeto");

       // dynamic_cast нужен для корректного преобразования типов. Если тип найденного ресурса не является TText то указателю будет присвоен NULL
	FTextTimeTo = dynamic_cast<TText*>(StyleObject);

	StyleObject = FindStyleResource("timefrom");
	FTextTimeFrom = dynamic_cast<TText*>(StyleObject);

	UpdateStyleData();
}

void __fastcall TMyListBoxItem::FreeStyle()
{
       // Стиль выгружен из памяти. Нужно очистить указатели что бы избежать ошибок
	FTextTimeTo = NULL;
	FTextTimeFrom = NULL;

	TListBoxItem::FreeStyle();
}

System::UnicodeString __fastcall TMyListBoxItem::GetDefaultStyleLookupName()
{
    // название стиля для нашего "Item"а по умолчанию
	return "mylistboxitemstyle";
}

void TMyListBoxItem::UpdateStyleData()
{
	if(FTextTimeTo)
		FTextTimeTo->Text = FTimeTo;
	if(FTextTimeFrom)
		FTextTimeFrom->Text = FTimeFrom;
}

void __fastcall TMyListBoxItem::SetTimeTo(const System::UnicodeString Value)
{
	FTimeTo = Value;
	if(FTextTimeTo)
		FTextTimeTo->Text = FTimeTo;
}

Вот и всё. Остается только добавит в наш проект ListBox и button для проверки.

Вот функция создания нашего "Item"а:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
	TMyListBoxItem *Item = new TMyListBoxItem(this);
	Item->Parent = ListBox1;
	Item->StyleLookup = "customstyle1";
	Item->TimeFrom = "11:20";
	Item->TimeTo = "12:50";
}

Скриншот программы:

post-1434-0-12060700-1454703141_thumb.pn

В архиве мой класс и стиль. Для корректного отображения некоторых символов нужен fontcustom

Какие вопросы задавайте. Отдельное спасибо Ярославу за мануал на дельфи: 

http://blogs.embarcadero.com/yaroslavbrovin/2012/10/15/listboxitem_styling_part2/

Администраторы и модераторы, прошу подкорректировать если что то неправильно.

ListBoxItem.zip

Изменено пользователем Axbor

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

9 ответов на этот вопрос

  • 0

Было бы круто если такой подход подойдет и для ListView.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Было бы круто если такой подход подойдет и для ListView.

увы такой же не сделать

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

имхо можно это же оформить процедурно для ListItem

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Всем доброго времени суток.

А где на Delphi проект найти. По указанной ссылке не доступен...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Добрый день.  Может быть кто-то подскажет: айтемы создаются без соблюдения размеров стиля. То есть все поля съезжаются в кучу и толщина айтема равна стандартной. КТо-нибудь сталкивался? 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
В 05.02.2016 в 23:34, Axbor сказал:

Было бы круто если такой подход подойдет и для ListView.

UP. (предыдущее сообщение)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

При применении стиль всегда растягивается по размеру контрола, а не наоборот. Если вы хотите, чтобы у вас всегда был фиксированный размер, то в стиле используйте FixedWidth, FixedHeight.

Если вы не хотите фиксировать размер итема, а лишь задать дефолтный размер, то переопределите в классе итема метод GetDefaultSize, в котором верните желаемый размер.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти

  • Похожий контент

    • От Макс Войтенко
      var Keyboard: IFMXVirtualKeyboardService; begin if TPlatformServices.Current.SupportsPlatformService( IFMXVirtualKeyboardService, IInterface( Keyboard ) ) then if TVirtualKeyboardState.Visible in Keyboard.GetVirtualKeyBoardState then ShowMessage( 'клавиатура открыта' ) else ShowMessage( 'клавиатура скрыта' ); end; ТАК Я на шел для делфи. Но мне нужно для C++
    • От Pulsarius
      Здравствуйте, Ярослав! Скажите, пожалуйста, есть ли какая либо информация о планах поддержки Linux в C++ Builder? Нашей компании очень подходит RAD Studio для наших целей и быстрой разработки. Планируем приобрести лицензию. В ближайшее время планируем разрабатывать наше решение для Windows, macOS и Android, пока этого достаточно. Но есть некоторые сомнения о выборе RAD Studio и всё из-за того, что примерно через год потребуется наше решение реализовать и для Linux. Какова вероятность, что C++ Builder обзаведётся поддержкой Linux'а в течении 1 - 1,5 года? Delphi не рассматриваем. Заранее спасибо за ответ.
    • От Pulsarius
      Здравствуйте! Очень нужна помощь с TIdTCPServer или возможно моя задача решается каким-то другим компонентом или библиотекой. В общем, мне нужно получить с сокета не только данные, но и весь пакет целиком, т.е. со всеми TCP и IP заголовками. Возможно ли сделать это через TIdTCPServer? Конечно можно на C++ самостоятельно реализовать TCP/IP стек, но не хотелось бы терять на это время и "изобретать велосипед" в очередной раз. А конкретнее мне нужно получить весь TCP/IP пакет с заголовками и данными, запаковать его ещё в PPP и отправить на COM порт, чтобы добиться некого аналога виндового стандартного телефонного модема (Dial In). Буду благодарен за какую-либо помощь!
    • От Pulsarius
      Всем привет! Кто-нибудь может подсказать как можно удалить ссылку в проекте на неиспользуемую статичную либу, чтобы она не линковалась к исполняемому файлу? Обыскал всё в настройках проекта, так и не смог найти. Дело в том, что я как-то в FMX проекте использовал невизуальный VCL компонент, добавленный через дизайнер форм. Потом я его удалил, но линковщик всё равно линкует в exe-шник библиотеки типа vcl.lib, vclx.lib, что абсолютно напрасно увеличивает размер исполняемого файла.
    • От Pulsarius
      Здравствуйте!
      Может кто-нибудь уже проходил через подобное и знает как это реализовать и подскажет. Мне нужно программно создать виртуальный модем и входящее подключение через него. Ну или хотя бы через командную строку. Пробовал через RAS API, но получается не то, что мне нужно. Вот визуализация того, что мне нужно проделать:
       
    • От MolarMak
      Всем доброго времени суток, столкнулся с такой проблемой, на определенной форме включается медиаплеер и начинает проигрывать определенный трек, но при блокировке трек продолжает играть. Как обработать событие блокировки экрана и по нему отключать медиаплеер? Пишу на c++ builder.
      Пробовал делать через EnteredBackground, руководствовался заметкой по написанию подобного на Delphi xe http://delphifmandroid.blogspot.com/2013/10/blog-post.html
      Возможно есть другие варианты решения?
    • От SerhioUser
      Всем доброе время суток.
      Делаю "универсальный" компонент для обоих библиотек на C++ Builder. Наследник от TComponent.
      Функционал компонента НЕ зависит от визуальной библиотеки и весь код прописывается в одном файле.
      Попробовал создать 2-а пакаджа. В каждом из них создал пустой компонент, каждый под свою платформу. Имя у компонентов одинаковое. 1-ый пакадж установился, 2-ой нет. Студия сказала, что компонент с таким именем содержится в 1-ом пакадже.
      Вопрос: как правильно создать пакаджи, чтоб компонент был доступен и для VCL-форм и для FMX-форм и имел одинаковое имя?
      Например UniDac компоненты видны для обоих библиотек и имеют одинаковые имена и для VCL и для FMX.
    • От Platon
      Делаю кросс-платформенное прилоежние - на Android работает, на Windows: not such table
      Как сделать так, чтобы на других ПК работало приложение с БД? 

    • От Tarik02
      Возможно ли использовать лямбда-выражения в C++ Builder XE7? Если да, то как?
    • От Tarik02
      Я работаю на Rad Studio XE7 C++ builder.
      Нужно загрузить obj-модель в TModel3D из TStream, или из файла, но когда вызываю LoadFromFile, модель стает пустой(если там загружена модель в Design Time). Как решить эту проблему?
  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу