-
Постов
2 124 -
Зарегистрирован
-
Посещение
-
Победитель дней
390
Активность репутации
-
-
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
-
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;
-
Brovin Yaroslav получил реакцию от Anatoliy в [Статья] Делаем скриншот любого контрола FireMonkey
Ссылка: http://yaroslavbrovin.ru/category/fmx_ru/graphics_ru/ Автор: Ярослав Бровин Статья рассказывает о том, как сделать скриншот любого контрола FireMonkey. Так же немного расскрывает общий процесс отрисовки компонентов.
-
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 -
Brovin Yaroslav получил реакцию от #WAMACO в Android 64 ошибка "External exception 1."
В общем исправление проблемы простое:
Добавляете в свой проект файл FMX.Helpers.Android.pas. Находите там строчку: FTimerHandle: Cardinal; Меняете ее на: FTimerHandle: TFmxHandle; Собираете и проблемы больше нет. -
Brovin Yaroslav получил реакцию от Ingalime в Android 64 ошибка "External exception 1."
В общем исправление проблемы простое:
Добавляете в свой проект файл FMX.Helpers.Android.pas. Находите там строчку: FTimerHandle: Cardinal; Меняете ее на: FTimerHandle: TFmxHandle; Собираете и проблемы больше нет. -
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 -
Brovin Yaroslav получил реакцию от Олег Киреев в OpenDialog для мобильных платформ
http://docwiki.embarcadero.com/RADStudio/Rio/en/Taking_and_Sharing_Pictures_and_Text_Using_Action_Lists
-
Brovin Yaroslav получил реакцию от Anatoliy в Какие статьи вы хотели бы видеть в блогах?
http://docwiki.embarcadero.com/RADStudio/Rio/en/Firebase_Android_Support
-
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; -
Brovin Yaroslav получил реакцию от Ingalime в Какие статьи вы хотели бы видеть в блогах?
Так же, как и в статье выше. Только использовать C++ код.
-
Brovin Yaroslav получил реакцию от Ingalime в Какие статьи вы хотели бы видеть в блогах?
http://docwiki.embarcadero.com/RADStudio/Rio/en/Firebase_Android_Support
-
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 устройств с ретиной экраном и без:
-
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 устройств с ретиной экраном и без:
-
Brovin Yaroslav получил реакцию от Ingalime в Показывает один и тот же Splash
Проект устанавливаете один и тот же или каждый раз новый?
Возможно картинка в кеше залипает.
Еще советую распаковать полученный в ходе сборки apk файл и проверить его содержимое на момент наличия сплеш картинок.
-
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 компоненты.
-
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.
-
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.
-
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.
-
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
-
Brovin Yaroslav отреагировална dnekrasov в рисование на Image1
А этот код и не должен ничего рисовать.
Почитайте про TPathData и его методы (хотя бы MoveTo и LineTo) У одного Canvas должно быть одинаковое количество BeginScene и EndScene - иначе получите Exception. В Image1MouseMove вообще не понятно что Вы хотели сделать. -
Brovin Yaroslav получил реакцию от #WAMACO в СОРТИРОВКА СПИСКА ПОСЛЕДНИХ СООБЩЕНИЙ
Восстановил столбец с последними сообщениями. После обновления форума слетел блок.
-
Brovin Yaroslav получил реакцию от Yarpda в СОРТИРОВКА СПИСКА ПОСЛЕДНИХ СООБЩЕНИЙ
Восстановил столбец с последними сообщениями. После обновления форума слетел блок.
-
Brovin Yaroslav получил реакцию от Ingalime в Андроид. Обучение пользователя новым функциям приложения
Я бы не делал скриншот. А просто поместил поверх прозрачный TPaintBox. А в OnPaint просто вычислил область ,которую не надо закрашивать и просто закрасил paintBox кистью с прозрачностью с учетом выреза.