-
Content Count
3001 -
Joined
-
Last visited
-
Days Won
135
Posts posted by Remy Lebeau
-
-
23 minutes ago, rvk said:Why is the date of the files on Fulgan updated each night?
I don't know, I thought they were done maintaining a copy, but I guess not.
23 minutes ago, rvk said:Maybe a readme file there pointing to the new official spot (or at least stating it is decommissioned) would make that more clear.
The readme on that mirror says:
QuoteAs of January 2020, the Indz source code is not available from this mirror anymore:
The indy source control system has been migrated to github. There is therefore no need for extra tools in order to download the latest snapshot.
All source code can be accessed from https://github.com/IndySockets
The Indy SSL libraries will remain here for the time being.
-
7 hours ago, dummzeuch said:Not quite the implementation I would have liked though. Triple quotes '''? Who came up with that? Is that copyied from another programming language?
Influenced by C# (like several features in Delphi have been):
-
1
-
-
7 hours ago, Die Holländer said:Your site (Lebeau Software) is not available anymore.
It is working fine for me.
7 hours ago, Die Holländer said:Are you planning to continue with the site?
Yes. My hosting provider did perform maintenance on my site's server yesterday, so maybe they messed something up, or have already resolved the issue.
-
20 hours ago, DelphiUdIT said:Except for a library for Android ARM64-V8 (64 bit) which is present in Indy and which is not present in Fulgan.
OK, well...
The fulgan mirror has been decommissioned for some time now, the GitHub repo is the official spot now.
-
On 9/17/2023 at 4:07 AM, PeterBelow said:Btw.: TeamB was a group of users offering support to other users on the old Borland newsgroups. As recognition they received goodies like free product licences, a bit like the current Embarcadero MVP program, and we had dedicated support partners at Borland. All that slowly died off after Codegear took over, unfortunately.
But at least we get some of that back via Embarcadero MVP!
-
3 hours ago, DelphiUdIT said:You can look to Indy repository too: https://github.com/IndySockets/OpenSSL-Binaries
Those are the same DLLs that used to be on the indy.fulgan.com site.
-
4 hours ago, domus said:Would anyone know if it's allowed to install a Community Edition of Delphi on two separate PCs simultaneously? (PC and laptop)
Yes, per the EULA:
QuoteINSTALLATION AND USE RIGHTS. You may install and use any number of copies of the software on your devices.
The EULA explains several restrictions on the Community Edition, but this is not one of them.
-
1
-
-
10 hours ago, Rollo62 said:I use ForceQueue and my own implementation of a DelayWorker successfully for years now,
but I never realized that ForceQueue has its own Delay option available too.
The Delay option was added in 10.4 Sydney, so it is a relatively recent addition (2020).
-
1
-
-
4 hours ago, alank2 said:sometimes I have a synchronous process and I want to make sure some VCL elements are updated beforehand. This always worked fine in bcb6.
BCB6 predates Visual Styles and VCL Styles and basically most modern UI practices.
4 hours ago, alank2 said:What could cause the Enabled change to _not_ create an immediate pending message?
For example, when UI changes are animated by the OS or Styles, it would thus take multiple paint cycles to fully animate the complete state change, and ProcessMessages() or Update() may not (likely will not) catch all of the paint cycles in a single call.
51 minutes ago, alank2 said:I realize that putting the "seconds to run" is more ideal in a thread, but that adds creating and managing a thread which I don't want to have to do for every process that takes a few seconds.
You can mitigate that somewhat by using thread pools, for instance.
51 minutes ago, alank2 said:Essentially I am looking for a function that will make sure the UI is fully updated before a period of time where it won't be updated.
There is nothing in UI programming that says like "state change is finished and the UI for it is fully drawn". Not even back in BCB6's day. Although back then, drawing was much simpler, and usually completed in 1 paint cycle. That may not be the case anymore in modern UIs.
51 minutes ago, alank2 said:I tried using calling Repaint for all 3 buttons before a ProcessMessages, but it didn't work.
Whatever is different between versions, perhaps changing a property from true to false takes a number of things to occur in sequence that rely on each other?
That is not really a factor of the property itself, but in the UI rendering behind the scenes, so more oriented to differ between OS versions rather than compiler/VCL versions.
13 minutes ago, alank2 said:DelphiUdIT - I tried the below (with and without the processmessages calls) and it still has the issue
Update() only processes paint messages that are already pending in the message queue. But you also need Invaliidate() to generate those messages in the first place, if they are not already generated for you. So that is where Repaint() comes into play, to signal that a new paint cycle is needed if it hasn't already been signaled.
-
2
-
-
6 hours ago, alank2 said:I think ProcessMessages was supposed to process all messages, right?
Yes, it does. But it can only handle messages that are already in the message queue (or synthetically generated by the queue) at the moment it is called. It does not process future messages. And the behavior you describe sounds like the actions are being delayed such that ProcessMessages() doesn't see all of them right away, which is why calling ProcessMessages() multiple times produces better results.
You really should not be using ProcessMessages() in this manner in the first place. Break up your code logic using TThread::ForceQueue() or a TTimer or equivalent to allow control to flow back into the main message loop so it can continue to process new messages while your desired time interval is waiting to elapse.
For example, using TThread::ForceQueue():
void __fastcall TForm1::Button1Click(TObject *Sender) { Button1->Enabled = false; Button2->Enabled = false; Button3->Enabled = false; TThread::ForceQueue(nullptr, &Step2, 3000); } void __fastcall TForm1::Step2() { Button1->Enabled = true; Button2->Enabled = true; Button3->Enabled = true; TThread::ForceQueue(&Step3, 3000); } void __fastcall TForm1::Step3() { //... } // alternatively void __fastcall TForm1::Button1Click(TObject *Sender) { Button1->Enabled = false; Button2->Enabled = false; Button3->Enabled = false; TThread::ForceQueue(nullptr, [this](){ Button1->Enabled = true; Button2->Enabled = true; Button3->Enabled = true; TThread::ForceQueue(nullpr, [](){ //... }, 3000); }, 3000); }
Or, using TTimer:
void __fastcall TForm1::Button1Click(TObject *Sender) { Button1->Enabled = false; Button2->Enabled = false; Button3->Enabled = false; //Timer1->Interval = 3000; Timer1->Tag = 1; Timer1->Enabled = true; } void __fastcall TForm1::Timer1Timer(TObject *Sender) { if (Timer1->Tag == 1) { Button1->Enabled = true; Button2->Enabled = true; Button3->Enabled = true; //Timer1->Interval = 3000; Timer1->Tag = 2; } else { //... Timer1->Enabled = false; Timer1->Tag = 0; } } // alternatively... void __fastcall TForm1::Button1Click(TObject *Sender) { Button1->Enabled = false; Button2->Enabled = false; Button3->Enabled = false; //Timer1->Interval = 3000; Timer1->OnTimer = Step2; Timer1->Enabled = true; } void __fastcall TForm1::Step2(TObject *Sender) { Button1->Enabled = true; Button2->Enabled = true; Button3->Enabled = true; //Timer1->Interval = 3000; Timer1->OnTimer = Step3; } void __fastcall TForm1::Step3(TObject *Sender) { //... Timer1->Enabled = false; Timer1->OnTimer = nullptr; }
-
3
-
-
2 hours ago, WalkingAway said:Is it possible to get / set through RTTI non standard type value?
I tries, but always got something like 'invalid tapecast' error.
Can you show the actual code you are having trouble with?
2 hours ago, WalkingAway said:What I want - to unified opportunity to set / get "Meta" value ,
it can be FirstFrame.Meta, SecondFrame.Meta, ...
What is "Meta" defined as?
2 hours ago, WalkingAway said:Now I have to write
if FirstFrame.Meta is AccountFrame then ...
else if FirstFrame.Meta is ReportFrame
What is it you are trying to do with "Meta", exactly? We can't really help you without more detail.
2 hours ago, WalkingAway said:If I have 50 frames it is too boring. RTTI may help me
Or maybe mnthere some libraries for that
Or maybe just re-think your design? Perhaps interfaces are more suitable? Hard to say without seeing what you are actually trying to do.
2 hours ago, WalkingAway said:Also I want to link that kind of link to "Meta" to listview (TValue.From) for same purpose. With no success also so far...
I'm sure there are ways to accomplish that, but again, it really depends on what your data looks like and how you are using it.
-
What @DelphiUdIT said. Indy 10 does have .dpk package files for Delphi 7, namely:
IndySystem70.dpk
IndyCore70.dpk
IndyProtocols70.dpk
dclIndyCore70.dpk
dclIndyProtocols70.dpk
-
1
-
1
-
-
57 minutes ago, Todd Grigsby said:I downloaded the latest Indy available on github two nights ago -- 10.6.2 -- and it does not work with TLS 1.3
Did you download only the main code, or did you also download the PR #299 code on top of it?
57 minutes ago, Todd Grigsby said:Any idea when the TLS 1.3 branch will get merged into main?
No ETA at this time. My understanding is that the code works as-is, but still needs to be updated/finalized to include design-time support, added to all of the supported packages, etc.
-
2
-
-
3 hours ago, aehimself said:A ComboBox suffers from the same 2-click issue
What, 1 click to open the list, and 1 click to select? I really don't think that is much of an issue. But if it is, then just use TRadioGroup/3xTRadioButton instead.
-
If UI space is an issue, you could use a TComboBox with Style=csDropDownList instead, and just have 3 items to choose from.
-
4 hours ago, dummzeuch said:Why not just use IFEND for all?
I also use {$LEGACYIFEND ON} in Indy for XE4+ versions. Helps the code remain backwards compatible with earlier versions by forcing the compiler to not accept {$ENDIF} to close {$IF}. The compiler can run into issues when you have nested {$IF} and {$IFDEF} blocks but don't use {$IFEND} consistently, which can trigger error E2029, as mentioned in the {$LEGACYIFEND} documentation (and I've run into it before).
-
1
-
-
7 hours ago, Anders Melander said:So, can anyone remember which version of Delphi broke that scheme?
It's not broken now, but I'm certain that there was a version after Delphi 6 that somehow broke {$IF} so it couldn't be used if backward and forward compatibility was needed.
I don't remember the specific version, but I know there was a time when the compiler had problems with the evaluation order of {$IF} and {$IFDEF}, I think that was around the early Kylix days, so would have probably been around Delphi 6-8. But that is just a guess...
-
1
-
-
10 hours ago, limelect said:Just for knowledge. How will you save TIdContext and then interrogate the list?
In my case, I use a stringlist with peernumber=worker# it is very
helpful to search for peernumber. or vice versa.
clients.IndexOfName(IntToStr(PeerPort)); in one case. or vice-versa.
P.S. I do not suspect using outside the network of the project.
Again, the PeerPort alone is typically not unique enough to identify clients. You are better off assigning your own custom IDs to the TIdContext objects when clients connect/login, eg:
type TMyContext = class(TIdServerContext) UserID: string; end; var Clients: TIdThreadSafeStringList; procedure TMyForm.FormCreate(Sender: TObject); begin Clients := TIdThreadSafeStringList.Create; IdTCPServer1.ContextClass := TMyContext; IdTCPServer1.Active := True; end; procedure TMyForm.FormDestroy(Sender: TObject); begin IdTCPServer1.Active := False; Clients.Free; end; procedure TMyForm.IdTCPServer1Connect(AContext: TIdContext); var UserID: string; List: TStringList; begin UserID := ...; // read user ID from client List := Clients.Lock; try if List.IndexOf(UserID) <> -1 then begin AContext.Connection.Disconnect; Exit; end; List.AddObject(UserID, AContext); TMyContext(AContext).UserID := UserID; finally Clients.Unlock; end; end; procedure TMyForm.IdTCPServer1Disconnect(AContext: TIdContext); begin if TMyContext(AContext).UserID <> '' then Clients.Remove(TMyContext(AContext).UserID); end;
And then you can search your Client's list for your user IDs whenever you need, and then you'll have access to the TIdContext object. Just be careful accessing it if it happens at the same time that the client disconnects. That's why if you intend to send data from outside of the server's own threads, it is best to add a queue to the TIdContext and have the OnExecute event send the queue when safe to do so.
-
1
-
-
On 8/26/2023 at 2:37 PM, Michael Taylor said:I have a fairly simple class where the only members are an enumerated type and an object whose members are two integers and a string. Nothing that needs memory management
Standard strings are compiler-managed types. They are created dynamically and are also reference-counted, so the compiler needs to be able to manage and release them correctly. Don't just let them leak. Otherwise, use fixed-length character arrays if you really don't want to allocate their memory dynamically.
On 8/26/2023 at 2:37 PM, Michael Taylor said:so I wanted to call my constructor "From" instead of "Create" to signify that no memory allocation takes place, and Free won't be necessary.
Instances of a Class are created dynamically and must be Destroy'ed/Free'd to avoid memory leaks. Otherwise, use a Record instead of a Class.
-
1
-
-
On 8/26/2023 at 9:01 AM, limelect said:I am using the server as a response to clients.
However, I would like to send specific client information from the server, which is impossible.
It is not impossible. You simply send the desired data using the IOHandler of the TIdContext object that represents the client on the server. But, you do have to be VERY careful when sending unsolicited (ie, non-requested) data from the server to a client. If you are not careful and send the unsolicited data incorrectly, you can easily corrupt your TCP communication. You need to make sure the client is not trying to request data at the same time that you are sending unsolicited data, or the client might misinterpret the data. Most protocols tat support unsolicited data design their messages in such a way that clients can identify what messages are unsolicited and what messages are responses to requests.
Is this particular client EVER requesting data from the server? Or does the server ALWAYS initiate the sending? It makes a BIG difference in how you design your protocol and manage it in your code. So it is kind of difficult to answer your question definitively without knowing more about your communication needs.
On 8/26/2023 at 9:01 AM, limelect said:Here comes the knowledge. If the server sends a message to whom does he send it? To all clients? Or else?
TCP is a 1:1 connection between client and server. There is no broadcasting. The data will be sent only to the specific client that you send it to.
On 8/26/2023 at 9:01 AM, limelect said:The server message is not a response to the client message.
Are there ANY requests being sent from this client to the server?
If yes, then you need to synchronize your sends so that unsolicited data does not overlap response data. This is typically done by creating a per-client queue of outgoing data, and then having the server's OnExecute event send the calling client's queue when it is safe to do so, ie when it is not servicing any requests.
If no, then you can simply send data directly to the client whenever you want.
On 8/26/2023 at 9:01 AM, limelect said:I could not find a write instruction with the peer number.
There is no "peer number" in TCP. But, the server does have a unique socket handle (ie, TIdContext object) for each connected client. And you can always assign your own ID to each client, as well. You would simply send to whichever socket/context that you are interested in. This is typically handled inside the server's OnExecute event, using the TIdContext that is passed in as a parameter. But, depending on your needs, you can also search the server's Contexts list for the desired client and then send to it (if/when safe to do so).
On 8/26/2023 at 9:01 AM, limelect said:As I have the PeerPort on my server software (I keep a list)
The PeerPort by itself is not adequate enough to uniquely identify clients. If clients connects to the server from different networks, they could use the same PeerPort. You would need the combination of PeerIP+PeerPort to uniquely identify each client. Better to just use the TIdContext objects instead, since they are already unique.
On 8/26/2023 at 9:01 AM, limelect said:I suspect it is not possible to send from server text to a specific Client.
Yes, it is.
-
1
-
-
7 hours ago, LeusKapus said:Wonder if you can recommend a good alternative to Indy to use SMTP with TLS 1.3, since it is not clear if this will be implemented in any foreseable future.
Indy's support for TLS 1.3 has already been implemented here, it just hasn't been merged into the main codebase yet. There is a difference. You are free to try the code for yourself and see if it meets your needs. Eventually, it will get merged in, I just couldn't tell you when. That doesn't mean you can't use it today. Other people are.
-
1
-
-
On 8/18/2023 at 2:34 AM, softtouch said:A workaround would be this I guess:
UniqueString() would have done the same thing with less code, eg:
s := GetPluginName; UniqueString(s);
To make things easier on the caller, that should be done inside of the package function instead, eg:
function GetPluginName: string; begin Result := 'test'; UniqueString(result); end;
On 8/18/2023 at 2:34 AM, softtouch said:If I dont set "tmp" to nil, it will crash.
That makes sense if you are letting the compiler clear "tmp" AFTER the package has been unloaded, since "tmp" will be pointing at unloaded memory when the RTL tries to access it for cleanup, Calling UniqueString()/Copy() BEFORE the package is unloaded addresses that problem. Of course, you could also solve the problem by simply not returning a string literal from the function in the first place, or by ensuring the caller is completely finished using any data from the package before unloading it from memory.
-
Rather than using a separate class in the TListItem.Data property, it would be safer and more efficient to derive a new class from TListItem and add whatever members you want to it, and then return that class type from the ListView's OnCreateItemClass event. You can then type-cast any TListItem in the ListView to your custom class type when needed, and you don't have to worry about freeing them manually. For example:
type TMyListItem = class(TListItem) public BoldText: Boolean; end; procedure TForm8.ListView1CreateItemClass(Sender: TCustomListView; var ItemClass: TListItemClass); begin ItemClass := TMyListItem; end; procedure TForm8.ListView1AdvancedCustomDrawSubItem(Sender: TCustomListView; Item: TListItem; SubItem: Integer; State: TCustomDrawState; Stage: TCustomDrawStage; var DefaultDraw: Boolean); begin if TMyListItem(Item).BoldText then Sender.Canvas.Font.Style := [fsBold]; end; ... var li := ListView1.Items.Add; TMyListItem(li).BoldText := True;
Of course, in this particular example, there is a much simpler solution - just look at the data being drawn and act accordingly, eg:
procedure TForm8.ListView1AdvancedCustomDrawSubItem(Sender: TCustomListView; Item: TListItem; SubItem: Integer; State: TCustomDrawState; Stage: TCustomDrawStage; var DefaultDraw: Boolean); begin if (SubItem > 0) and (StrToInt(Item.SubItems[SubItem-1]) < 0) then Sender.Canvas.Font.Style := [fsBold]; end;
-
2
-
-
Have you tried making the FMX form override its CreateHandle() method to apply the WS_EX_TOPMOST style?
End of licence Comunity edition.
in General Help
Posted
Per the CE FAQ:
https://www.embarcadero.com/products/delphi/starter/faq