Watch, Follow, &
Connect with Us

Fire Monkey - Yaroslav Brovin

FireMonkey. Календарь с подсветкой дней на базе TCalendar без создания нового компонента

В этой статье мы рассмотрим расширение функционала стандартного календаря TCalendar и добавим поддержку раскраски требуемых дней в календаре. Расширение будет продемонстрировано с использованием нового подхода разработки компонента в FireMonkey.

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

Статья базируется на версии RAD Studio Delphi Seattle 10. Для ранних версий она не применима.

Код рабочего проекта: Delphi Seattle XE10

Полная статья доступна здесь

Posted by Yaroslav Brovin on September 15th, 2015 under Firemonkey (RUS) | 3 Comments »


Создание нативных представлений для iOS. TSpinBox и UIStepper. Часть 3

Продолжим рассмотрение нового подхода разработки (1 часть, 2 часть) и в этой статье рассмотрим использование нативных контролов на базе механизма презентаций для iOS. В качестве примера мы превратим TSpinBox в нативный для iOS.

Полная статья доступна здесь

Posted by Yaroslav Brovin on April 15th, 2015 under Firemonkey (RUS) | Comment now »


New approach of development of FireMonkey control "Control — Model — Presentation". Part 2. TEdit with autocomplete

We will continue a subject of the review of new approach on division of a control into the model and presentation described here. And in this article we will consider practical uses of this approach on the example autocompletion of input in TEdit.

Full article is available here

Posted by Yaroslav Brovin on April 9th, 2015 under Uncategorized | 2 Comments »


[XE6, XE7] New approach of development of FireMonkey control “Control – Model – Presentation”. Part 1

I would like to tell you about new approach in components development in Firemonkey,  which is used for visual component, which support several implementation in one platform. We are gonna talk about advantages and opportunities of new approach for creating visual component.

Full article is available here

Posted by Yaroslav Brovin on April 3rd, 2015 under Firemonkey (ENG) | Comment now »


Все о новом подходе разработки компонентов FireMonkey “Контрол – Модель – Презентация”. Часть 2. TEdit с автозавершением

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

Read the rest of this entry »

Posted by Yaroslav Brovin on March 27th, 2015 under Firemonkey (RUS) | 6 Comments »


Все о новом подходе разработки компонентов FireMonkey “Контрол – Модель – Презентация”. Часть 1

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

Read the rest of this entry »

Posted by Yaroslav Brovin on March 25th, 2015 under Firemonkey (RUS) | 1 Comment »


#1. Tips and tricks in FireMonkey

I would like to suggest your set of links about frequent firemonkey questions

1. Logging in Firemonkey on all mobile platforms

Detail reviewing of all methods of logging in FireMonkey for iOS and Android.

2. How to delete control in runtime in mobile platforms with ARC

The method description as it is necessary to delete controls in a run mode taking into account operation of the mechanism of automatic reference counting.

3. Making multi forms for Phone and Pad in FireMonkey

How to make different forms for Phone and tablet devices in Firemonkey.

4. Deploy our resources in mobile application in FireMonkey

All way to include your data files into mobile application (Deployment manager and Project Resources)

5. How to close form on mobile application?

Posted by Yaroslav Brovin on January 28th, 2014 under Firemonkey (ENG) | 2 Comments »


#1. Подборка ссылок по FireMonkey

Вашему вниманию я хочу предоставить подборку полезных ссылок на часто задаваемые вопросы:

1. Средства логирования в FireMonkey

Детальное рассмотрение всех способов логирования в FIreMonkey под Андроид и iOS.

2. Как правильно удалять контролы в RunTime в мобильных платформах под ARC

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

3. Делаем в FireMonkey несколько разных форм отдельно для телефона отдельно для планшетов

Рассматриваем способ использования стандартного механизма выбора форм для разных устройств.

4. Включаем свои файлы и ресурсы в мобильное приложение

Рассматриваются все варианты включения в приложения своих файлов (картинки, графика, медиа и тд) используя менеджер развертывания и встраивание ресурсов через Project Resources.

5. Как правильно закрыть форму на мобильной платформе?

Описание приема корректного закрытия формы на мобильных платформах под ARC.

Posted by Yaroslav Brovin on January 28th, 2014 under Firemonkey (RUS) | 4 Comments »


FireMonkey. Доступ к пикселям TBitmap. Аналог Scanline из VCL.

Добрый день. По скольку одним из частых вопросов по использованию TBitmap в FireMonkey является: "Как мне получить доступ к пикселям TBitmap?". То стоит рассказать про это один раз и помочь разработчикам. А так же ответить на вопрос: "Почему в FMX у TBitmap нету метода SсanLine и причины перехода на Map и UnMap?"

Вопрос: Как мне получить доступ на чтение/изменение пикселей в TBitmap?

Ответ: Для манипуляции с содержимым (точками) в TBitmpa есть два метода: TBitmap.Map и TBitmap.Unmap.

    { Direct access  }
    function Map(const Access: TMapAccess; var Data: TBitmapData): Boolean;
    procedure Unmap(var Data: TBitmapData);

Map - возвращает объект для работы напрямую с точками, информацию о формате пикселей (TBitmapData.PixelFormat), размер изображения в точках (TBitmapData.Width, TBitmapData.Height), размер одного пикселя в текущем представлении точек (TBitmapData.BytesPerPixel).

В качестве параметров функция принимает:

  1. Вид доступа (Чтение - TMapAccess.maRead, запись - TMapAccess.maWrite, чтение и запись  - TMapAccess.maReadWrite). Если вы хотите только прочитать информацию о точках, то используйте вид доступа - TMapAccess.maRead. Это позволит избежать накладных расходов на манипуляцию с данными TBitmap.
И возвращает:
  1. Объект (Data: TBitmapData) содержащий буфер TBitmap и простые методы по манипуляции с буфером.

Получив TBitmapData в вашем распоряжении арсенал по работе с точками, работа непосредственно с буфером памяти TBitmap и мета информация о формате хранения данных TBitmap.

После окончания работы с данными, НЕОБХОДИМО!!! закрыть доступ к данным применив метод TBitmap.Unmap. Иначе результат изменения не отобразится. Вот в принципе и все.

Пример:

var
  M: TBitmapData;
...
  if FBitmap.Map(TMapAccess.maWrite, M) then
    try
      for i := 0 to FColorBitmap.Width - 1 do
        for j := 0 to FColorBitmap.Height - 1 do
          M.SetPixel(i, j, TAlphaColorRec.Red);
    finally
      FColorBitmap.Unmap(M);
    end;
...

Вопрос: Зачем это сделано? Почему нельзя было оставить Scanline в TBitmap, как это сделано в VCL?

Это самый важный вопрос. VCL для хранения и работы с  bitmap изображением использует оболочку над Winapi. В FMX TBitmap это более сложный объект. Так как он должен работать как на всех платформах, так и в разных графических библиотеках. Поэтому прямого доступа к памяти нет, из-за особенностей хранения изображений в разных системах. Где-то мы можем напрямую производить изменение буфера, а где-то нет

Например: в канве GPU работа с битмапом идет через текстуры. Поэтому при вызове метода Map, создается копия буфера. Затем пользователь производит ее модификацию и по методу unmap происходит обновление текстуры новым изображением. Такая же ситуация происходит с использованием канвы D2D под Windows

Надеюсь я пролил свет на работу с буфером битмапа. Если буду вопросы, задавайте. По мере возможности напишу пару статей в формате Вопрос-Ответ.

Posted by Yaroslav Brovin on June 17th, 2013 under Firemonkey (RUS) | 7 Comments »


Часть 3. Разработка компонентов под FMX 2.0. Кликабельная метка

Наконец-то закончилось предрелизное время и теперь можно, отложив все дела, сдать должок - "Кликабельная метка". Здесь можно посмотреть запись с вебинара. Перейдем сразу к делу.

Постановка задачи

Необходимо расширить стандартную метку, известную как "TLabel", добавив возможность открытия ссылки в штатном браузере.

Проблема

Задача довольно классическая и простая с использованием FireMonkey, но имеет один нюанс. В нашем случае мы обязаны мыслить в условиях кроссплатформенности (только для компонентов, имеющих спецефичную функциональность, зависящую от операционных систем - запуск процесса, открытие ссылки и тд.). Метка должна уметь открывать ссылку в любом браузере и под любой, поддерживаемой операционной системе (Win32, Win64, OSX).

Решение

Решение будет состоять из двух частей:

  1. Реализация части компонента не зависящей от операционных систем (вывод текста, настройки, шрифты и тд)
  2. Реализация платформозависимой части (запуск системного процесса на открытие ссылки в браузере)

Общая часть

По сути наш компонент является функциональным расширением существующего компонента TLabel. Поэтому не будем реализовывать метку с нуля, а всего лишь отнаследуемся от TLabel. Назовем наш класс TCustomLinkedLabel.

Дополнительно в наш класс нужно добавить поля для хранения:

  1. Строку с URL - FUrl
  2. Цвет метки, когда ссылка не посещена - FColor
  3. Цвет метки, когда ссылка выделена - FHoverColor
  4. Цвет метки, когда ссылка посещена - FVisitedColor
  5. Флаг, Была ли ссылка посещена? - FVisited

В нашем случае наша метка не требует изменения стиля, поэтому за основу будет взят стандартный стиль. Для этого не забываем переопределить метод TCustomLinkedLabel.GetDefaultStyleLookupName и вернуть название стиля по умолчанию:

function TCustomLinkedLabel.GetDefaultStyleLookupName: string;
begin
  Result := 'labelstyle';
end;

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

procedure TCustomLinkedLabel.DoMouseEnter;
begin
  inherited;
  Cursor := crHandPoint;
  Repaint;
end;
procedure TCustomLinkedLabel.DoMouseLeave;
begin
  inherited DoMouseLeave;
  Cursor := crDefault;
  Repaint;
end;

Теперь перейдем к непосредственно самой отрисовки метки. На не нужно ее рисовать, по скольку это делегируется компоненту TLabel. Но нам необходимо выполнить только задание нужно цвета перед отрисовкой. Для этого в перекрытом методе TCustomLinkedLabel.Paint выполняем задание цвета через TextSettings.FontColor. Это новая структура для задания настроек выводимого текста:

procedure TCustomLinkedLabel.Paint;
begin
  if IsMouseOver then
    TextSettings.FontColor := FHoverColor
  else
  if FVisited then
    TextSettings.FontColor := FVisitedColor
  else
    TextSettings.FontColor := Color;
  inherited Paint;
end;

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

procedure TCustomLinkedLabel.Click;
begin
  if Assigned(FLaunchService) then
  begin
    FLaunchService.OpenURL(Url);
    FVisited := True;
  end;
end;

Вот и все. Теперь можно приступить к платформозависимой части.

Платформозависимая часть

Все платформозависимые части FireMonkey реализуются с использованием понятия сервис. Общую информацию о том, что такое сервисы, как они устроены и как их получить, можно прочитать тут в разделе "Сервисы". А я лишь коротко скажу, что для нас сервис - это интерфейс + несколько реализаций этого интерфейса под разные платформы. Поэтому необходимо все платформозависимые функции выделить в отдельный интерфейс. У нас такая функция всего одна: "Открыть ссылку в браузере по умолчанию". Не забываем задать GUID для нашего интерфейса сервиса. В RadStudio его можно сгенерировать автоматически, используя комбинацию клавиш Ctrl + Shift + G.

IFMXLaunchService = interface
  ['{3C0888FA-61DD-4B76-9F0E-1956E6E08E86}']
  function OpenURL(const AUrl: string): Boolean;
end;

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

FLaunchService: IFMXLaunchService;

Так же не забываем, что сервис не обязательно реализуется под все платформы. И может выйти так, что сервис не реализуется в приципе на каких-то платформах. Поэтому обязательно добавляем проверка на его наличие:

if Assigned(FLaunchService) then
begin
  FLaunchService.OpenURL(Url);
  FVisited := True;
end;

Все сервисы FMX централизованно хранятся в хранилище TPlatformServices.Current. Каждый имеет право запросить реализацию любого сервиса и даже зарегистрировать там свой. Что мы и сделаем чуть позже. А пока, сервис запрашивается следующей строчкой кода:

TPlatformServices.Current.SupportsPlatformService(IFMXLaunchService, IInterface(FLaunchService));

Если реализации сервиса нет, то этот метод вернет нам nil. Если есть, то под интерфейсом FLaunchService будет скрываться реализация. Как видите, это позволяет полностью отделить наш компонент от нижнего уровня, зависимого от платформы.

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

Реализация сервиса под Windows

Согласно правилу хорошего тона, основной компонент мы разместим в юните: FMX.LinkedLabel. Тогда как все реализации зависимые от платформы располагаются в файлах, полученных путем добавления суффикса платформы к окончанию названия базового юнита:

  1. Для Windows - FMX.LinkedLabel.Win
  2. Для OSX - FMX.LinkedLabel.OSX
Реализация сервиса под Windows довольно банальна:
type
TWinLaunchService = class (TInterfacedObject, IFMXLaunchService)
public
{ IFMXLaunchService }
function OpenURL(const AUrl: string): Boolean;
end;
{ TWinLaunchService }
function TWinLaunchService.OpenURL(const AUrl: string): Boolean;
begin
Result := ShellExecute(0, 'open', PChar(AUrl), nil, nil, SW_SHOWNORMAL) = NO_ERROR;
end;

Мы используя Winapi.ShellApi открываем ссылку.
Регистрацию нашего сервиса в системе осуществляется в секции инициализации следующим способом:

TPlatformServices.Current.AddPlatformService(IFMXLaunchService, TWinLaunchService.Create);

Реализация сервиса под OSX

Аналогично делается и для OSX

type
 TMacLaunchService = class (TInterfacedObject, IFMXLaunchService)
 public
   { IFMXLaunchService }
   function OpenURL(const AUrl: string): Boolean;
 end;
{ TWinLaunchService }
function TMacLaunchService.OpenURL(const AUrl: string): Boolean;
var
  Workspace: NSWorkspace;
  Url: NSURL;
begin
  Workspace := TNSWorkspace.Wrap(TNSWorkspace.OCClass.sharedWorkspace);
  Url := TNSUrl.Wrap(TNSUrl.OCClass.URLWithString(NSStr(AUrl)));
  Result := Workspace.openURL(Url);
end;
initialization
  TPlatformServices.Current.AddPlatformService(IFMXLaunchService, TMacLaunchService.Create);
end.

Подключение разных реализаций сервисов

Осталось рассмотреть только, как теперь нам совместить в одном проекте реализации сервиса под разные платформы. Это делается просто с использование директив условной компиляции, следующим образом:

uses
  FMX.Platform
{$IFDEF MSWINDOWS}
  , FMX.LinkedLabel.Win
{$ELSE}
  {$IFDEF MACOS}
  , FMX.LinkedLabel.Mac
  {$ENDIF}
{$ENDIF};

Заключение

Домашнее задание: Реализовать сервис под ios после релиза мобильной студии.

Posted by Yaroslav Brovin on April 16th, 2013 under Firemonkey (RUS) | 14 Comments »




Server Response from: BLOGS1