-
Content Count
2983 -
Joined
-
Last visited
-
Days Won
134
Everything posted by Remy Lebeau
-
"Variable Required" compiler error only in Delphi 10.4.2
Remy Lebeau replied to Dave Novo's topic in Delphi IDE and APIs
Yes, that is indeed odd. One would have hoped those helpers would have used WriteBuffer() instead of Write(), but they don't. Why knows why. Bad decision, IMHO. -
Because drawing events are meant JUST for drawing, using the current UI state to decide what to draw. They are not meant for managing/updating the UI state. As long as you are changing the color/font of the Canvas that you are drawing onto, then that is perfectly fine. That is not UI state, that is just drawing state. On the other hand, changing the color/font of a UI control from inside a drawing event would be wrong, and can lead to endless repaint loops that eat up CPU cycles and slow down the UI message loop. Because that is NOT needed OR appropriate during a drawing event. That is for UI logic to handle instead, for instance in reaction to some action. Changing the visibility of a UI control will trigger a UI repaint to draw the updated UI display with/without the control in it. The drawing should account for the control's current state, not update its state.
-
"Variable Required" compiler error only in Delphi 10.4.2
Remy Lebeau replied to Dave Novo's topic in Delphi IDE and APIs
It should not be working. Either it will pass the address of the Pointer itself rather than the address of the TRect, or else it will misinterpret the Pointer as a TBytes. Either way would be wrong. It needs to be either Write(r, sizeof(r)) or WriteData(@r, sizeof(r)). -
"Variable Required" compiler error only in Delphi 10.4.2
Remy Lebeau replied to Dave Novo's topic in Delphi IDE and APIs
Ideally, it should not compile. There are only 3 overloads of Write(), and that code does not logically match any of them: function Write(const Buffer; Count: Longint): Longint; overload; virtual; function Write(const Buffer: TBytes; Offset, Count: Longint): Longint; overload; virtual; function Write(const Buffer: TBytes; Count: Longint): Longint; overload; There is an overload of WriteData() that does match, though: function WriteData(const Buffer: Pointer; Count: Longint): Longint; overload; That being said, there is a known issue when passing a Pointer to Write(): https://delphihaven.wordpress.com/2012/09/30/potential-xe3-gotcha-dodgy-old-code-vs-new-tstream-overloads/ And that is the case here - as seen above, Write() is overloaded to accept either untyped or TBytes parameters. So, it is possible that sometime between Seattle and Sydney, Embarcadero finally fixed this bug in the compiler. Or, maybe it is just a matter of {$TYPEDADDRESS} being OFF in the Seattle code but ON in the Sydney code. As it should be, -
Absolutely DO NOT EVER update UI state in a drawing event! It shouldn't be doing that at all. Get rid of it.
-
TBitmap to TBytes for ESC/POS Thermal Printer
Remy Lebeau replied to at3s's topic in RTL and Delphi Object Pascal
FMX's TBitmap has a Map() method for accessing the raw pixel data. Map() returns a TBitmapData, which has a GetScanline() method. -
Here is a 3rd option: ... IdSMTP1 := TIdSMTP.Create(nil); try IdSSLIOHandlerSocketOpenSSL1 := TIdSSLIOHandlerSocketOpenSSL.Create(IdSMTP1); IdMessage1 := TIdMessage.Create(IdSMTP1); ... finally IdSMTP1.Free; end;
-
Indy is on GitHub: https://github.com/IndySockets/Indy/
-
Yes, it is. But I didn't notice that initially, I thought it was a String instead (which it should be).
-
I checked, and overload was added to TFileStream in Delphi 6, when the 3-parameter constructor for passing in Rights was introduced.
-
I'm aware of that. But I have never seen an example of anyone ever passing an existing file handle to a TFileStream constructor, only to a THandleStream constructor.
-
I didn't say it was wrong, just that it does not follow what Microsoft says to do.
-
I said to use THandleStream, not TFileStream. TFileStream does not have a constructor that accepts an external THandle as input. Unless that is a recent addition that has not been documented yet. Sure, eg: procedure TForm1.FormCreate(Sender: TObject); var lFile: THandle; lStrList: TStringList; lStream: THandleStream; lFileName: PChar; lAttrs: DWORD; begin lStrList := TStringList.Create; try ... lFileName := 'D:\temp\0104.txt'; lAttrs := GetFileAttributes(PChar(lFileName)); if lAttrs = INVALID_FILE_ATTRIBUTES then begin if GetLastError() <> ERROR_FILE_NOT_FOUND then RaiseLastOSError; lAttrs = FILE_ATTRIBUTE_NORMAL; end; lFile := CreateFile(lFileName, GENERIC_WRITE, FILE_SHARE_WRITE, nil, CREATE_ALWAYS, lAttrs, 0); if lFile = INVALID_HANDLE_VALUE then RaiseLastOSError; try lStream := THandleStream.Create(lFile); try lStrList.SaveToStream(lStream); finally lStream.Free; end; finally CloseHandle(lFile); end; finally lStrList.Free; end; end;
-
Yes, you should be able to simply configure the project's search/library paths to point at the Indy 10 source folders rather than the Indy 9 source folders.
-
Indy with Lazarus on Raspberry PI using IPV6 – problem
Remy Lebeau replied to Drewsky's topic in Indy
That does not necessarily mean that is the interface's IP from the server's perspective for binding. That is just the IP that the LAN uses to reach the device. Do you get meaningful IPv6 addresses from Indy's GStack.GetLocalAddressList() method (not sure if it is implemented for Raspberry Pi)? Do you see that IP in the list? -
From the CreateFile documentation: So, you don't have to actually remove the attributes, just match the existing attributes. Which FileCreate() can't do. But you could call CreateFile() directly, and then wrap the HANDLE in a THandleStream if needed.
-
TidHTTPServer with SSL in Delphi 10.3.3 and 10.4.2
Remy Lebeau replied to Cristian Peța's topic in Indy
You are not taking this change into account: Behavioral change to HTTPS handling in TIdHTTPServer When using non-default HTTP/S ports (as you are), you need to assign an OnQuerySSLPort event handler to tell TIdHTTPServer which port(s) you want to activate SSL/TLS on. In the older version, you could get away with not having that handler, but it is required now. -
That is because IDLIST is an array (of integers), but you are trying to read it as a string. jso.GetValue('IDLIST') will return a TJSONValue pointer to a TJSONArray, which does not implement the Value() method, so it returns a blank string. You need to type-cast the TJSONValue to TJSONArray and enumerate its elements, eg: var jso: TJsonObject; jsa: TJSONArray; s, RetIDList: string; i: Integer; begin s := '{"RESULT":200, "IDLIST":[1,2,3,4,5]}'; jso := TJsonObject.ParseJSONValue(s) as TJsonObject; if jso <> nil then try ... RetIDList := ''; jsa := jso.GetValue('IDLIST') as TJSONArray; if jsa <> nil then begin if jsa.Count > 0 then begin RetIDList := jsa[0].Value; for i := 1 to jsa.Count-1 do RetIDList := RetIDList + ',' + jsa[i].Value; end; end; ... finally jso.Free; end; end;
-
Blogged : Advice for Delphi library authors
Remy Lebeau replied to Vincent Parrett's topic in Tips / Blogs / Tutorials / Videos
C++ supports abstract classes. But abstract classes in C++ can't be used in all contexts that Delphi supports them. Also, not all of the empty methods are for abstract support, they are simply placeholders to allow descendants to hook into strategic places if they want to. -
FreePascal/Lazarus's RTL/LCL frameworks are fairly API-equivalent to Delphi's RTL/VCL, about on par with Delphi 7-ish, with a few 2009+ features thrown in (UnicodeString, etc). So, if you have something already working in VCL, it will likely port as-is (or close to it) to Lazarus.
-
I miss the old newsgroups 😢 None of the newer web-based forums have really matched up to them, in terms of usability, monitoring, organization. It is just not the same.
-
Blogged : Advice for Delphi library authors
Remy Lebeau replied to Vincent Parrett's topic in Tips / Blogs / Tutorials / Videos
My plan for Indy 11 many years ago was very different than the current plan. Originally, Indy 11 was going to be for a bunch of new features I was working on. Then a few years ago, we decided to make Indy 11 be just a maintenance release instead to cleanup the existing codebase (drop old compilers, cleanup ifdefs, etc), and push back new features to Indy 12. The "Restructure" branch currently in the GitHub repo is what will eventually become Indy 11. The majority of the work is already done, it just needs to be brought up-to-date with the latest master branch, rebranded, validate everything builds with the new folder/naming structures, etc. -
Blogged : Advice for Delphi library authors
Remy Lebeau replied to Vincent Parrett's topic in Tips / Blogs / Tutorials / Videos
But the naming of the DCP would change, and that would break existing projects. At the very least, I would have to issue an advisory and document that any Indy upgrades made past X release would require project updates to continue using Indy. I was waiting until Indy 11 to make that change, since I'm restructuring the packages anyway. -
Comunicate with POS terminal (Ingenico)
Remy Lebeau replied to boris.nihil's topic in Network, Cloud and Web
The code I presented is only handling 1 request/response at a time, per the documented flow chart. If there are multiple messages involved in a single transaction, then of course you will have to adjust the code to account for that. In the part where it says "use ReceivedText as needed...", you would have to actually look at the message data, and if it is INSERT CARD then progress to the next state and act accordingly to continue the transaction, not go back to the stIdle state until the transaction is finished. I have posted examples of that MANY times before, in many different forums. Should not be hard to find with some searching around. The best way to handle this is to implement a per-client thread-safe queue for each TIdContext, then your UI thread can push data into the queue of the desired client as needed, and the server's OnExecute event can send queued data for the calling TIdContext when it is safe to do so. -
Are you SURE your entire process just terminates immediately when exit() is called, and you are not simply failing to catch an exception that causes your main thread to end? Have you wrapped the Python4Delphi code in a try/except block? I am not familiar with Python4Delphi, but after a quick look through its source code, it appears like it might catch a Python SystemExit exception and raise a Delphi-style EPySystemExit exception into user code. Not sure about that, though. Have you tried catching EPySystemExit?