Перейти к содержанию
Fire Monkey от А до Я

Brovin Yaroslav

Администраторы
  • Постов

    2 124
  • Зарегистрирован

  • Посещение

  • Победитель дней

    390

Активность репутации

  1. Like
    Brovin Yaroslav получил реакцию от Ingalime в [TMapView] кнопки на карте   
    Нет
  2. Like
    Brovin Yaroslav отреагировална Алиса Романец в Приложение на macOS не отправляет уведомления   
    Есть приложение, написанное ещё в RAD Studio 10.3 и мигрировавшее на 10.4. При миграции на 10.3.3 у приложения просто исчезла возможность отправлять уведомления. TNotificationCenter на macOS выдавал ошибку AccessViolation, в то время как на Windows всё работало отлично, уведомления приходили, никаких проблем.
    Спустя какое-то время, приложение мигрировало на RAD Studio 10.4, где переписали компонент TNotificationCenter и исправили баг в Macapi.Foundation (что позволило адекватным способом отправлять уведомления напрямую через Cocoa). Но теперь вылезла другая проблема - формы с компонентом TNotificationCenter стали падать, даже не доходя до события OnCreate с ошибкой в консоли PAServer
    2020-07-21 01:05:06.361 AErenderLauncher[11672:433325] *** Assertion failure in +[UNUserNotificationCenter currentNotificationCenter], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UserNotifications/UserNotifications-279/UNUserNotificationCenter.m:47 2020-07-21 01:05:06.362 AErenderLauncher[11672:433325] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'application bundle identifier for LSApplicationProxy with bundle identifier (null)' То есть, как я поняла, проблема именно в компоненте TNotificationCenter, который стал фаталить всю прогу. Убрала этот компонент со всех форм, ограничила его {$IFDEF MSWINDOWS} в коде - прога стала прекрасно запускаться на macOS. Тут уже у меня возникли некоторые вопросы, потому что в новых приложениях такой ошибки не возникало (там возникала другая, что TNotificationCenter не может спросить разрешения у системы на отправку уведомлений). Решила я найти способ, как можно отправлять уведомления напрямую из Cocoa, и нашла следующий код на Swift
    @IBAction func sendNotification(_ sender: Any) { let notification = NSUserNotification(); notification.title = "Notification Title"; notification.subtitle = "Foo Bar"; notification.informativeText = "Very informative. Such notification!"; notification.soundName = NSUserNotificationDefaultSoundName; let notificationCenter = NSUserNotificationCenter.default; notificationCenter.deliver(notification); } Перепишем на Object Pascal, получим
    procedure TMainForm.Button1Click(Sender: TObject); begin var ANotification: NSUserNotification := TNSUserNotification.Wrap(TNSUserNotification.Alloc.init); ANotification.setTitle(StrToNSStr('Notification Title')); ANotification.setSubtitle(StrToNSStr('Foo Bar')); ANotification.setInformativeText(StrToNSStr('Very informative. Such notification!')); ANotification.setSoundName(NSUserNotificationDefaultSoundName); var ANotificationCenter: NSUserNotificationCenter := TNSUserNotificationCenter.Wrap(TNSUserNotificationCenter.OCClass.defaultUserNotificationCenter); ANotificationCenter.deliverNotification(ANotification); end; И в результате имеем ту же самую проблему - во всех новых приложениях данный код работает, как надо (и разрешение на отправку уведомлений приходит, и уведомления отправляются, даже запланированные работают), а в основной программе, что долго гуляла по студиям - тишина, вообще ничего не происходит, даже ошибок никаких нет. То есть, код выполняется, но абсолютно безрезультатно. Скажите пожалуйста, с чем это может быть связано?
    macOS Catalina 10.15 / PAServer 21.0 / RAD Studio 10.4
  3. Like
    Brovin Yaroslav отреагировална H Visli в Can't stretch the video under the 2K / 4K screen   
    Finally solved. Although it is not perfect, but it can satisfy my use. Share to everyone: 
    (Base on @ Brovin yaroslav  and @ cezif  's post, Thanks!)
    procedure TWindowsMedia.UpdateMediaFromControl; function GetScreenScale: Single; var ScreenService: IFMXScreenService; begin Result := 1; if TPlatformServices.Current.SupportsPlatformService (IFMXScreenService, IInterface(ScreenService)) then Result := ScreenService.GetScreenScale; end; var R: TRect; Bounds: TRectF; Form: TCommonCustomForm; ScaleRatio: Single; begin FVMRWindowlessControl9.SetAspectRatioMode(VMR9ARMode_LetterBox); if FWnd <> 0 then begin if (Control <> nil) and not (csDesigning in Control.ComponentState) and (Control.ParentedVisible) and (Control.Root <> nil) and (Control.Root.GetObject is TCommonCustomForm) then begin Form := TCommonCustomForm(Control.Root.GetObject); ScaleRatio := GetScreenScale; Bounds := TRectF.Create(0, 0, Control.AbsoluteWidth * ScaleRatio, Control.AbsoluteHeight * ScaleRatio); Bounds.Fit(RectF(0, 0, Control.AbsoluteWidth * ScaleRatio, Control.AbsoluteHeight * ScaleRatio)); Bounds.Offset(Control.AbsoluteRect.Left, Control.AbsoluteRect.Top); SetParent(FWnd, WindowHandleToPlatform(Form.Handle).Wnd); SetWindowPos(FWnd, 0, Bounds.Round.Left, Bounds.Round.Top, Bounds.Round.Width, Bounds.Round.Height, 0); R := TRect.Create(0, 0, Bounds.Round.Width, Bounds.Round.Height); if FVMRWindowlessControl9 <> nil then FVMRWindowlessControl9.SetVideoPosition(nil, @R); if FVMRWindowlessControl7 <> nil then FVMRWindowlessControl7.SetVideoPosition(nil, @R); ShowWindow(FWnd, SW_SHOW) end else begin SetParent(FWnd, ApplicationHWND); ShowWindow(FWnd, SW_HIDE) end; end; end;  
  4. Like
    Brovin Yaroslav получил реакцию от Anatoliy в [Статья] Делаем скриншот любого контрола FireMonkey   
    Ссылка: http://yaroslavbrovin.ru/category/fmx_ru/graphics_ru/ Автор: Ярослав Бровин Статья рассказывает о том, как сделать скриншот любого контрола FireMonkey. Так же немного расскрывает общий процесс отрисовки компонентов.
  5. Like
    Brovin Yaroslav получил реакцию от slav_z в Включение своих файлов в приложение   
    Добрый вечер,
     
    Тут есть два способа:
    Работа с Deployment менеджером. Он довольно подробно описан на Embarcadero Doc Wiki: http://docwiki.embarcadero.com/RADStudio/XE5/en/Deployment_Manager Работа через менеджер ресурсов и их получение через ResourceStream. Этот способ описал MyDelphiPw в сообщении выше тут. 1. Deployment Manager
    Специальная настройка проекта, которая позволяет указать, какие файлы нужно включить в состав пакета (Андроид) или бандла (iOS). Суть его работы простая, вы указываете какие файлы с вашего компьютера нужно перенести на устройство (в какое место). А далее работаете с ними из приложения так, как при обычной работе с файлами под Windows.
     
    На мобильных платформах нужно учесть специфику возможных местоположений файла. Пакет/Бандл (приложение) не допускает изменения внутренних файлов, потому что подписывается сертификатом. Поэтому теоретически при изменении файлов приложения, вы нарушаете целостность подписи. Именно по этому файлы внутри пакета/бандла доступны только на ЧТЕНИЕ.
     
    Однако, мобильные платформы предлагают широкий круг специальных мест для хранения (временные папки, песочницы, документы, карточка памяти и тд) изменяемых файлов (например файл локальной базы данных, или настройки в ini файле и тд).
     
    Описание всех вариантов местоположений с описанием путей есть в записе TPath (RTL): http://docwiki.embarcadero.com/RADStudio/XE5/en/Standard_RTL_Path_Functions_across_the_Supported_Target_Platforms. 

    Общие действия для использования менеджера развертывания такие:
    1. Открываем менеджер развертывания: Системное Меню -> Project -> Deployment.

    2. Выбираем в верхнем выпадающем меню платформу и конфигурацию сборки.

    3. Нажимаем кнопку добавить файл и выбираем нужный файл.
     
    4. Указываем местоположение файла, куда он должен поместиться после развертывания приложения на устройстве. Тут есть особенность, если файл нужен только на чтение, то пути менять не надо. Если возможна ситуация, когда файл может быт изменен, то файл нужно поместить под iOS в Startup\Documents\ (регистр важен)

    Под Андроид в assets\internal (регистр важен) - для внутреннего доступа из пакета приложения или assets - для внешнего доступа

    5. Получаем пути к расположению файлов:
    Под iOS:
    TPath.Combine(TPath.GetDocumentsPath, 'filename') Под Андроид:
    TPath.Combine(TPath.GetDocumentsPath, 'filename') { Внутренний доступ} TPath.Combine(TPath.GetSharedDocumentsPath, 'filename') { Внешний доступ } Полезные ссылки
    Подробное руководство по добавлению файлов для iOS: http://docwiki.embarcadero.com/RADStudio/XE5/en/Creating_an_iOS_App#Loading_and_Deploying_Files Подробное руководство по добавлению файлов для Android: http://docwiki.embarcadero.com/RADStudio/XE5/en/Creating_an_Android_App#Loading_and_Deploying_Files
  6. Like
    Brovin Yaroslav получил реакцию от #WAMACO в Android 64 ошибка "External exception 1."   
    В общем исправление проблемы простое:
    Добавляете в свой проект файл FMX.Helpers.Android.pas. Находите там строчку:   FTimerHandle: Cardinal; Меняете ее на: FTimerHandle: TFmxHandle; Собираете и проблемы больше нет.
  7. Like
    Brovin Yaroslav получил реакцию от Ingalime в Android 64 ошибка "External exception 1."   
    В общем исправление проблемы простое:
    Добавляете в свой проект файл FMX.Helpers.Android.pas. Находите там строчку:   FTimerHandle: Cardinal; Меняете ее на: FTimerHandle: TFmxHandle; Собираете и проблемы больше нет.
  8. Like
    Brovin Yaroslav получил реакцию от Voron в Включение своих файлов в приложение   
    Добрый вечер,
     
    Тут есть два способа:
    Работа с Deployment менеджером. Он довольно подробно описан на Embarcadero Doc Wiki: http://docwiki.embarcadero.com/RADStudio/XE5/en/Deployment_Manager Работа через менеджер ресурсов и их получение через ResourceStream. Этот способ описал MyDelphiPw в сообщении выше тут. 1. Deployment Manager
    Специальная настройка проекта, которая позволяет указать, какие файлы нужно включить в состав пакета (Андроид) или бандла (iOS). Суть его работы простая, вы указываете какие файлы с вашего компьютера нужно перенести на устройство (в какое место). А далее работаете с ними из приложения так, как при обычной работе с файлами под Windows.
     
    На мобильных платформах нужно учесть специфику возможных местоположений файла. Пакет/Бандл (приложение) не допускает изменения внутренних файлов, потому что подписывается сертификатом. Поэтому теоретически при изменении файлов приложения, вы нарушаете целостность подписи. Именно по этому файлы внутри пакета/бандла доступны только на ЧТЕНИЕ.
     
    Однако, мобильные платформы предлагают широкий круг специальных мест для хранения (временные папки, песочницы, документы, карточка памяти и тд) изменяемых файлов (например файл локальной базы данных, или настройки в ini файле и тд).
     
    Описание всех вариантов местоположений с описанием путей есть в записе TPath (RTL): http://docwiki.embarcadero.com/RADStudio/XE5/en/Standard_RTL_Path_Functions_across_the_Supported_Target_Platforms. 

    Общие действия для использования менеджера развертывания такие:
    1. Открываем менеджер развертывания: Системное Меню -> Project -> Deployment.

    2. Выбираем в верхнем выпадающем меню платформу и конфигурацию сборки.

    3. Нажимаем кнопку добавить файл и выбираем нужный файл.
     
    4. Указываем местоположение файла, куда он должен поместиться после развертывания приложения на устройстве. Тут есть особенность, если файл нужен только на чтение, то пути менять не надо. Если возможна ситуация, когда файл может быт изменен, то файл нужно поместить под iOS в Startup\Documents\ (регистр важен)

    Под Андроид в assets\internal (регистр важен) - для внутреннего доступа из пакета приложения или assets - для внешнего доступа

    5. Получаем пути к расположению файлов:
    Под iOS:
    TPath.Combine(TPath.GetDocumentsPath, 'filename') Под Андроид:
    TPath.Combine(TPath.GetDocumentsPath, 'filename') { Внутренний доступ} TPath.Combine(TPath.GetSharedDocumentsPath, 'filename') { Внешний доступ } Полезные ссылки
    Подробное руководство по добавлению файлов для iOS: http://docwiki.embarcadero.com/RADStudio/XE5/en/Creating_an_iOS_App#Loading_and_Deploying_Files Подробное руководство по добавлению файлов для Android: http://docwiki.embarcadero.com/RADStudio/XE5/en/Creating_an_Android_App#Loading_and_Deploying_Files
  9. Thanks
    Brovin Yaroslav получил реакцию от Олег Киреев в OpenDialog для мобильных платформ   
    http://docwiki.embarcadero.com/RADStudio/Rio/en/Taking_and_Sharing_Pictures_and_Text_Using_Action_Lists
  10. Like
    Brovin Yaroslav получил реакцию от Anatoliy в Какие статьи вы хотели бы видеть в блогах?   
    http://docwiki.embarcadero.com/RADStudio/Rio/en/Firebase_Android_Support
  11. Thanks
    Brovin Yaroslav получил реакцию от EricMyval в Как скопировать текст в буфер обмена?   
    Запрашиваете сервис IFMXClipBoardService. У него есть два метода для копирования данных любого типа в буфер и обратно.
    uses FMX.Platform, System.Rtti; {$R *.fmx} procedure TForm13.Button1Click(Sender: TObject); var Service: IFMXClipBoardService; begin if TPlatformServices.Current.SupportsPlatformService(IFMXClipBoardService, Service) then begin Service.SetClipboard(TValue.From<string>('My Text')); // Service.GetClipboard.AsString // Получения строкового значения обратно. end; end;
  12. Thanks
    Brovin Yaroslav получил реакцию от Ingalime в Какие статьи вы хотели бы видеть в блогах?   
    Так же, как и в статье выше. Только использовать C++ код.
  13. Like
    Brovin Yaroslav получил реакцию от Ingalime в Какие статьи вы хотели бы видеть в блогах?   
    http://docwiki.embarcadero.com/RADStudio/Rio/en/Firebase_Android_Support
  14. Like
    Brovin Yaroslav получил реакцию от Tom1984 в Получаем разрешение экрана устройства, логические и физические размеры экрана в FireMonkey   
    Введение
    Появление экранов повышенной плотность физических точек, привело с одной стороны к проблеме адаптации графического интерфейса под разные разрешения экранов при их одинаковых физических размерах, с другой к увеличению четкости и качества картинки.
     
    Например, если раньше на iPhone 3 при размере экрана 3,5 дюйма позволял отобразить 320х480 точек, то на устройстве iPhone 4 при таком же физическом размере экрана, экран мог уже отображать 640х960 точек. Это хорошо видно на увеличенном изображении обычного экрана и ретина экрана на рисунке ниже (слева - не ретина, справа - ретина (2х)). Справа количество физических точек ровно в четыре раза больше, чем слева:

     
    Для разработчика это могло означать, что интерфейс привязанный к разрешению 320х480 на Retina экране будет занимать только четверть экрана. Естественно, что использование разрешения экрана в физических координатах не удобно с этой точки зрения. Именно по этому появились логические координаты, которые гарантируют, что тот же пользовательский интерфейс для iPhone 3, будет иметь такие же размеры (физические) и на экране с ретиной.
     
    FireMonkey работает в логических координатах. Это означает, что на iPhone 3 - 4 мы работаем с логическим разрешением 320x480 точек. Однако, при отображении интерфейса на iPhone 4 c (с двойной плотностью пикселей по сравнению с iPhone 3), интерфейс автоматически масштабируется на физическое разрешение 640х960 с коэффициентом масштабирования равным 2. 
     
    Практика
    Теперь посмотрим, как получить всю эту информацию. Вся информация об экране (логический размер и коэффициент масштабирования) находится в сервисе IFMXScreenService. 
    Чтобы получить физическое разрешение экрана, нужно логический размер умножить на коэффициент масштабирования.
     
    Код ниже показывает, как получить доступ к этому сервису и извлечь требуемые параметры:
    var ScreenService: IFMXScreenService; LogicScreenSize: TPoint; ScreenScale: Single; begin // Запрашиваем сервис экрана, для получения информации о размере и текущем коэффициенте масштабирования if TPlatformServices.Current.SupportsPlatformService(IFMXScreenService, IInterface(ScreenService)) then begin LogicScreenSize := ScreenService.GetScreenSize.Round; ScreenScale := ScreenService.GetScreenScale; LabelLogicScreenSize.Text := Format('Логический размер: %d, %d', [LogicScreenSize.X, LogicScreenSize.Y]); LabelPhysicScreenSize.Text := Format('Физический размер: %f, %f', [LogicScreenSize.X * ScreenScale, LogicScreenSize.Y * ScreenScale]); LabelScreenScale.Text := Format('Коэффициент масштабирования: %f',[ScreenService.GetScreenScale]); end; end; Результат кода приведен на снимке экранов ниже для iPad устройств с ретиной экраном и без:

  15. Like
    Brovin Yaroslav получил реакцию от Alisson R Oliveira в Получаем разрешение экрана устройства, логические и физические размеры экрана в FireMonkey   
    Введение
    Появление экранов повышенной плотность физических точек, привело с одной стороны к проблеме адаптации графического интерфейса под разные разрешения экранов при их одинаковых физических размерах, с другой к увеличению четкости и качества картинки.
     
    Например, если раньше на iPhone 3 при размере экрана 3,5 дюйма позволял отобразить 320х480 точек, то на устройстве iPhone 4 при таком же физическом размере экрана, экран мог уже отображать 640х960 точек. Это хорошо видно на увеличенном изображении обычного экрана и ретина экрана на рисунке ниже (слева - не ретина, справа - ретина (2х)). Справа количество физических точек ровно в четыре раза больше, чем слева:

     
    Для разработчика это могло означать, что интерфейс привязанный к разрешению 320х480 на Retina экране будет занимать только четверть экрана. Естественно, что использование разрешения экрана в физических координатах не удобно с этой точки зрения. Именно по этому появились логические координаты, которые гарантируют, что тот же пользовательский интерфейс для iPhone 3, будет иметь такие же размеры (физические) и на экране с ретиной.
     
    FireMonkey работает в логических координатах. Это означает, что на iPhone 3 - 4 мы работаем с логическим разрешением 320x480 точек. Однако, при отображении интерфейса на iPhone 4 c (с двойной плотностью пикселей по сравнению с iPhone 3), интерфейс автоматически масштабируется на физическое разрешение 640х960 с коэффициентом масштабирования равным 2. 
     
    Практика
    Теперь посмотрим, как получить всю эту информацию. Вся информация об экране (логический размер и коэффициент масштабирования) находится в сервисе IFMXScreenService. 
    Чтобы получить физическое разрешение экрана, нужно логический размер умножить на коэффициент масштабирования.
     
    Код ниже показывает, как получить доступ к этому сервису и извлечь требуемые параметры:
    var ScreenService: IFMXScreenService; LogicScreenSize: TPoint; ScreenScale: Single; begin // Запрашиваем сервис экрана, для получения информации о размере и текущем коэффициенте масштабирования if TPlatformServices.Current.SupportsPlatformService(IFMXScreenService, IInterface(ScreenService)) then begin LogicScreenSize := ScreenService.GetScreenSize.Round; ScreenScale := ScreenService.GetScreenScale; LabelLogicScreenSize.Text := Format('Логический размер: %d, %d', [LogicScreenSize.X, LogicScreenSize.Y]); LabelPhysicScreenSize.Text := Format('Физический размер: %f, %f', [LogicScreenSize.X * ScreenScale, LogicScreenSize.Y * ScreenScale]); LabelScreenScale.Text := Format('Коэффициент масштабирования: %f',[ScreenService.GetScreenScale]); end; end; Результат кода приведен на снимке экранов ниже для iPad устройств с ретиной экраном и без:

  16. Like
    Brovin Yaroslav получил реакцию от Ingalime в Показывает один и тот же Splash   
    Проект устанавливаете один и тот же или каждый раз новый?
    Возможно картинка в кеше залипает.
    Еще советую распаковать полученный в ходе сборки apk файл и проверить его содержимое на момент наличия сплеш картинок.
  17. Like
    Brovin Yaroslav получил реакцию от Ingalime в Средства логирования в FireMonkey   
    RAD Studio XE5 предоставляет несколько способов логирования под платформы Андроид и iOS. Давайте их рассмотрим:
    Встроенный в FIreMonkey механизм логирования (кроссплатформенный). Использование системных функция каждой платформы для логирования Использование файлов для вывода логов. Использование сети для передачи сообщений лога 1. Встроенный механизм логирования
    FireMonkey содержит специальный класс FMX.Types.Log для осуществления логирования на всех платформах.
    Этот класс использует на каждой платформе системные средства вывода лога.
    Log = class abstract public class procedure d(const Msg: String); overload; class procedure d(const Fmt: String; const Args: array of const); overload; class procedure d(const Tag: String; const Instance : TObject; const Msg : String); overload; class procedure d(const Tag: String; const Instance : TObject; const Method : String; const Msg : String); overload; class procedure TimeStamp(const Msg: String); overload; class function ObjToString(const Instance : TObject) : String; class function ArrayToString(const AArray : TEnumerable<TFmxObject>) : String; overload; class function ArrayToString(const AArray : TEnumerable<TFmxObject>; MakeStr : ToStringFunc) : String; overload; class procedure DumpFmxObject(const O: TFmxObject; Nest: Integer = 0); end; Он предоставляет довольно много методов по вывода лога. 
    Чтобы его использовать достаточно вызвать любой нужный классовый метод. Например в моем приложении по нажатию на кнопку я буду выводить сообщение: "Log message from FireMonkey application"
    procedure TFormPhone.Button1Click(Sender: TObject); begin Log.d('Log message from FireMonkey application'); end; Далее нужно понять, куда будет выведено это сообщение.
     
    1.1. Андроид
    Под андроид это сообщение попадает в системный журнал. Прочитать его можно в утилите Андроида LogCat - это специальная утилита для просмотра системного лога. Ее можно запустить двумя способами:
    C GUI оболочкой Из командной оболочки (консольный вариант). Первый способ (с GUI). В Eclipse с Android SDK открыть Window->ShowView->LogCat. Откроется окно с GUI интерфейсом, в котором вы сможете увидеть все сообщения, которые отправляют все приложения на телефоне. Стоит отметить, что это вариант LogCat в эклипсе содержит ряд полезных функций по фильтрации лога и его управлению. Поэтому я предпочитаю этот способ, нежели использовать консольный вариант этой же утилиты. Сразу же перед использования советую полностью очистить текущий журнал логов телефона, так как он вначале будет содержать огромное количество сообщений. Для очистки нажмите кнопку очистки лога в окне (кнопка с листком и красным крестиком).

     
    Второй способ (консольный режим). Второй вариант запуска утилиты LogCat заключается в вызове утилиты из командной строки. Утилита просмотра журналов логов входит в общую утилиту ADB.exe. Чтобы запустить лог изз командой строки воспользуйтесь следующей командой:
    .\sdk\platform-tools\adb.exe logcat Утилита лежит в папке platform-tools Android SDK. В вашем случае вы должны указать свой путь к этому файлу. Ключ logcat запускает просмотр журнала логирования.
    Так же как и в первом варианте я советую предварительно очистить лог вызвав logcat с ключом -c:
    .\sdk\platform-tools\adb.exe logcat -с Описание всех ключей утилиты logcat: logcat
    После того, как мы открыли Logcat любым из предложенных способов, запускаем нашу программу и смотрим сообщение в логе:

     
    1.2 Йос
    В йос лог попадает в два журнала в зависимости от того, где вы запускаете свою программу (Симулятор или устройство).
     
    iOS Симулятор. Открываем журнал лога в меню симулятора Отладка->Открыть системный журнал...
     
     
    iOS устройство. Открываем XCode Органайзер и выбираем вкладку Console у вашего устройства.

     
    2. Использование системных функций логирования
    Для тех, кто по каким-то причинам не хочет использовать FireMonkey для этих целей может использовать на каждой платформе системные функции логирования.
     
    2.1 Андроид
    Для андроида в Delphi предусмотрены системные функции из Androidapi.Log:
    { Helper functions } function LOGI(Text: MarshaledAString): Integer; function LOGW(Text: MarshaledAString): Integer; function LOGE(Text: MarshaledAString): Integer; function LOGF(Text: MarshaledAString): Integer;  Каждая из которых выводит сообщение с указанным типом (I - информационное сообщение, W - предупреждение, E - ошибка, F - фатальная ошибка)
     
    2.2 iOS
    В IOS вы можете использовать системную функцию iOSapi.Foundation.NSLog.
    procedure NSLog(format: PNSString); cdecl; varargs; external libFoundation name _PU + 'NSLog'; 3. Логирование в файл
    Является самым стандартным средством. Для его использования вы можете использовать стандартные способы работы с текстовыми файлами, которые полностью работают на всех платформах.
     
    4. Логирование по сети
    Этот способ так же имеет место быть и заключается в создании простого TCP клиента на стороне вашего приложения и FTP сервера на Windows. С приложения вы просто шлете на указанный адрес сервера сообщения, а на стороне сервера просто отображаете. Для этих целей можно использовать стандартные Indy компоненты. 
  18. Like
    Brovin Yaroslav отреагировална IVGSoft в Can not save record(data) into database mySQL Using Delphi 10.3 Rio in Release Mode   
    As I told you in a previous message - use logging after each potentially errorneous block/line.
  19. Like
    Brovin Yaroslav отреагировална IVGSoft в Can not save record(data) into database mySQL Using Delphi 10.3 Rio in Release Mode   
    Separate UI code from other logic. 
  20. Like
    Brovin Yaroslav отреагировална IVGSoft в Can not save record(data) into database mySQL Using Delphi 10.3 Rio in Release Mode   
    procedure TLocationForm.btnSendClick(Sender: TObject); begin with dmMyLocation do begin if not fgActivityDialog.IsShown then begin fgActivityDialog.Message := 'Please, Wait'; fgActivityDialog.Show; FActivityDialogThread := TThread.CreateAnonymousThread(procedure begin Sleep(1000); if TThread.CheckTerminated then Exit; TThread.Synchronize(nil, procedure begin fgActivityDialog.Message := 'Sending data...'; end); try qInsert.SQL.Clear; qInsert.SQL.Add('INSERT INTO mabsensilokasi('); qInsert.SQL.Add('idlokasi,'); qInsert.SQL.Add('tgllokasi,'); qInsert.SQL.Add('latx,'); qInsert.SQL.Add('longx,'); qInsert.SQL.Add('latlongx,'); qInsert.SQL.Add('namalokasi) '); qInsert.SQL.Add('VALUES('); qInsert.SQL.Add(':idlokasi,'); qInsert.SQL.Add(':tgllokasi,'); qInsert.SQL.Add(':latx,'); qInsert.SQL.Add(':longx,'); qInsert.SQL.Add(':latlongx,'); qInsert.SQL.Add(':namalokasi)'); qInsert.Prepare; qInsert.Params[0].AsInteger := 0; qInsert.Params[1].AsDateTime := Now; qInsert.Params[2].AsFloat := strToFloat(ENUSLat); qInsert.Params[3].AsFloat := strToFloat(ENUSLong); qInsert.Params[4].AsString := ENUSLat+':'+ENUSLong; qInsert.Params[5].AsString := edtNamaLokasi.Text; try UniConnection1.Connect; qInsert.ExecSQL; TThread.Synchronize(nil, procedure begin ShowMessage('Record was saved into MySQL Server DB...'); //showup windows of dialog when data was save succesfully into db mysql server end); except on e:exception do begin TThread.Synchronize(nil, procedure begin ShowMessage(e.Message); UniConnection1.Disconnect; end); end;//exception end;//try //fgActivityDialog.ExecuteAction(btnSend); Sleep(1000); if TThread.CheckTerminated then Exit; TThread.Synchronize(nil, procedure begin fgActivityDialog.Message := 'Finish'; end); Sleep(500); if TThread.CheckTerminated then Exit; finally if not TThread.CheckTerminated then TThread.Synchronize(nil, procedure begin fgActivityDialog.Hide; end); end;//try end);//FActivityDialogThread FActivityDialogThread.FreeOnTerminate := False; FActivityDialogThread.Start; end;//if end;//endDM end;//endProc I have changed your code a little bit. To make some kind of separation.
  21. Like
    Brovin Yaroslav отреагировална dnekrasov в рисование на Image1   
    Если в качестве курсора (картинки) карандаша, то ещё следует изучить как преобразовывать координаты:
    procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single); begin if D=1 then Image2.Position.Point := Image1.LocalToAbsolute(PointF(X, Y)); end; Да и HitTest у Image2 следует поставить False, а клик отслеживать на Image1. Да и когда D=1 и курсор находится внутри Image1 курсор мышки лучше сделать невидимым.
    Да и вообще - рисовать удобнее на PaintBox
  22. Like
    Brovin Yaroslav отреагировална dnekrasov в рисование на Image1   
    А этот код и не должен ничего рисовать.
    Почитайте про TPathData и его методы (хотя бы MoveTo и LineTo) У одного Canvas должно быть одинаковое количество BeginScene и EndScene - иначе получите Exception. В Image1MouseMove вообще не понятно что Вы хотели сделать.
  23. Like
    Brovin Yaroslav получил реакцию от #WAMACO в СОРТИРОВКА СПИСКА ПОСЛЕДНИХ СООБЩЕНИЙ   
    Восстановил столбец с последними сообщениями. После обновления форума слетел блок.
  24. Like
    Brovin Yaroslav получил реакцию от Yarpda в СОРТИРОВКА СПИСКА ПОСЛЕДНИХ СООБЩЕНИЙ   
    Восстановил столбец с последними сообщениями. После обновления форума слетел блок.
  25. Like
    Brovin Yaroslav получил реакцию от Ingalime в Андроид. Обучение пользователя новым функциям приложения   
    Я бы не делал скриншот. А просто поместил поверх прозрачный TPaintBox. А в OnPaint просто вычислил область ,которую не надо закрашивать и просто закрасил paintBox кистью с прозрачностью с учетом выреза.
×
×
  • Создать...