Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 04/04/19 in all areas

  1. dummzeuch

    Decorating read-only controls

    Not only IT-designers. It's designers <period>. Show me an unusable product and in 90% it will turn out that it was perfectly usable when the engineers finished. And then the designers ruined it. There used to be a credo "form follows function", but today it's "it doesn't matter whether it works, let's make it flashy." </rant>
  2. Edwin Yip

    Tool to convert form components to run-time and vice-versa

    GExperts. Once installed you'll see the Component to Code menu item when you right click on any components on a form at design time.
  3. Only if you use the syntax you showed, yes. An alternative would be to use the TList<T>.List property instead, which gives you somewhat more direct access to the internal array: procedure TForm1.FormCreate(Sender: TObject); var ... vList: TList<TRecLine>; vNode: PVirtualNode; ... begin ... vList.List[0].VirtualNode := vNode; ... end; Or, use the TList<T>.PList property instead, which is as bare-bones as you can get to the internal array: type TRecLine = record ... end; PRecLine = ^TRecLine; procedure TForm1.FormCreate(Sender: TObject); var ... vList: TList<TRecLine>; vNode: PVirtualNode; ... begin ... (PRecLine(vList.PList)+0{Index}).VirtualNode := vNode; ... end; Do note that System.TArray<T> (not to be confused with System.Generics.Collections.TArray<T>) has supported insert and concatenation operations since XE7. See String-Like Operations Supported on Dynamic Arrays and Dynamic Arrays in Delphi XE7. VST doesn't care how you store your data, only that you should store a user-defined value inside each VST node so you can get back to your data given a node when needed. The best way to do that would be to store an actual TRecLine pointer in the node, where that pointer points to an item in your TList/TArray. But, if you are going to be adding/removing items from your TList/TArray, then that gets dangerous since you will be invalidating stored pointers. The next best option would be to store a TList/TArray index in each node instead, but then you have to worry about invalidating stored indexes. The next best option might be to store a unique ID number in each TRecLine, and then store those IDs in each node, and look for them in your TList/TArray when needed, but then you get into performance issues having to re-iterate the TList/TArray all the time. Certainly other options may exist, but what they are really depends on the design of your data and how you intend to use/manipulate it.
  4. Even though TList<T> uses a dynamic array internally, accessing its elements is very different than accessing the elements of TArray<T>. In your case, accessing vArray[n] is direct access to your record items, but vList[n] uses the TList<T>.Items property, which returns a copy of your record items, and you can't modify a copy inline the way you are trying to. You would have to manually save that copy to a variable and reassign it back to the TList<T> after modifying it, eg: procedure TForm1.FormCreate(Sender: TObject); var vArray: TArray<TRecLine>; vList: TList<TRecLine>; vNode: PVirtualNode; vRec: TRecLine; begin ... vArray[0].VirtualNode := vNode; // OK //vList[0].VirtualNode := vNode; // NOT OK! vRec := vList[0]; vRec.VirtualNode := vNode; vList[0] := vRec; ... end;
  5. Since you are developing for mobile. DO NOT run blocking tasks in the main UI thread, it must service only the UI. Long-running tasks must be done in the background instead. In your case, you have a LONG-running task (5.5 seconds) that blocks the UI until the task is finished. Tokyo let you get away with it using a hack. Rio doesn't. So just don't do it anymore. You need to change the code (even for Tokyo) to work with the main UI thread correctly, stay away from ProcessMessages() at all costs (especially now that Embarcadero has broken it and doesn't want to fix it). Do things asynchronously so flow returns to the main UI message loop in a timely manner (otherwise Android is likely to kill your app!). For example: procedure TForm2.Button1Click(Sender: TObject); var StartTimer: TProc; begin ProgressBar1.Max := 100; ProgressBar1.Value := 0; StartTimer := procedure begin Timer1.Interval := 500; // <-- can be set at design-time Timer1.Enabled := True; end; {$IF CompilerVersion < 33} // 10.2 Tokyo or earlier TabControl1.TabIndex := 1; StartTimer; {$ELSE} // 10.3 Rio or later TabControl1.SetActiveTabWithTransitionAsync(TabControl1.Tabs[1], TTabTransition.None, TTabTransitionDirection.Normal, StartTimer); {$IFEND} end; procedure TForm2.Timer1Timer(Sender: TObject); begin ProgressBar1.Value := ProgressBar1.Value + 10; if ProgressBar1.Value >= ProgressBar1.Max then Timer1.Enabled := False; end; Yes, sorry about that. Fixed above. What is there not to understand? The TTabControl is transitioned to the desired Tab and a timer is started, then flow is returned to the main UI message loop. When the timer fires after 500ms, the ProgressBar is incremented and flow is returned to the main UI message loop. The timer fires again after another 500ms, and again, each time returning to the main UI message loop. Eventually, the ProgressBar reaches its Max and the timer is stopped.
×