-
Content Count
2684 -
Joined
-
Last visited
-
Days Won
113
Everything posted by Remy Lebeau
-
There is another possibility. If you don't mind assigning the OnHint events in code at runtime (or at least looping through the actions at runtime to update their OnHint handlers that are assigned at design-time), then you can use the TMethod record to alter the event handler's Self pointer to point at each TAction object instead of the TForm object. Then you can just type-cast the Self pointer inside the handler. For example: procedure TForm1.FormCreate(Sender: TObject); var Evt: THintEvent; begin ... Evt := Action1.OnHint; // or: Evt := @ActionHint; TMethod(Evt).Data := Action1; // instead of Form1 Action1.OnHint := Evt; ... // repeat for all TAction objects that share ActionHint()... end; procedure TForm1.ActionHint(var HintStr: string; var CanShow: Boolean); begin // use TAction(Self) as needed... end;
-
I don't have an up-to-date version to verify this with, but I seriously doubt what you claim is true. Up to at least XE8, FileExists() was never coded to raise any exceptions. I can't imagine Embarcadero would ever add exception handling to FileExists() in the years since that release.
-
Unfortunately, you can't, at least not from the event itself, anyway. You will have to instead use a different event handler for each action, making them call a common method if they need to share code, eg: procedure TForm1.Action1Hint(var HintStr: string; var CanShow: Boolean); begin DoActionHint(Action1, HintStr, CanShow); end; procedure TForm1.Action2Hint(var HintStr: string; var CanShow: Boolean); begin DoActionHint(Action2, HintStr, CanShow); end; procedure TForm1.DoActionHint(Sender: TObject; var HintStr: string; var CanShow: Boolean); begin ... end; .
-
Apparently, this is a known bug since inline variables were first introduced in 10.3 Rio, and the following tickets are still open: RSP-22359: Nameless types are not allowed within inline variable declarations RSP-31970: How to inline static array variables in Rio Based on the comments on the tickets, the workaround I suggested earlier to pre-define the array type should work for an inline variable: type Char256Array = array [0 .. 255] of Char; var buffer: Char256Array;
-
List counts are 32bit Integers, not 16bit Smallints. I doubt you will ever have more than 32K Forms/DataModules active at a time, but it is less efficient to make the compiler compare a Smallint loop counter to an Integer count on every iteration, the counter would have to be scaled up to 32bits each time. Is that an actual compiler error? Or just an ErrorInsight error, but the code actually compiles fine?
-
Yes. Its scope is limited to the loop body, so it will enter and leave scope on each iteration. Not really, no. If ARC were involved (which is no longer the case), that would include incrementing and decrementing the object's refcount. But in any case, since the variable is just a pointer, the compiler is likely to optimize the variable to reuse the same memory for each new instance each time the loop iterates. What does the error message actually say? It looks OK ome, so I'm guessing that the compiler simply hasn't implemented support for inline arrays. Do you have the same problem if you declare the array type beforehand? type Char256Array = array [0 .. 255] of Char; var buffer: Char256Array; Last I heard, the CodeEditor/ErrorInsight still hadn't been updated to support the new inline syntax yet. But the compiler will still accept it.
-
To use a custom file extension like that, you have to create and register a custom TMedia class to handle it. The StackOverflow link I gave you earlier explained that.
-
A gem from the past (Goto)
Remy Lebeau replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
I would have just wrapped the logic in a loop instead: function whatever: SomeType; begin repeat // some code that generates the result until Result <> ResultIWantToDebug; end; Or, renamed the original function and introduced a new function with the original name to call the new function in a loop: function actual_whatever: SomeType; begin // some code that generates the result end; function whatever: SomeType; begin repeat // some code that generates the result until Result <> ResultIWantToDebug; end; -
How can i stream audio from mediaplayer with idhttp
Remy Lebeau replied to Linuxuser1234's topic in FMX
Why are you sending a new HTTP request from inside the TIdHTTP.OnAuthorization event? There is already an HTTP request in progress when that event is fired, it is asking you to provide credentials for that request. If you look at the example more carefully, it is not even using TIdHTTP to stream the actual media, TMediaPlayer is handling that internally. TIdHTTP is simply being used to retrieve a list of available media URLs from a server, and then a selected URL is given directly to TMediaPlayer to play, one at a time. So, what is stopping you from doing the same thing in your code? Did you even try giving TMediaPlayer a media URL to play? MediaPlayer1.FileName := 'https://radio.weatherusa.net/NWR/KEC61_2.mp3'; MediaPlayer1.Play; If that still doesn't work, then see my earlier StackOveflow answer to How play .mp3 files loaded from a URL in TMediaPlayer with Firemonkey? -
How can i stream audio from mediaplayer with idhttp
Remy Lebeau replied to Linuxuser1234's topic in FMX
Have you looked at Embarcadero's Streaming Media example yet? https://docwiki.embarcadero.com/CodeExamples/en/FMX.StreamingMedia_Sample -
Type-cast the 3rd parameter: SetWindowLong(thisform.Handle, GWL_STYLE, LONG(WS_POPUP or WS_CLIPSIBLINGS or WS_CLIPCHILDREN or WS_SYSMENU)); Though, SetWindowLong() has been deprecated for a long time, as it doesn't support 64-bit apps. You really should be using SetWindowLongPtr() instead: SetWindowLongPtr(thisform.Handle, GWL_STYLE, LONG_PTR(WS_POPUP or WS_CLIPSIBLINGS or WS_CLIPCHILDREN or WS_SYSMENU));
-
Anyone else having trouble accessing https://docwiki.embarcadero.com ?
-
Unfortunately, the underlying Win32 tab control which TPageControl is built on does not provide that information natively. The TPageControl.OnChanging event is fired BEFORE the active TabSheet changes, and the TPageContro.OnChange event is fired AFTER the active TabSheet is changed. So, you will have to keep track of the previous TabSheet in your own code, eg: private PreviousTabSheet: TTabSheet; procedure TForm1.PageControl1Changing(Sender: TObject; var AllowChange: Boolean); begin PreviousTabSheet := PageControl1.ActivePage; AllowChange := True; end; procedure TForm1.PageControl1Change(Sender: TObject); begin if PreviousTabSheet <> nil then begin // use PreviousTabSheet as needed... PreviousTabSheet := nil; end; end;
-
Embarcadero's DPI handling is still quite broken. They have taken several major releases to work on it, and it still has problems. You are probably best off simply disabling DPI awareness at the project level, and then scale your UI in your own code as needed.
-
You can either subclass the Gauge control to handle the CM_HINTSHOW message, or you can use the TApplication.OnShowHint/TApplicationEvents.OnShowHint event, to get access to a (pointer to a) THintInfo record, which has HintControl, HintStr, CursorPos, and CursorRect members (amongst other things). As the mouse moves around your UI, the THintInfo members will update accordingly. When the mouse moves from one control to another, the active hint gets reset. When the mouse stays inside of a given control and the CursorPos moves outside of the CursorRect, the active hint gets updated. This allows a control to sub-divide itself so it can have separate hints for different areas. So, if you want the hint to be updated with new text on every mouse move while the mouse is inside of the Gauge control, then whenever the THintInfo's HintControl is pointing at the Gauge control, you can simply set the THintInfo's CursorRect to a 1x1 pixel square at the current CursorPos coordinates, and set the HintStr to the desired text. This way, the next mouse move will go outside of the CursorRect and update the active hint with the new HintStr text. No, you do not.
-
Memory leak on TBlobField(FieldByname(field_name)).SavetoStream(Stream);
Remy Lebeau replied to alogrep's topic in VCL
LoadFromStream() can potentially raise an exception, which will bypass your Free'ing of the TBitmap. Move LoadFromStream() inside the try..except block. -
Embarcadero took over DelphiFeeds 2 years ago to revive it: https://blogs.embarcadero.com/the-all-new-delphifeeds-com/ I guess they are not doing a very good job of that. Or, maybe they are just having system troubles? This wouldn't be the first time an Embarcadero system used by the community went down for weeks at a time.
-
I did, actually. I stated as much in my earlier reply:
-
You are instantiating a TVariantManager instance without populating it, so it has unassigned function pointers at the time you are calling VarToInt64(). You would need to call GetVariantManager() first to initialize the record before you can use it, eg: var v : Variant; N : Int64; VMGR : TVariantManager; begin v := 1234567890; if IsVariantManagerSet then begin GetVariantManager(VMGR); N := VMGR.VarToInt64(v); end; end; However, TVariantManager has been deprecated for a very long time (since sometime between D7..D2006, so approx 20 years!), so wherever did you get the idea that you need to use it in the first place? Since at least D2006 (maybe earlier), GetVariantManager() just fills the record with nil pointers, and IsVariantManagerSet() always returns False. In modern coding, simply assign the Variant directly to the Int64 variable and let the compiler handle the conversion for you, eg: var v : Variant; N : Int64; begin v := 1234567890; N := v; // compiler generates: N := System.Variants._VarToInt64(v); end;
-
Have you read the official documentation yet? https://docwiki.embarcadero.com/RADStudio/en/Generics_Index
-
That is an app-specific internal folder, so it should get deleted on app uninstall. Are you saying that is not the case? If so, then you will have to take up that issue with Google.
-
NetHTTPCLient, NetHTTPRequest and CURL
Remy Lebeau replied to sfrazor's topic in Network, Cloud and Web
Why are you using 'string' for binary data? Don't do that. Use TBytes/TArray<Byte> for that instead. And then you can wrap that with TBytesStream instead of TMemoryStream (avoiding an unnecessary copy) Or, just pass your TMemoryStream into ZipAddJson() and let it Write() its bytes directly to the stream (again avoiding an unnecessary copy). Either way, you are not Seek()'ing the stream back to Position 0 before calling AddStream(). -
In fmx how can i display files from a website to a combobox
Remy Lebeau replied to Linuxuser1234's topic in FMX
There is no facility in the HTTP or HTML standards for a web server to provide a list of files on the server. If a webpage does offer such a list, it does so manually, so you will have to download that page's HTML and parse it yourself to extract the list. There is no standard format for this. -
That does not sound right. TPath.GetDocumentsPath() is documented as using Android's Context.getFilesDir() method, and Android documents that as an app-specific internal folder that gets removed during app uninstall. Clearly. But the question is, why? What path does TPath.GetDocumentsPath() actually return on your device? It must be using a public/shared folder, rather than an internal app-specific folder.
-
NetHTTPCLient, NetHTTPRequest and CURL
Remy Lebeau replied to sfrazor's topic in Network, Cloud and Web
It expects that in the URL itself? That is extremely odd. But even so, that doesn't change anything I said earlier. The code I provided, for both TNetHTTPClient and TIdHTTP, sends a POST in 'multipart/form-data' format, same as curl's CURLOPT_MIMEPOST option does. This is a standardized format. So, what exactly is the server complaining about this when using the code I gave you? Then please show the RAW request that curl is actually transmitting (which you can get by using the CURLOPT_VERBOSE and CURLOPT_DEBUGFUNCTION options), compared to the RAW requests that TNetHTTPClient and TIdHTTP are transmitting (not sure how to get that info with TNetHTTPClient, but for TIdHTTP you can assign any TIdLog... component to the TIdHTTP.Intercept property). In what way, exactly? Oh, so that data is not in the URL, but actually in the POST body? That makes more sense. But even so, the code I gave you should be posting that data just fine. Whatever bytes you put into the TStream will get transmitted to the server. Can you be more specific? Of course, according to the MIME standards for the 'multipart/form-data' format. Yes, you do, because that is what the original curl code is doing, too.