Евгений Корепов
-
Постов
738 -
Зарегистрирован
-
Посещение
-
Победитель дней
101
Ответы сообщества
-
Пост Евгений Корепов - сообщение в как очистить память клавиатуры был отмечен как ответ
Нашел еще более изящный способ, без исчезновения/показа клавиатуры:
procedure TForm1.Button1Click(Sender: TObject); begin Memo1.SelectAll; Memo1.DeleteSelection; end;
-
Пост Евгений Корепов - сообщение в Непонятная ситуация в Webbrowser был отмечен как ответ
Продукты Apple не умеют корректно декодировать URL. Это исключительно ваша задача. Все другие платформы делают это автоматически.
Вам нужно добавить код:
uses System.NetEncoding; ... URL:='http://blabla.com/php/pay2.php?eks=' + System.NetEncoding.TURLEncoding.URL.Encode('блабла&sum=100&hash=блабла&orderid=205');
-
Пост Евгений Корепов - сообщение в [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
-
Пост Евгений Корепов - сообщение в Как застать 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
-
Пост Евгений Корепов - сообщение в Как получить содержимое item при событии OnDeleteItem в ListView был отмечен как ответ
procedure TForm1.ListView1DeleteItem(Sender: TObject; AIndex: Integer); Var AMyItemIndex : Integer; begin AMyItemIndex:=(ListView1.Items.Item[AIndex] as TListViewItem).Detail.ToInteger; ... end;
-
Пост Евгений Корепов - сообщение в Разрешения для приложения не вступают в силу на Android был отмечен как ответ
Вот как то так, на базе штатного примера:
Такс, я малость лопухнулся, это пример я уже под карнавал переделал, работать на токио и остальных версиях не будет. Так что я его удалил. Поищите по форуму - уже неоднократно обсуждалась тема.
-
Пост Евгений Корепов - сообщение в Сохранение данных из Андроид устройства в сетевую папку. был отмечен как ответ
Вот, по моему мнению, самый просто и быстрый способ:
Устанавливаете на сервере 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/';
-
Пост Евгений Корепов - сообщение в Обработка анимированных 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
-
Пост Евгений Корепов - сообщение в Не соблюдается порядок добавляемых компонентов был отмечен как ответ
Кроме Align = Top, установите еще свойство Top = 10000, что бы они добавлялись заведомо ниже всех существующий элементов. Если не устанавливать Top, то по умолчанию позиция у всех будет 0 и порядок элементов будет зависеть от погрешности вычислений Single.
-
Пост Евгений Корепов - сообщение в 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;
-
Пост Евгений Корепов - сообщение в 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;
-
Пост Евгений Корепов - сообщение в Одинаковые логотипы и картинки был отмечен как ответ
Получите от медицинского центра разрешение на использование их логотипа. Можно на русском языке. Текст произвольный - поручаем Kitty изготовление приложения и разрешаем использование логотипов, торговых марок, фирменных наименований и т.д. в приложениях.
Подробнее здесь https://play.google.com/intl/ru/about/ip-deception-spam/impersonation-ip/
И отправьте скан (pdf к примеру) этого письма в гугл, подробности тут https://support.google.com/googleplay/android-developer/answer/6320428
Последнее время все сложнее публиковать приложения, правила уже балансируют на грани маразма. Одно моё приложение заблокировали по причине того что я "выдавал" себя за магазин линолиума в какой то немецкой деревушке - логотип приложения был немного искаженной зеркальной копией логотипа этого магазина, так же отличались цвета - у магазина желтый, у приложения оранжевый. Вот такие дела...
Так же сильно зависит от места модерации - если повезет попасть в британский офис, то вам досконально объяснят причину блокировки, приведут примеры правильного и не правильного решения вашего вопроса. Вот пример из моей практики:
Если не повезет попасть в подмосковье - то вы не получите комментариев, апелляция будет проигнорирована и относится к вам будут как к ничтожеству. Российская специфика - мальчик получивший работу в Великом Гугле, благодаря двоюродному дяде, сам становится Великим. И естественно он обязан быть гавном, так у него в должностной инструкции написано ;-)
-
Пост Евгений Корепов - сообщение в Сборка Application Store был отмечен как ответ
Посмотрите Deployment проекта, конфигурации Debug и Release, возможно в режиме Release не отмечена какая то из библиотек .so
-
Пост Евгений Корепов - сообщение в NetHTTPClient и личные сообщения на сайте forum.ru-board.com на C++Builder 10.1 был отмечен как ответ
Сейчас посмотрю исходники. Минутку...
Да, в Update1 System.Net.HttpClient.pas исправлен :-)
-
Пост Евгений Корепов - сообщение в как правильно очистить данные модели был отмечен как ответ
Вот кусок кода исходников из 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;
-
Пост Евгений Корепов - сообщение в Раскрытый список как 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;
-
Пост Евгений Корепов - сообщение в Возвращаясь к вопросу о подсчете высоты текста 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.
-
Пост Евгений Корепов - сообщение в Дата/время в сервисе был отмечен как ответ
У вас ошибка в коде, неверно 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 формате
-
Пост Евгений Корепов - сообщение в Тормоза при первом переключении вкладок TTabControl был отмечен как ответ
Проблема решена. Но решена методом научного тыка. Сделал так:
ATabItem:=TabControl.Add(); ATabItem.DisableDisappear:=True; и задержка исчезла совсем. Так же убрал все рекурсивные предварительные ApplyStyleLookup, тоже работает идеально.
Help и сайты с документацией молчат по поводу DisableDisappear - это свойство науке не известно. По крупицам собраны сакральные знания,позволяют догадываться что отвечает оно за "запрет контролу выгружать стиль, когда он скрывается со сцены (С) Brovin Yaroslav"
-
Пост Евгений Корепов - сообщение в Установка ScrollViewPos после добавления ListViewItem был отмечен как ответ
Вы будете смеяться, но проблема решена. Методом научного тыка.
Не работающая установка значения ListView.ScrollViewPos решается следующей строкой ListView.ItemIndex:=0; (Не важно 0 или любое другое число).
Т.е. для того чтоб заработало делаем так:
ListView.ItemIndex:=0; ListView.ScrollViewPos:=333; // Ура, работает!!! Почему так работает, я не понял.
-
Пост Евгений Корепов - сообщение в Получить размер файла был отмечен как ответ
Ура! Я победил проблему. Причем с помощью почти забытой мной процедуры 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; -
Пост Евгений Корепов - сообщение в 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
-
Пост Евгений Корепов - сообщение в Ввод числа - самый простой способ фильтрации был отмечен как ответ
Посмотрел на код и решил еще на пару строк сократить, совместил проверку на "пусто" и минус в одном условии
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; -
Пост Евгений Корепов - сообщение в FilterChar в XE8 Update 1 на Андроид так и не работает? был отмечен как ответ
Ответ по Update1:
Ответ по FilterChar