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

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

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

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

  • Посещение

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

    100

Сообщения, опубликованные Евгений Корепов

  1. 24 минуты назад, gelo1 сказал:

    Ребята спасиБО за ответы.

    Кропоткину:-локальная сеть, 80 компов, сообщения типа "Подойди к моему столу...". Может дадите ссылку на уже реализованное решение?

    Олег.

    Может вам не писать тогда свой мессенджер а использовать что то готовое? Я в свей конторе использую http://www.commfort.com/ru/

  2. Посмотрите файлы на устройстве по пути /sys/class/tty/  , по идее должен быть файл с вашим tty устройством (com-портом). Работать с ним так же как и на linux системах - можно писать в файл и читать из него. Или погуглите фразу "android com port" - информации очень много, правда в основном для C, придется переводить на Delphi

  3. Как уже выше сказали нужно установить Билд конфигурацию - Release, и конфигурацию платформы - Application Store.

    Assertions не влияет, его можно оставить в любом состоянии, хотя среда по умолчанию его включает для релизной конфигурации:

    Assertions - Enables or disables the generation of code for assertions in a Delphi source file. The option is enabled (equivalent to {$C+}) by default. Since assertions are not usually used at run time in shipping versions of a product, compiler directives that disable the generation of code for assertions are provided. Deselect this option to disable assertions.

    Ошибка возникает когда в конфигурации платформы выставить "Development". На картинке выделено жирным

    Снимок.PNG

  4. В GetHTTP отправляю токен и id на свой сервер

    procedure TFormMain.GetHTTP(ACommand : String; AIndex : Integer; AImageURL : String);
    Var FHTTPRec : THTTPRec;
        AFileName, APath : String;
    begin
    ....
        FHTTPRec.Query:=APIURL+'?cmd='+ACommand+'&region='+Setting.RegionCode+
          '&DeviceID='+HDevicePushParams.DeviceID+'&DeviceToken='+HDevicePushParams.DeviceToken;
    .......
      FQueueRequest.PushItem(FHTTPRec);  
    end;

     

  5. Вот мой код из работающего проекта, может поможет разобраться

    interface
    
    uses
      System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
      FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
      System.Generics.Collections, System.JSON,
      FMX.TextLayout,
      System.IOUtils,
      FMX.Surfaces,
      System.Math,
      System.Net.URLClient,
    //  SyncObjs,
    {$IFDEF ANDROID}
      FMX.Platform.Android,
      System.PushNotification,
      uVedroProcess,
      FMX.VirtualKeyboard,
      FMX.Platform,
      androidapi.JNI.GraphicsContentViewText,
      Androidapi.JNI.JavaTypes,
      Androidapi.JNI.Net,
      Androidapi.Helpers,
    {$ENDIF ANDROID}
      UnitGetHttpThread,
      UnitSettingPage,
      FMX.Controls.Presentation, FMX.StdCtrls, FMX.Advertising,
      FMX.Objects,
      UnitTypesAndFunction, FMX.Notification,  FMX.Layouts,
      FMX.TabControl,
      FMX.ListView.Types,
      FMX.ListView,
      FGX.ApplicationEvents,
      FMX.Ani, FMX.ExtCtrls, FMX.ListBox, FMX.MultiView, FMX.Edit;
    
    .....
    
    implementation
    {$IFDEF ANDROID}
    uses FMX.PushNotification.Android;
    
    Var APushService : TPushService;
        AServiceConnection : TPushServiceConnection;
    {$ENDIF ANDROID}
    {$R *.fmx}
    
    procedure TFormMain.FormCreate(Sender: TObject);
    begin
    ........
      PushServiceInit;
    ........
    end;
    
    procedure TFormMain.PushServiceInit;
    begin
    //  if Debug then
    //    Exit;
      try
        APushService:=TPushServiceManager.Instance.GetServiceByName(TPushService.TServiceNames.GCM);
        APushService.AppProps[TPushService.TAppPropNames.GCMAppID]:='568*********';
    
        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];
      finally
        NotificationCenter:=TNotificationCenter.Create(Self);
        NotificationCenter.OnReceiveLocalNotification:=NotificationCenterOnReceiveLocalNotification;
      end;
    end;
    
    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;
    
    procedure TFormMain.ServiceConnectionOnReceiveNotification(Sender: TObject; const ANotification: TPushServiceNotification);
    Var JSONValue : TJSONValue;
    begin
      if ANotification.Json.TryGetValue('message',JSONValue) Then
        if Not JSONValue.Value.IsEmpty then
        begin
    //      GetHTTP(CommandActions, -1, '');
    //      Memo.Lines.Add(JSONValue.Value);
    //      ShowMessage(JSONValue.Value);
        end
    end;
    
    procedure TFormMain.NotificationCenterOnReceiveLocalNotification(Sender: TObject; ANotification: TNotification);
    begin
    //  ShowMessage(ANotification.AlertBody);
    end;

    Еще забыл объявление:

    type
      TFormMain = class(TForm)
    .........
      private
        { Private declarations }
    ......
        HDevicePushParams : TDevicePushParams;
    .......

     

  6. Заметил странность - приложение запущено и видно на экране, телефон самостоятельно блокируется по таймауту, через 5-10-15 минут разблокирую телефон, вижу на экране приложение.

    Но приложение заморожено наглухо - контролы не реагируют, списки не прокручиваются, кнопка Назад не работает.

    Тоже самое приложение собранное с помощью Delphi Berlin нормально ведет себя после разблокировки, что то в Токио намудрили с UI thread.

    Попробовать можно на этом приложении https://play.google.com/store/apps/details?id=ru.flintnet.SuprnovaStat. 100% воспроизводится на трех телефонах, особенно хорошо на открытом TListView (можете зайти в Setting-SettingPools)

    P.S. Заодно можете поставить пятерку приложению. Хотя с такими глюками я бы сам не поставил.

  7. 19 минут назад, Major сказал:

    По вашей ссылке в основном открываются программы для взлома.

    кстати, если не секрет, вашу программу взламывали?

    Ссылка это поиск в гугле интересующей вас информации. Думать о жутких хакерах и взломе вашего приложения можно начинать при количестве скачиваний вашего приложения от миллиона и выше. Или при стоимости приложения в несколько тысяч рублей. В противном случае гипотетических хакеров можно не принимать во внимание. 

  8. 6 минут назад, Major сказал:

    Спасибо за код.

    А зачем в вашем коде:

    
    Var AppLicenseKey : String;
    ...
      AppLicenseKey:='MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxim8ZGAIhK/FPhpXT0r6MXHYxYi1qcMfIiKOkiBDHcRYgRLK7';
      AppLicenseKey:=AppLicenseKey+'********************************************************************************';
      AppLicenseKey:=AppLicenseKey+'******************************************************************************';
      AppLicenseKey:=AppLicenseKey+'*******************************************************************************';
      AppLicenseKey:=AppLicenseKey+'Mgv7JP8A+qcDV3lm4M9OKBgxBRLaejxHd1iH3tsMR8PLkKUUf3yrMW8QIDAQAB';

    Чтобы запутать взломщика?

    Хм. Можно и так это рассматривать. Но лучше сначала изучить теоретическую часть покупок в приложении и понять что именно и для чего вы делаете. Копипастить код не поможет. Подробности тут https://www.google.ru/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=покупки+в+приложениях+андроид&*

  9. Тоже не хватает такой функции, давно смирился... Сейчас модно использовать гей-дизайнерский подход - рабочая область не должна превышать по размерам пачку сигарет. Прошу прощения за резкие высказывания - бросаю курить и не люблю дизайнеров ;-)

  10. Вот мой юнит для работы с покупками в приложении:

    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;
    

     

  11. 13 часа назад, krapotkin сказал:

    Ждем с нетерпением версию FastReport без составления отчетов.

    Вам надоело просматривать эти бесконечные отчеты?

    У вас устают глаза?

    На вас ругается начальник?

    Новая версия Fast-Report Buddha Edition. Вы нажимаете кнопку и ничего не происходит!

    Гармония мира ничем не нарушается.

    А можно мне версию с показом фотографий котиков? ;-)

  12. Можно поступить проще - заливать в полуручном режиме 

    procedure ShareFile(aFileName, aComment : String);
    {$IFDEF ANDROID}
    var Intent    : JIntent;
        uri       : Jnet_Uri;
        AttachmentFile: JFile;
        S : String;
    {$ENDIF ANDROID}
    begin
    {$IFDEF ANDROID}
      Intent := TJIntent.Create;
      Intent.setAction(TJIntent.JavaClass.ACTION_SEND);
      Intent.setFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK);
      S:=TPath.GetFileName(aFileName);
      Intent.putExtra(TJIntent.JavaClass.EXTRA_SUBJECT, StringToJString(aComment));
      Intent.putExtra(TJIntent.JavaClass.EXTRA_TEXT, StringToJString(aComment));
      AttachmentFile := TJFile.JavaClass.init(StringToJString(aFileName));
      Uri := TJnet_Uri.JavaClass.fromFile(AttachmentFile);
      Intent.putExtra(TJIntent.JavaClass.EXTRA_STREAM, TJParcelable.Wrap((Uri as ILocalObject).GetObjectID));
      Intent.setType(StringToJString('text/plain'));
    //  Intent.setDataAndType(StrToJURI('file:' + TPath.Combine(TPath.GetSharedDownloadsPath, 'picture.png')), StringToJString ('image/png'));
      SharedActivity.startActivity(Intent);
    {$ENDIF ANDROID}
    end;

    Пользователю выведется диалог отправки файла, он должен будет выбрать DropBox... Конечно это решение для разовой отдачи, если нужно регулярная отсылка в авторежиме, то оно не подойдет.

  13. Не выходит каменная чаша... Вроде все сделал правильно, но при загрузке пакета получаю ошибки:

    Цитата

    SuprnovaMonitor.appx5.8 МБ

    Ошибка подтверждения приема пакета: You need to accept the Centennial Early Adopter Program Addendum before you can submit this app.
    Ошибка подтверждения приема пакета: У вас нет разрешений на указание следующих пространств имен в файле манифеста appx пакета SuprnovaMonitor.appx: http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities
    Ошибка подтверждения приема пакета: Your developer account doesn’t have permission to submit apps converted with the Desktop Bridge at this time. https://aka.ms/desktopbridgeforwindowsstore

     

  14. Видимо никак. Проще сделать свой MessageBox - layout на весь экран, на него все остальное.

    Я уперся рогом и минут сорок пытался закрыть, вот что уже попробовал (но не сработало):

    procedure TForm1.Timer1Timer(Sender: TObject);
    Var APointF : TPointF;
        Key: Word;
        KeyChar: System.WideChar;
        MessageBase : TMessageBase;
    begin
      Memo1.Lines.Add('Срабатывает таймер');
      APointF.X:=100;
      APointF.Y:=100;
      Key:=vkHardwareBack;
      KeyChar:=#0;
    //  Self.BringToFront;
    //  MessageBase:=TMessageBase.Create;
    //  Self.VirtualKeyboardChangeHandler(Self, MessageBase);
    //  SetFocused();
    //  Self.KeyDown(Key, KeyChar, []);
    //  Self.Focused.SetFocus;
    //  Self.Tap(APointF);
    //  Self.DoTap(APointF);
    //  Self. Action. Tap(APointF);
      Timer1.Enabled:=False;

     

  15. 32 минуты назад, x11 сказал:

    Вот именно, что хорошо бы без TLabel, чтобы у контейнера была своя подпись.

    Шикарное решение у DevExpress в TcxLayoutControl. И пользлватель сам может редактировать форму в Runtime.

    Элементарно - TListBoxItem.Text:='Это включает такую то фичу';

  16. 20 минут назад, x11 сказал:

     

    хмммм, неплохо, а где и как можно поизучать матчасть и примеры о том, как вставлять компоненты в TListBox или в TListView?

    Кидаете на форму TListBox, правой кнопкой по нему и через контекстное меню создаете TListBoxItem. В TListBoxItem кидаете TLabel с выравниванием по левому краю, пишите текст "Это включает такую то фичу". В тот же TListBoxItem кидаете нужный контрол, к примеру TSwitch с выравниванием по правому краю и привязываете к нему нужный код. Все, повторяете необходимое количество раз. Если нужно много подобного - проделываете тоже самое в процессе выполнения приложения программно.

  17. В Tokyo данный косяк решили сохранить, видимо он им дорог как память :-)

    Вот кусок из System.Net.HttpClient.Win.pas

      // Send data
      if DataLength > 0 then
      begin
        SetLength(Buffer, BUFFERSIZE);
        while LRequest.FSourceStream.Position < LRequest.FSourceStream.Size do
        begin
          ToRead := LRequest.FSourceStream.Size - LRequest.FSourceStream.Position;
          if ToRead > BUFFERSIZE then
            ToRead := BUFFERSIZE;
          LRequest.FSourceStream.ReadBuffer(Buffer, ToRead);
          // Write data to the server.
          if not WinHttpWriteData(LRequest.FWRequest, Buffer[0], ToRead, @BytesWritten) then
            raise ENetHTTPClientException.CreateResFmt(@SNetHttpClientSendError, [GetLastError, SysErrorMessage(GetLastError, FWinHttpHandle)]);
          if BytesWritten < ToRead then
            LRequest.FSourceStream.Position := LRequest.FSourceStream.Position - (ToRead - BytesWritten);
        end;
      end;

     

  18. 4 часа назад, x11 сказал:

    Мультиплатформенное приложение. Проверяю на Windows (на Android пока не проверял).

    На форме лежит TVertScrollBox, а внутри этого ScrollBox`а лежит GridPanelLayout.

    Проблема в том, что у VertScrollBox не появляется полоса прокрутки.

     

    Изначально задача такая. На форме мобильного приложения для смартфона может быть много разных компонент. И нужно иметь возможность прокручивать форму, а вернее компоненты, вверх вниз.

    Сейчас пытаюсь сделать так. Компонента TGridPanelLayout разделена 2 колонки: подпись слева (в левой колонке TLabel) и в правой колонке компоненты редактирования (TEdit, TComboBox и другие).

    Пытаюсь спроектировать форму редактирования объявления, где много разных параметров: дата, тип, картинки, многострочный текст, выпадающие списки, кнопки и т.д.

    Я для таких целей использую TListBox. Проще и удобнее. Плюс некоторые строки по мере надобности можно скрывать/показывать.

  19. 17 минут назад, ENRGY сказал:

    В мобильных приложениях надо экономить место. Поэтому лэйбл положите прямо внутрь Tedit и TCombobox или Memo (можно сделать в инспекторе объектов), поставьте ему enabled := false чтобы он был серого цвета. Затем на OnChange или OnChangeTracking проверяйте кол. символов и прячьте лэйбл: 

    Label1.Visible :=   Edit1.Text.Length = 0;

    Эта плюшка уже есть в TEdit, называется TEdit.TextPrompt 

  20. Пока нашел только одно решение. Только для случая с TListView, и только с одной картинкой на ListViewItem. Да, и только для Tokyo (добавили TListViewItem.TagObject)

        AListItem:=ListView.Items.Add;
        AListItem.TagObject:=TMemoryStream.Create;
        FAsyncResponse := FHTTPClient.BeginGet(DoEndDownload, URL, AListItem.TagObject as TMemoryStream);

    Т.е. MemoryStream, в который производится скачивание, мы создали в AListItem.TagObject, по окончании загрузки будем знать в какую картинку какого итема грузить .

     

×
×
  • Создать...