Kitty
-
Постов
792 -
Зарегистрирован
-
Посещение
-
Победитель дней
16
Активность репутации
-
Kitty отреагировална Равиль Зарипов (ZuBy) в Подключение в VCL компонента FMX
на VCL так не принято, хотя если постараться, то думаю можно такое сделать
-
Kitty отреагировална krapotkin в Подключение в VCL компонента FMX
почему-то мне кажется, что функционал будет сильно отличаться, например, когда я захочу сделать клик сквозь "прозрачную" область?
так что пользуемся TPanel ...
-
Kitty отреагировална ENERGY в Утечка при использовании анонимного метода или анонимные методы, циклические ссылки и ARC
Это касается ARC компиляторов, Android, iOS и будущего Linux.
Если контейнер владелец, содержит классы, которые используют анонимный метод для общения с ним (классом владельцем), то такая конструкция порождает утечку памяти из-за появления циклической ссылки. Т.к. при присваивании анонимного метода инкрементируется счетчик ссылок и не меняется. Причем это не указано в хелпе.
А дело было так - при вызове MyCore.Free класс не уничтожался - не вызывался деструктор из за того, что после вызова Free, счетчик ссылок (reference Count) был равен 1. Приходилось пользоваться DisposeOf. Решил разобраться.
Для этого перекрыл виртуальные методы TObject отвечающие за изменения счетчика объекта (см. также полный пример ниже).
function __ObjAddRef: Integer; override;
function __ObjRelease: Integer; override;
Итак TCore содержит класс TTestClass - у которого есть событие OnMyEvent.
Прототип описан как анонимная процедура - TAnonymProc = reference to procedure;
При указании анонимной процедуры, т.е. :
procedure TCore.SetEvent; begin fTest.OnMyEvent := procedure () begin fSetFlag := true; end; end; счетчик ссылок TCore увеличивается на 1 и не изменяется при выходе из SetEvent.
Теперь при вызове Free TCore - не будет вызван деструктор, который должен уничтожит классы TCore и TTestClass и произойдет утечка памяти.
Решение :
1. Использовать слабые ссылки - weak, в нашем примере добавить атрибут [weak]:
TTestClass = class strict private [weak]fOnMyEvent:TAnonymProc; public property OnMyEvent: TAnonymProc read fOnMyEvent write fOnMyEvent; end; При присваивании объекта в переменную со слабой ссылкой не происходит увеличение счётчика ссылок объекта на единицу. Аналогично, при очистке слабой ссылки не происходит уменьшение счётчика объекта на единицу.
2. Не использовать анонимные методы, а использовать обычные указатели на метод:
Вместо TAnonymProc = reference to procedure; используем классический
TAnonymProc = procedure of object;
Демо пример, где можно отследить утечку прикрепил.
Полный код:
AnonMethodsCycle.zip
-
Kitty отреагировална AngryOwl в Подключение в VCL компонента FMX
Ой, не надо...
P.S. Ну а "по факту", где-то что-то было подобное.
-
Kitty отреагировална krapotkin в Подключение в VCL компонента FMX
желание привинтить колеса от бмв даже к мерседесу обычно считается странным.
а тут аж Layout из FMX-2012 к VCL-1992 )))
-
Kitty отреагировална Gingercat в Как определить отсутствие изображения как такового в TBitmap?
Странная потребность, если не вариант пробежать по диагонали, тогда, возможно как вариант)):
создайте массив размера Width * Height * глубину (на 4 в случае 32 bit);
Глубина в данном случае не совсем корректно, чтоб было понятно: на R+G+B+Alpha
обнулите его через, увы не силен в Delphi на ++ через ZeroMemory;
Byte *destPtr; destPtr = (Byte*)bitmap->ScanLine[bitmap->Height - 1] это указатель на начало dib битмапа;
ну а дальше сравните просто сравните два участка памяти через memcmp или как угодно.
Не факт что сработает, но попробовать можно. Я таким макаром сравнивал изображения, когда нужно было очень быстро.
-
Kitty отреагировална Равиль Зарипов (ZuBy) в файл не находится
Все используют деплой, вот попробуйте этот проект запустить у себя
-
Kitty отреагировална Andrey Efimov в Version Info, label (Android)
Прямая ссылка в блог: Автоматическая смена названия приложения в зависимости от языка системы
Ссылка на форуме(Раздел "Статьи"): [Статья][Android] Автоматическая смена названия приложения в зависимости от языка системы
и ещё есть обычные темы по этому вопросу, но прикладывать не буду.
p.s. Народ совсем обленился, сложно поиском воспользоваться...
-
Kitty отреагировална Равиль Зарипов (ZuBy) в Странное поведение TThread
procedure LoadBitmapFromURL(const aURL: string; aBitmap: TBitmap; const aSuccess: TThreadProcedure = nil; const aError: TThreadProcedure = nil); var thread: TThread; begin thread := TThread.CreateAnonymousThread( procedure var HTTP: THTTPClient; Result: TMemoryStream; begin Result := TMemoryStream.Create; HTTP := THTTPClient.Create; try try HTTP.Get(aURL, Result); TThread.Synchronize(TThread.CurrentThread, procedure var aSourceBmp: TBitmap; begin aSourceBmp := TBitmap.Create; try aSourceBmp.LoadFromStream(Result); if not aSourceBmp.IsEmpty then begin aBitmap.SetSize(aSourceBmp.Width, aSourceBmp.Height); aBitmap.CopyFromBitmap(aSourceBmp); if Assigned(aSuccess) then aSuccess; end; finally FreeAndNil(aSourceBmp); end; end); except TThread.Synchronize(TThread.CurrentThread, procedure begin if Assigned(aError) then aError; end); end; finally FreeAndNil(Result); FreeAndNil(HTTP); end; end); thread.FreeOnTerminate := true; thread.start; end; в последнее время пользуюсь такой конструкцией
-
Kitty отреагировална Равиль Зарипов (ZuBy) в Странное поведение TThread
а что удивительного? вы загружаете в синхронизации, т.е. в главном потоке
-
Kitty отреагировална enatechno в Странное поведение TThread
Synchronize(LoadImage); Эта строка означает, что LoadImage выполняется в главном потоке (для каждой картинки!).
Для примера посмотрите эту тему:
-
Kitty отреагировална Brovin Yaroslav в Описание TfgRatingBar
Доработал компонент. Добавлено:
Поддержка Tint эффекта - TfgRatingBar.TintColor Автоматический размер - TfgRatingBar.AutoSize Режим только отображения - TfgRatingBar.ReadOnly Событие окончательного изменения рейтинга (отжатие пальца от экрана или кнопки мышки) - TfgRatingBar.OnChange Событие в процессе изменения рейтинга - TfgRatingBar.OnChanging
-
Kitty отреагировална SerhioUser в Как получить версию APK-файла под Win32?
Благодарю, Евгений Корепов!
Вот функция GetApkVersion() на C++ для получения версии APK-файла, и слегка подкорректированная вышеописанная функция запуска:
String __fastcall ShellExecutePipe(String CommandLine, String AWorkDir = "C:\\", UINT Flag = SW_HIDE) { TSecurityAttributes SA; TStartupInfo SI; TProcessInformation PI; HANDLE StdOutPipeRead, StdOutPipeWrite; bool WasOK; char Buffer[256]; unsigned long BytesRead; String WorkDir; bool Handle; String AOutputLine; String Result; SA.nLength = sizeof(SA); SA.bInheritHandle = true; SA.lpSecurityDescriptor = NULL; CreatePipe(&StdOutPipeRead, &StdOutPipeWrite, &SA, 0); try { setmem(&SI, sizeof(SI), 0); SI.cb = sizeof(SI); SI.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; SI.wShowWindow = Flag; SI.hStdInput = (unsigned)GetStdHandle(STD_INPUT_HANDLE); // don't redirect stdin SI.hStdOutput = (unsigned int)StdOutPipeWrite; SI.hStdError = (unsigned int)StdOutPipeWrite; WorkDir = AWorkDir; Handle = CreateProcess(NULL, CommandLine.c_str(), NULL, NULL, true, 0, NULL, WorkDir.c_str(), (STARTUPINFO*)&SI, &PI); } catch(Exception &e) { } CloseHandle(StdOutPipeWrite); if (Handle) { try { do { WasOK = ReadFile(StdOutPipeRead, Buffer, 50, &BytesRead, NULL); if(BytesRead > 0) { Buffer[BytesRead] = 0; AOutputLine = Buffer; Result = Result + AOutputLine; } }while(WasOK && (BytesRead != 0)); WaitForSingleObject(PI.hProcess, INFINITE); } __finally { CloseHandle(PI.hThread); CloseHandle(PI.hProcess); } } CloseHandle(StdOutPipeRead); return Result; } //--------------------------------------------------------------------------- String __fastcall GetShortName(String sLongName) { String ret; String sShortName; int nShortNameLen; sShortName.SetLength(MAX_PATH); nShortNameLen = GetShortPathName( sLongName.c_str(), sShortName.c_str(), MAX_PATH - 1); if (nShortNameLen != 0) { sShortName.SetLength(nShortNameLen); ret = sShortName; } return ret; } //--------------------------------------------------------------------------- String __fastcall GetApkVersion(String FileName) { String ret; String AppPath = GetShortName(ExtractFileDir(Application->ExeName)); FileName = GetShortName(FileName); if(FileName != "") { String cmd = (String)"cmd /c \""+ AppPath + "\\aapt.exe\"" + " dump badging " + FileName; String res = ShellExecutePipe(cmd, AppPath); TStringList *sl = new TStringList; sl->Delimiter = ' '; sl->DelimitedText = res; ret = AnsiDequotedStr(sl->Values["versionName"], '\''); if(ret != "") ret += "."; ret += AnsiDequotedStr(sl->Values["versionCode"], '\''); delete sl; } return ret; } //--------------------------------------------------------------------------- Всем спасибо за участие.
-
Kitty отреагировална Евгений Корепов в файл не находится
Добавьте проверку на наличие файла. Ваш код выдает ошибку, но вы не знаете причину ошибки - отсутствие файла или ошибка в процессе LoadFromFile
AFilePath:=System.IOutils.TPath.Combine(System.IOutils.TPath.GetDocumentsPath, 'Image_640x960.png'); if TFile.Exists(AFilePath) then Image2.Bitmap.LoadFromFile(AFilePath) else ShowMessage('File not found');
-
Kitty отреагировална Alex7wrt в Загрузка произвольной картинки в TImageList динамически
Думаю, стоит перед загрузкой битмапа из Stream добавить
Stream.Position:=0
-
Kitty отреагировална enatechno в Запуск компилированного приложения.
Создал 2 тестовых проекта (один VCL, другой FMX). В обоих только форма с кнопкой.
Компилировал из 10 Seattle и 10 Berlin (конфигурация Debug).
Запускал на win 7 и 10.
Задержки в 1-2 сек не наблюдал. На глаз оба проекта запускаются с одинаковой скоростью.
Конфигурация компьютера аналогична Вашей.
https://www.youtube.com/watch?v=5q8ZKiYEWko
-
Kitty отреагировална Brovin Yaroslav в Загрузка произвольной картинки в TImageList динамически
Мне кажется, у вас не указан scale для загружаемой картинки в MultiResBitmap.
BI.Scale := 1;
-
Kitty отреагировална Brovin Yaroslav в [TScrollBox] Можно ли изменить Increment у ScrollBar?
Не уверен, что это возможно, так как сам ScrollBox настраивает скролл боксы по своему усмотрению. Но вы можете получить к ним доступ и попробовать изменить их программным путем:
type TOpenScrollBox = class(TCustomScrollBox); procedure TForm2.Button1Click(Sender: TObject); begin TOpenScrollBox(ScrollBox1).VScrollBar.ViewportSize; TOpenScrollBox(ScrollBox1).HScrollBar.ViewportSize; end;
-
Kitty отреагировална Равиль Зарипов (ZuBy) в vkHardwareBack, vkHome, vkMenu (Android)
как понять список доступных кнопок?
на счёт кнопки Home, все верно, так и должно быть
-
Kitty отреагировална Равиль Зарипов (ZuBy) в Кодировки языков в APPLE
Все оно верно даст
Вы проверяли?
У меня все отлично, стоит регион Казахстан, язык системы русский
Результат кода - ru
Не поленился и запустил симулятор, языки естественно менял на соответствующие
-
Kitty отреагировална Alex7wrt в файл не находится
В iOS нужно писать StartUp\Documents.
В Android assets\internal.
Посмотрите, что у вас представляет собой filename. Судя по вашему коду должно быть имя файла плюс расширение.
-
-
Kitty отреагировална Brovin Yaroslav в [Windows] Как загрузить HICON в TBitmap?
Добрый день,
Так же, как и в случае конвертации HBitmap -> TBitmap
var tmpIcon: Vcl.Graphics.TIcon; tmpStream: TMemoryStream; begin tmpIcon := TIcon.Create; try tmpIcon.Handle := GetIcon; tmpStream := TMemoryStream.Create; try tmpIcon.SaveToStream(tmpStream); Image1.Bitmap.LoadFromStream(tmpStream); finally tmpStream.Free; end; finally tmpIcon.Free; end; end; GetIcon - функция, которая возвращает хендл иконки. в вашем случае infofile.hIcon
-
Kitty отреагировална krapotkin в Рисование маршрута на MapView, Delphi, Android
TForm1 = class(TForm) b1: TButton; b2: TButton; MapView1: TMapView; procedure b1Click(Sender: TObject); procedure b2Click(Sender: TObject); public LineDestroy:TmapPolyline; end; procedure TForm1.b1Click(Sender: TObject); var Line:TmapPolylineDescriptor; Points:TArray<TMapCoordinate>; begin SetLength(Points, 2); MapView1.Location :=TmapCoordinate.Create(49.901493, 28.587838); Points[0]:=TmapCoordinate.Create(49.901493, 28.587838); Points[1]:=TmapCoordinate.Create(49.897793, 28.585026); Line:=TmapPolylineDescriptor.Create(Points); Line.Geodesic:=True; Line.StrokeColor:=TAlphaColorRec.Red; LineDestroy:=MapView1.AddPolyline(Line); end; procedure TForm1.b2Click(Sender: TObject); begin LineDestroy.Remove; end;
-
Kitty отреагировална kami в [ANDROID] Создание и удаление компонентов run-time
Поправка: это самый верный способ для FMX, вне зависимости от платформы.
Емнип, у TCircle нет наследников. Ну и - для использования Release не обязательно приводить тип к истинному классу объекта.
Поэтому сей код можно записать так (не проверял в IDE, но если скомпилируется - значит всё нормально):
for k:=Layout1.ChildrenCount-1 downto 0 do if Layout1.Children[k] is TCircle then Layout1.Children[k].Release;