-
Content Count
1406 -
Joined
-
Last visited
-
Days Won
22
Posts posted by programmerdelphi2k
-
-
25 minutes ago, David P said:NewChild.Top = HeightofCurrentContents + 50;
NewChild.Parent = myScrollbox;
NewChild.Align = alTop
sometimes, it's necessary ALIGN = NONE!!! then with your "PARENT" defined, now you can put on the position out this control! you see? after this, you can (again) re-align to TOP or BOTTOM, as you need
- first, define the Parent
- later, define align=none
- position=x (out this control, maybe xControl.Top (absolute position on screen) + xControl.Height + NNNN) -> if your xControl is into a another control, use this control-parent to get the values)
- re-define align to Top or Bottom
-
10 minutes ago, hackbrew said:If the OnSaveState event is added to the MainForm, when I exit the mapping app, I'm returned to the Home screen, not to my app which is a problem.
and if you "assign" to current FORM active? unassign for any other... or be, only when you go to MAPs, you assign it, later unassign it!
- the app above is a FMX in MSWindows, not VCL!!!! then when app end, the SaveState is called as expected
-
did you try, before insert the items, define the property position "Y" (or X if horizontally), before that define the "alingment"?
for example: -(value out of screen) (negative or positive) value to position?
-
Another thing:
-
as you use FDMemTable (I think), then, you can save your data on JSON/XML file using the properties for that:
- ResourceOptions ->PersistentFileName + Persistent=true
- then, when you re-open your table, the data should be there!
-
as you use FDMemTable (I think), then, you can save your data on JSON/XML file using the properties for that:
-
28 minutes ago, hackbrew said:Is the data wiped from the memory table and/or embedded database (SQLite) if the app were to say crash/lose focus/device reset?
by default, the all "SaveState" is transitory (tmp), then, you can try save it permanently on disk using: xxSaveState;Name := 'xxxxx'; xxSaveState.StoragePath := 'xxxx';
like this:
- create your FOLDER before save it!!!!
- ALL components should exists on form as exists on SaveState file!!!
// here Im not take care about "AV" ok? do it yourself... implementation {$R *.fmx} procedure TForm1.Button1Click(Sender: TObject); begin // you can use this on "OnCreate" from "form1"... or any place that you desire! // SaveState.Name := 'mySaves.TMP'; SaveState.StoragePath := 'd:\mytmpSaveStateDir'; // if SaveState.Stream.Size > 0 then begin for var i: integer := 0 to (ComponentCount - 1) do SaveState.Stream.ReadComponent(Components[i]); // reading... // ShowMessage('SaveState size on disk: ' + SaveState.Stream.Size.ToString); end else; end; procedure TForm1.FormSaveState(Sender: TObject); begin // 1º FormCloseQuery // 2º FormClose // 3º FormSaveState <---- // 4º FormDestroy // ... SaveState.Stream.Clear; SaveState.Name := 'mySaves.TMP'; // in disk, it will be [ ~project1_ + "your name to SaveState" ] SaveState.StoragePath := 'd:\mytmpSaveStateDir'; // for var i: integer := 0 to (ComponentCount - 1) do SaveState.Stream.WriteComponent(Components[i]); // saving all components on "Form1" // ShowMessage('FormSaveState fired'); end; end.
-
7 minutes ago, shalapai said:it must not be named with schema name,
I dont use PG, then "schema" is really necessary in your definition, say, here: "vTable.SchemaName:='test_schem'; "
-
4 hours ago, shalapai said:vTable.IndexDefs.Add(format('%s_pkey', [vTable.TableName]), 'login;ticket', [ixPrimary]);
here "LOGIN" shouldnt be quoted too?
-
14 hours ago, Bart Kindt said:Uh, I have never heard of "
LLocationForegroundPermission
Have you seen this in my code?
... initialization LLocationForegroundPermission := [ { ARRAY } 'android.permission.ACCESS_COARSE_LOCATION', { } 'android.permission.ACCESS_FINE_LOCATION' { } ]; // LLocationBackgroundPermission := [ { ARRAY } 'android.permission.ACCESS_BACKGROUND_LOCATION' { in Android 11, you'll can see your "Allow all the time" option!!! } ];
-
I think that is explained here not?
read about "SaveState" usage on Android apps:
https://docwiki.embarcadero.com/RADStudio/Alexandria/en/FireMonkey_Save_State
-
read about "SaveState" usage on Android apps:
https://docwiki.embarcadero.com/RADStudio/Alexandria/en/FireMonkey_Save_State
-
-
by default, in Android 11+++ you CANNOT ASK "foreground/background" permissions at same time!!!
- first one, later other! Otherwise, the Android dont use anyone!!!
that way, you can :
procedure TForm1.BtnForegroundClick(Sender: TObject); begin TPermissionsService.DefaultService.RequestPermissions( { } LLocationForegroundPermission, { } MyReqPerms, { } MyRatDisplay { } ); end; procedure TForm1.BtnBackgroundClick(Sender: TObject); begin TPermissionsService.DefaultService.RequestPermissions( { } LLocationBackgroundPermission, { } MyReqPerms, { } MyRatDisplay { } ); end; initialization LLocationForegroundPermission := [ { } 'android.permission.ACCESS_COARSE_LOCATION', { } 'android.permission.ACCESS_FINE_LOCATION' { } ]; // LLocationBackgroundPermission := [ { } 'android.permission.ACCESS_BACKGROUND_LOCATION' { in Android 11, you'll can see your "Allow all the time" option!!! } ];
-
by default, in Android 11+++ you CANNOT ASK "foreground/background" permissions at same time!!!
-
22 minutes ago, Mike Warren said:but it's not what I'm after.
no problem... dont forget that you can move the elements beyond the containers ( negative or positive positions), background or foreground
-
did you read this:
https://developer.android.com/training/location/background
https://developer.android.com/training/location/permissions
QuoteNote: The Google Play store has updated its policy concerning device location, restricting background location access to apps that need it for their core functionality and meet related policy requirements. Adopting these best practices doesn't guarantee Google Play approves your app's usage of location in the background.
Learn more about the policy changes related to device location.
-
what about this idea...
-
1 TLayout (or any other container to Image/Rectangle) = HitTest = TRUE!
- then you can use Layout client-area to expand your rectangle and no needs to do nothing in Timage... doubleclick on rectangle to expand for all client-area from TLayout/container
... private FMouseMoving : boolean; FControlMouseClickPositionXY: TPointF; FRectangleSizeDefault : TRectF; public ... implementation {$R *.fmx} { TForm1 } procedure TForm1.FormCreate(Sender: TObject); begin FRectangleSizeDefault := Rectangle1.BoundsRect; end; procedure TForm1.Layout1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single); begin FControlMouseClickPositionXY := PointF(X, Y); TControl(Sender).AutoCapture := true; FMouseMoving := true; end; procedure TForm1.Layout1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single); begin TControl(Sender).AutoCapture := false; FMouseMoving := false; end; procedure TForm1.Layout1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single); var XY: TPointF; begin if FMouseMoving then begin XY := TControl(Sender).LocalToAbsolute(PointF(X - FControlMouseClickPositionXY.X, Y - FControlMouseClickPositionXY.Y)); TControl(Sender).Position.X := XY.X; TControl(Sender).Position.Y := XY.Y; end; end; procedure TForm1.Rectangle1DblClick(Sender: TObject); begin if (Rectangle1.Align = TAlignLayout.Client) then begin Rectangle1.Align := TAlignLayout.Right; Rectangle1.BoundsRect := FRectangleSizeDefault; end else Rectangle1.Align := TAlignLayout.Client; end; end.
-
1 TLayout (or any other container to Image/Rectangle) = HitTest = TRUE!
-
on OnKeyPress / OnKeyDown event
...
key := uppercase( key ); // keyChar
-
dont forget: you can use "CharCase" property := ecUpperCase to get uppercase without any workaround
-
38 minutes ago, Jud said:. It seems that thread.queue is NOT thread-safe for doing this.
"Queue" put on queue and go back to next command-line (code)... then when possible, your command (queued) will be executed.
QuoteQueue causes the call specified by
AMethod
to be asynchronously executed using the main thread, thereby avoiding multi-thread conflicts.QuoteIf you are unsure whether a method call is thread-safe, call it from within the Synchronize or Queue methods to ensure that it executes in the main thread.
QuoteUnlike Synchronize, execution of the current thread is allowed to continue. The main thread will eventually process all queued methods.
https://docwiki.embarcadero.com/Libraries/Alexandria/en/System.Classes.TThread.Queue
-
I has this case, normally, Code-Editor/LSP assistence stop code-complition work:
Example:
- im creating a new unit to create a class (any) basic nothing advanced. 1create 1 destroy, 1 method any
- then, I decide use "interface" in my new class, then...
- I create a new unit for my new "interface"... ok
- now, I go back to my unit class and add my unit-interface in my uses and add my interface in my class declaration (TInterfacedObject, ImyInterf....) as usual
- now, I try use new class-INTERFACED (now) in my form1 test, and the code-complition does not works anymore... (already known "red-lines" in Editor)
- summary: I need close the project, and re-opent it and all it's ok
- sometimes I see on window Messages: LSP starting
did you try this too?
-
@KodeZwerg your codes dont answer the OP... unfortunatelly I dont have time to time-competition, for now! perhaps another day
-
- If the test is "Ctrl+click" in "Test; (procedure)", in my IDE (RAD11.3 patch 1), the cursor goes to "procedure TForm1.Test;" as expected
-
when I click in "Winapi.Messages," (in uses clauses), the cursor goes to your new "Winapi.Messages.pas" in your project too!
- if I delete this from "uses clauses", the cursor goes to "Winapi.Messages.pas in RAD sources folder" (as expected by default) and Ctrl+click in "Tests" still working as expected too
- if is this, then all works as expected
-
try this way if works for you
- using "Queue" no order will be used, but in "Parallel" you cannot control the flow (calls) too (by default)
implementation {$R *.dfm} uses System.Threading; var LTask: ITask; procedure MyProcToParallelFor(AValue: integer); begin TThread.Queue(nil, procedure begin Form1.Memo1.Lines.Add( { } Format('Thread: %d, AValue: %d', [TThread.CurrentThread.ThreadID, AValue]) { } ); end); // sleep(50); // for responsive tests... end; procedure TForm1.Button1Click(Sender: TObject); var LStart, LEnd: integer; begin LStart := 1; LEnd := 1000; // LTask := TTask.Create( { } procedure begin TParallel.For(LStart, LEnd, MyProcToParallelFor); end); // LTask.Start; end; procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin CanClose := (LTask = nil); // if not CanClose then CanClose := not(LTask.Status in [TTaskStatus.Running, TTaskStatus.WaitingToRun, TTaskStatus.WaitingForChildren]); // if not CanClose then Caption := 'Task in process... ' + TimeToStr(now); end; initialization ReportMemoryLeaksOnShutdown := true;
-
27 minutes ago, KodeZwerg said:No need to do all that what @programmerdelphi2k wrote at all.
as I said: the code is from internet... I just checked the ParentID!
of course, that exists API functions for better checking!
now test your code for: as I did in my code above... same step-by-step
- Run the app as usual
- now, re-run this same app using
-
procedure TForm1.Btn_Run_ME_againClick(Sender: TObject); begin // run me again... by myself! ShellExecute(0, PWideChar(''), PWideChar('project1.exe'), PWideChar(''), PWideChar(''), sw_normal); end;
- now, on first app run your code again
summary:
- the 2 session app will be showing that it was load by itself!!! --> but the first app (session) was called by BDS.exe or Explorer, and 2nd app was called by 1st App
- then, your code is fail too! only the 2nd session was loaded by itself ... the 1st session was loaded by BDS.exe!!!
- each session has a ID distinct, because it is process distincts
-
I think that "ProcessMessages" it's not necessary.
you can use "Synchronize" (wait me ...) or "Queue" (dont wait me ...)
-
you would can some like this...
- You could check the "processID" of the "parent" that ran the current process. Normally, when running an application, "MSExplorer" is the "parent" (but not necessarily).
- So, if Exe2 executed Exe1, "Exe2" would have to be the "parent" of "Exe1", naturally, this might not be true at all, as there are ways to bypass this task.
here is a very easy code to find on the internet, and that I just did some checks to try to find the answer
- im PROJECT1.exe ...
-
see the "2nd" Project1.exe on left Memo and the right Memo = ProcessID from 1º and ParentID from 2º
- we'll have 2 instance of "Project1.exe" = 1 with BDS.exe and 1 with "Project1.exe" (from "run me" button)
- now, just do the changes and clean the code not necessary... the code is not mine! ok
implementation {$R *.dfm} uses Winapi.ShellAPI, Winapi.PsAPI, Winapi.TlHelp32; function SearchParentProcessFrom(const PID: cardinal): string; var hProcess: THandle; path : array [0 .. MAX_PATH - 1] of char; begin result := '... Parent empty ...'; hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, false, PID); // if hProcess <> 0 then try if (GetModuleFileNameEx(hProcess, 0, path, MAX_PATH) <> 0) then // RaiseLastOSError; result := PID.ToString + '=' + ExtractFileName(path); // get Exename/Module finally CloseHandle(hProcess) end else result := '.... ERROR hProcess = 0 = No-Opended file = no problem at all'; end; function CheckProcessOnMemory: TArray<string>; const PROCESS_TERMINATE = $0001; var ContinueLoop : BOOL; FSnapshotHandle : THandle; FProcessEntry32 : TProcessEntry32; ListOfProcessOnMemory: TStringList; LArrIDandName : TArray<string>; LProcessID : cardinal; LProcessParentID : cardinal; i, LCounter : integer; LText : string; begin result := []; // ListOfProcessOnMemory := TStringList.Create; try FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); try FProcessEntry32.dwSize := SizeOf(FProcessEntry32); Process32First(FSnapshotHandle, FProcessEntry32); // while Process32Next(FSnapshotHandle, FProcessEntry32) do ListOfProcessOnMemory.AddPair( { a=b=c } { } FProcessEntry32.th32ProcessID.ToString + '=' + FProcessEntry32.th32ParentProcessID.ToString, { } FProcessEntry32.szExeFile); // Form1.Memo1.Lines.AddStrings(ListOfProcessOnMemory.ToStringArray); finally CloseHandle(FSnapshotHandle); end; // i := ListOfProcessOnMemory.Count; LCounter := 0; // while (LCounter < i) do begin LArrIDandName := ListOfProcessOnMemory[LCounter].Split(['=']); // 3 items (a=b=c) above... // if (length(LArrIDandName) = 3) then begin LProcessID := StrToIntDef(LArrIDandName[0], 0); // processID LProcessParentID := StrToIntDef(LArrIDandName[1], 0); // parentID // // if (LProcessID <> 0) then // "0" = "System" begin LText := SearchParentProcessFrom(LProcessParentID); // find parentID name // // parentID + processName if not(LText.IsEmpty) and LText.Contains(LArrIDandName[1]) and (LText.Contains(LArrIDandName[2])) then LText := LText + ' = load by itself'; // Form1.Memo2.Lines.Add(LArrIDandName[0] + '=' + LArrIDandName[2] + ' Parent: ' + LArrIDandName[1] + ' -> Search: ' + LText); end; end; // LCounter := LCounter + 1; end; finally ListOfProcessOnMemory.Free; end; end; procedure TForm1.Btn_All_Process_On_MemoryClick(Sender: TObject); begin CheckProcessOnMemory; end; procedure TForm1.Btn_Run_ME_againClick(Sender: TObject); begin // run me again... by myself! ShellExecute(0, PWideChar(''), PWideChar('project1.exe'), PWideChar(''), PWideChar(''), sw_normal); end;
App persistence and restoring state
in FMX
Posted
let's imagine a "regular case" = no critical-crash on the system!
maybe not, maybe yes... maybe your code be the "bug"... needs more details/code and somebody that know how Android works behind the scenes...
your code, how do you call the another app into your app? it's possible show the code?