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

Пользователи
  • Публикаций

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

  • Посещение

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

    65

Весь контент Евгений Корепов

  1. В первом сообщении этой темы есть ссылка на обсуждаемый здесь компонент TKRBarCodeSanner.zip, у этого компонента есть событие TKRBarCodeScannerScanResult(Sender: TObject; AResult: string), ну и AResult - это то где находится результат сканирования.
  2. Евгений Корепов

    Отладка Android приложения (и не только)

    Если не получается сразу определить источник ошибок, я публикую для бетатестеров новую версию приложения, где FAppStage прописана более подробно - начало конец вызова каждой подозрительной функции или кода.
  3. Евгений Корепов

    Отладка Android приложения (и не только)

    Я использую дополнительный модуль с отдельным потоком отправляющий все что надо на мой сервер. На сервере кусок кода на php все это пишет в лог. В основном коде использую глобальную переменную FAppStage : procedure TFormMain.ServiceConnectionOnChange(Sender: TObject; AChange: TPushService.TChanges); begin FAppStage:='ServiceConnectionOnChange start'; if AChange=[TPushService.TChange.DeviceToken] Then GetHTTP(CommandActions, -1, ''); FAppStage:='ServiceConnectionOnChange stop'; end; В проекте лежит TfgApplicationEvents, в нужных событиях, к примеру fgApplicationEventsException, идет отправка FAppStage и E: Exception. В логе я вижу где и какое исключение произошло. Достаточно удобно мне кажется.
  4. Вместо массива использовать TDictionary<TKey,TValue>?
  5. Евгений Корепов

    Как Вы используете RAD Studio

    Я использую как разминающее мозги хобби, в свободное от работы время. Доход от приложений - приятное дополнение. До основного иструмента Delphi пока не дотягивает - нет компилятора под Linux, основную рабочую лошадку 90% предприятий в моей отрасли (ISP).
  6. Полностью согласен. Ширину я устанавливаю в ListViewActionsUpdateObjects, и только после этого вызываю функцию.
  7. Почитал, посмотрел все варианты и сделал работу над ошибками. Переделал свой, показанный выше, код. Проверил на Windows и Android, с стилем по умолчанию и другими стилями - работает безупречно. Так же не нуждается в подгонках типа "Height:= Round(t) + 30;". Преимущество кода в том что на вход подаем ATextObject : TListItemText, т.е. можно легко использовать для вычисления Text или Detail. function TFormMain.CalculateListItemObjectHeight(ATextObject : TListItemText) : Single; begin FTextLayout.BeginUpdate; try FTextLayout.Text:=ATextObject.Text; FTextLayout.MaxSize:=TPointF.Create(ATextObject.Width, TTextLayout.MaxLayoutSize.Y); FTextLayout.Font.Assign(ATextObject.Font); FTextLayout.WordWrap:=ATextObject.WordWrap; FTextLayout.Trimming:=ATextObject.Trimming; FTextLayout.HorizontalAlign:=ATextObject.TextAlign; FTextLayout.VerticalAlign:=ATextObject.TextVertAlign; finally FTextLayout.EndUpdate; end; Result:=FTextLayout.Height; end; Пример использования: у меня Text непредсказуемой длины, вверху ListItem, по всей ширине ListItem. Под Text располагаются слева Image, справа Detail. Текст Detail может быть от пары слов, до нескольких предложений procedure TFormMain.ListViewActionsUpdateObjects(const Sender: TObject; const AItem: TListViewItem); Var AItemTextHeight, AItemDetailHeight, AItemImageHeight, AItemHeight : Single; AListView: TListView; begin AListView:=TListView(Sender); AItem.Objects.TextObject.Width:=AListView.Width - AListView.ItemSpaces.Left - // Вычисляем ширину Text AListView.ItemSpaces.Right - DefaultScrollBarWidth; AItemTextHeight:=CalculateListItemObjectHeight(AItem.Objects.TextObject); // Вычисляем высоту Text AItem.Objects.DetailObject.PlaceOffset.Y:=AItemTextHeight; // Устанавливаем смещение для Detail AItem.Objects.ImageObject.PlaceOffset.Y:=AItemTextHeight; // Устанавливаем смещение для Image AItemDetailHeight:=CalculateListItemObjectHeight(AItem.Objects.DetailObject); // Вычисляем высоту Text AItemImageHeight:=AItem.Objects.ImageObject.Height; AItem.Objects.DetailObject.Height:=AItemImageHeight; AItemHeight:=AItemTextHeight + Max(AItemDetailHeight, AItemImageHeight); // Вычисляем высоту всего Item AItem.Height:=Round(AItemHeight); end;
  8. Вот тут расписано как и что https://forums.embarcadero.com/thread.jspa?threadID=211952
  9. Для десктопа уже 15 лет пользуюсь EhLib. Вот там гриды, так гриды. Вот купила бы их эмбаркадера и включила в Дельфи, было бы хорошо. Для осознания их недосягаемой крутизны достаточно посмотреть скриншоты компонентов http://www.ehlib.com/ru/skrinshoty
  10. Евгений Корепов

    Прочитать DNS запрос в idUDPServer

    Вот посмотрите, просто и красиво TSimpleDNSServer http://www.delphipraxis.net/87433-dns-server-mit-indys-tiddnsserver-%3D-verwirrung.html
  11. У меня не заработал на XE8 к сожалению код. Но принцип тот же самый, разве что не совсем понятно что за "m" // Get layout height Result := Round(Layout.Height); // Add one em to the height Layout.Text := 'm'; Result := Result + Round(Layout.Height); Заметил странность, если установить размер шрифта отличный от стандартного, к примеру 11,99 или 12,01, то все начинает нормально работать, текст влазит. Но размер шрифта на экране в полтора раза меньше "стандартного". Не знаю какой стандартный, но точно не 12, больше похож на 14 или 15. Может из за этого и косяк? В недрах FMX расчет ведется с "стандартным" шрифтом 12, а на экране отрисовывается гораздо более крупным.
  12. Подтверждаю что на андроиде этот код косячит, выдает высоту процентов на 10-15 меньше нужной. Осталось разобраться почему в других моих проектах все работает нормально. Может действительно из за большого текста с сплошными строками накапливается ошибка? P.S. Заменил текст на кусок из книги, та же самая фигня, обрезает снизу.
  13. А с каким именно прибором вы хотите установить связь? С их роутером VR-006 или с преобразователями интерфейсов VR-001-5 ? Роутер, как я понял настраивается как прозрачный шлюз на преобразователи интерфейсов? Тупо пересылает пакеты, а преобразователи интерфейсов пересылают обратно? Если все так, то протокол TCP/IP. Компонет TIdTCPClient, а лучше TIdTCPServer. Если вы умеете общаться с счетчиком по USB, то есть вариант проще - найдите дешевый телефон с поддержкой OTG (можно найти за тысячи полторы), китайский OTG переходник с подзарядкой и втыкайте USB преобразователя интерфейса (или счетчика, если есть такие) прямо в смартфон. На телефоне пишите приложение, которое будет работать с счетчиком по USB, а отдавать данные как вам удобнее, от смс и email, до http сервера и push сообщения. Весь этот колхоз будет раза в три дешевле колхоза с приведенного вами сайта. Хотя на сайте штуки прикольные, подумаю о покупке некоторых изделий.
  14. Евгений Корепов

    Прочитать DNS запрос в idUDPServer

    Для начал у вас не правильно работает function ReplaceSpecSymbol, она оставляет спецсимволы в конце строки. Вот накидал правильно работающую: function ReplaceSpecSymbol(S: String): String; var Count : Integer; begin Count:=0; Result:=''; while True do begin Count:=Ord(S.Chars[0]); Result:=Result+S.Substring(1,Count)+'.'; S:=S.Remove(0,Count+1); if Ord(S.Chars[0])=0 Then break; end; Result:=Result.TrimRight(['.']); end; После этого в вашем проекте нормально все ресолвится, но что отсылать в ответ на lookup я не имею представления. Не знаю как заставить IdDNSResolver отдать данные в сыром формате, надо искать и читать документацию. Вот код процедуры, но надо разобраться что слать: procedure TMainForm.IdUDPServerUDPRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle); var S, Domain: String; I : Integer; ABuffer : TIdBytes; begin S:=ReplaceSpecSymbol(BytesToString(AData,12)); Memo_Log.Lines.Add(S); if Pos('in-addr.arpa',S)=0 then begin IdDNSResolver.Resolve(S); for I := 0 to IdDNSResolver.QueryResult.Count-1 do if IdDNSResolver.QueryResult[I].RecType = qtA then begin S:=TARecord(IdDNSResolver.QueryResult[I]).IPAddress; Memo_Log.Lines.Add('IdDNSResolver: '+S); end; // Вот дальше не знаю что именно пересылать // ABuffer:=DNSHeader.GenerateBinaryHeader; // ABuffer:=IdDNSResolver.PlainTextResult; // ABuffer:=ABuffer+IdDNSResolver.InternalQuery; // ABuffer:=IdDNSResolver.InternalQuery; ABinding.Send(ABuffer); end; Вы можете поразбираться с помощью простейшего DNS прокси, по крайней мере будете видеть что идет в запросе и что в ответе. Код ниже, только пропишите глобальную переменную ALocalPort : Integer, для запоминания забинденного порта на 127.0.0.1 procedure TMainForm.IdUDPServerUDPRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle); Const ExternalDNSHost = '8.8.8.8'; LocalHost = '127.0.0.1'; begin if ABinding.PeerIP.Equals(LocalHost) then // если запрос с локального, пересылаем на внешний dns begin ALocalPort:=ABinding.PeerPort; IdUDPServer.SendBuffer(ExternalDNSHost,53,AData); end; if ABinding.PeerIP.Equals(ExternalDNSHost) then // если с внешнего, пересылаем на локальный IdUDPServer.SendBuffer(LocalHost,ALocalPort,AData); exit; end; в коммандной строке используйте "nslookup -retry=1 -timeout=30 google.ru 127.0.0.1 " (один повтор запроса, чтоб не засирать отладку и таймаут сколько нужно секунд, что не отвалился запрос пока будете разбираться)
  15. Так весь проект целиков и выложил. В форме только апперанс у ListView выставил в Custom. А куда дели Parent? Это важное свойство хранящее родителя. Может как то переименовали? P.S. Вы можете AListView заменить за свой конкретный ListView, доступ через парент сделал для красоты и универсальности, если несколько ListView в проекте...
  16. Делать было нечего, дело было вечером... Вот попробовал, свою процедуру чуть изменил, добавил константы ширины скроллбара из 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.
  17. Возможно вы не учитывате свойство Trimming, а судя по скринам оно у вас включено. Я пользуюсь вот таким кодом, работает идеально на всех платформах. procedure TFormMain.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, 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; При создании формы не забудьте FTextLayout := TTextLayoutManager.DefaultTextLayout.Create; Применять вот так: procedure TFormMain.ListViewNewsUpdateObjects(const Sender: TObject; const AItem: TListViewItem); begin CalculateTListViewItemHeight(AItem); end;
  18. Евгений Корепов

    Прочитать DNS запрос в idUDPServer

    Не понял ваш вопрос. Приложите ваш проект (или полный листинг), трудно понимать вырванные из контекста вопросы и куски кода.
  19. Евгений Корепов

    Прочитать DNS запрос в idUDPServer

    Отправлять ответ вы должны там же где получаете запрос procedure TForm1.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle); begin .. .. ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort, Ваши данные...); end;
  20. Я бы логику работы приложения сделал по другому - не хранил ничего на телефоне пользователя, ибо люди врут и оставлять данные учета им на откуп не очень хорошо. Удалить все, пользователь может просто очистив данные приложения в настройках и обвинить в этом разработчика. И самое обидно вы не докажете обратное. Проще и надежнее было бы отправлять на сервер запрос по http с хешем логина/пароля/id маячка(есть такое у них?). Приложение сильно бы упростилось - человек подошел к маячку, запустил приложение, приложение идентифицирует маячек, замешивает хеш и отправляет на сервер, сервер отвечает подтверждением приема данных и приложение демонстрирует подтверждение пользователю. Привязка приложения к работнику, как я понял, не осуществляется? Т.е. только по письму полученному от работника? Кто ему мешает отослать поддельное письмо с компьютера? Благо исходящие письма с примерами он может посмотреть в яндексе. Привязку приложения удобно осуществить с помощью однократного считывания QR кода, с экрана компьютера отдела кадров. В коде зашифровать необходимую для идентификации информацию, в том числе информацию о адресе API сервера конкретного предприятия, дабы не привязывать приложение к одному. Отсутствие сервера конечно резко снижает эффективность приложение. А так можно было бы натолкать маяков в туалеты, курилки, близлежащие пабы и контролировать рабов сотрудников на полную катушку ;-)
  21. Евгений Корепов

    Вертикальный текст на TextButton

    Возможно ли в ListView сделать кнопку с текстом повернутым на 90 градусов, т.е. вертикальная надпись на кнопке? В стиле, в listviewstyle есть button (TStyleObject), у button есть RotationAngle, но установка в 90 никакого результата не дает. Может есть другой путь?
  22. Забавно, мне понравилось! Поставил пятёрку. Глюк заметил - на странице меню движущийся фон смотрится не обычно, но в какой то момент дергается и это пугает ;-)
  23. Евгений Корепов

    Прочитать DNS запрос в idUDPServer

    Все правильно получаете, кодировка тут не при чем. Согласно спецификации "DNS Packet Structure", вы получаете не строку, а пакет который нужно разобрать. К примеру если запрос будет "nslookup www.google.ru 127.0.0.1", то там где вы получаете имя хоста будет строка "''#3'www'#6'google'#2'ru'#0#0#1#0#1". Парсинг простейший: #3 - означает что далее идут 3 символа хоста 'www' - вот ожидаемые 3 символа #6 - далее идут еще 6 символов хоста 'google' - ага, вот они #2 - ну и еще 2 символа 'ru' - ура, они здесь #0 - конец имени хоста, складываем в кучу, перемежая точками и получаем www.google.ru #0 - дальше у нас служебная информация... #1 #0 #1 Вот как то так. P.S. А зачем вам на таком низком уровне работать? Может использовать IdDNSServer : TIdDNSServer ? P.P.S. Правильно Memo1.Lines.Add(BytesToString(AData,12)); //(12, а не 13)
  24. Евгений Корепов

    Проблемы с отрисовкой

    Эта фраза здесь звучала много раз, но повторюсь "Никогда, ни в коем случае, ни при каких обстоятельствах, не работайте с объектами основной формы (основного потока) из другого потока", для этого умные люди специально создали потокобезопасные способы - синхронизация, очереди, события и т.д. Даже если вам кажется что ваш код работает, то это случайность, на пятый или сотый запуск все у вас упадет, или упадет сразу на другой версии андроида или другом производителе железа. Такое ощущение что вы не слышите, или не читаете ответы на заданные вами вопросы, и каждое новое сообщение от вас звучит примерно так "А вот если я на эти грабли не наступлю, а с разбега прыгну, что будет?" ;-) Надеюсь я не слишком эмоционально высказался? Не хотел никого обидеть.
  25. Евгений Корепов

    Запретить появления клавиатуры

    Это настраивается в самом андроиде, в настройках клавиатуры. К сожалению в Самсунге не только USB разъем вверх ногами, но и реакция на подключение OTG устройств не адекватная. Но настроить можно, точно не подскажу как, давно было, но после двух часов тыкания в настройках мне это удалось.