Jump to content

Remy Lebeau

Members
  • Content Count

    2998
  • Joined

  • Last visited

  • Days Won

    135

Everything posted by Remy Lebeau

  1. Remy Lebeau

    Floating Form Designer option gone in Delphi Alexandria?

    I wouldn't hold my breath on that. They made the intentional decision to remove the Floating Designer in 10.4.1. It is gone. I don't see them ever adding it back in, they want people to use the docked editor instead. But, as the blog article explained, you can still have multiple editors open, across multiple monitors.
  2. Remy Lebeau

    Sending SMS via FMX application

    You should be able to simply replace this: Date_SentIdx := Cursor.GetColumnIndex(StringToJstring('date_sent')); with this: Date_SentIdx := Cursor.GetColumnIndex(StringToJstring('report_date'));
  3. Remy Lebeau

    Sending SMS via FMX application

    Known issue, at least for "date_sent". You need to use "report_date" instead. See SMS messages date_sent on Android with Delphi XE5 always returns 0? on StackOverflow. Not sure if there is a similar workaround for "status".
  4. Remy Lebeau

    How to force update to label during a loop

    You don't necessarily need threading, you just need to return control to the main UI message loop periodically. For instance, break up your loop into chunks that you can trigger with TThread.ForceQueue() for each iteration, eg: procedure TMyForm.DoProcessing(i: Integer); begin Label1.Text := 'Step ' + IntToStr(i); Inc(i); if i <= 10 then TThread.ForceQueue(nil, procedure begin DoProcessing(i); end, 200) else TThread.ForceQueue(nil, AfterProcessing); end; procedure TMyForm.StartProcessing; begin DoProcessing(1); end; procedure TMyForm.AfterProcessing; begin ... end;
  5. Remy Lebeau

    TTimer limit..

    Agreed. For lengthy periods, I would ask the OS to notify me when the desired time has been reached, rather than polling the time regularly.
  6. Remy Lebeau

    TTimer limit..

    The TTmer interval is expressed in milliseconds, not microseconds. Yes. 4,294,967,295 milliseconds is 49.7 days. What EXACTLY is not working for you?
  7. Remy Lebeau

    How to force update to label during a loop

    <sigh> Turns out they are methods of TControl, which TForm is not derived from in FMX, unlike in VCL. And this is just one of a hundred reasons why I hate FMX and will never ever use it.
  8. Remy Lebeau

    sorry for the newbe question...

    Then what does this have to do with Delphi/FMX?
  9. Remy Lebeau

    How to force update to label during a loop

    Did you try Repaint()'ing the Form itself, rather than just the TLabel?
  10. Remy Lebeau

    How to force update to label during a loop

    No, but Repaint() is. In any case, depending on what the rest of your loop is doing, it may be worthwhile to move the logic into a worker thread, and then have that post updates to the UI thread when it wants to display something.
  11. Just a small nitpick - you can change this: RE.SelStart := Perform(EM_LINEINDEX, myLineIndex, 0); RE.SelLength := length(Lines[myLineIndex]); To this instead: var myLineStart: Integer; myLineStart := Perform(EM_LINEINDEX, myLineIndex, 0); RE.SelStart := myLineStart; RE.SelLength := Perform(EM_LINELENGTH, myLineStart, 0); That will avoid a memory allocation trying to retrieve the actual String of the line in question. The RichEdit already knows how many characters are on the line without needing to access the actual characters. An then to can be optimized further by using EM_EXSETSEL directly instead of the SelStart/Length properties: var rng: CHARRANGE; rng.cpMin := Perform(EM_LINEINDEX, myLineIndex, 0); rng.cpMax := rng.cpMin + Perform(EM_LINELENGTH, rng.cpMin, 0); Perform(EM_EXSETSEL, 0, LParam(@rng)); Further speed optimizations can be accomplished using EM_SETCHARFORMAT/2 and EM_SETEVENTMASK messages, see Faster Rich Edit Syntax Highlighting for details.
  12. Remy Lebeau

    Getting of dynamic array from Variant

    I honestly can't see how it could ever work to assign a pointer-to-pointer-to-data to a dynamic-array. What is the original code trying to accomplish, exactly? If it just wants to access the elements of the Variant array, there is no need to assign the raw data pointer to a dynamic array at all. I seriously doubt that. I would have to see how the original code is populating the Variant, and how it is accessing the dynamic array that is assigned from the Variant's raw data. Because it is not supposed to work (and you should not have relied on it to begin with, even if it did compile. Just because something compiles doesn't make it right). Embarcadero intentionally changed the compiler in a later version to no longer allow assigning a raw untyped Pointer to a dynamic array.
  13. Remy Lebeau

    Getting of dynamic array from Variant

    By default, an array inside a Variant is stored as (a pointer to) a COM SAFEARRAY: https://docs.microsoft.com/en-us/archive/msdn-magazine/2017/march/introducing-the-safearray-data-structure https://docs.microsoft.com/en-us/windows/win32/api/oaidl/ns-oaidl-safearray Which is completely different than a Delphi-style dynamic array. The two are not compatible with each other. The only way to store a Delphi-style dynamic array AS-A dynamic array in a Variant is to use a custom Variant type: https://docwiki.embarcadero.com/RADStudio/en/Defining_Custom_Variants That being said, Delphi 10.2 and later are more strict about NOT letting you assign a raw Pointer to a dynamic array, as you are trying to do: So, you would have to type-cast the raw Pointer in order to get the old Delphi 6 behavior, eg: type TDoubleArray = array of double; var Value: Variant; //this variable is assigned to a dynamic array somewhere in the code ... procedure DoSomething; var rv: TDoubleArray; begin rv := TDoubleArray(TVarData(Value).VArray.Data); // note, no @ used here. Why would you want to assign a PPointer to a dynamic array??? ... end; But, it never made sense to me why anyone would ever want to do this, since this makes the dynamic array point at something that is not a valid dynamic array, and can't be accessed as a dynamic array. The structure of a SAFEARRAY and a dynamic array are completely different. In any case, to safely access the raw data of a SAFEARRAY, you MUST use the SafeArrayAccessData() function, which Delphi's RTL has wrapped in the VarArrayLock() function, eg: var Value: Variant; //this variable is assigned to a dynamic array somewhere in the code ... procedure DoSomething; var rv: PDouble; begin rv := PDouble(VarArrayLock(Value)); try // use rv as needed... finally VarArrayUnlock(Value); end; end;
  14. Remy Lebeau

    No protocols available

    That line is effectively setting SSLOptions.Method to sslvSSLv23 and SSLOptions.SSLVersions to [sslvTLSv1_1, sslvTLSv1_2]. Which means, if the server does not support TLS 1.1 or TLS 1.2 then the TLS handshake will fail. Typically, that line should be as follows instead: SSL.SSLOptions.SSLVersions := [sslvSSLvTLS1, sslvTLSv1_1, sslvTLSv1_2]; The sslvSSLv23 flag has special meaning for Indy's internals and should not be used directly in most cases. The only valid use for using sslvSSLv23 in your code is to enable all supported SSL/TLS versions, eg: SSL.SSLOptions.Method := sslvSSLv23; // will set Method=sslvSSLv23 and SSLVersions=[sslvSSLv2,sslvSSLv3,sslvTLSv1,sslvTLSv1_1,sslvTLSv1_2] SSL.SSLOptions.SSLVersions := [sslvSSLv23]; // will set Method=sslvSSLv23 and SSLVersions=[sslvSSLv2,sslvSSLv3,sslvTLSv1,sslvTLSv1_1,sslvTLSv1_2] Otherwise, just ignore that the sslvSSLv23 flag exists, and set the SSLVersions property to just the desired protocol versions (2/3 is not a protocol version, it is a wildcard).
  15. Remy Lebeau

    SMS Sending - Still valid??

    That is because your code is not using the IdSSL variable for anything. You are creating the TIdSSLIOHandlerSocketOpenSSL instance and assigning it directly to the TIdHTTP.IOHandler property, thus leaving all of the IOHandler's sub-properties at their default values. Assign the instance to the IdSSL variable first, and then you can customize its properties as needed, eg: lHTTP := TIdHTTP.Create(nil); try IdSSL := TIdSSLIOHandlerSocketOpenSSL.Create(lHTTP); IdSSL.SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2]; // set other properties as needed... lHTTP.IOHandler := IdSSL; ... finally lHTTP.Free; end;
  16. The extra bytes are for a hidden pointer to a System.TMonitor instance (not to be confused with Vcl.Forms.TMonitor). Every TObject instance has an optional TMonitor instance associated with it. The actual TMonitor instance is created the 1st time it is accessed, but the parent TObject's InstanceSize includes space for a pointer to the TMonitor instance. AFAIK, yes. Read the TMonitor documentation, and also see What is TMonitor in Delphi System unit good for? You could, yes. You would simply call TMonitor.Enter(obj) and TMonitor.Exit(obj) where needed.
  17. Remy Lebeau

    SMS Sending - Still valid??

    Does the server require TLS 1.1+, by chance? By default, TIdSSLIOHandlerSocketOpenSSL enables only TLS 1.0 (issue #181). Have you tried enabling TLS 1.1 and/or TLS 1.2 in the TIdSSLIOHandlerSocketOpenSSL.SSLOptions.SSLVersions property? Define "latest". TIdSSLIOHandlerSocketOpenSSL requires OpenSSL 1.0.2 or earlier, it does not support OpenSSL 1.1+. For that, you need to use this SSLIOHandler instead.
  18. Remy Lebeau

    Conditional Define for Packages

    No, there is not. You would have to create your own conditional in the Package's project options. Yes.
  19. Remy Lebeau

    How to synchronize splitters?

    When using an Interposer, this is the way I would have do it, too.
  20. Remy Lebeau

    TIdHTTPProxyServer hangs when used with RemObjects

    I have merged it now.
  21. Remy Lebeau

    How to synchronize splitters?

    Simply move the logic into another procedure that you can pass the Sender into, eg: procedure TForm1.MoveOtherSplitterImpl(Sender: TSplitter; var aMsg: TMessage); begin if (fMovingControl = nil) or (fMovingControl = Sender) then case aMsg.Msg of WM_MOUSEFIRST..WM_MOUSELAST: begin fMovingControl := Sender; try if Sender = Splitter1 then Splitter2.Perform(aMsg.Msg, aMsg.WParam, aMsg.LParam) else if Sender = Splitter2 then Splitter1.Perform(aMsg.Msg, aMsg.WParam, aMsg.LParam); finally fMovingControl := nil; end; end; end; end; end; procedure TForm1.MoveOtherSplitter(var aMsg: TMessage); begin MoveOtherSplitterImpl(Splitter1, aMsg); fOriginalWindowProc(aMsg); end; procedure TForm1.MoveOtherSplitter2(var aMsg: TMessage); begin MoveOtherSplitterImpl(Splitter2, aMsg); fOriginalWindowProc2(aMsg); end; If you really want something more generic, then you should link the two Splitters together, such as by their Tag properties, eg: procedure TForm1.FormCreate(Sender: TObject); begin Splitter1.Tag := NativeInt(Splitter2); fOriginalWindowProc := Splitter1.WindowProc; Splitter1.WindowProc := MoveOtherSplitter; Splitter2.Tag := NativeInt(Splitter1); fOriginalWindowProc2 := Splitter2.WindowProc; Splitter2.WindowProc := MoveOtherSplitter2; end; procedure TForm1.MoveOtherSplitterImpl(Sender: TSplitter; var aMsg: TMessage); begin if (fMovingControl = nil) or (fMovingControl = Sender) then case aMsg.Msg of WM_MOUSEFIRST..WM_MOUSELAST: begin fMovingControl := Sender; try TSplitter(Sender.Tag).Perform(aMsg.Msg, aMsg.WParam, aMsg.LParam); finally fMovingControl := nil; end; end; end; end; end; procedure TForm1.MoveOtherSplitter(var aMsg: TMessage); begin MoveOtherSplitterImpl(Splitter1, aMsg); fOriginalWindowProc(aMsg); end; procedure TForm1.MoveOtherSplitter2(var aMsg: TMessage); begin MoveOtherSplitterImpl(Splitter2, aMsg); fOriginalWindowProc2(aMsg); end;
  22. Can you show the actual code that is populating the TRichEdit and the formatting of its lines?
  23. Remy Lebeau

    Sending Email via GMail Using OAuth 2.0 via Indy

    That branch is still a work in progress, there has been some hiccups in it this week related to Microsoft's use of OAuth2 (see the discussion on https://github.com/IndySockets/Indy/issues/192).
  24. Remy Lebeau

    Exception call stacks on Windows with only a few LOCs

    It is a nice start. But from experience, having just the raw stack addresses is still a PITA to debug. I took a similar approach in one of my projects (not using the build-in Exception.StackTrace callbacks, though), but I also output the module name that each address belongs to, and for a DLL module I also worked out the exported function name+offset based on the address. I was planning on adding logic to resolve non-DLL function names using the generated MAP file, but I didn't get that far before the project was discontinued.
  25. There is no functional difference between those two.
×