Jump to content

Remy Lebeau

Members
  • Content Count

    3060
  • Joined

  • Last visited

  • Days Won

    139

Everything posted by Remy Lebeau

  1. Remy Lebeau

    exit terminates delphi app

    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?
  2. Remy Lebeau

    Read ASCII file from URL like a file

    WinInet supports both HTTP and HTTPS. InternetReadFile() works just fine with HTTPS resources.
  3. Remy Lebeau

    Blogged : Advice for Delphi library authors

    I just looked at the Pull Request history, and I do see 2 requests that you had submitted and then closed. I don't think I ever saw them while they were open, otherwise I would have merged them. I have merged them now, and I will look into whether your changes should to be merged into other scripts.
  4. Remy Lebeau

    Blogged : Advice for Delphi library authors

    I know. But since Indy has never used LIBSUFFIX, its package project names are suffixed, and so the dcp files are also suffixed. Well, they do use Indy inside some of their own tech, so they need a stable version to link against. But they are supposed to be using a private copy that is separate from the public copy they ship for users. That being said, it is a goal for Indy to eventually be phased out of the IDE releases and move into GetIt instead. But its complicated installation steps (more for C++ than Delphi) makes that difficult right now. I'm hoping to clean that up in Indy 11. True, most IDE releases don't ship with the latest Indy release available at the time. 10.4 did, though (which its Indy is already not the latest anymore).
  5. Remy Lebeau

    Blogged : Advice for Delphi library authors

    Despite the title, that post is shaming Indy much more than it does TeeChart. And at the end, it says: I'm well aware of the issues you raised in that post. OK granted, the .bat scripts are a bit of a mess (I never use them myself, and the only reason they even exist is for supporting C++Builder). But the package names having hard-coded suffixes is not about being sloppy, it is about backwards compatibility. Indy still supports all the way back to Delphi 5 and even 4, which predate the LIBSUFFIX option. And by the time LIBSUFFIX actually became commonly used by component authors, it was too late to update Indy 10 without major breakages in existing user code. There is an open ticket to add LIBSUFFIX support to Indy, which is scheduled to be implemented in Indy 11, when support for old compilers will be dropped. Frankly, I don't know why TeeChart was ever referencing IndyProtocols.dcp in the first place, since Indy has NEVER used non-suffixed package names. IIRC, it might have been CodeGear/Embarcadero that did, at one time, strip off the suffixes in their private copies of Indy that shipped with the IDE. But the official version of Indy has ALWAYS used suffixed package names.
  6. Remy Lebeau

    Enumerating Windows Sounds

    What's wrong with enumerating that folder? That is likely what the dialog is doing. Why do you expect there to be an API that provides that list? Not everything in a system UI has a dedicated API behind it.
  7. Remy Lebeau

    "Value assigned to 'xxxxxxxx' never used" issue..

    As you should be, because THAT value you are assigning to dlgResult at THAT point in the code is indeed NOT being used, so it doesn't matter what value you assign to dlgResult. You are OVERWRITING that value afterwards, at "if FilterID1.Value.IsEmpty then dlgResult := False else dlgResult := True;" hence the compiler warning is correct. The compiler is not complaining that the dlgResult variable itself is not being used. It is complaining that the VALUE you are assigning to the dlgResult variable after FilterID1.Execute() exits is not used, so there is no point in assigning that value at all. I think you need to tweak this code a little. Try something more like this: dlgResult := FilterID1.Execute; if dlgResult then begin FilterValue := Trim(FilterID1.Value); dlgResult := not FilterValue.IsEmpty; end; if dlgResult then begin if not TryStrToInt(FilterValue, iJobNo) then begin MessageBeep(MB_ICONERROR); ShowMessage('An Invalid Job # has been entered!'); end else Break; end else ApplyFilter := False;
  8. Remy Lebeau

    Comunicate with POS terminal (Ingenico)

    Why are you clearing the InputBuffer? If you are reading messages correctly, you should never need to do that. As I said earlier, since the ACK/NAK is only 1 byte, you should use ReadByte() instead of WaitFor(), eg: var b: Byte; b := IdTCPClient1.IOHandler.ReadByte; if b = $6 then // ACK begin // read POS's next message... end else if b = $15 then // NAK begin // failure of previous message you sent... end else begin // unexpected, do something... end; Personally, I would just get rid of the timer completely. Following the flow chart you posted earlier is easier when using blocking I/O operations with the IOHandler's ReadTimeout property, eg: var iTry: Integer; b, lrc: Byte; ReceivedText: string; procedure AddToMemo(const S: string); begin Memo1.SelStart := Memo1.GetTextLen; Memo1.SelLength := 0; Memo1.SelText := S + sLineBreak; end; begin iTry := 0; try IdTCPClient1.IOHandler.DefStringEncoding := IndyTextEncoding_8Bit; IdTCPClient1.IOHandler.ReadTimeout := 1000; repeat IdTCPClient1.IOHandler.Write(...); // send message to POS try b := IdTCPClient1.IOHandler.ReadByte; // wait for ACK/NAK except on E: EIdReadTimeout do begin Inc(iTry); if iTry < 3 then Continue; raise; end; end; if b <> $6 then // not ACK? begin Inc(iTry); if iTry < 3 then Continue; raise Exception.Create('No ACK received'); end; repeat // wait for message... ReceivedText := IdTCPClient1.IOHandler.WaitFor(#3, True, True); lrc := IdTCPClient1.IOHandler.ReadByte; AddToMemo('Received message:' + ReceivedText + Char(lrc)); if (ReceivedText is not valid) then begin IdTCPClient1.IOHandler.Write(Byte($15)); // send NAK Continue; // keep waiting... end; IdTCPClient1.IOHandler.Write(Byte($6)); // send ACK if (ReceivedText is HOLD message) then Continue; // keep waiting... // use ReceivedText as needed... Break; // all done... until False; until False; except on E: Exception do AddToMemo('ERROR! ' + E.Message); end; end; But, if you really want to use a separate timer, you should implement a state machine, eg: type TState = (stIdle, stSendingMsg, stWaitingForAck, stWaitingForMsg, stError); private iTry: Integer; CurrentMsg: string; State: TState; ... procedure TMyForm.AddToMemo(const S: string); begin Memo1.SelStart := Memo1.GetTextLen; Memo1.SelLength := 0; Memo1.SelText := S + sLineBreak; end; procedure TMyForm.IdTCPClient1Connected(Sender: TObject); begin IdTCPClient1.IOHandler.DefStringEncoding := IndyTextEncoding_8Bit; IdTCPClient1.IOHandler.ReadTimeout := 1000; State := stIdle; end; procedure TMyForm.DoSomething; begin iTry := 0; CurrentMsg := ...; State := stSendingMsg; Timer1.Interval := 10; Timer1.Enabled := True; end; procedure TMyForm.Timer1Timer(Sender: TObject); var b, lrc: Byte; ReceivedText: string; begin case State of stSendingMsg: begin try IdTCPClient1.IOHandler.Write(CurrentMsg); // send message to POS except on E: Exception do begin State := stError; Timer1.Enabled := False; AddToMemo('ERROR! ' + E.Message); Exit; end; end; State := stWaitingForAck: end; stWaitingForAck: begin try b := IdTCPClient1.IOHandler.ReadByte; // wait for ACK/NAK except on E: Exception do begin if E is EIdReadTimeout then begin Inc(iTry); if iTry < 3 then begin State := stSendingMsg; Exit; end; end; State := stError; Timer1.Enabled := False; AddToMemo('ERROR! ' + E.Message); Exit; end; end; if b <> $6 then // not ACK? begin Inc(iTry); if iTry < 3 then begin State := stSendingMsg; end else begin State := stError; Timer1.Enabled := False; AddToMemo('ERROR! No ACK received'); end; Exit; end; State := stWaitingForMsg; end; stWaitingForMsg: begin try ReceivedText := IdTCPClient1.IOHandler.WaitFor(#3, True, True); lrc := IdTCPClient1.IOHandler.ReadByte; except on E: Exception do begin State := stError; Timer1.Enabled := False; AddToMemo('ERROR! ' + E.Message); Exit; end; end; AddToMemo('Received message:' + ReceivedText + Char(lrc)); if (ReceivedText is not valid) then begin IdTCPClient1.IOHandler.Write(Byte($15)); // send NAK Exit; // keep waiting... end; IdTCPClient1.IOHandler.Write(Byte($6)); // send ACK if (ReceivedText is HOLD message) then Exit; // keep waiting... // use ReceivedText as needed... State := stIdle; Timer1.Enabled := False; end; end; end;
  9. Remy Lebeau

    tlsv1 alert protocol version

    You need to upgrade to the latest Indy, yes. Indy 10 still supports Delphi/C++Builder 6.
  10. It really depends on the format that the ESC/POS is expecting. It might be as simply as using TBitmap.SaveToStream() to save to a TBytesStream, and then using the stream's Bytes and Size properties. Or it may be more complex, like having to extract the individual pixels, like that other code is doing. You are going to have to provide more details about your particular situation.
  11. Remy Lebeau

    DecodeDate Issue

    Just on a side note, I probably would have used FormatDateTime() instead of DecodeDate() for for this, eg: uses ..., System.SysUtils; procedure TfAccounts.Button1Click(Sender: TObject); begin Label1.Caption := FormatDateTime('"Today is Day "d" of Month "m" of Year "yyyy', Now); end;
  12. Remy Lebeau

    play all videos in one folder delphi?

    VCL's TMediaPlayer has an OnNotify event, which you can use to detect the end of playback. Load the video file paths into a list, start playing the 1st file, and use OnNotify to play the next file in the list, repeating until the list is finished.
  13. Remy Lebeau

    [Android] [FMX] Task synchronization problem with Android

    The 2nd approach is correct - do the REST request in a background thread, leaving the UI thread free to manage the UI. You can update the UI to hide the progress screen when the thread is finished. We can't tell you why the progress screen is not displaying correctly, as you did not show a complete example. Maybe you are still blocking the UI thread in a way that we can't see. Are you able to display the screen if you disable the REST request? Please show a more complete example from start to finish.
  14. Remy Lebeau

    Delphi is 26 years old - Marco's blog

    And now we are drawing particles instead, my how far things have come
  15. Remy Lebeau

    [Rio][FMX]How to compile for iOS without an Apple device?

    The nice thing about this one is that it already provides support for RAD Studio, you don't have to do anything extra for that. I don't know if this one supports RAD Studio by default or not.
  16. Remy Lebeau

    TIdSSLIOHandlerSocketOpenSSL.MaxLineAction issue.

    No. GitHub provides an SVN interface. I was referring more to the fact that Indy doesn't use its own SVN server anymore now that it has migrated to GitHub: https://www.indyproject.org/2019/11/28/indy-svn-retiring-long-live-github/
  17. Remy Lebeau

    TIdSSLIOHandlerSocketOpenSSL.MaxLineAction issue.

    Instructions can be found here: https://web.archive.org/web/20200925081341/http://ww2.indyproject.org/Sockets/Docs/Indy10Installation.EN.aspx (the live page on Indy's main website is offline right now). Indy doesn't use SVN anymore.
  18. Remy Lebeau

    TIdSSLIOHandlerSocketOpenSSL.MaxLineAction issue.

    Yes. Is your project using VCL or FMX? VCL is compiled with OFF by default. FMX is compiled with ON by default. AFAIK, there is no IDE setting for Scoped Enums, they are controlled only via the {$SCOPEDENUMS} compiler directive. Should, yes. Indy's IdGlobal unit.
  19. Remy Lebeau

    TIdSSLIOHandlerSocketOpenSSL.MaxLineAction issue.

    First off, you DO NOT need to set the IOHandler's Destination, Host, and Port properties. Those are handled internally by Indy for you. As for the error, check if Scoped Enums is enabled. If so, you will have to fully-qualify the value by the enum's type name, eg: MaxLineAction := TIdMaxLineAction.maException; That being said, the MaxLineAction property defaults to maException anyway, so there is no need to set that value explicitly in this case.
  20. Undocumented intrinsic routines Undocumented Delphi routines Undocumented Delphi record alignment directive Just to name a few. I know there are other sites that document more, I just don't have the time to hunt them down.
  21. Remy Lebeau

    Create a Delphi Dll and load it with DllMain

    You already asked this on StackOverflow, and were basically told DON'T DO THIS, IT IS NOT SAFE! https://stackoverflow.com/questions/66233151/
  22. Remy Lebeau

    Comunicate with POS terminal (Ingenico)

    I already explained to you earlier why your use of the IOHandler's ReadLn() method is incorrect in this situation, and how to use ReadLn() (or WaitFor()) to read the POS's messages correctly. The ACK doesn't change what I said earlier. You would simply do an extra read with ACK, #6, as the line terminator instead. However, since the ACK is only 1 byte, the IOHandler's ReadByte() method would be more appropriate, especially if the POS can ever send a NAK instead of an ACK. You can use the IOHandler's Write(Byte) method for that. No, it is not sufficient by itself. I am not at a computer right now to write you working code, it will have to wait until tomorrow.
  23. Remy Lebeau

    caFree & ,Free??

    It is perfectly safe to call Free() on a Form (or any other TComponent descendant) that has an Owner assigned. The Form/component will simply remove itself from its Owner's internal list, so that the Owner will not try to destroy it a 2nd time when the Owner is destroyed.
  24. Remy Lebeau

    caFree & ,Free??

    Yes, it is perfectly safe. Using Action=caFree in the Form's OnClose event will call the Form's Release() method, which is a *delayed* destruction. A CM_RELEASE message is posted to the Form's window. The Form is not actually destroyed until that message is processed at a later time. If the Form/window is destroyed before that happens, the message is discarded. Then something else in your project is freeing the Form prematurely. It is not your OnClose handler doing it. Run your code in the debugger and put a breakpoint in the Form's destructor or OnDestroy event, and look at the call stack to track down where the Form is being destroyed.
  25. Remy Lebeau

    Visual Control for selecting a date range

    There is no standard multi-calendar component in the VCL, so you would have to look around for a 3rd party solution, or just use the VCL's standard TDateTimePicker component alongside the TMonthCalendar, TCalendarView, or TCalendarPicker components.
×