-
Content Count
3006 -
Joined
-
Last visited
-
Days Won
135
Everything posted by Remy Lebeau
-
TDirectory.GetFiles is listing the contents of Packages such as PhotosLibrary
Remy Lebeau replied to Incus J's topic in RTL and Delphi Object Pascal
Unfortunately, I see nothing in Delphi that would allow you to use that flag in this situation. TDirectory.GetFiles() is just a wrapper for a typical SysUtils.FindFirst/Next() loop, so it handles whatever files and directories that loop would normally report. If a Package file is treated as if it were a directory (ie FindFirst/Next() returns TSearchRec.Attr with the faDirectory flag set), then TDirectory.GetFiles() is going to recurse into the Package's content if the SearchOption parameter is set to soAllDirectories (as it is in your example). Also, more importantly, FindFirst/Next() simply don't use the FileManager API to enumerate files, they use the POSIX opendir() and readdir_r() functions instead, which have no such skip-Package flag available. Unfortunately, the TDirectory.GetFiles() predicate is only called for files and not for directories (ie, only for items that do not have the faDirectory attribute). Which makes sense, since TDirectory.GetFiles() is looking for only files to add to its output array, so there is no point in it filtering out directories. To prevent TDirectory.GetFiles() from recursing into Packages automatically, you would have to call it with its SearchOption parameter set to soTopDirectoryOnly (which is its default value), and then manually call TDirectory.GetFiles() for any non-Package sub-directory you are interested in. Of course, TDirectory.GetFiles() won't report directories to you, so you would have to use a separate call to TDirectory.GetDirectories() (with SearchOption=soTopDirectoryOnly) and filter out the Packages as needed. Which means, your enumeration time is going to double from having to scan each directory twice. So, in this case, you will likely have to use the FileManager API directly, and not use TDirectory at all. -
To the Application->OnGetActiveFormHandle event, not to the Application->FOnGetActiveFormHandle data member. But yes, you get the idea. Not set a Form as active, no. The RTL is querying you to choose which Form window should be considered "active" at that moment. So, you would need to enumerate your existing Forms and decide which one you want the MessageBox to be on top of. But you don't actually make that Form window be focused. The RTL is merely establishing a Z-Order relationship between the MesageBox and its Owner window. It is not moving input focus around.
-
Agreed. I never understood why they did that in the first place, and why it was never updated to use String parameters instead.
-
[Solved] Can't build project using TJson
Remy Lebeau replied to Alexander I.'s topic in General Help
Why would it? If all you did was add an #include statement to your code, the IDE is not smart enough to know which library to automatically add to the project to make the code in that header file link correctly. It doesn't even know what code is in that header file until the compiler is invoked, and by then it is too late. The IDE can do automatic linkage of libraries only for components that are dropped on a Form/Frame/DataModule in the Designer. Did you do that for the REST components? I'm guessing no. But this issue is not specific to just REST, it applies to any library. For non-designtime code, you are responsible for setting up your project with any necessary library references as needed. -
[Solved] Can't build project using TJson
Remy Lebeau replied to Alexander I.'s topic in General Help
You are not linking to the BPL library that implements TJson. Try adding a reference to the RESTComponents.bpi file to your project. -
Which *should* be returning the modal Form's window, if the modal Form has focus at the time TApplication.MessageBox() is called. It should be noted that if no *active Form* window is found, then TApplication.MessageBox() uses the hidden TApplication window, which is what allows the MessageBox dialog to appear behind Form windows. You could alternatively just call the Win32 MessageBox() API directly (or TaskDialog/Indirect() instead), specifying the desired Form window as its owner window.
-
DBcheckbox
Remy Lebeau replied to abdellahmehdi's topic in Algorithms, Data Structures and Class Design
Your question is too broad. What is the specific issue you are having trouble with? -
Non-Visual Component Caption Color / Transparency IDE
Remy Lebeau replied to MJBComp's topic in Delphi IDE and APIs
You are using a Dark theme in the IDE, which presumably has white text elements defined. It sounds more like MJBComp simply has their Form's Color set to a dark color, which is not the same thing. -
RAD Studio 10.4 Community Edition - missing Delphi.Personality
Remy Lebeau replied to TCH's topic in General Help
Are you installing the IDE on Windows 7, by chance? Windows 7 (and 8 ) was dropped as a supported installation platform for the IDE in 10.4 Sydney (it is still supported as a target platform for compiled projects): -
Left side cannot be assigned to
Remy Lebeau replied to AlanScottAgain's topic in RTL and Delphi Object Pascal
Other people have already explained why that doesn't work. But, if you really want it to make it work, you could declare your property as returning a PRectF pointer instead, eg: type TDrawingObject = class private ... FBoundsRect: TRectF; ... function GetBoundsRect: PRectF; public ... property BoundsRect: PRectF read GetBoundsRect; ... end; function TDrawingObject.GetBoundsRect: PRectF; begin Result := @FBoundsRect; end; -
RAD Studio 10.4 Community Edition - missing Delphi.Personality
Remy Lebeau replied to TCH's topic in General Help
It is not a file. In RAD Studio, Delphi and C++ are implemented as separate "personalities", each with its own toolchain, IDE settings, etc. Each project specifies which personality it targets. Think of personalities as the IDE plugins for implementing different programming languages. So, the "missing personality" error means the IDE can't find the Delphi personality installed. Which Community Edition did you actually install? There is no RAD Studio CE, there are only separate Delphi CE and C++Builder CE. This is covered in the Community Edition FAQs. You can't open Delphi projects in C++Builder CE, as there is no Delphi personality installed. To work with Delphi projects, you need either Delphi CE, or the full RAD Studio. -
Indy download and installation on Lazarus running on Ubuntu
Remy Lebeau replied to ChrisChuah's topic in Indy
There is an installation guide in FPC's wiki: https://wiki.freepascal.org/Indy_with_Lazarus However, note that Indy is available in Lazarus' OPM, that is the easiest way to install Indy into Lazarus. I think that version is a few months behind in updates from Indy's GitHub repo, so I'll ping GetMem to get that updated to the latest. -
Getting input from a TListBox and continuing execution
Remy Lebeau replied to giomach's topic in VCL
That is what I was thinking, too. -
The link works fine for me. Or, did you mean that the *information* presented on the linked page doesn't work for you?
-
Indy OpenSSL static linking
Remy Lebeau replied to danielKishlakov's topic in Network, Cloud and Web
FYI, that is already on Indy's radar: #410 Support YuOpenSSL Since the migration path from OpenSSL 1.1.1 to 3.0 is fairly minimal, I wonder why they don't support 3.0 for Indy. -
Indy OpenSSL static linking
Remy Lebeau replied to danielKishlakov's topic in Network, Cloud and Web
As I mentioned earlier to your comment on StackOverflow, you can't do it that way: -
Then that is a bug that needs to be reported to Embarcadero/Dinkumware, because std::cbegin() is defined as always returning a const_iterator when passed a standard container. The input parameter of std::cbegin() is supposed to be taken as a const, but that is not the case in the example you have shown.
-
Waiting for something without blocking the UI
Remy Lebeau replied to softtouch's topic in General Help
I've already said my piece about that. -
IdUDPClient send packet to Broadcast address. how to avoid getting the data back
Remy Lebeau replied to ChrisChuah's topic in Indy
That is not right. It should be the sender's IP, not the target's IP. Where are you getting that IP from? No (and even if there were, the IP alone is not enough, you need the associated subnet mask, too). You would have to calculate the broadcast IP yourself, or on some platforms you can use an API to query it from the network adapter directly. -
Waiting for something without blocking the UI
Remy Lebeau replied to softtouch's topic in General Help
It seems like you are receiving the server's response asynchronously. In which case, I would suggest not waiting for the response at all. Send the request, and then move on. Let the asynchronous handler notify your code whenever the response actually arrives. You can always disable the UI in the meantime, if needed. Otherwise, if you must make the function act synchronously, even though the response is asynchronous, then at least consider waiting on a TEvent instead of a boolean, eg: function GetTCPIPC(const msg: string): string; begin if not clientclass.Connected then begin Result := ''; Exit; end; clientclass.MsgEvent.Reset; idTCPClient.IOHandler.WriteLn(msg); while clientclass.MsgEvent.WaitFor(10) <> wrSignaled do Application.ProcessMessages; Result := clientclass.msgfromserver; end; Otherwise, consider changing the function to read the response directly in the function itself, not asynchronously from elsewhere. That way, you can place a TIdAntiFreeze component on your Form to keep the UI responsive while the TCP socket is blocking the UI thread, eg: function GetTCPIPC(const msg: string): string; begin if not clientclass.Connected then begin Result := ''; Exit; end; IdTCPClient.IOHandler.WriteLn(msg); //read response here Result := msgfromserver; end; Though, you really should not be doing socket I/O in the UI thread at all. Consider a threaded approach, similar to what ioan showed earlier. -
IdUDPClient send packet to Broadcast address. how to avoid getting the data back
Remy Lebeau replied to ChrisChuah's topic in Indy
On some platforms, you might be able to just set the TIdUDPClient.BoundIP property to the IP of the network adapter you are sending broadcasts from. On other platforms, you might have to resort to using TIdUDPClient.Binding.SetSockOpt(SO_BINDTODEVICE) to bind to a network interface by name instead of IP. But either way, this should prevent your outgoing network adapter from receiving duplicates of its own broadcasts. Not quite sure I understand what you are asking. If you are asking how to ignore the IP of the broadcaster, then whenever you receive a packet, you are also given the sender's IP (and port). You can just ignore packets that come from your own IP. If you are asking what a broadcast IP is in general, then it is a network IP that is masked by its subnet mask, and then OR'ed with the inverse of the subnet mask. So, for example, if you have an IP of 192.168.100.5 and a subnet mask of 255.255.255.0, then the broadcast IP is 192.168.100.255: 192.168.100.5 & 255.255.255.0 = 192.168.100.0 ~255.255.255.0 = 0.0.0.255 192.168.100.0 | 0.0.0.255 = 192.168.100.255 -
How to use a particular network interface to send out UDP data
Remy Lebeau replied to ChrisChuah's topic in Indy
You can optionally set the TIdUDPClient.BoundIP property to the IP of the desired network adapter. If you don't bind the client, the OS will route the packet using the network adapter it thinks is most appropriate, based on its configured routing tables. -
Unfortunately, those version numbers predate Indy's switch from SVN to GIT, when build number versioning was lost. So I can't diff those versions to see what changed between them (unless you have dates on them, at least). But the behavior should have improved from older to newer, not degraded. It is technically possible (you would have to peek - not read - the first handful of bytes to detect whether a SSL/TLS header is present, and if so then set PassThrough=False. I do not recommend this approach. You should use separate ports, one port with SSL/TLS enabled, and one port without. It is just easier, safer, and more reliable that way. I posted an example in Indy's AToZed forum a few years ago (it was written for TIdHTTPServer, but you can adapt it for TIdTCPServer): https://www.atozed.com/forums/thread-367-post-834.html#pid834
-
You should double-check that, since you clearly do have an SSL/TLS handshake being performed. TIdServerIOHandlerSSLOpenSSL.Accept() should be creating a new TIdSSLIOHandlerSocketOpenSSL whose PassThrough is True, so the server can then decide when it is best to set it to False (ie, when the client is connected to an implicit SSL port, or after receiving a STARTTLS-style command, etc). Note that there was a bug where PassThrough was initialized as False in TIdSSLIOHandlerSocketBase, that was fixed a few years ago, I think that might have been after 10.6.2.5366. You might consider upgrading to the latest version from Indy's GitHub repo and see if the problem continues, just to make sure you have all of the latest fixes.
-
That is simply not possible the way you describe. The ONLY way you can get that error is during an SSL/TLS handshake, which is NOT performed when PassThrough is set to True (ie, pass-through raw data as-is) thus disabling SSL/TLS. So, you MUST be setting PassThrough to False (ie, intercept data for SSL/TLS processing) in order to get that error. Which version of Indy are you using? IIRC, there was a bug in old versions where a server would set PassThrough to false for all clients, causing an SSL/TLS handshake for non-SSL/TLS clients. But that was fixed a LONG time ago.