Alex7wrt
-
Постов
508 -
Зарегистрирован
-
Посещение
-
Победитель дней
31
Активность репутации
-
Alex7wrt получил реакцию от Anatoliy в [Apple Store]нужен совет
Заметил, что у вас кнопка "Поделиться с друзьями" имеет Андроидовский дизайн. А у Apple это прямоугольник со стрелкой, направленной вверх.
-
Alex7wrt отреагировална Brovin Yaroslav в Описание TfgImageList
Первый набросок компонента, позволяющего организовать централизованное хранение графических ресурсов для всех платформ.
Основные особенности:
Спроектирован для использования одного экземпляра изображения во многих компонентах. Позволяет хранить все графические ресурсы любых размеров. В будущем не будет грузить картинки в память, если они не используются. А будет подгружать их из файла по мере необходимости. Тем самым будет значительно экономиться память. Хранение именованных графических ресурсов, а не по индексу. Это позволяет отразить в названии назначение картинки. Использование папок. Группировка изображений по смыслу для удобства работы с ними. Возможность загрузки разных картинок для разных устройств, или же загрузить один набор картинок для всех устройств. Удобная и быстрая загрузка изображений путем перетаскивания Хранение отступов изображения. Наглядное отображение картинки в свойствах компонентах. При изменении имени картинки, в компонентах используемых картинку идет автоматическое обновление имени картинки. В стандартном TImageList, из-за индексной структуру все картинки съезжают и при удалении картинки, компонент начинает отображать уже другую картинку.
-
Alex7wrt отреагировална Andrey Efimov в Tokyo, артефакты при отрисовке на канве, Android
Рекомендую вернуться на Berlin Upd2.
Tokyo вышла очень бажная, особенно в плане мобильной разработки. Юзать текущую версию себе дороже выйдет. Нужно дождаться как минимум Upd1, но я думаю лучше сразу Upd2 ждать.
-
Alex7wrt получил реакцию от Евгений Корепов в Почему приложение вылетает при смене ориентации?
Возможно в файле манифеста нужно дописать
android:configChanges="orientation|keyboard|keyboardHidden|screenSize" -
Alex7wrt отреагировална krapotkin в Команды для переключения мониторов, Windows
https://social.msdn.microsoft.com/Forums/vstudio/en-US/7c9fd6d4-cee7-490a-8507-afb9512b3e8b/change-mode-of-multimonitor-setup-programmatically?forum=csharpgeneral
https://msdn.microsoft.com/en-us/library/dd183554(VS.85).aspx
-
Alex7wrt отреагировална Brovin Yaroslav в Как правильно организовать многопоточный алгоритм
Пулл потоков вам в помощь. Это о вопросе долго времени создания и удаления инстансов потоков.
-
Alex7wrt отреагировална Камышев Александр в Как правильно организовать многопоточный алгоритм
имхо, с firemonkey неплохо работает такая схема:
1. создать две потокозащищенные очереди (структуры), на си для этого подходит std::deque, в fmx можно TList. Защита стандартно TCriticalSection;
2. создать несколько потоков, с помощью TEvent указать им ссылки на очереди и критические секции;
3. в потоках:
3.1 TCriticalSection::Enter лочим очередь задач,
3.2 забираем крайнюю задачу
3.3 TCriticalSection::Leave отпускаем очередь задач
3.4 вычисления
3.5 по аналогии с очередью задач лочим очередь результатов, выкладываем результаты, отпускаем
3.6 повтор с пункта 3.1
4. в основном потоке в очереди (тоже lock unlock) выкладывать задачи и при наличии результатов отрисовывать имеющимися средствами.
в 4 пункте нужен будет нужен будет какой-нибудь mmtimer.
-
Alex7wrt отреагировална GASCHE в Как правильно организовать многопоточный алгоритм
Если верить интернету, то в Windows создание потоков и синхронизация с основным потоком довольно "трудозатратая" операция. Для Windows я торможу поток dwStatus := WaitForSingleObject( Parms.fvEventUSB, INFINITE ); Когда надо запустить поток устанавливаю Event, данные из потока скидываю в потокобезопасный буффер и сообщаю об окончании обработки данных установкой другого Event.
-
Alex7wrt отреагировална kami в Как правильно организовать многопоточный алгоритм
А точно нужно дожидаться, пока все потоки отработают? Это не асинхронные задачи?
В качестве еще одного варианта - воспользуйтесь interlocked-функциями. Главный поток определяет, сколько вторичных потоков он запустит. И выставляет нужное значение в integer-переменной.
Каждый поток, завершив виток просчета вызывает InterlockedDecrement(ThreadCounter); При достижении нуля - из последнего вторичного потока вызывается TThread.Queue для сообщения главному потоку "все просчеты завершены". Ну и - потоки входят в спячку, например - на ожидании TEvent. А получив очередную порцию данных для просчета - выходят из ожидания события.
Даже лучше не так: каждый поток при запуске делает InterlockedIncrement(ThreadCounter), не стоит главному потоку выставлять начальное значение, хватит с него и запуска вторичных потоков. А вот всё остальное - да, остается в силе.
-
Alex7wrt отреагировална kami в Как правильно организовать многопоточный алгоритм
Если Windows - то это WaitForMultipleObjects
в остальных случаях - см. TTask.WaitForAll
-
Alex7wrt отреагировална enatechno в Параллельные вычисления, System.Threading
Видео (Task, Future, Parallel, WaitForAll etc.)
и на русском
-
Alex7wrt отреагировална krapotkin в Параллельные вычисления, System.Threading
если у вас возникали проблемы с TThread то лучше понять источник проблем. Использование System.Threading ничем не отличается в этом плане. Те же потоки создаются. Та же синхронизация требуется.
Для меня TTask - это способ в лучшем случае сделать что-то "по-быстрому". Если серьезное что, с отладкой, лучше по-прежнему пользовать TThread.
-
Alex7wrt отреагировална Maximus в Параллельные вычисления, System.Threading
Вкратце вот здесь можно почитать http://proghouse.ru/programming/36-delphi-xe7-ppl
Например, если таск организован как бесконечный цикл, то после завершения каждого таска, в главном потоке увеличивать счётчик. Как только он станет равным количеству запущенных, можно будет обновлять информацию на экране и делать повторный запуск. Разумеется доступ к главному потоку должен быть синхронизирован. А если в таске конечная последовательность действий, то можно просто проверять статусы всех тасков.
Логично. WaitForAll приостанавливает поток в котором был вызван до тех пор, пока не будут завершены все таски.
-
Alex7wrt отреагировална Равиль Зарипов (ZuBy) в [Обзор] #3 ModernListView - динамическая подгрузка контента
Ссылка: http://blog.rzaripov.kz/2016/12/3-modernlistview.html
Автор: Зарипов Равиль @ZuBy
Описание: Реализация динамической подгрузки контента:
Бесконечный скроллинг (например как лента в ВК) Паджинация/Пагинация (постраничная загрузка) -
-
-
Alex7wrt отреагировална Brovin Yaroslav в Определение положения экрана
Самый простой и тупой способ это у формы в OnResize анализировать ширину и высоту. Этот способ будет одинаково работать везде.
Если хочется более нативного варианта решения задачи, то можно воспользоваться TfgApplicationEvents.OnDeviceOrientationChanged.
-
Alex7wrt отреагировална Mars M в Глобальные и локальные координаты позиции курсора
Вот тут скорее всего как раз про это
-
Alex7wrt получил реакцию от AngryOwl в [Android] Отслеживание сворачивания приложения
Добрый день.
Andrey Yefimov в своем блоге подробно описал получение событий жизненного цикла приложения, в том числе и потерю активности.
http://delphifmandroid.blogspot.com/2013/10/blog-post.html
function TForm1.HandleAppEvent(AAppEvent: TApplicationEvent; AContext: TObject): Boolean; begin case AAppEvent of TApplicationEvent.BecameActive: Log('Became Active'); TApplicationEvent.EnteredBackground: Log('Entered Background'); TApplicationEvent.WillBecomeForeground: Log('Will Become Foreground'); end; Result := True; end; procedure TForm1.FormCreate(Sender: TObject); var aFMXApplicationEventService: iFMXApplicationEventService; begin ............ if TPlatformServices.Current.SupportsPlatformService(IFMXApplicationEventService, IInterface(aFMXApplicationEventService)) then aFMXApplicationEventService.SetApplicationEventHandler(HandleAppEvent); ............ end; -
Alex7wrt получил реакцию от MrSergei2017 в TPath Как программно указать TPathData
Например так:
var path: TPathData; .......... Path:=TPathData.Create; Path.Clear; Path.MoveTo(PointF(x[0],y[0])); for i:=1 to N do Path.LineTo(PointF(x[i],y[i])); Path.ClosePath;
-
Alex7wrt получил реакцию от Kitty в TPath Как программно указать TPathData
Например так:
var path: TPathData; .......... Path:=TPathData.Create; Path.Clear; Path.MoveTo(PointF(x[0],y[0])); for i:=1 to N do Path.LineTo(PointF(x[i],y[i])); Path.ClosePath;
-
Alex7wrt получил реакцию от Равиль Зарипов (ZuBy) в Не могу добавить сторонний txt файл в скомпилированый пакет под андроид
То есть просто вы раньше не добавляли наклонную черту-разделитель между директорией и именем файла. Вот и вся загвоздка.
-
Alex7wrt отреагировална ENERGY в как заставить TTimeEdit работать в режиме 24ч.
А если нужно будет указать длительность 24 или 25 часов?
Сделай обычный TLabel и рядом кнопки + - которые будут прибавлять убавлять единицу, или можно использовать TSpinBox
-
Alex7wrt отреагировална Евгений Корепов в Пример с TInAppPurchase
Вот мой юнит для работы с покупками в приложении:
unit UnitInAppPurchase; interface uses // UnitGetDeviceInfo, FMX.InAppPurchase, System.Classes, System.SysUtils, System.Hash; //const // HashMixer = 'p345mcq34mq'; type TBillingEventPurchased = procedure(ASecretKey : String) of object; TBillingEventNotPurchased = procedure of object; TBillingLog = procedure(AMessage : String) of object; TBilling = class private InAppPurchase: TInAppPurchase; FBillingEventPurchased : TBillingEventPurchased; FBillingEventNotPurchased : TBillingEventNotPurchased; FBillingLog : TBillingLog; FNoAdsID : String; FSecretKey : String; FApplicationLicenseKey : String; procedure InAppPurchaseSetupComplete(Sender: TObject); procedure InAppPurchaseProductsRequestResponse(Sender: TObject; const Products: TIAPProductList; const InvalidProductIDs: TStrings); procedure InAppPurchaseError(Sender: TObject; FailureKind: TFailureKind; const ErrorMessage: string); procedure InAppPurchasePurchaseCompleted(Sender: TObject; const ProductID: string; NewTransaction: Boolean); procedure ConsumeComplete(Sender: TObject; const ProductID: string); procedure ConsumeFailed(Sender: TObject; const ProductID, ErrorMessage: string); function GetSecretKey : String; function CheckSecretKey : Boolean; procedure LogMy(AMessage : String); public // Constructor Create(AApplicationLicenseKey, ANoAdsID, ASecretKey : String); constructor Create(AApplicationLicenseKey, ANoAdsID : String); destructor Destroy; procedure CheckPurchase; procedure Purchase; // published property OnPurchased : TBillingEventPurchased read FBillingEventPurchased write FBillingEventPurchased; property OnNotPurchased : TBillingEventNotPurchased read FBillingEventNotPurchased write FBillingEventNotPurchased; property OnPurchasedError : TBillingEventNotPurchased read FBillingEventNotPurchased write FBillingEventNotPurchased; property OnLog : TBillingLog read FBillingLog write FBillingLog; end; implementation //Constructor TBilling.Create(AApplicationLicenseKey, ANoAdsID, ASecretKey : String); Constructor TBilling.Create(AApplicationLicenseKey, ANoAdsID : String); begin FNoAdsID:=ANoAdsID; FApplicationLicenseKey:=AApplicationLicenseKey; // FSecretKey:=ASecretKey; InAppPurchase:=TInAppPurchase.Create(Nil); InAppPurchase.ApplicationLicenseKey:=FApplicationLicenseKey; InAppPurchase.ProductIDs.Add(FNoAdsID); InAppPurchase.OnSetupComplete := InAppPurchaseSetupComplete; InAppPurchase.OnProductsRequestResponse := InAppPurchaseProductsRequestResponse; InAppPurchase.OnError := InAppPurchaseError; InAppPurchase.OnPurchaseCompleted := InAppPurchasePurchaseCompleted; InAppPurchase.OnConsumeCompleted := ConsumeComplete; InAppPurchase.OnConsumeFailed := ConsumeFailed; end; Destructor TBilling.Destroy; begin if Assigned(InAppPurchase) then FreeAndNil(InAppPurchase); inherited; end; procedure TBilling.Purchase; begin try InAppPurchase.PurchaseProduct(FNoAdsID); except LogMy('PurchaseProduct except'); end; end; procedure TBilling.CheckPurchase; begin if CheckSecretKey Then begin LogMy('CheckSecretKey True - Disable Ads'); FSecretKey:=GetSecretKey; if Assigned(OnPurchased) then OnPurchased(FSecretKey); Exit; end; LogMy('CheckSecretKey False - Check InAppPurchase status'); InAppPurchase.SetupInAppPurchase; end; function TBilling.GetSecretKey : String; Var ADeviceIMEI : String; begin // Это был костыль для хранения флага о покупке локально, не оправдал себя и изъят из обращения // ADeviceIMEI:=GetDeviceIMEI; // Result:=System.Hash.THashSHA1.GetHashString(HashMixer+ADeviceIMEI+FNoAdsID); end; function TBilling.CheckSecretKey : Boolean; begin Result:=False; // Result:=FSecretKey.Equals(GetSecretKey); end; procedure TBilling.InAppPurchaseSetupComplete(Sender: TObject); begin LogMy('InAppPurchaseSetupComplete'); try LogMy('InAppPurchase.QueryProducts'); InAppPurchase.QueryProducts; except on E:Exception do LogMy('QueryProducts Exception: '+e.Message); end; end; procedure TBilling.InAppPurchaseProductsRequestResponse(Sender: TObject; const Products: TIAPProductList; const InvalidProductIDs: TStrings); var Product: TProduct; begin LogMy('TMainForm.InAppPurchaseProductsRequestResponse'); LogMy('Start search '+FNoAdsId); LogMy('Products.Count='+Products.Count.ToString); for Product in Products do begin LogMy('Start search '+FNoAdsId); if Product.ProductID = FNoAdsId then begin LogMy('Founded '+FNoAdsId); if InAppPurchase.IsProductPurchased(FNoAdsId) then begin // КУПЛЕНО!!!! LogMy(FNoAdsID+' Yes ProductPurchased'); FSecretKey:=GetSecretKey; if Assigned(OnPurchased) then OnPurchased(FSecretKey); end Else begin LogMy(FNoAdsID+' Not ProductPurchased'); if Assigned(OnNotPurchased) then OnNotPurchased; end; Exit; end; end; LogMy('Product not found - OnNotPurchased'); if Assigned(OnNotPurchased) then OnNotPurchased; LogMy('TMainForm.InAppPurchaseProductsRequestResponse END'); end; procedure TBilling.InAppPurchaseError(Sender: TObject; FailureKind: TFailureKind; const ErrorMessage: string); Var S: String; begin if FailureKind = TFailureKind.ProductsRequest Then S:='ProductsRequest'; if FailureKind = TFailureKind.Purchase Then S:='Purchase'; if Assigned(OnPurchasedError) then OnPurchasedError; LogMy('Purchasing error ('+S+'):'+ErrorMessage); end; procedure TBilling.InAppPurchasePurchaseCompleted(Sender: TObject; const ProductID: string; NewTransaction: Boolean); begin LogMy('TMainForm.InAppPurchasePurchaseCompleted'); if ProductID = FNoAdsID then begin LogMy('HideAndDestroyAds'); FSecretKey:=GetSecretKey; if Assigned(OnPurchased) then OnPurchased(FSecretKey); end; end; procedure TBilling.ConsumeComplete(Sender: TObject; const ProductID: string); begin LogMy('Consume Complete: ' + ProductID); end; procedure TBilling.ConsumeFailed(Sender: TObject; const ProductID, ErrorMessage: string); begin LogMy('Consume Failed: ' + ProductID); end; procedure TBilling.LogMy(AMessage : String); begin if Assigned(OnLog) then OnLog(AMessage); end; end. Использовать вот так:
const NoAdsID = 'mysuperapp_remove_ad'; //название товара, тоже что и консоли разработчика ... private Billing : TBilling; procedure BillingEventPurchased(ASecretKey : String); procedure BillingEventNotPurchased; procedure BillingEventPurchasedError; procedure BillingLog(AMessage : String); procedure DisablePurchaseUI; procedure EnablePurchaseUI; ... FormCreate start Var AppLicenseKey : String; ... AppLicenseKey:='MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxim8ZGAIhK/FPhpXT0r6MXHYxYi1qcMfIiKOkiBDHcRYgRLK7'; AppLicenseKey:=AppLicenseKey+'********************************************************************************'; AppLicenseKey:=AppLicenseKey+'******************************************************************************'; AppLicenseKey:=AppLicenseKey+'*******************************************************************************'; AppLicenseKey:=AppLicenseKey+'Mgv7JP8A+qcDV3lm4M9OKBgxBRLaejxHd1iH3tsMR8PLkKUUf3yrMW8QIDAQAB'; Billing:=TBilling.Create(AppLicenseKey, NoAdsID); Billing.OnPurchased:=BillingEventPurchased; Billing.OnNotPurchased:=BillingEventNotPurchased; Billing.OnPurchasedError:=BillingEventPurchasedError; Billing.OnLog:=BillingLog; Billing.CheckPurchase; FormCreate stop ... procedure TFormMain.BillingEventPurchased(ASecretKey : String); begin // LogMy('CheckSecretKey True - Disable Ads'); Setting.Flags.AdsShowFlag:=False; DisablePurchaseUI; // удаляет кнопки и прочую фигню предлагающую купить товар (товар в данном случае - Удаление рекламы) HideAndDestroyAds; // удаление рекламы из приложения, так как товар куплен // Setting.SecretKey:=ASecretKey; // SaveFormState; end; procedure TFormMain.BillingEventNotPurchased; begin Setting.Flags.AdsShowFlag:=True; EnablePurchaseUI; ShowAds; end; procedure TFormMain.BillingEventPurchasedError; begin Setting.Flags.AdsShowFlag:=True; // EnablePurchaseUI; ShowAds; end; procedure TFormMain.BillingLog(AMessage : String); begin // Memo.Lines.Insert(0,AMessage); end; procedure TFormMain.DisablePurchaseUI; begin ButtonRemoveAds.Visible:=False; LayoutRemoveAds.Visible:=False; end; procedure TFormMain.EnablePurchaseUI; begin LayoutRemoveAds.Visible:=True; ButtonRemoveAds.Visible:=True; end;
-
Alex7wrt отреагировална Fedor K в TListView: список в виде CheckBox в ListViewItem
У стандартного TListView уже все есть:
//устанавливаем режим редактирования у списка либо в редакторе свойств выставляем ListView1.EditMode := True; //... //Получаем список всех выбранных элементов ListView1.Items.CheckedIndexes(true); //обращаться к свойству текущего элемента так: ListView1.Items.SetChecked(const Index: Integer; const Value: Boolean); ListView1.Items.GetChecked(const Index: Integer): Boolean;