Jump to content

Remy Lebeau

Members
  • Content Count

    2929
  • Joined

  • Last visited

  • Days Won

    131

Posts posted by Remy Lebeau


  1. You don't really need a per-topic option. Read the topics that you are actually interested in, and then you can "Mark site read" to clear out the unwanted topics. If you are on mobile, the option is in the top-right menu in the Account section. If you are on desktop, the option is on the bottom footer of every page.


  2. 18 minutes ago, Rolphy Reyes said:

    Using the component suites mentioned above I get all kinds of errors

    Such as? Can you be more specific?

    18 minutes ago, Rolphy Reyes said:

    However, using the PostMan application, the API returns correctly

    What exactly are you entering into postman?

    18 minutes ago, Rolphy Reyes said:

    Can you help me resolve this issue?

    Not without knowing what the endpoint is actually expecting, and what your actual code looks like that is not working for you.

    • Like 1

  3. 2 hours ago, Rick Malik said:

    Thank you. At least you didn't bash me around.

    I'm not bashing you around.  I'm trying to be straight with you.  StackOverflow is a Q&A site, not a help forum.  It can be a pretty hard place on beginners who don't take the time to read the documentation and follow the guidelines. Your question in its initial form was not a good fit for the site, that's why it got closed pretty quick. But rather than fix it, you chose to delete it. As is your right. But, I suggest you take some time to learn how the site actually works before posting a new question there again.

    2 hours ago, Rick Malik said:

    pascal example I found

    That's Visual Basic, not Pascal.

    51 minutes ago, Rick Malik said:

    Funny, I can't tell the difference 🙂 

    VB and Pascal are very different languages, with different syntaxes and semantics.

    2 hours ago, Rick Malik said:

    in c++

    You made some minor mistakes in the translation.  Specifically:

    • you aren't setting a couple of VSSpell's properties
    • your while loop is looking at the wrong value
    • your switch block is missing a case
    • when VSR_CHECK_CANCELED is detected, you are exiting the whole function instead of just breaking the loop.

     

    Try this:

    SpellChk->EventOptions = 0;
    SpellChk->AutoPopup = false;
    SpellChk->CheckText = Memo1->Text;
    int ResCode = SpellChk->ResultCode;
    
    while (ResCode < 0)
        {
        switch (ResCode)
            {
            case VSR_WORD_MISSPELLED:
            case VSIR_IGNORE:
                SpellChk->PopupWordMisspelled = 1;
                ResCode = SpellChk->ResultCode;
                break;
            case VSR_BREAK:
                SpellChk->ReplaceRecheck;
                break;
            }
        if (ResCode == VSR_CHECK_CANCELED)
            break;
        ResCode = SpellChk->ResumeCheck;
        }
    Memo1->Text = SpellChk->Text;

     


  4. 8 hours ago, Rick Malik said:

    BTW, your code wouldn't compile

    It compiles and runs perfectly fine for me.

    8 hours ago, Rick Malik said:

      [C++ Error] Unit1.cpp(28): E2268 Call to undefined function '_D'

    What version of C++Builder are you using?  The _D() macro is defined in sysmac.h (a core system header) and has been available since C++Builder 2009 when the  RTL switched to Unicode.  The macro ensures a string/character literal matches the same data type used by System::Char depending on which platform you are compiling for - wchar_t on Windows and char16_t on Posix.

    8 hours ago, Rick Malik said:

      [C++ Error] Unit1.cpp(30): E2015 Ambiguity between '_fastcall System::operator +(int,const System::Variant &)' and '_fastcall System::operator +(int,const System::Currency &)'
      [C++ Error] Unit1.cpp(38): E2015 Ambiguity between '_fastcall System::operator +(int,const System::Variant &)' and '_fastcall System::operator +(int,const System::Currency &)'

    There are no Variant's or Currency's in this code, so you should not be getting those errors.  The only use of  operator+ is to concatenate a string literal with a System::String, and that is a well-defined operation.

     

    I'm starting to think you are trying to run VCL GUI code in a project that does not actually have the VCL enabled properly.

    8 hours ago, Rick Malik said:

      [C++ Warning] Unit1.cpp(55): W8070 Function should return a value

    That is because you declared the square() method as having an 'int' return type, but there was no 'return' statement inside the method's body.  If you look at the code I gave you, I declared square() with a 'void' return type instead. Because there is no value worth returning to the caller.

    8 hours ago, Rick Malik said:

    So why num and nums are in the header is so they wouldn't fall out of scope

    But, you are not USING THEM for anything, they are just sitting there.  The rest of your code uses only LOCAL VARIABLES of the same names, which shadow the class members,

    8 hours ago, Rick Malik said:

    as I placed them under a second button. This time they both came out zeros(?)

    All data members of a TObject-derived class (like TForm is) are initialized to zeroes before the constructor is called.  And then you were not assigning any new values to them afterwards.

    8 hours ago, Rick Malik said:

    And I didn't try to rewrite his method

    But you did rewrite it nonetheless, even if unintentionally.

    8 hours ago, Rick Malik said:

    I simply removed the couts so I could just run the function(). 

    Which is exactly what the code I gave you does.

    8 hours ago, Rick Malik said:

    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
        int i, nums[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        for(i = 0; i < 10; i++)
        square(nums, 10);
        for(i = 0; i < 10; i++)
        return ;
    }

    This code is written wrong.  You removed the couts, but you did not remove the loops, too.  You are calling square() inside the 1st loop, and calling 'return' in the 2nd loop.  So, this code behaves as-if you had written it like this:

    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
        int i, nums[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        for(i = 0; i < 10; i++) {
            square(nums, 10);
        }
        for(i = 0; i < 10; i++) {
            return;
        }
    }
    8 hours ago, Rick Malik said:

    int __stdcall TForm1:: square(int *n, int num)
    {
        while(num)
        {
            *n = *n * *n;
            num--;
            n++;
        }
        return num;
    }

    You are using the num variable that is local to the square() method, not the num variable that is declared as a member of the TForm1 class.  And num is ALWAYS 0 when the 'return' statement is reached.

    8 hours ago, Rick Malik said:

    void __fastcall TForm1::Button2Click(TObject *Sender)
    {
    Label1->Caption = IntToStr(nums);
    Label2->Caption = IntToStr(num);
    }

    This code is displaying the values of the class members, which you are NEVER assigning any values to, so they just have their initial values of 0.

     

    If you really want to use class members, then the code should look something more like this:

    class TForm1 : public TForm
    {
    __published:
    	TButton *Button1;
    	TButton *Button2;
    	TLabel *Label1;
    	TLabel *Label2;
    	void __fastcall Button1Click(TObject *Sender);
    	void __fastcall Button2Click(TObject *Sender);
    private:	// User declarations
    	int nums[10], num;
    	void square();
        ...
    };
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    	for(int i = 0; i < 10; ++i) {
    		nums[i] = i+1;
    	}
    
    	num = 10;
    	square();
    }
    //---------------------------------------------------------------------------
    void TForm1::square()
    {
    	int *n = nums;
    	while(num)
    	{
    		*n = *n * *n;
    		num--;
    		n++;
    	}
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button2Click(TObject *Sender)
    {
    	String s = _D("Array values:");
    	for(int i = 0; i < 10; ++i) {
    		s += (_D(" ") + IntToStr(nums[i]));
    	}
    
    	Label1->Caption = s;
    	Label2->Caption = IntToStr(num);
    }
    //---------------------------------------------------------------------------

     


  5. 3 hours ago, MarkShark said:

    It looks like this is just my own misinterpretation of how concatenating variants works.  I always thought the conversion took into account the type of the first "item" in the concatenation.

    It does, but in this case, since the operation involves a native type (string) on the left and a custom user type (TBcd) on the right, the operation gives the custom type an opportunity to decide whether to cast the left side to the custom type, which it does in this situation, and then the failure occurs during that cast from string to TBcd.

    • Like 1

  6. 2 hours ago, Rick Malik said:

    I put this in the .h

    int nums,num;

    Why? Those variables are not being used anywhere, so there is no point in declaring them there.

    2 hours ago, Rick Malik said:

        for(i = 0; i < 10; i++)
        square(nums, 10);

    Why are you calling the function 10 times? The original OP code called it only 1 time.

     

    Each time the function is called, the contents of the array are altered, but your code is not using the array values for anything, so there's really no point in altering the array at all.  At least the OP's code was outputting the original values and then the altered values.  You are not doing that.

    2 hours ago, Rick Malik said:

        for(i = 0; i < 10; i++)
        Label1->Caption = IntToStr(nums);

    Why are you updating the Label 10 times with the same value?  Perhaps you meant to display nums[ i ] instead?  But then you would end up displaying only the last integer in the array.  If you want to display all 10 values at one time, this is not the correct code for that task.

    2 hours ago, Rick Malik said:

    Label1 says 1
    Label2 says 0

    am I doing this right?

    You are updating the Labels in different places using different variables that have different values, so of course the results are going to be different.

     

    When updating Label1, you are using the nums variable that is local to the Button1Click() method.  For starters, that code should not even compile as shown, as nums is an array, but the Sysutils::IntToStr() function does not accept an array as input,  If this is indeed your actual code, the only way it could work is if the compiler decays the array into an int* pointer to the 1st array element, and then implicitly converts that pointer into a boolean, and then implicitly converts that boolean into an integer. That is too many implicit conversions for one statement, per the C++ standard.  But, lets assume your compiler ignores that fact, then that would explain how you end up with a final output of "1", as a non-null pointer converts to a boolean true, and true converts to an integer 1.

     

    When updating Label2, you are using the num parameter that is local to the square() method, which was decremented to 0 while the loop ran.

     

    If you really want to replicate the OP's code but display the results in a GUI instead of a console, then try something more like this instead:

    class TForm1 : public TForm
    {
        TButton *Button1;
        TLabel *Label1;
        TLabel *Label2;
        void __fastcall Button1Click(TObject *Sender);
    private:
        void square(int *n, int num);
    };
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
        int i, nums[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        String s;
    
        s = _D("Original array values:");
        for(i = 0; i < 10; ++i)
            s += (_D(" ") + IntToStr(nums[i]));
    
        Label1->Caption = s;
    
        square(nums, 10);
    
        s = _D("Altered array values:");
        for(i = 0; i < 10; ++i)
            s += (_D(" ") + IntToStr(nums[i]));
    
        Label2->Caption = s;
    }
    //---------------------------------------------------------------------------
    void TForm1::square(int *n, int num)
    {
        while(num)
        {
            *n = *n * *n;
            num--;
            n++;
        }
    }
    //---------------------------------------------------------------------------

     


  7. 2 hours ago, Rick Malik said:

    Stack Overflow [closed] my question because they thought I was looking for books, software, or tutorials....

    Because, that is essentially what you did ask for - a tutorial on how to use the OCX control.

    2 hours ago, Rick Malik said:

    I just wanna know what to do with BadWordFound so I can replace the stupid thing in my TMemo when it finds it.

    THAT is what you should have asked for instead.  That would have made for a better StackOverflow question, and less likely to be closed. Also, since you clearly know what you are looking for, you should have explained/shown what you had already tried that didn't work for you.

    Quote

    There's plenty of VB and pascal examples, but I only speak c/c++. 

    Then you should have included one of those examples in your StackOverflow question and asked how to accomplish the same thing in C++.  I can't find any documentation or examples of the OCX control, in ANY programing language.  Can you provide a source?


  8. 24 minutes ago, Rick Malik said:

    But aren't there 11 nums? 0 thru 10 = 11

    No. There are only 10 integers declared in the array (values 1..10). Valid indexes into the array are only 0..9, inclusive.


  9. 4 hours ago, kokoslolos said:

    And now as I'm writing this post, it just hit me that in my approach, if the FormName (custom property) is changed at design time, this cannot update my action's custom properties 😄 ! Need a bit of rethinking there.

    I would suggest making the Action hold a pointer to the desired Form, and simply read the Form's current Name whenever needed.  And if the Form's Name changes, then have the Form notify any Action that is pointing at it so they can use the new Name as needed. Easy to do if Actions register themselves with the Form so it can maintain a list of pointers to the Actions.


  10. 2 hours ago, alogrep said:

    The first error is ignored, no warning, no message.

    That code is performing floating-point division. And as Lejos mentioned, floating-point exceptions behave differently in Delphi 12 than they did in earlier versions.

     

    https://dalijap.blogspot.com/2023/09/coming-in-delphi-12-disabled-floating.html


    This is also documented by Embarcadero:
     

    https://docwiki.embarcadero.com/RADStudio/Athens/en/What's_New#Disabling_Floating-Point_Exceptions_on_All_Platforms

     

    Quote

    The second error is caught, but it does not show the call stack

    If you want to see a Call Stack at runtime, you have to display it yourself. You can catch the Exception (or use the TApplication(Events).OnException event) and then read the Exception.StackTrace property. However, this requires you to install a 3rd party exception logging library, such as MadExcept or EurekaLog, to populate the trace details. Embarcadero does not provide that functionality. In which case, you may as well use that library's own logging capabilities.


  11. Are you using C++ or Delphi? Integer division or floating-point division? Can you provide an example that is not working for you? 


  12. 1 hour ago, bobD said:

    Because a TFDConnection connects very quickly, but takes a long time to fail, and it's annoying to sit and wait <g>. Gethostbyname fails a lot quicker.

    Even if you could lookup the database server's IP quickly, there is no guarantee that the database engine is actually running/responding, so you still have to wait for the full connection before you can do anything with the database, and still handle any failure that may occur.  So, may as well just do that by itself, and deal with the slowness of reporting a failure (you should probably file a ticket about that).


  13. 2 hours ago, bobD said:

    Program is a client/server design can that use either a tcp-ip connection to my home network database, or a local connection to an onboard copy. It should default to network if at home, and default to local if I'm on the road. It can also do things like demand additional authorization, etc.

    Without having explicit knowledge of your home network setup, there is simply no way for your app to detect whether you are connected to your home network or not.  You could try looking for a connected LAN adapter, but what if you are in a hotel that offers LAN access? You could try looking for a connected Wifi adapter, but most public networks are Wifi.  You would need your Wifi's SSID to differentiate between a home Wifi and a public Wifi.

     

    I think you are making the issue harder then it needs to be.  I would suggest taking out the guesswork completely and simply just provide two options in your program's configuration:

     

    - connect to a tcp hostname

     

    - local copy only

     

    And then make it easy to switch between the two configurations as needed.  Perhaps wrap them in profiles and then switch the active profile when you leave home and then come home.

     

    Another option would be to just skip the local copy altogether and just always connect to your home database server even when you're on the road.  Setup port forwarding on your home router and then register a static DynDNS hostname so you can easily find your router's WAN ip/port from public networks (and for added security, setup a VPN server on your home network and then connect to the VPN when on a public network).  This way, you always have access to your database server and can connect to it via its IP or hostname on your private LAN.

    2 hours ago, bobD said:

    Here's what I've come up with so far:  (actually, modified from code I found that you posted some 17 years ago)

    If you really want to go down this route, then you need to assign a unique static hostname to your database server, and then you can use gethostbyname() (or better, getaddrinfo()) to lookup that hostname whenever you connect to the database.  No need to validate the IP prefix.  If you connect to the database by hostname instead of by IP, then you don't even need to perform the lookup yourself, as most TCP libraries/database drivers will handle this task for you.  But either way, if the hostname fails to resolve, then you are likely not connected to your home network.  Done.


  14. 3 hours ago, bobD said:

    Basically, program needs to act differently if at home or away--so how do I know?

    Ask the user. The OS only knows whether there is a network connection or not. It doesn't care where the network is located or what it's connected to. That's up to the hardware to deal with.

    Quote

    Is there another way to get the name of the local network LAN that works both wired (desktop machines) and wifi?

    No. And as far as sockets are concerned, there is no difference whatsoever whether you are connected to a wired LAN, or to a Wifi, or a cellular provider, etc.  The socket API works the same way. The difference is in how the hardware routes the traffic.

    Quote

    I'd like to try using winsock's gethostbyname but I haven't found a good use example.

    Likely because this is not what that API is intended for.

    Quote

    Or is there a better way?

    What EXACTLY are you trying to accomplish in the first place?


  15. Running a process as an (impersonated) admin user, and running a process in an elevated state, are two different things.  Being an admin user does not imply automatic elevation, but an elevation prompt does require an admin user.

     

    In any case, perhaps have a look at the CreateProcessWithLogonElevatedW() and CreateProcessWithTokenElevatedW() functions provided in the Elevate DLL of this old CodeProject article: Vista UAC: The Definitive Guide (I think the site is down undergoing a redesign at the moment, though. Maybe you can find another copy of the DLL elsewhere).

     


  16. 2 hours ago, davornik said:

    I have tried to catch OnPaint message, something like this, but no success 😞

    You are catching the FORM'S paint event, not the BUTTON'S paint event.  Every window receives its own painting messages (WM_PAINT, WM_DRAWITEM, etc).

    1 hour ago, davornik said:

    Finally, made it work 🙂

    Your code can be simplified a little. If you use the button's WindowProc property, you won't need to call GetWindowLongPtr() directly (and even then, SetWindowSubclass() would have been a better choice). Also, since your DrawColoredTxt() function is completely erasing the button and drawing it yourself, there is no point in calling the default paint handler at all.

     

    Try this:

    ...
        procedure DrawColoredTxt(aBtn: TButton; aCaption: string);
      private
        FOriginalButtonProc: TWndMethod;
        procedure ButtonWndProc(var Message: TMessage);
    ...
    
    procedure TForm1.DrawColoredTxt(aBtn: TButton; aCaption: string);
    begin
      ...
    end;
    
    procedure TForm1.ButtonWndProc(var Message: TMessage);
    var
      PS: TPaintStruct;
    begin
      case Message.Msg of
        WM_PAINT: begin
          BeginPaint(Button2.Handle, PS);
          try
            FOriginalButtonProc(Message);
            DrawColoredTxt(Button2, 'Admin');
          finally
            EndPaint(Button2.Handle, PS);
          end;
        end;
      // Forward all other messages to original handler
      else
        FOriginalButtonProc(Message);
      end;
    end;
    
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      FOriginalButtonProc := Button2.WindowProc;
      Button2.WindowProc := ButtonWndProc;
      Button2.Repaint;
    end;
    
    procedure TForm1.Button3Click(Sender: TObject);
    begin
      if Assigned(FOriginalButtonProc) then
      begin
        Button2.WindowProc := FOriginalButtonProc;
        FOriginalButtonProc := nil;
      end;
      Button2.Caption := 'Admin';
      Button2.Repaint;
    end;

    But, that being said, since you are drawing the entire button anyway, you may as well just use the BS_OWNERDRAW style and handle the WM_DRAWITEM message, as explained earlier in this discussion thread.

    • Like 1

  17. 4 hours ago, davornik said:

    I have tried to do drawtext over text on TButton and it works partially.

    ...

    I get changed font color like this:

    ...

    But when I move the mouse into Button2 everything falls apart 😞

    That is because you are drawing outside of a painting event.  As soon as the button gets repainted for any reason, your drawing is lost.  This is why you must owner-draw the button so that any custom drawing can be persisted across multiple paint events.


  18. 1 hour ago, Mark- said:

    I was using the OnError callback. Call connect, onError is called but, "LastError" was zero.

    Have you tried calling WSAGetLastError() directly?  At the point where OnError is called, the last socket error code might not have been overwritten yet.

    1 hour ago, Mark- said:

    Switched to catching it as an exception try Connect except end; LastError is still zero.

    The error code is stored in the raised ESocketException in its ErrorCode property.

    1 hour ago, Mark- said:

    Looked in the source at

    
    procedure TCustomWSocket.BindSocket;
    ...
    if WSocket_Synchronized_bind(HSocket, PSockAddrIn(@LocalSockName)^, SockNamelen) <> 0 then begin
    

    and the correct error code 10049 (WSAEADDRNOTAVAIL) is present but, it is never assigned to LastError, that I could see.

    Sounds like a bug that should be reported to the ICS author.

    • Like 1

  19. 3 hours ago, JohnLM said:

    I will figure out a way to fix this the code (above) to handle a source file copied to the clipboard to process when copying whole source codes from the Delphi IDE that could potentially be hundreds of lines.

    First off, you don't need your fix13and10str() function, as the RTL has its own AdjustLineBreaks() function:

    Quote

    AdjustLineBreaks adjusts all line breaks in the given string to the indicated style.

     

    When Style is tlbsCRLF, the function changes all CR characters not followed by LF and all LF characters not preceded by CR into CR/LF pairs. When Style is tlbsLF, the function changes all CR/LF pairs and CR characters not followed by LF to LF characters.

    For example:

    uses
      ..., System.SysUtils;
      
    procedure TForm1.btnProcessClick(Sender: TObject);
    var
      s: string;
    begin
      s := AdjustLineBreaks(Clipboard.AsText, tlbsCRLF);
      // or, just let it use the platform default style...
      // s := AdjustLineBreaks(Clipboard.AsText);
      m1.Lines.Add(s);
    end;

    Alternatively, you can assign the clipboard text as-is to a TStrings.Text property and let it parse the line breaks for you:

     

    https://docwiki.embarcadero.com/Libraries/en/System.Classes.TStrings.Text

    Quote

    When setting Text, the value will be parsed and separated into substrings whenever the LineBreak value is encountered. For backward compatibility, on POSIX, if the LineBreak separator is LF, then LF, CR, or CRLF are treated as separators. On Windows if the LineBreak separator is CRLF, then LF, CR, or CRLF are treated as separators.

    For example:

    procedure TForm1.btnProcessClick(Sender: TObject);
    var
      sl: TStringList;
    begin
      sl := TStringList.Create;
      try
        // sl.LineBreak is set to System.sLineBreak by default...
        // sl.LineBreak := sLineBreak;
        sl.Text := Clipboard.AsText;
        m1.Lines.AddStrings(sl);
      finally
        sl.Free;
      end;
    end;

    Or simpler (if you don't mind the entire TMemo content being replaced):

    procedure TForm1.btnProcessClick(Sender: TObject);
    begin
      m1.Lines.Text := Clipboard.AsText;
    end;
    3 hours ago, JohnLM said:

    For the record, I do not use notepad++ and I am not saying it is bad or anything.  I just never found uses for it up to this point.

    One handy use-case is changing line breaks in text.  You can copy the code from the IDE, paste it into Notepad++ (or just open the original file directly in Notepad++), specify a new type of line feed (bare-CR, bare-LF, and CRLF are supported), copy the new text back to the clipboard, and paste it into your app.

    • Thanks 1

  20. 22 minutes ago, GabrielMoraru said:

    How do you deal with Android? It does not support blocking messages...

    When displaying a popup message, you have to use the non-modal version, and break up your code logic so it can be continued by the popup's asynchronous callback when the popup is closed.

    • Like 1
×