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

Евгений Корепов

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

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

  • Посещение

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

    100

Ответы сообщества

  1. Пост Евгений Корепов - сообщение в как очистить память клавиатуры был отмечен как ответ   
    Нашел еще более изящный способ, без исчезновения/показа клавиатуры:
    procedure TForm1.Button1Click(Sender: TObject); begin Memo1.SelectAll; Memo1.DeleteSelection; end;  
  2. Пост Евгений Корепов - сообщение в Непонятная ситуация в Webbrowser был отмечен как ответ   
    Продукты Apple не умеют корректно декодировать URL. Это исключительно ваша задача. Все другие платформы делают это автоматически.
    Вам нужно добавить код:
    uses System.NetEncoding; ... URL:='http://blabla.com/php/pay2.php?eks=' + System.NetEncoding.TURLEncoding.URL.Encode('блабла&sum=100&hash=блабла&orderid=205');  
  3. Пост Евгений Корепов - сообщение в [Android] обмен сообщениями между потоками и формой был отмечен как ответ   
    На основе вашего кода накидал свой вариант.
    Главная форма создает 2 очереди: FMyQueueIn - очередь из потока в форму, и FMyQueueOut - очередь из формы в поток. Тип очередей сделал вот такой: 
    TMyMessage = record StringMessage : String; PackedNumber : Integer; X : Integer; Y : Integer; Z : Integer; end; Вдруг вам понадобятся данные в виде цифр, а не в виде строки.
    Конструктор потока получает в качестве параметров эти два потока (но поменянные местами  - чтоб в контексте потока они соотвествовали своим названиям).
    Так же добавил по нажатию кнопки отправку текстового  сообщения из формы в поток. Поток получает его, добавляет в начало фразу 'Из главного потока получено: '  и возвращает в форму с очередными данными.
    Код и архив проекта прилагаю:
    unit Unit1; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, Generics.Collections, System.Generics.Collections, FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo, FMX.StdCtrls; type TMyMessage = record StringMessage : String; //Я вынужден был добавить еще строку, иначе в Rio косяк https://quality.embarcadero.com/browse/RSP-21806 PackedNumber : Integer; X : Integer; Y : Integer; Z : Integer; end; TMyQueue = TThreadedQueue<TMyMessage>; TMyThread = class(TThread) protected FMyQueueIn : TMyQueue; FMyQueueOut : TMyQueue; FPackedNumber : Integer; procedure Execute; override; public constructor Create(AMyQueueIn, AMyQueueOut : TThreadedQueue<TMyMessage>); end; TForm1 = class(TForm) Memo: TMemo; ToolBar1: TToolBar; Button1: TButton; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure Button1Click(Sender: TObject); private { Private declarations } FMyQueueIn: TMyQueue; FMyQueueOut: TMyQueue; FMyThread : TMyThread; procedure OnIdle(Sender: TObject; var Done: Boolean); public { Public declarations } end; var Form1: TForm1; implementation {$R *.fmx} constructor TMyThread.Create(AMyQueueIn, AMyQueueOut : TMyQueue); begin FMyQueueIn:=AMyQueueIn; FMyQueueOut:=AMyQueueOut; FPackedNumber:=0; inherited Create(False); end; procedure TMyThread.Execute; var AMyMessage : TMyMessage; S : String; begin while (not Terminated) do begin S:=''; if FMyQueueIn.PopItem(AMyMessage) = TWaitResult.wrSignaled then S:='Из главного потока получено: ' + AMyMessage.StringMessage; Inc(FPackedNumber); with AMyMessage do begin StringMessage:=S; PackedNumber:=FPackedNumber; X:=Random(1000); Y:=Random(1000); Z:=Random(1000); end; // Отправляем Record в главную форму (главный поток) FMyQueueOut.PushItem(AMyMessage); sleep(random(800)); end; end; procedure TForm1.FormCreate(Sender: TObject); begin FMyQueueIn:=TMyQueue.Create(30, 1000, 10); FMyQueueOut:=TMyQueue.Create(30, 1000, 10);; Application.OnIdle:=OnIdle; // При передаче в поток меняем местами In и Out - чтоб к контексте потока Out формы был In потока и наоборот. FMyThread:=TMyThread.Create(FMyQueueOut, FMyQueueIn); end; procedure TForm1.FormDestroy(Sender: TObject); begin FMyThread.Terminate; FMyThread.WaitFor; FMyThread.Free; FMyQueueIn.Free; FMyQueueOut.Free end; procedure TForm1.OnIdle(Sender: TObject; var Done: Boolean); Var AMyMessage : TMyMessage; S : String; begin while FMyQueueIn.PopItem(AMyMessage) = TWaitResult.wrSignaled do begin S:='Пакет№ ' + AMyMessage.PackedNumber.ToString + ' X=' + AMyMessage.X.ToString + ' Y=' + AMyMessage.Y.ToString + ' Z=' + AMyMessage.Z.ToString + ' ' + AMyMessage.StringMessage; Memo.BeginUpdate; Memo.Lines.Add(S); Memo.GoToTextEnd; Memo.EndUpdate; end; end; procedure TForm1.Button1Click(Sender: TObject); Var AMyMessage : TMyMessage; begin AMyMessage.StringMessage:='Сообщение для потока № ' + Random(100).ToString; FMyQueueOut.PushItem(AMyMessage); end; end.  
    test161.zip
  4. Пост Евгений Корепов - сообщение в Как застать TWebBrowser обрабатывать адреса эл. почты (Android) был отмечен как ответ   
    Прошу прощения, я ввел вас в заблуждение (тестировал на одном своем проекте). Открытие подобных ссылок вы должны делать самостоятельно, обрабатывая событие браузера ShouldStartLoadWithRequest.
    Вот код:
    uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, {$IFDEF ANDROID} Androidapi.JNI.Net, Androidapi.JNI.GraphicsContentViewText, Androidapi.Helpers, {$ENDIF ANDROID} FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls, FMX.WebBrowser, FMX.Controls.Presentation; ..... const ConstMainURL = 'http://www.docme.ru/contacts'; .... procedure THeaderFooterForm.WebBrowser1ShouldStartLoadWithRequest( ASender: TObject; const URL: string); begin if Not URL.StartsWith(ConstMainURL) then // Если ссылка перехода отличается от базовой, то открываем ее через активити begin WebBrowser1.Stop; OpenURL(URL); end; end; procedure THeaderFooterForm.OpenURL(const AUrl: string); {$IFDEF ANDROID} var Uri: Jnet_Uri; OpenLinkIntent: JIntent; {$ENDIF ANDROID} begin {$IFDEF MSWINDOWS} ShellExecute(0, 'open', PChar(AUrl), nil, nil, SW_SHOWNORMAL); {$ENDIF MSWINDOWS} {$IFDEF ANDROID} Uri := StrToJURI(AUrl); OpenLinkIntent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_VIEW, Uri); TAndroidHelper.Activity.startActivity(OpenLinkIntent); {$ENDIF ANDROID} end; И прикрепляю ваш проект с моими изменениями
    WebPrj.zip
  5. Пост Евгений Корепов - сообщение в Как получить содержимое item при событии OnDeleteItem в ListView был отмечен как ответ   
    procedure TForm1.ListView1DeleteItem(Sender: TObject; AIndex: Integer); Var AMyItemIndex : Integer; begin AMyItemIndex:=(ListView1.Items.Item[AIndex] as TListViewItem).Detail.ToInteger; ... end;  
  6. Пост Евгений Корепов - сообщение в Разрешения для приложения не вступают в силу на Android был отмечен как ответ   
    Вот как то так, на базе штатного примера:
      Такс, я малость лопухнулся, это пример я уже под карнавал переделал, работать на токио и остальных версиях не будет. Так что я его удалил. Поищите по форуму - уже неоднократно обсуждалась тема.
  7. Пост Евгений Корепов - сообщение в Сохранение данных из Андроид устройства в сетевую папку. был отмечен как ответ   
    Вот, по моему мнению, самый просто и быстрый способ:
     Устанавливаете на сервере FTP сервер. К примеру SlimFTPd (http://www.whitsoftdev.com/slimftpd/), его можно запустить как сервис. Не забываете настроить папку, пользователя (с паролем) и остальное. Там все просто.
    В своем приложении отправка файла на FTP сервер займет у вас несколько строчек:
    IdFTP:=TIdFTP.Create; IdFTP.Host:=Host; IdFTP.Username:=ALogin; IdFTP.Password:=APassword; IdFTP.Passive:=True; IdFTP.TransferType:=ftBinary; IdFTP.ReadTimeout:=ConstFTPTimeout; IdFTP.TransferTimeout:=ConstFTPTimeout; try IdFTP.Connect; except on E : Exception do begin Error:=True; ErrorMessage:=E.Message; end; end; AFilePathLocal:='Путь к файлу который хотите отправить'; AFilePathRemote:='/Download/'; if TFile.Exists(AFilePathLocal) then try IdFTP.Put(AFilePathLocal, AFilePathRemote); except on E : Exception do begin Error:=True; ErrorMessage:=E.Message; end; end; IdFTP.Disconnect; IdFTP.Free; Вот как то так.
    P.S. Не верно написал путь для отправки.
    Исправил AFilePathRemote:='ftp://192.168.0.150/Download/'; на AFilePathRemote:='/Download/';
  8. Пост Евгений Корепов - сообщение в Обработка анимированных GIF по рецепту китайского коллеги был отмечен как ответ   
    Принцип работы такой:
    На форму кладете стандартный TImage Создаете экземпляр TGifPlayer Задаете свойство FGifPlayer.Image:=Image; где Image это лежащая на форме TImage Загружаете гифку FGifPlayer.LoadFromFile('D:\Embarcadero\Projects\ShareCode\FMX.GifUtils\GIF_Example.gif'); Запускаем проигрывание гифки FGifPlayer.Play; Вот код:
    unit UnitFormMain; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.GifUtils, FMX.Objects; type TFormMain = class(TForm) Image: TImage; procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } FGifPlayer : TGifPlayer; end; var FormMain: TFormMain; implementation {$R *.fmx} procedure TFormMain.FormCreate(Sender: TObject); begin FGifPlayer:=TGifPlayer.Create(Self); FGifPlayer.Image:=Image; FGifPlayer.LoadFromFile('D:\Embarcadero\Projects\ShareCode\FMX.GifUtils\GIF_Example.gif'); FGifPlayer.Play; end; end. Вот демо проект во вложении:
     
    FMX.GifUtils.Demo.zip
  9. Пост Евгений Корепов - сообщение в Не соблюдается порядок добавляемых компонентов был отмечен как ответ   
    Кроме Align = Top, установите еще свойство Top = 10000, что бы они добавлялись заведомо ниже всех существующий элементов. Если не устанавливать Top, то по умолчанию позиция у всех будет 0 и порядок элементов будет зависеть от погрешности вычислений Single.
  10. Пост Евгений Корепов - сообщение в ListView задать размер скроллбара был отмечен как ответ   
    Во время добавления так же можно отключить обработчики  ListView1.OnUpdatingObjects и(или) ListView1.OnUpdateObject (если у вас в них есть какой либо код).
    ListView1.BeginUpdate; ListView1.OnUpdatingObjects:=Nil; ListView1.OnUpdateObjects:=Nil; for i := 0 to List.Count - 1 do begin LVItems := ListView1.Items.Add; LVItems.Data['MyData']:=... ... end; ListView1.OnUpdatingObjects:=ListView1UpdateObjects; ListView1.OnUpdateObjects:=ListView1UpdatingObjects; ListView1.EndUpdate;  
  11. Пост Евгений Корепов - сообщение в ListView с картинкой - не работает под Android был отмечен как ответ   
    Блин! У меня нет слов! Проблема решилась многочасовым гугленьем. Самое смешное  - решение нашел на этом форуме в сообщении http://fire-monkey.ru/topic/3014-ne-otobrazhaetsya-tlistitemimage/?do=findComment&comment=18113 , спасибо огромное @DimArt за решение!
    Вся проблема была в недокументированном свойстве OwnsBitmap, достаточно после загрузки изображения в ListItemImage.Bitmap добавить строчку ListItemImage.OwnsBitmap:=True; И все начинает отлично работать под Android.
    Документация ембаркадеро говорит нам о этом свойстве следущее "Embarcadero Technologies does not currently have any additional information." (http://docwiki.embarcadero.com/Libraries/Tokyo/en/FMX.ListView.Types.TListItemImage.OwnsBitmap). Б*%дь, ну как так то? У меня одни маты, два дня просраны вхолостую...
    Итоговый, работоспособный код функции SetupImageObject ниже
    function SetupImageObject(const AName : String; AWidth, AHeight, X , Y : Single; AAlign, AVertAlign: TListItemAlign) : TListItemImage; Var AImageURL : String; begin Result:=TListItemImage(AItem.View.FindDrawable(AName)); if Result=Nil then begin Result:=TListItemImage.Create(AItem); AImageURL:=AItem.Data['ImageURL'].AsString; Result.Bitmap:=LoadImageFromURL(AImageURL); Result.OwnsBitmap:=True; end; Result.Name:=AName; Result.Width:=AWidth; Result.Height:=AHeight; Result.PlaceOffset.X:=X; Result.PlaceOffset.Y:=Y; Result.Align:=AAlign; Result.VertAlign:=AVertAlign; Result.ScalingMode:=TImageScalingMode.StretchWithAspect; end;  
  12. Пост Евгений Корепов - сообщение в Одинаковые логотипы и картинки был отмечен как ответ   
    Получите от медицинского центра разрешение на использование их логотипа. Можно на русском языке. Текст произвольный - поручаем Kitty изготовление приложения и разрешаем использование логотипов, торговых марок, фирменных наименований и т.д. в приложениях. 
    Подробнее здесь https://play.google.com/intl/ru/about/ip-deception-spam/impersonation-ip/ 
    И отправьте скан (pdf к примеру) этого письма в гугл, подробности тут https://support.google.com/googleplay/android-developer/answer/6320428
     
    Последнее время все сложнее публиковать приложения, правила уже балансируют на грани маразма. Одно моё приложение заблокировали по причине того что я "выдавал" себя за магазин линолиума в какой то немецкой деревушке - логотип приложения был немного искаженной зеркальной копией логотипа этого магазина, так же отличались цвета - у магазина желтый, у приложения оранжевый. Вот такие дела... 
    Так же сильно зависит от места модерации - если повезет попасть в британский офис, то вам досконально объяснят причину блокировки, приведут примеры правильного и не правильного решения вашего вопроса. Вот пример из моей практики:
    Если не повезет попасть в подмосковье - то вы не получите комментариев, апелляция будет проигнорирована и относится к вам будут как к ничтожеству. Российская специфика - мальчик получивший работу в Великом Гугле, благодаря двоюродному дяде, сам становится Великим. И естественно он обязан быть гавном, так у него в должностной инструкции написано ;-)
  13. Пост Евгений Корепов - сообщение в Сборка Application Store был отмечен как ответ   
    Посмотрите Deployment проекта, конфигурации Debug и Release, возможно в режиме Release не отмечена какая то из библиотек .so
  14. Пост Евгений Корепов - сообщение в NetHTTPClient и личные сообщения на сайте forum.ru-board.com на C++Builder 10.1 был отмечен как ответ   
    Сейчас посмотрю исходники. Минутку...
    Да, в Update1 System.Net.HttpClient.pas исправлен :-)
  15. Пост Евгений Корепов - сообщение в как правильно очистить данные модели был отмечен как ответ   
    Вот кусок кода исходников из XE8 unit FMX.Controls.Model :
    procedure TDataModel.SetData(const Index: string; const Value: TValue); var DataRecord: TDataRecord; begin if FDataSource = nil then FDataSource := TDictionary<string, TValue>.Create; if Value.IsEmpty then FDataSource.Remove(Index) else FDataSource.AddOrSetValue(Index, Value); DataRecord := TDataRecord.Create(Index, Value); SendMessage<TDataRecord>(MM_DATA_CHANGED, DataRecord); end; Судя по коду, нужно делать как то так :
    procedure TForm1.FormCreate(Sender: TObject); begin Edit1.Model.Data['aaa']:=TStringList.Create; Edit1.Model.Data['aaa'].AsType<TStringList>.Add('111'); Edit1.Model.Data['aaa'].AsType<TStringList>.Add('222'); Edit1.Model.Data['aaa'].AsType<TStringList>.Add('333'); Edit1.Model.Data['aaa'].AsType<TStringList>.Clear; Edit1.Model.Data['aaa'].AsType<TStringList>.Free; Edit1.Model.Data['aaa']:=TValue.Empty; if Edit1.Model.Data['aaa'].IsEmpty Then beep; end;  
  16. Пост Евгений Корепов - сообщение в Раскрытый список как ComboEdit был отмечен как ответ   
    Тут главное не забыть RadioButton1.GroupName:='SelectDestiny' и так для всех RadioButton одинаковый GroupName, тогда выбираться будет только один.
    procedure TFormMain.CreateOpenComboEdit; Const GroupName = 'Select destiny'; Var I : Integer; ALisBoxItem : TListBoxItem; ARadioButton : TRadioButton; begin for I := 0 to 5 do begin ALisBoxItem:=TListBoxItem.Create(ListBox); ALisBoxItem.Text:=''; ARadioButton:=TRadioButton.Create(ALisBoxItem); ARadioButton.GroupName:=GroupName; ARadioButton.Text:=GroupName+' '+I.ToString; ARadioButton.Align:=TAlignLayout.Client; ALisBoxItem.AddObject(ARadioButton); ListBox.AddObject(ALisBoxItem); end; end;  
  17. Пост Евгений Корепов - сообщение в Возвращаясь к вопросу о подсчете высоты текста TListView был отмечен как ответ   
    Делать было нечего, дело было вечером... Вот попробовал, свою процедуру чуть изменил, добавил константы ширины скроллбара из ListView
    unit Unit1; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.ListView.Types, FMX.ListView, FMX.TextLayout, System.StrUtils; const {$IFDEF IOS} DefaultScrollBarWidth = 7; {$ELSE} {$IFDEF MACOS} DefaultScrollBarWidth = 7; {$ENDIF} {$ENDIF} {$IFDEF MSWINDOWS} DefaultScrollBarWidth = 16; {$ENDIF} {$IFDEF ANDROID} DefaultScrollBarWidth = 7; {$ENDIF} type TForm1 = class(TForm) ListView1: TListView; procedure FormCreate(Sender: TObject); procedure ListView1UpdateObjects(const Sender: TObject; const AItem: TListViewItem); private { Private declarations } public { Public declarations } FTextLayout : TTextLayout; procedure CalculateTListViewItemHeight(Sender: TObject); end; var Form1: TForm1; implementation {$R *.fmx} procedure TForm1.FormCreate(Sender: TObject); Var AText : String; begin FTextLayout := TTextLayoutManager.DefaultTextLayout.Create; AText:= 'FMX.Dialogs.MessageDlg - RAD Studio API Documentation ' + 'docwiki.embarcadero.com/.../en/FMX.Dialogs.MessageDlg ' + 'docwiki.embarcadero.com/.../en/FMX.Dialogs.MessageDlg ' + 'Перевести эту страницу ' + 'docwiki.embarcadero.com/.../en/FMX.Dialogs.MessageDlg ' + 'Перевести эту страницу ' + 'docwiki.embarcadero.com/.../en/FMX.Dialogs.MessageDlg ' + 'Перевести эту страницу ' + 'docwiki.embarcadero.com/.../en/FMX.Dialogs.MessageDlg ' + 'Перевести эту страницу ' + 'docwiki.embarcadero.com/.../en/FMX.Dialogs.MessageDlg ' + 'Перевести эту страницу ' + 'docwiki.embarcadero.com/.../en/FMX.Dialogs.MessageDlg ' + 'Перевести эту страницу ' + 'docwiki.embarcadero.com/.../en/FMX.Dialogs.MessageDlg ' + 'Перевести эту страницу ' + 'docwiki.embarcadero.com/.../en/FMX.Dialogs.MessageDlg ' + 'Перевести эту страницу ' + 'docwiki.embarcadero.com/.../en/FMX.Dialogs.MessageDlg ' + 'Перевести эту страницу ' + 'docwiki.embarcadero.com/.../en/FMX.Dialogs.MessageDlg ' + 'Перевести эту страницу ' + '11 февр. 2016 г. - function MessageDlg(const AMessage: string; const ADialogType: TMsgDlgType; const ... extern DELPHI_PACKAGE int __fastcall MessageDlg _DEPRECATED_ATTRIBUTE1("Use FMX.DialogService methods") ' + 'Перевести эту страницу ' + '11 февр. 2016 г. - function MessageDlg(const AMessage: string; const ADialogType: TMsgDlgType; const ... extern DELPHI_PACKAGE int __fastcall MessageDlg _DEPRECATED_ATTRIBUTE1("Use FMX.DialogService methods") ' + 'Перевести эту страницу ' + '11 февр. 2016 г. - function MessageDlg(const AMessage: string; const ADialogType: TMsgDlgType; const ... extern DELPHI_PACKAGE int __fastcall MessageDlg _DEPRECATED_ATTRIBUTE1("Use FMX.DialogService methods") ' + 'Перевести эту страницу ' + '11 февр. 2016 г. - function MessageDlg(const AMessage: string; const ADialogType: TMsgDlgType; const ... extern DELPHI_PACKAGE int __fastcall MessageDlg _DEPRECATED_ATTRIBUTE1("Use FMX.DialogService methods") ' + '(const System::UnicodeString AMessage, const ... Warning: MessageDlg is deprecated. ***'; with ListView1.Items.Add do Text:=AText; with ListView1.Items.Add do Text:= ReverseString(AText); with ListView1.Items.Add do Text:= AText; end; procedure TForm1.ListView1UpdateObjects(const Sender: TObject; const AItem: TListViewItem); begin CalculateTListViewItemHeight(AItem); end; procedure TForm1.CalculateTListViewItemHeight(Sender: TObject); var AListItem: TListViewItem; AListView: TListView; begin if (Sender is TListViewItem) then begin AListItem := Sender as TListViewItem; if (AListItem.Parent is TListView) then AListView:=AListItem.Parent as TListView Else Exit; FTextLayout.BeginUpdate; try FTextLayout.Text:=AListItem.Text; FTextLayout.MaxSize:=TPointF.Create(AListView.Width - AListView.ItemSpaces.Left - AListView.ItemSpaces.Right - DefaultScrollBarWidth, 1000); FTextLayout.Font:=AListView.ItemAppearanceObjects.ItemObjects.Text.Font; FTextLayout.WordWrap:=AListView.ItemAppearanceObjects.ItemObjects.Text.WordWrap; FTextLayout.Trimming:=AListView.ItemAppearanceObjects.ItemObjects.Text.Trimming; FTextLayout.HorizontalAlign:=AListView.ItemAppearanceObjects.ItemObjects.Text.TextAlign; FTextLayout.VerticalAlign:=AListView.ItemAppearanceObjects.ItemObjects.Text.TextVertAlign; finally FTextLayout.EndUpdate; end; AListItem.Height:=Round(FTextLayout.Height + AListView.ItemSpaces.Top + AListView.ItemSpaces.Bottom); end; end; end.  


  18. Пост Евгений Корепов - сообщение в Дата/время в сервисе был отмечен как ответ   
    У вас ошибка в коде, неверно SDT:=DateTimeToStr(Now()), а вот так верно SDT:=DateTimeToStr(ADateTime,FormatSettings). Вы не использовали выставленные в FormatSettings значения.
    Но есть и другие варианты хранения:
    var IniFile: TIniFile; SDT: string; FS: TFormatSettings; ADateTime : TDateTime; ADateTimeUnix : Int64; begin IniFile := TIniFIle.Create(System.IOUtils.TPath.Combine( System.IOUtils.TPath.GetDocumentsPath, 'D.ini')); try ADateTime:=Now(); // Ваш вариант FormatSettings.ShortDateFormat:='yyyy-mm-dd'; FormatSettings.DateSeparator := '-'; FormatSettings.LongTimeFormat := 'hh:nn:ss'; FormatSettings.TimeSeparator := ':'; SDT:=DateTimeToStr(ADateTime,FormatSettings); // Обратите внимание на второй параметр // Вариант с использованием настроек устройства FS:=TFormatSettings.Create; // В FS теперь настройки локали устройства SDT:=DateTimeToStr(ADateTime,FS); // Вариант с использованием ISO8601 SDT:=DateToISO8601(ADateTime); //Вариант хранения в Unix формате - наиболее надежный в плане обратимости ADateTimeUnix:=DateTimeToUnix(ADateTime); SDT:=ADateTimeUnix.ToString; IniFile.WriteString('SERVER','LastOnline',SDT); finally IniFile.free; end; end; Если не нужна человекочитаемость ini файла, то лучше хранить в UNIX формате
  19. Пост Евгений Корепов - сообщение в Тормоза при первом переключении вкладок TTabControl был отмечен как ответ   
    Проблема решена. Но решена методом научного тыка. Сделал так:
        ATabItem:=TabControl.Add();     ATabItem.DisableDisappear:=True; и задержка исчезла совсем. Так же убрал все рекурсивные предварительные  ApplyStyleLookup, тоже работает идеально.
    Help и сайты с документацией молчат по поводу DisableDisappear - это свойство науке не известно. По крупицам собраны сакральные знания,позволяют догадываться что отвечает оно за "запрет контролу выгружать стиль, когда он скрывается со сцены (С) Brovin Yaroslav"
  20. Пост Евгений Корепов - сообщение в Установка ScrollViewPos после добавления ListViewItem был отмечен как ответ   
    Вы будете смеяться, но проблема решена. Методом научного тыка.
     
    Не работающая установка значения ListView.ScrollViewPos решается следующей строкой   ListView.ItemIndex:=0; (Не важно 0 или любое другое число).
    Т.е. для того чтоб заработало делаем так:
      ListView.ItemIndex:=0;   ListView.ScrollViewPos:=333; // Ура, работает!!! Почему так работает, я не понял.
  21. Пост Евгений Корепов - сообщение в Получить размер файла был отмечен как ответ   
    Ура! Я победил проблему. Причем с помощью почти забытой мной процедуры FindFirst ;-) Код работает корректно под Windows и Android. Файл не передергивается, антивирус спокоен.
    function TFileManager.GetFileSize(APath : String) : String; Var AFileSizeByte : Int64;     AFileSizeFloat : Double;     SearchRec : TSearchRec;     FileAttrs: Integer; begin   FileAttrs :=faArchive;   FileAttrs := FileAttrs + faAnyFile;   Result:='unknow';   AFileSizeByte:=0;   try     FindFirst(APath,FileAttrs,SearchRec);     AFileSizeByte:=SearchRec.Size;     FindClose(SearchRec);   except       Exit;   end;   if AFileSizeByte<1024 then   begin     Result:=Format('%d',[AFileSizeByte])+' Byte';     Exit;   end;   if AFileSizeByte<1048576 then   begin     AFileSizeFloat:=AFileSizeByte/1024;     Result:=Format('%6.3f',[AFileSizeFloat])+' KByte';     Exit;   end;   if AFileSizeByte<1073741824 then   begin     AFileSizeFloat:=AFileSizeByte/1048576;     Result:=Format('%6.3f',[AFileSizeFloat])+' MByte';     Exit;   end;   AFileSizeFloat:=AFileSizeByte/1073741824;   Result:=Format('%6.3f',[AFileSizeFloat])+' GByte'; end;
  22. Пост Евгений Корепов - сообщение в PushEvents без Provider был отмечен как ответ   
    Var HDevicePushParams : TDevicePushParams;        APushService : TPushService;       AServiceConnection : TPushServiceConnection;       SQuery : String; begin     APushService:=TPushServiceManager.Instance.GetServiceByName(TPushService.TServiceNames.GCM);     APushService.AppProps[TPushService.TAppPropNames.GCMAppID]:='ХХХХХХХХХХХХХХХХ';     AServiceConnection:=TPushServiceConnection.Create(APushService);     AServiceConnection.Active:=True;     AServiceConnection.OnChange:=ServiceConnectionOnChange;     AServiceConnection.OnReceiveNotification:=ServiceConnectionOnReceiveNotification;     HDevicePushParams.DeviceID:=APushService.DeviceIDValue[TPushService.TDeviceIDNames.DeviceID];     HDevicePushParams.DeviceToken:=APushService.DeviceTokenValue[TPushService.TDeviceTokenNames.DeviceToken];   SQuery:=APIURL+'?DeviceID='+HDevicePushParams.DeviceID+'&DeviceToken='+HDevicePushParams.DeviceToken;     HTTPThread:=THTTPThread.Create(SQuery,FQueue);  // Здесь просто отправка на сервер в потоке. Сервер принимает стоку и складывает в базу пары "DeviceID - DeviceToken", можно еще что нибудь отправлять, чтоб точно идентифицировать клиента.
    А на сервере все еще проще. Вот php: $title = 'Это заголовок'; $message = 'Это текст сообщения.' $devices = 'DeviceToken - один конкретный получатель'; $apiKey = "AIzaХХХХХХХХХХХХХХХХХХХХХХХХХХХХХХХХХХХХ"; $gcpm = new GCMPushMessage($apiKey); $gcpm->setDevices($devices); $response = $gcpm->send($message, array('title' => $title)); Лениво было писать велосипед, использовал готовую отсылалку https://github.com/mattg888/GCM-PHP-Server-Push-Message . Там все просто, она заворачивает все в json и отправляет  на http
  23. Пост Евгений Корепов - сообщение в Ввод числа - самый простой способ фильтрации был отмечен как ответ   
    Посмотрел на код и решил еще на пару строк сократить, совместил проверку на "пусто" и минус в одном условии
    procedure TFormMain.Edit1ChangeTracking(Sender: TObject); Var FEdit : TEdit; FFloat : Single; begin If Not (Sender is TEdit) Then // Защитимся от не выспавшегося самого себя Exit; FEdit:=(Sender as TEdit); // Для удобства... FEdit.Text:=FEdit.Text.Replace(' ',''); // Убираем случайные пробелы if (FEdit.Text.IsEmpty) or (FEdit.Text.Equals('-')) then // Если пусто (ничего не введено или все удалено) или только минус, ничего не делаем Exit; FEdit.Text:=FEdit.Text.Replace('.',','); // Заменяйм точку запятой if FEdit.Text.Equals(',') then // Если введен разделитель, добавляем перед ним ноль для красоты (не обязательно) begin FEdit.Text:='0,'; FEdit.CaretPosition:=FEdit.CaretPosition+1; // без этого курсор останется между нулём и запятой end; if TryStrToFloat(FEdit.Text,FFloat) Then // Пробуем преобразовать в число FEdit.TagString:=FEdit.Text // Если удалось, сохраняем в временном хранилище Else FEdit.Text:=FEdit.TagString; // Если не удалось, восстанавливаем из временного хранилища end;
  24. Пост Евгений Корепов - сообщение в FilterChar в XE8 Update 1 на Андроид так и не работает? был отмечен как ответ   
    Ответ по Update1:
    Ответ по FilterChar 
×
×
  • Создать...