kami
-
Постов
643 -
Зарегистрирован
-
Посещение
-
Победитель дней
41
Активность репутации
-
kami отреагировална krapotkin в List of new features and customer reported issues fixed in RAD Studio 10.2 Tokyo Release 3
почему-то самое важное не зашло
теперь Mobile Pack вошел в Professional
-
kami получил реакцию от DMS в TWebBrowser вместо кучи TEdit
В общем случае обратная связь "браузер - приложение" не предусмотрена. Разве что вы будете сразу из веббраузера отправлять запрос на сервер. Но тогда - зачем вообще приложение, если можно всё сделать в веб ?
К примеру, в браузере - форма с кучей полей, отправляющая POST-запрос на сервер и редиректящая на какую-нибудь страницу. Приложение через OnBeforeNavigate (или_как_там_оно) видит это и запрашивает данные с сервера для своих "внутренностей".
-
kami получил реакцию от Brovin Yaroslav в Передача параметра программе
Есть волшебная аббревиатура - IPC. Inter process communication.
Считайте, что у вас два разных приложения.Абсолютно разных. Которым нужно взаимодействовать друг с другом. Одно - источник, второе - приемник.
Среди вариантов для Windows:
1. Через сообщения, например - WM_COPYDATA (емнип, так обзывается). Нужно знать хендл окна, которому отправится сообщение (не уверен, что с WM_COPYDATA пройдет фокус с функцией BroadcastMessage) и нужно чтобы целевое приложение было на том же уровне изоляции (UIPI, кажется). Т.е. если приемник запущен от админа, а источник - как обычное приложение - этим способом их не состыковать.
2. Через NamedPipes. Способ хорош для организации постоянного обмена между двумя любыми приложениями на одном компьютере (не только, но чаще всего - на одном). Для однократной передачи информации держать слушающий пайп в отдельном потоке, наверное, избыточно. Хотя я бы взял именно этот способ.
3. TCP/IP и надстройки над ним: http, ftp и другое tp. Чаще всего используются для организации обмена между приложениями на разных компьютерах. Для локального - избыточно, да и проблемы с файрволлом могут быть.
4. Через файловые потоки или данные в файле подкачки. Одно приложение пишет, второе периодически смотрит "а не появилось ли для меня чего нового". Как-то делал даже двусторонний обмен данными по этому механизму.
Это навскидку. Выбирайте, потом можно говорить дальше.
-
kami получил реакцию от Ingalime в Передача параметра программе
Есть волшебная аббревиатура - IPC. Inter process communication.
Считайте, что у вас два разных приложения.Абсолютно разных. Которым нужно взаимодействовать друг с другом. Одно - источник, второе - приемник.
Среди вариантов для Windows:
1. Через сообщения, например - WM_COPYDATA (емнип, так обзывается). Нужно знать хендл окна, которому отправится сообщение (не уверен, что с WM_COPYDATA пройдет фокус с функцией BroadcastMessage) и нужно чтобы целевое приложение было на том же уровне изоляции (UIPI, кажется). Т.е. если приемник запущен от админа, а источник - как обычное приложение - этим способом их не состыковать.
2. Через NamedPipes. Способ хорош для организации постоянного обмена между двумя любыми приложениями на одном компьютере (не только, но чаще всего - на одном). Для однократной передачи информации держать слушающий пайп в отдельном потоке, наверное, избыточно. Хотя я бы взял именно этот способ.
3. TCP/IP и надстройки над ним: http, ftp и другое tp. Чаще всего используются для организации обмена между приложениями на разных компьютерах. Для локального - избыточно, да и проблемы с файрволлом могут быть.
4. Через файловые потоки или данные в файле подкачки. Одно приложение пишет, второе периодически смотрит "а не появилось ли для меня чего нового". Как-то делал даже двусторонний обмен данными по этому механизму.
Это навскидку. Выбирайте, потом можно говорить дальше.
-
kami получил реакцию от DMS в Введение в Delphi for iOS
Достаточно много посетителей форума говорило, что работает с XCode на виртуалке.
Получается - не нужен.
-
kami получил реакцию от DMS в Введение в Delphi for iOS
Без реального устройства - никуда.
Емнип, Apple теперь принимает только 64битные приложения. Delphi пока не умеет работать с симулятором в 64 бита. А с учетом того, что SDK 11 именно 64 бита - устройство становится жизненно необходимым.
Некоторые вещи вылезают только на устройстве. Имеется реальный опыт, когда вполне конкретная последовательность действий на симуляторе отрабатывала хорошо, а на устройстве приложение сваливалось.
-
kami получил реакцию от Akad в Кто хорошо знает внутреннюю структуру FMX?
Есть дикое ощущение, что могли поломать синхронизацию через TMonitor.Wait.
В Телеграме обсуждали подобный глюк, по stacktrace было похоже на это.
-
kami получил реакцию от Fedor K в Асинхронный NetHTTPClient
Пруфов про потоки в асинхронных вызовах не будет, если я правильно понял...
Я тоже могу повторить, что завершение всех инициированных собой операций - это проблема создателя этих операций, которую он обязан решить. Если прервать никак - значит дождаться завершения. Более того, возможно (но пока не могу утверждать), что с уничтожением экземпляра THTTPClient его асинхронная операция должна уйти в небытие.
А вот здесь ткните меня носом, пожалуйста. Что за HTTPServer - в справке в классах System,Net я такого не нашел. И в исходниках (правда, у меня Берлин) тоже. Возможно - плохо искал.
THTTPClient. Причем - без необходимости таскания с собой всяких OpenSSL Library в разных ипостасях. Обратите внимание - я говорил именно за отказ от Indy в http(s) обмене. А не про "полный отказ".
-
kami отреагировална Кривяков Виталий в Асинхронный NetHTTPClient
Добрый день!
Все проще, гораздо.
Net := THTTPClient.Create;
Net.BeginPost(
procedure (const Value : IAsyncResult)
begin
AsyncResult(Value); // Вот тут можно вызвать любую процедуру, или просто обработать результат.
end, URL, InputStream, OutputStream, Headers);
В анонимной процедуре просто вызываете нужную процедуру, для интерактивной одну, для периодических запросов другую.
-
kami отреагировална Brovin Yaroslav в Нужен нормальный JSON парсер
Если пытаться кормить json парсер кривым json и ожидать, что почему вдруг объект станет неожиданно массивом и не будет исключений, то таких парсеров вам не найти. Проще написать самому: быстро, дешево, без 100500 классов и исключений. И такой, который будет считать, что {} - это массив.
А вообще, рекомендую начать с http://www.json.org/
Возможно, после этого придет понимание того, почему нужно то или иное количество классов, ну или хотя бы вы сами разберетесь и поймете, почему так происходит.
-
kami получил реакцию от Равиль Зарипов (ZuBy) в VersionCode
(с) не помню чье:
var FProgramVersion: string; function GetProgramVersion: string; var {$IFDEF ANDROID} PackageManager: JPackageManager; PackageInfo: JPackageInfo; {$ENDIF} {$IFDEF IOS} s: MarshaledAString; {$ENDIF} {$IFDEF MSWINDOWS} Exe: string; Size, Handle: DWORD; Buffer: TBytes; FixedPtr: PVSFixedFileInfo; {$ENDIF} begin if FProgramVersion <> '' then begin Result := FProgramVersion; exit; end; {$IFDEF ANDROID} PackageManager := TAndroidHelper.Context.getPackageManager; PackageInfo := PackageManager.getPackageInfo(TAndroidHelper.Context.getPackageName, 0); Result := JStringToString(PackageInfo.versionName); {$ENDIF} {$IFDEF IOS} s := TNSString.Wrap(CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle, kCFBundleVersionKey)).UTF8String; Result := string(s); {$ENDIF} {$IFDEF MSWINDOWS} Exe := ParamStr(0); Size := GetFileVersionInfoSize(PChar(Exe), Handle); if Size = 0 then begin Result := 'Unknown'; exit; end; SetLength(Buffer, Size); if not GetFileVersionInfo(PChar(Exe), Handle, Size, Buffer) then begin Result := 'Unknown'; exit; end; if not VerQueryValue(Buffer, '\', Pointer(FixedPtr), Size) then begin Result := 'Unknown'; exit; end; Result := Format('%d.%d.%d.%d', [LongRec(FixedPtr.dwFileVersionMS).Hi, // major LongRec(FixedPtr.dwFileVersionMS).Lo, // minor LongRec(FixedPtr.dwFileVersionLS).Hi, // release LongRec(FixedPtr.dwFileVersionLS).Lo]); // build {$ENDIF} FProgramVersion := Result; end;
-
kami получил реакцию от Brovin Yaroslav в VersionCode
(с) не помню чье:
var FProgramVersion: string; function GetProgramVersion: string; var {$IFDEF ANDROID} PackageManager: JPackageManager; PackageInfo: JPackageInfo; {$ENDIF} {$IFDEF IOS} s: MarshaledAString; {$ENDIF} {$IFDEF MSWINDOWS} Exe: string; Size, Handle: DWORD; Buffer: TBytes; FixedPtr: PVSFixedFileInfo; {$ENDIF} begin if FProgramVersion <> '' then begin Result := FProgramVersion; exit; end; {$IFDEF ANDROID} PackageManager := TAndroidHelper.Context.getPackageManager; PackageInfo := PackageManager.getPackageInfo(TAndroidHelper.Context.getPackageName, 0); Result := JStringToString(PackageInfo.versionName); {$ENDIF} {$IFDEF IOS} s := TNSString.Wrap(CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle, kCFBundleVersionKey)).UTF8String; Result := string(s); {$ENDIF} {$IFDEF MSWINDOWS} Exe := ParamStr(0); Size := GetFileVersionInfoSize(PChar(Exe), Handle); if Size = 0 then begin Result := 'Unknown'; exit; end; SetLength(Buffer, Size); if not GetFileVersionInfo(PChar(Exe), Handle, Size, Buffer) then begin Result := 'Unknown'; exit; end; if not VerQueryValue(Buffer, '\', Pointer(FixedPtr), Size) then begin Result := 'Unknown'; exit; end; Result := Format('%d.%d.%d.%d', [LongRec(FixedPtr.dwFileVersionMS).Hi, // major LongRec(FixedPtr.dwFileVersionMS).Lo, // minor LongRec(FixedPtr.dwFileVersionLS).Hi, // release LongRec(FixedPtr.dwFileVersionLS).Lo]); // build {$ENDIF} FProgramVersion := Result; end;
-
kami получил реакцию от x11 в Вызвать форму, сделать выбор и вернуть результат
в объявлении reference to procedure забыт пробел между const и названием переменной. Синтаксис отличается и компилятор ругается.
-
kami получил реакцию от Евгений Корепов в Разница в вызовах Synchronize
Поправка: RemoveQueuedEvents вызывается само в деструкторе TThread.
Если важно, чтобы все синхронизируемые события отработали - при уничтожении TThread в главном потоке нужно вызывать System.Classes.CheckSynchronize(0) до того момента, как оно вернет False.
-
kami отреагировална FeLDMARShaL в Изменение стиля TfgActivityDialog №2
После упорных попыток, не получилось подружить компонент с созданной темой, возможно ее ид как то не так получаю и ниже приведенный код возвращает что то не то
themId := TAndroidHelper.Context.getResources.getIdentifier(StringToJString('styles_dialog'), StringToJString('layout'), TAndroidHelper.Context.getPackageName) Но реализовать нужно было пришлось пофиксить немного стандартные компоненты, и именно в части
const UndefinedThemeID = -1; Теперь компоненты считаю что ThemeID=0 - это кастомная тема.
После чего, вот такой код (и измненная стандартная тема приложения):
if not Assigned(fg_my) then begin fg_my := TfgActivityDialog.Create(nil); fg_my.Theme := TfgDialogTheme.Custom; fg_my.ThemeID := 0; end; fg_my.Show; sleep(3000); fg_my.Hide; Приводят вот к такому результату (разумеется индикатор крутится как надо):
-
kami получил реакцию от dnekrasov в Разница в вызовах Synchronize
Разница есть. И она не только в вызове Synchronize, но и Queue.
Указание потока в качестве источника метода синхронизации позволяет вам впоследствии сделать TThread.RemoveQueuedEvents(myThread) перед его удалением.
Вызов RemoveQueuedEvents необходим, если в синхронизируемых методах может идти обращение к полям и методам уничтожаемого потока. Потому что с удалением потока то, что подлежало синхронизации, никуда не пропадет, а раз поток уже не существует - у вас вылезет AV на ровном месте. Или же ваш код испортит чью-то память, что еще труднее отловить.
-
kami получил реакцию от #WAMACO в Разница в вызовах Synchronize
Разница есть. И она не только в вызове Synchronize, но и Queue.
Указание потока в качестве источника метода синхронизации позволяет вам впоследствии сделать TThread.RemoveQueuedEvents(myThread) перед его удалением.
Вызов RemoveQueuedEvents необходим, если в синхронизируемых методах может идти обращение к полям и методам уничтожаемого потока. Потому что с удалением потока то, что подлежало синхронизации, никуда не пропадет, а раз поток уже не существует - у вас вылезет AV на ровном месте. Или же ваш код испортит чью-то память, что еще труднее отловить.
-
kami получил реакцию от Winexcel в Разница в вызовах Synchronize
Разница есть. И она не только в вызове Synchronize, но и Queue.
Указание потока в качестве источника метода синхронизации позволяет вам впоследствии сделать TThread.RemoveQueuedEvents(myThread) перед его удалением.
Вызов RemoveQueuedEvents необходим, если в синхронизируемых методах может идти обращение к полям и методам уничтожаемого потока. Потому что с удалением потока то, что подлежало синхронизации, никуда не пропадет, а раз поток уже не существует - у вас вылезет AV на ровном месте. Или же ваш код испортит чью-то память, что еще труднее отловить.
-
kami получил реакцию от Brovin Yaroslav в Разница в вызовах Synchronize
Разница есть. И она не только в вызове Synchronize, но и Queue.
Указание потока в качестве источника метода синхронизации позволяет вам впоследствии сделать TThread.RemoveQueuedEvents(myThread) перед его удалением.
Вызов RemoveQueuedEvents необходим, если в синхронизируемых методах может идти обращение к полям и методам уничтожаемого потока. Потому что с удалением потока то, что подлежало синхронизации, никуда не пропадет, а раз поток уже не существует - у вас вылезет AV на ровном месте. Или же ваш код испортит чью-то память, что еще труднее отловить.
-
kami получил реакцию от Maximus в Разница в вызовах Synchronize
Разница есть. И она не только в вызове Synchronize, но и Queue.
Указание потока в качестве источника метода синхронизации позволяет вам впоследствии сделать TThread.RemoveQueuedEvents(myThread) перед его удалением.
Вызов RemoveQueuedEvents необходим, если в синхронизируемых методах может идти обращение к полям и методам уничтожаемого потока. Потому что с удалением потока то, что подлежало синхронизации, никуда не пропадет, а раз поток уже не существует - у вас вылезет AV на ровном месте. Или же ваш код испортит чью-то память, что еще труднее отловить.
-
kami получил реакцию от Ingalime в Разница в вызовах Synchronize
Разница есть. И она не только в вызове Synchronize, но и Queue.
Указание потока в качестве источника метода синхронизации позволяет вам впоследствии сделать TThread.RemoveQueuedEvents(myThread) перед его удалением.
Вызов RemoveQueuedEvents необходим, если в синхронизируемых методах может идти обращение к полям и методам уничтожаемого потока. Потому что с удалением потока то, что подлежало синхронизации, никуда не пропадет, а раз поток уже не существует - у вас вылезет AV на ровном месте. Или же ваш код испортит чью-то память, что еще труднее отловить.
-
kami отреагировална krapotkin в AutoSize работает иначе под Tokyo!
Ну вообще для меня вот неочевидно, что размер невидимого компонента должен быть определен.
если у меня три панели и две из них невидимы, то это сильно влияет на размеры и положение третьей
-
kami получил реакцию от Равиль Зарипов (ZuBy) в Непонятки с TWebBrowser
Попробуйте использовать Navigate (без параметров) вместо Reload.
Ну и - делать невидимую работу по правке файла, используя визуальный компонент (Memo) - это, мягко говоря, не комильфо.
-
kami получил реакцию от Brovin Yaroslav в Открытие ссылки в проекте Firemonkey
Вы не там ифдефы пишете. Не нужно здесь много модулей.
Для примера. (емнип - автор @Равиль Зарипов (ZuBy) ). Единая точка входа в функцию и отличаются только внутренности.
function OpenURL(const URL: string; const DisplayError: Boolean = False): Boolean; var {$IFDEF ANDROID} Intent: JIntent; {$ENDIF} {$IFDEF IOS} NSU: NSUrl; {$ENDIF} {$IFDEF MSWINDOWS} Res: HINST; {$ENDIF} begin {$IFDEF ANDROID} // There may be an issue with the geo: prefix and URLEncode. // will need to research Intent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_VIEW, TJnet_Uri.JavaClass.parse(StringToJString(TIdURI.URLEncode(URL)))); try TAndroidHelper.Activity.startActivity(Intent); exit(true); except on e: Exception do begin if DisplayError then TDialog.ShowMessage('Error: ' + e.Message); exit(False); end; end; {$ENDIF} {$IFDEF IOS} // iOS doesn't like spaces, so URL encode is important. NSU := StrToNSUrl(URL); if SharedApplication.canOpenURL(NSU) then exit(SharedApplication.OpenURL(NSU)) else begin if DisplayError then TDialog.ShowMessage('Error: Opening "' + URL + '" not supported.'); exit(False); end; {$ENDIF} {$IFDEF MSWINDOWS} Res := ShellExecute(0, 'open', PChar(URL), nil, nil, SW_SHOW); Result := Res > 32; {$ENDIF} end; И теперь "снаружи" этой функции вам без разницы, под какую платформу идет сборка. В любом случае вы пишете "OpenURL('http://blablabla.net');". Безо всяких IFDEF.
-
kami получил реакцию от #WAMACO в Открытие ссылки в проекте Firemonkey
Вы не там ифдефы пишете. Не нужно здесь много модулей.
Для примера. (емнип - автор @Равиль Зарипов (ZuBy) ). Единая точка входа в функцию и отличаются только внутренности.
function OpenURL(const URL: string; const DisplayError: Boolean = False): Boolean; var {$IFDEF ANDROID} Intent: JIntent; {$ENDIF} {$IFDEF IOS} NSU: NSUrl; {$ENDIF} {$IFDEF MSWINDOWS} Res: HINST; {$ENDIF} begin {$IFDEF ANDROID} // There may be an issue with the geo: prefix and URLEncode. // will need to research Intent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_VIEW, TJnet_Uri.JavaClass.parse(StringToJString(TIdURI.URLEncode(URL)))); try TAndroidHelper.Activity.startActivity(Intent); exit(true); except on e: Exception do begin if DisplayError then TDialog.ShowMessage('Error: ' + e.Message); exit(False); end; end; {$ENDIF} {$IFDEF IOS} // iOS doesn't like spaces, so URL encode is important. NSU := StrToNSUrl(URL); if SharedApplication.canOpenURL(NSU) then exit(SharedApplication.OpenURL(NSU)) else begin if DisplayError then TDialog.ShowMessage('Error: Opening "' + URL + '" not supported.'); exit(False); end; {$ENDIF} {$IFDEF MSWINDOWS} Res := ShellExecute(0, 'open', PChar(URL), nil, nil, SW_SHOW); Result := Res > 32; {$ENDIF} end; И теперь "снаружи" этой функции вам без разницы, под какую платформу идет сборка. В любом случае вы пишете "OpenURL('http://blablabla.net');". Безо всяких IFDEF.