Jump to content

Remy Lebeau

Members
  • Content Count

    1441
  • Joined

  • Last visited

  • Days Won

    57

Everything posted by Remy Lebeau

  1. Remy Lebeau

    Printer ip

    You can't assign a WAN IP to a printer on the LAN side. If you are trying to access your LAN printer over the public Internet, you will have to setup port forwarding on your router to route incoming connections from a WAN IP/Port to the printer's LAN IP/Port. Then, as others have mentioned, there are plenty of external services you can query to get your current WAN IP. Otherwise, a better option is to just create a VPN into your LAN network, and then use the printer's LAN IP.
  2. Remy Lebeau

    Printer IP

    duplicate thread:
  3. Remy Lebeau

    Apps not appearing in right task bar??

    That is already set to True by default in new projects, but defaults to False in older projects migrated to newer IDEs.
  4. Remy Lebeau

    Issue with TDialogService.InputQuery fmx for IOS

    I can't attest to the behavior of the OK and Cancel buttons. But one problem I see is your NewString variable. Where is it declared, and where is it used after the dialog closes? Remember, this dialog is asynchronous, so make sure you are not accessing NewString out of scope. Also, your 'with ASyncService' block is being wasted and should be removed.
  5. The question was about the SQUARE brackets (Attribute), not the ANGLE brackets (Generic).
  6. Remy Lebeau

    exceptions and static storage duration objects

    Without an example showing the error in action, it is hard to diagnose this.
  7. Remy Lebeau

    Issue with TDialogService.InputQuery fmx for IOS

    What is '<.' ? What is 'mrOK2'? Did you mean 'if AResult <> mrOK then ...' instead?
  8. Remy Lebeau

    how to flush buffers on Indy components

    Unless your communication protocol is specifically designed to allow resyncing communications without closing the socket, then this is usually not a viable option. What does your protocol actually look like? How are your messages delimited? What does your "disrupted flow of data" look like? At the very least, it is possible to discard bytes only until the next message delimiter is reached. But you won't know if you discarded a (partial) message that was important to your communications, so resyncing via a reconnect is usually the best option.
  9. Remy Lebeau

    how to flush buffers on Indy components

    FYI, your use of the TIdIOHandler.ReadFromSource() method is just mirroring what the public TIdIOHandler.CheckForDataOnSource() method does internally, so you don't really need your TIdIOHandlerHelper class at all, just use CheckForDataOnSource(1) instead of ReadFromStack(False, 1, False).
  10. Remy Lebeau

    how to flush buffers on Indy components

    Unless the data is structured in such a way that you can definitively identify, from ANY point within the data, where the data ends and the next piece of communication begins, then "flushing" the existing data to resume communications is usually not a viable option. Especially if the next piece of communication has already been received and buffered and waiting for your code to read it from the buffer. Are you using a standard protocol like FTP for the transfer, or are you using a custom protocol? Unless the exception is a socket error, then you don't know the actual state of the socket, or how the data was buffered by the socket or by Indy. So, once the exception occurs, usually the only sane thing to do is to just disconnect and reconnect to restart communications fresh, yes. This is true for any TCP library, it is not limited to just Indy. Since you know how much data you transferred before the exception, you can resume the transfer from that position, if your system allows for resuming.
  11. Remy Lebeau

    how to flush buffers on Indy components

    I don't really understand what you are asking for, but why would you ever need something like this? Please provide a use-case example. No (if such a flush were possible). By default, there is no write buffering beyond the send buffer that is built-in to the underlying socket at the OS layer. You can't "flush" that buffer, but you can reduce its size with the SO_SNDBUF socket option, or disable/avoid it with the TCP_NODELAY socket option (Indy's UseNagle property). On top of that, Indy does provide an application-level send buffer via the IOHandler.WriteBuffer...() methods. That buffer is flushed to the socket when the specified threshold is reached, or when WriteBufferFlush() or WriteBufferClose() is called. That buffer can be discarded with WriteBufferCancel(). Read buffering is a bit trickier. There is the receive buffer that is built-in to the underlying socket at the OS layer. You can't "flush" that buffer, only reduce its size with the SO_RCVBUF socket option. On top of that is the application-level buffering that Indy implements via the IOHandler.InputBuffer property, where the IOHandler.RecvBufferSize property controls how many bytes Indy attempts to read from the socket's receive buffer into the InputBuffer at a time. Once data is in the InputBuffer, you can "flush" that buffer by calling its Clear() or Remove() method (in the latter case, you could use the IOHandler.Discard() method instead). So, what is it that you really want to "flush", exactly? What is the scenario that you feel "flushing" is the solution for?
  12. Remy Lebeau

    Ignore exception type from code

    No (plus, that would require changing and recompiling the code, in which case you may as well just take out the offending code to begin with). But, you can accomplish something similar using breakpoints instead. Put a breakpoint at the beginning of the function, go into its properties, and disable the 'Break' option, and enable the 'Ignore subsequent exceptions' option. Then, put another breakpoint at the end of the function, go into its properties, and disable the 'Break' option, and enable the 'Handle subsequent exceptions' option.
  13. Remy Lebeau

    TTask.Run Finish Order???

    You have the call to ShowDialogAfterTaskFinishes() in the wrong place. TTask runs asynchronously, but you are calling ShowDialogAfterTaskFinishes() immediately after the TTask object is created (and possibly before the TTask even begins to run). You need to move the call to ShowDialogAfterTaskFinishes() inside of the TTask procedure itself, similar to what you have for the call to UpdateMainWindow(), eg: procedure TfQBDailyInvoices.TransferEvent; begin TTask.Run( procedure var x: Integer; begin try for x := 0 to qInvoice.RecordCount - 1 do begin DidWorkorderTransfer := ProcessInvoice; TThread.Synchronize(nil, procedure begin { Update User Interface } UpdateMainWindow; end ); qInvoice.Next; end; finally TThread.Queue(nil, ShowDialogAfterTaskFinishes); end; end ); end; Alternatively, you can use TThread.CreateAnonymousThread() instead, so you can use the TThread.OnTerminate event (which is Synchronize()'d with the main UI thread), eg: procedure TfQBDailyInvoices.TransferEvent; var Thread: TThread; begin Thread := TThread.CreateAnonymousThread( procedure var x: Integer; begin for x := 0 to qInvoice.RecordCount - 1 do begin DidWorkorderTransfer := ProcessInvoice; TThread.Synchronize(nil, procedure begin { Update User Interface } UpdateMainWindow; end ); qInvoice.Next; end; end ); Thread.OnTerminate := TransferEventThreadTerminated; Thread.Start; end; procedure TfQBDailyInvoices.TransferEventThreadTerminated; begin ShowDialogAfterTaskFinishes; end; :
  14. Remy Lebeau

    exceptions and static storage duration objects

    That is not what you described originally: Two different things. So, which one are you actually working with? Can you provide a code example that is crashing for you?
  15. It shouldn't work, though. This is just straight up undefined behavior, since the TMemo.Lines property does not point at a TStringList object, it points at a TMemoStrings object instead. And TSStringList overrides Add() whereas TMemoStrings does not, so even the vtable contents are different. Don't write code like this. The correct solution is to make FillStrings() take a TStrings instead: function FillStrings(aStrings: TStrings): boolean; begin aStrings.Add('a'); aStrings.Add('b'); end; ... FillStrings(Memo1.Lines); Correct, because FillStrings() expects a TStringList specifically, not a TStrings generally. Nope. Nope.
  16. Remy Lebeau

    Which Package to Install

    If only there was a system where component authors could update their GetIt submissions whenever they wanted..... oh wait, we were promised that years ago, but it never materialized.....
  17. Remy Lebeau

    Community Edition expiring again, no new keys

    They are only just now working on this? When CE was first introduced several years ago, they didn't think this might be a problem down the line? They've had 3 years to fix it, what are they hoping to do in a few days?
  18. Remy Lebeau

    String on heap?

    The type of sublist is the plain Pointer-based TList, so it makes sense that these hoops have to be done manually to store strings in it, but it is really not optimal. If the code were updated to use TStringList or TList<String> instead, then you wouldn't have to worry about manually managing the string memory at all.
  19. On the other hand, depending on the situation, it would probably be better not to perform the calculation at all if the input is invalid, in which case TryStrToFloat() would make more sense if you want to avoid the exception and skip the calculation at the same time.
  20. I still think it is likely a bug in the program, not in Windows itself. Like if the program had opened the StorageDevicePolicies key for some unrelated purpose, and then accidentally used that opened HKEY handle as a base when writing its settings to its own subkey rather than using the predefined base HKLM handle.
  21. You can't perform arithmetic with a Double and a String as operands. You have to first convert the String to a Double/Extended first. Use StrToFloat() or equivalent for that. And then you can convert the result back to a String using FloatToStr() or equivalent. Try something more like this: DBEdit43.Text := FloatToStr(0.000844 * StrToFloat(scGPDBEdit82.Text));
  22. Remy Lebeau

    When execute, this error appears

    Yeah, like not using a TEdit for date/time input in the first place. Use a UI control that is specifically designed for date/time input (ie, TDateTimePicker, TDatePicker, TTimePicker). Same with integers, for instance (ie, TSpinEdit).
  23. Yes, that is where I would expect them, too. That is absolutely wrong. Application settings do not belong there. That is likely a bug in the program. It is a system-managed key, and it holds system settings, hardware configurations, service setups, etc. Note that HKLM\SYSTEM likely contains other keys ControlSet001, ControlSet002, etc. Those are like backups/previous versions of CurrentControlSet. If something goes wrong with the current settings, Windows has something it can roll back to. Every computer has a CurrentControlSet key. But not every computer has a StorageDevicePolicies key (mine doesn't). Absolutely not. You should contact the program author and explain the issue so they can fix it.
  24. Remy Lebeau

    When execute, this error appears

    You have 2 StrToDate() calls in that highlighted code (presumably more offscreen?), both are converting scGPDBDateEdit11.Text. Your earlier screenshot show the Text is ' / / ', which is obviously NOT a valid date string, which is why StrToDate() raises EConvertError. It should work just fine, eg: if TryStrToDate(scGPDBDateEdit11.Text, mydate) then begin // use mydate as needed... end else begin // do something else... end; Though, like I said, TDateTimePicker makes a lot more sense then a TEdit for date inputs, eg: mydate := IncYear(DateTimePicker11.Date, a); ... mydate := IncDay(DatePicker11.Date, a); ...
  25. Remy Lebeau

    TMemo instead of TLabel

    You can use the 'is' operator for that purpose, eg: procedure GetString(param1: string; param2: string; myControl: TControl); begin if myControl is TLabel then TLabel(myControl).Caption := GetDescription() else if myControl is TMemo then TMemo(myControl).Lines.Add(GetDescription()) else ...; end; Alternatively, every TControl has a Caption (and Text) property, even if it is not published. You can take advantage of that, eg: type TControlAccess = class(TControl) end; procedure GetString(param1: string; param2: string; myControl: TControl); begin if myControl is TMemo then TMemo(myControl).Lines.Add(GetDescription()) else TControlAccess(myControl).Caption := GetDescription(); end; Or, you can use RTTI instead, eg: procedure GetString(param1: string; param2: string; myControl: TControl); var Ctx: TRttiContext; Typ: TRttiType; Prop: TRttiProperty; begin Ctx := TRttiContext.Create; try Typ := Ctx.GetType(myControl.ClassType); Prop := Typ.GetProperty('Caption'); if (Prop <> nil) and (Prop.Visibility = mvPublished) then begin Prop.SetValue(myControl, GetDescription()); Exit; end; Prop := Typ.GetProperty('Text'); if (Prop <> nil) and (Prop.Visibility = mvPublished) then begin Prop.SetValue(myControl, GetDescription()); Exit; end; Prop := Typ.GetProperty('Lines'); if (Prop <> nil) and (Prop.Visibility = mvPublished) then begin (Prop.GetValue(myControl).AsObject() as TStrings).Add(GetDescription()); Exit; end; ... finally Ctx.Free; end; end;
×