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

kami

Пользователи
  • Постов

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

  • Посещение

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

    41

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

  1. Like
    kami получил реакцию от Евгений Корепов в Проверка наличия прав   
    Похоже, ответ появился:  https://en.delphipraxis.net/topic/2949-zxing-delphi-for-104/?do=findComment&comment=23777
  2. Like
    kami получил реакцию от MrAnderson в argument out of range Listview(Баг ?)   
    точно не правильно.
    1. Создавать TNetHTTPClient нужно в execute потока, а не использовать лежащий на форме.
    2. Работать с визуальными объектами нельзя из execute, об этом 100500 раз предупреждали.
    Посему, правильно с технической точки зрения (упустим пока архитектуру) будет:
    1. в execute создать сетевой компонент и выполнить запрос.
    2. Распарсить запрос
    3. Передать результаты в основной поток и уже в нем работать с ListView.
    Полезно для правильного написания вынести код потока в отдельный модуль. Который НИЧЕГО не должен знать о модуле формы. Поток должен иметь событие, через которое он передает результаты своей работы куда надо. Само собой - вызывать это событие нужно в основном потоке, используя средства синхронизации. Форма при создании потока назначает ему обработчик события и выполняет в нем необходимые действия.
  3. Like
    kami отреагировална krapotkin в Фреймворк для стандартного ListView   
    Всем привет!
    После долгого творческого запоя я запилил альфу либы, которая позволяет юзать обычный, не-генномодифицированный ListView.
    Данные подаются в виде модели данных, описание раскладки итема лежит в JSON.

    Для работы пишется примитивный наследник класса-адаптера, который биндит данные модели на элементы из JSON. Я решил, что руками делать это дешевле чем через RTTI
    { TMyAdapter } procedure TMyAdapter.SetupDrawableContent(const ADrawable: TListItemDrawable; const AData: TMyData); begin if SameText( ADrawable.Name, 'text') then begin (ADrawable as TListItemText).Text := AData.Text; end else if SameText( ADrawable.Name, 'detail') then begin (ADrawable as TListItemText).Text := AData.Detail; end else if SameText( ADrawable.Name, 'balance') then begin (ADrawable as TListItemText).Text := FormatFloat('0.00', AData.Balance); end else if SameText( ADrawable.Name, 'reserved') then begin (ADrawable as TListItemText).Text := FormatFloat('0.00', AData.Reserved); end end; Главная хитрость и отличие от стандартного DynamicAppearance+LiveBinding - переменная высота итемов ListView и использование арифметики в описании раскладки.
    Можно указать Detail.Y  = Text.Bottom + 5, ItemHeight = Detail.Bottom + 10, Detail.W = ItemWidth/2 - X
    {"Kind":"rect","Name":"BonusRect","Value":"", "Place":{"X":"itemwidth*3/4","Y":"Text.Y","W":"ItemWidth/4-5","H":"50"}, "BorderColor":"#FF005500", "Color":"lime", "LineWidth":3}, {"TextHAlign":2,"TextVAlign":1,"Kind":"text","Name":"Balance","Value":"", "Place":{"X":"BonusRect.x+5","Y":"Text.Y","W":"BonusRect.w-10","H":"50"}, "WordWrap":true, "Color" :"Black", "Font":{"Size":18,"Style":""}} ], "ItemHeight":"detail.bottom+10", Это дает довольно гибкую систему. Не на все случаи жизни, но все, что нужно, можно после автоматической раскладки дополнительно приписать в OnUpdateObjects 
    Код для работы примерно такой
    procedure TForm1.FormCreate(Sender: TObject); begin data:= TMyDataList.CreateFromFile(ExePath()+'data.json'); // загрузка в модель данных Adapter := TMyAdapter.Create(lvWallets, data.Items, ExePath()+'pattern.json'); // создание адаптера и загрузка шаблона Adapter.Pattern.SetupListView(lvWallets); // задать отступы и разную мелочь Adapter.ResetView(); // здесь в цикле из модели данных создается нужное количество итемов ListView end; procedure TForm1.lvWalletsUpdatingObjects(const Sender: TObject; const AItem: TListViewItem; var AHandled: Boolean); begin Adapter.SetupContent(AItem); // загрузить текст, картинки и другое содержимое в элементы итема Adapter.Pattern.DoLayout(AItem); // поправить раскладку в соответствии с содержимым элементов итема end; Для использования кроме стандартных - текст, картинка, кнопка - создано несколько дополнительных элементов итема - прямоугольник, круг, уголок, линия.
    Отличие от ModernLV - , 
    1) все происходит без правки системных файлов
    2) пока нет колонок и других особых изысков.
    На результат работы смотреть тут. Исходники пока не причесаны, будут чуть позже
    UPD.
    ссылки на репозитории ниже
     
  4. Like
    kami получил реакцию от Евгений Корепов в Поток в Android-е   
    Тут нет кода, выполняемого в доп.потоке.
    Метод Synchronize делает следующее: "приостановить выполнение себя (т.е. доп.потока), переключиться в основной поток, выполнить там действие и после этого вернуться в себя (в доп.поток)".
    Ввиду того, что в коде доп.потока есть только synchronize - то единственное, что поток делает - ждёт, пока выполнится его действие в основном потоке.
    То есть - является абсолютно бессмысленным.
  5. Like
    kami получил реакцию от GASCHE в Поток в Android-е   
    Тут нет кода, выполняемого в доп.потоке.
    Метод Synchronize делает следующее: "приостановить выполнение себя (т.е. доп.потока), переключиться в основной поток, выполнить там действие и после этого вернуться в себя (в доп.поток)".
    Ввиду того, что в коде доп.потока есть только synchronize - то единственное, что поток делает - ждёт, пока выполнится его действие в основном потоке.
    То есть - является абсолютно бессмысленным.
  6. Like
    kami отреагировална krapotkin в Не срабатывает деструктор   
    может, доки прочесть?
    в мобильных платформах используется ARC 
    поэтому, пока есть хоть одна ссылка на объект, он не уничтожается
    зато, когда ссылок нет, он уничтожается самостоятельно
    вызов Delete для компонента нужен для сохранения кросс-платформенной совместимости
    в Windows он работает, в ARC - пустой
    а принудительный вызов деструктора скорее всего только навредит, ибо архитектурный косяк прикрывается костылем...
  7. Like
    kami отреагировална RoschinSpb в Как убить кнопку кликнув на нее саму   
    Не ссоритесь девочки пож.
    Возвращаясь к сути вопроса. Основная сложность тут в том, что в Delphi нельзя разрушать экземпляр класса внутри метода этого класса за исключением тех случаев, когда метод использует только для разрушения Free, DisposeOf. Почему так, а не иначе, какие есть исключения и почему "уменяфсёработает" объяснять долго, поэтому в первом приближении предлагаю принять это за аксиому.
    Обработчики событий OnClick и пр. вызываются из методов классов, так что разрушать контрол внутри события нельзя от слова совсем. Кроме очевидных случаев типа Self.DisposeOf существуют более запутанные варианты, когда к примеру закрывает и разрушается форма, что приводит к разрушению всех дочерних контролов.
    Образно говоря, самоубийства строго запрещены, но не запрещено нанимать киллера и в качестве жертвы указывать себя. Т.е. должен быть некий другой (глобальный) объект который будет разрушать объекты, которые хотели бы самоубицо. Реализацию такого объекта можете придумать сами, или использовать TPurgatory (чистилище, в католическом учении — промежуточное место между раем и адом). Но чтобы убедиться в правильности работы можно создать своего наследника TButton в котором перекрыть деструктор и поставить в нем точку останова. При запуске в режиме отладки посмотрите стек вызова деструктора (надо быть внимательным, он может быть длиннющим), ни где в этом стеке не должно быть метода разрушаемого экземпляра. Если в Вы нашли метод разрушаемого объекта (за исключением вышеуказанных), то Ваш способ удаления работает не правильно и с некоторой долей вероятности будет приводить к AV и другим "неприятностям" которые почти невозможно отловить в режиме отладки.
  8. Like
    kami получил реакцию от Barbanel в Как убить кнопку кликнув на нее саму   
    Вы выискиваете какие-то обходные маневры, генерацию уникальных имен с привлечением guid, обнуление имени после создания...
    а на самом деле ничего из этих костылей не нужно.
  9. Like
    kami получил реакцию от Ingalime в Как убить кнопку кликнув на нее саму   
    помнится, отвечал уже кому-то на форуме. Для динамически создаваемых компонентов просто не указывайте имя. Не нужно оно им. Тогда эта проблема отпадает сама собой.
  10. Like
    kami получил реакцию от Brovin Yaroslav в Как убить кнопку кликнув на нее саму   
    тут нет потока. forceQueue не использует создание потоков, оно пишет напрямую в структуры синхронизации.
    Я у себя уже давно сделал хелпер с одним методом - Release. И его использую не получая сообщений от компилятора.
  11. Like
    kami отреагировална GASCHE в C наступающим Новым Годом!   
  12. Like
    kami отреагировална Slym в Delphi 10.1 FMX android данные с сервера в base64 закодирован хранится pdf как его раскодировать и сохранить на устройстве   
    1. для упрощения кода работы с JSON давно можно использовать сложные пути
    ABase64:=JSON.GetValue<string>('body.nextStep.pdf');
    2.  ну нельзя так: 
    AStreamSource.WriteBuffer(Pointer(ABase64)^, Length(ABase64) * 2); так безопасней AStreamSource:=TBytesStream.Create(TEncoding.UTF8.GetBytes(ABase64));
    3. И сохранять лучше сразу в TFileStream - меньше расход памяти 
    4. не забываем finally Free (их выше нету)... хоть оно и может AUTOREFCOUNT (а может и нет!), но правила хорошего тона никто не отменял
  13. Like
    kami получил реакцию от Tumaso в Delphi 10.1 FMX android данные с сервера в base64 закодирован хранится pdf как его раскодировать и сохранить на устройстве   
    А в чем загвоздка?
    Достать поле из JSON - вроде просто, обычная работа с JSON далеко не самой сложной структуры.
    Раскодировать из Base64 - uses System.NetEncoding; TNetEncoding.Base64.DecodeStringToBytes и сохранить их в файл
    Потом открыть файл через интент.
  14. Like
    kami получил реакцию от Anatoliy в Delphi 10.1 FMX android данные с сервера в base64 закодирован хранится pdf как его раскодировать и сохранить на устройстве   
    А в чем загвоздка?
    Достать поле из JSON - вроде просто, обычная работа с JSON далеко не самой сложной структуры.
    Раскодировать из Base64 - uses System.NetEncoding; TNetEncoding.Base64.DecodeStringToBytes и сохранить их в файл
    Потом открыть файл через интент.
  15. Like
    kami получил реакцию от МихаилЪ чайковЪ в Telega π - Библиотека для работы с Telegram Bot API в Delphi   
    У меня большая просьба: вместо кучи маленьких сообщений, которые вы пишете буквально одно за другим, составьте одно, в которое напишите всё то, что хотели сказать.
    Это не чат, где "кто в онлайне - прочитали, остальным пофиг". Это форум. И искать зерна истины в этой портянке из мимолетных мыслей как минимум неудобно.
  16. Like
    kami отреагировална ophion в Записать картинку с камеры в BLOB   
    Вот пример того, как писать и читать BLOB
    procedure SaveToFireDACBlob; var MemStream: TMemoryStream; begin FireDAC.Connected := True; MemStream := TMemoryStream.Create; try Image1.Bitmap.SaveToStream(MemStream); MemStream.Seek(0,0); FDQueryInsert.ParamByName('Media').LoadFromStream(MemStream,ftBlob); FDQueryInsert.ParamByName('MType').AsString := '0'; FDQueryInsert.ExecSQL(); except on e: Exception do begin ShowMessage(e.Message); end; end; MemStream.Free; FireDAC.Connected := False; end; procedure LoadFromFireDACBlob; var BlobStream: TStream; begin FireDAC.Connected := True; try FDQuerySelect.Open; FDQuerySelect.First; while(not FDQuerySelect.EOF)do begin // access a stream from a blob like this BlobStream := FDQuerySelect.CreateBlobStream(FDQuerySelect.FieldByName('Media'),TBlobStreamMode.bmRead); // access a string from a field like this if (FDQuerySelect.FieldByName('MType').AsString='0') then begin // load your blob stream data into a control ImageViewer.Bitmap.LoadFromStream(BlobStream); end; BlobStream.Free; FDQuerySelect.Next; end; except on e: Exception do begin //ShowMessage(e.Message); end; end; FireDAC.Connected := False; end; {источник http://www.fmxexpress.com/read-and-write-a-blob-field-using-firedac-with-firemonkey-on-android-and-ios/} Касательно работы с изменением качества/размера, считаю что необходимо использовать TBitmapSurface  (unit FMX.Surfaces)
  17. Like
    kami получил реакцию от Barbanel в Telega π - Библиотека для работы с Telegram Bot API в Delphi   
    У меня большая просьба: вместо кучи маленьких сообщений, которые вы пишете буквально одно за другим, составьте одно, в которое напишите всё то, что хотели сказать.
    Это не чат, где "кто в онлайне - прочитали, остальным пофиг". Это форум. И искать зерна истины в этой портянке из мимолетных мыслей как минимум неудобно.
  18. Like
    kami получил реакцию от Maximus в Telega π - Библиотека для работы с Telegram Bot API в Delphi   
    У меня большая просьба: вместо кучи маленьких сообщений, которые вы пишете буквально одно за другим, составьте одно, в которое напишите всё то, что хотели сказать.
    Это не чат, где "кто в онлайне - прочитали, остальным пофиг". Это форум. И искать зерна истины в этой портянке из мимолетных мыслей как минимум неудобно.
  19. Like
    kami получил реакцию от Brovin Yaroslav в Передача параметра программе   
    Самые очевидные ошибки и недочеты:
    1. Почему FindWindowA? Зачем явное указание Ansi-версии этой функции?
    2. cbData - это размер данных в байтах. 1 символ <> 1 байт.
    3. SendMessage - это функция. И она возвращает результат. Его необходимо анализировать.
    4. StrLCopy... вы уверены, что ParamStr(1) влезет в 100 символов?
    Ощущение, что этот код вы скопировали из какого-то VCL примера времен Delphi5
  20. Like
    kami получил реакцию от Brovin Yaroslav в Передача параметра программе   
    Есть волшебная аббревиатура - IPC. Inter process communication.
    Считайте, что у вас два разных приложения.Абсолютно разных. Которым нужно взаимодействовать друг с другом. Одно - источник, второе - приемник.
    Среди вариантов для Windows:
    1. Через сообщения, например - WM_COPYDATA (емнип, так обзывается). Нужно знать хендл окна, которому отправится сообщение (не уверен, что с WM_COPYDATA пройдет фокус с функцией BroadcastMessage) и нужно чтобы целевое приложение было на том же уровне изоляции (UIPI, кажется). Т.е. если приемник запущен от админа, а источник - как обычное приложение - этим способом их не состыковать.
    2. Через NamedPipes. Способ хорош для организации постоянного обмена между двумя любыми приложениями на одном компьютере (не только, но чаще всего - на одном). Для однократной передачи информации держать слушающий пайп в отдельном потоке, наверное, избыточно. Хотя я бы взял именно этот способ.
    3. TCP/IP и надстройки над ним: http, ftp и другое tp. Чаще всего используются для организации обмена между приложениями на разных компьютерах. Для локального - избыточно, да и проблемы с файрволлом могут быть.
    4. Через файловые потоки или данные в файле подкачки. Одно приложение пишет, второе периодически смотрит "а не появилось ли для меня чего нового". Как-то делал даже двусторонний обмен данными по этому механизму.
    Это навскидку. Выбирайте, потом можно говорить дальше.
  21. Haha
    kami отреагировална Brovin Yaroslav в Встреча в Питере 11-го октября 2018   
    Я буду, как обычно. На встрече дам попробовать демки, сделанные с библиотекой FGX Native.
  22. Like
    kami отреагировална Brovin Yaroslav в Как отловить изменение положения контрола   
    Если это свой компонент, то перекройте метод TControl.DoAbsoluteChanged и не забудьте вызывать базовый метод через inherited;
  23. Like
    kami получил реакцию от Tumaso в сборка проекта с библиотеками   
    Вы используете передачу небезопасных параметров между exe и dll?
    Зря.
  24. Like
    kami получил реакцию от Maximus в сборка проекта с библиотеками   
    Вы используете передачу небезопасных параметров между exe и dll?
    Зря.
  25. Like
    kami отреагировална dnekrasov в сборка проекта с библиотеками   
    В свойствах проекта укажите "Link with runtime packages = False"
×
×
  • Создать...