-
Content Count
2943 -
Joined
-
Last visited
-
Days Won
133
Everything posted by Remy Lebeau
-
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 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.
-
Not natively, no. But I'm sure a 3rd party one exists if you search around.
- 7 replies
-
- delphi xe7
- trackbar
-
(and 1 more)
Tagged with:
-
Are you using C++ or Delphi? Integer division or floating-point division? Can you provide an example that is not working for you?
-
How to get the result of Activity.startActivityForResult in android
Remy Lebeau replied to iken's topic in Cross-platform
You are not going to get a notification if you use startActivity(), you need to use startActivityForResult(). -
should be simple: is computer on home network?
Remy Lebeau replied to bobD's topic in Network, Cloud and Web
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). -
should be simple: is computer on home network?
Remy Lebeau replied to bobD's topic in Network, Cloud and Web
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. 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. -
should be simple: is computer on home network?
Remy Lebeau replied to bobD's topic in Network, Cloud and Web
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. 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. Likely because this is not what that API is intended for. What EXACTLY are you trying to accomplish in the first place? -
Run as admin on unauthorized Windows username
Remy Lebeau replied to Mustafa E. Korkmaz's topic in Windows API
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). -
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). 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.
-
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.
-
I don't think you need to call WsocketErrorDesc() as ESocketException also has an ErrorMessage property.
-
Have you tried calling WSAGetLastError() directly? At the point where OnError is called, the last socket error code might not have been overwritten yet. The error code is stored in the raised ESocketException in its ErrorCode property. Sounds like a bug that should be reported to the ICS author.
-
Delphi project source codes is all on one line
Remy Lebeau replied to JohnLM's topic in Delphi IDE and APIs
First off, you don't need your fix13and10str() function, as the RTL has its own AdjustLineBreaks() function: 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 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; 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.- 4 replies
-
- delphi xe7
- all-on-one-line
-
(and 1 more)
Tagged with:
-
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.
-
How can you list all the datasources linked to a dataset?
Remy Lebeau replied to PiedSoftware's topic in VCL
That approach is dependent on the layout of the original class, and could break between updates, so use with caution. It is also not a last resort, either. A safer approach would be to use RTTI to get the offset of the desired class member, and then use pointer arithmetic to access the member, eg: uses ..., System.Rtti; private DataSourcesOffset: Integer; ... procedure TForm1.Form1Create(Sender: TObject); var Ctx: TRttiContext; begin DataSourcesOffset := Ctx.GetType(TClientDataSet).GetField('FDataSources').Offset; end; procedure TForm1.Button1Click(Sender: TObject); type PDataSourceList = ^TList<TDataSource>; begin var ds := PDataSourceList(PByte(ClientDataSet1) + DataSourcesOffset)^; for var src in ds do ShowMessage(src.Name); end; -
How can you list all the datasources linked to a dataset?
Remy Lebeau replied to PiedSoftware's topic in VCL
Class helpers don't have access to private members anymore since Delphi 10.1 Berlin. https://blogs.embarcadero.com/closing-the-class-helpers-private-access-loophole/ -
Component with sub-property event
Remy Lebeau replied to Anders Melander's topic in Delphi IDE and APIs
That sounds like a lot of extra work for very little gain. I don't think it is very good design to expose design-time access to sub-property events. The sub-properties are part of the main component. All events should be part of the main component, as well. But that is just my opinion. -
How do I use a range-based for loop to sum all elements
Remy Lebeau replied to 357mag's topic in General Help
That's like the very definition of Undefined Behavior. Accessing the array out of bounds is reaching into surrounding memory, and the content of that memory is random/indeterminate on each new run. It could be random bytes left over from a previous run/process. It could be bytes belonging to other local variables on the stack. You just don't know. myArray[2] = 7 myArray[4] = 9 myArray[7] = out of bounds, UB! myArray[8] = out of bounds, UB! myArray[9] = out of bounds, UB! -
Component with sub-property event
Remy Lebeau replied to Anders Melander's topic in Delphi IDE and APIs
Which is what, exactly? -
Component with sub-property event
Remy Lebeau replied to Anders Melander's topic in Delphi IDE and APIs
That was my first instinct too, but it doesn't work. I tried it. -
Component with sub-property event
Remy Lebeau replied to Anders Melander's topic in Delphi IDE and APIs
The Object Inspector does not display events for nested sub-properties. It can only display the events that are directly members of the selected object(s), which in this case is your TTest component, not the TTestSub nested sub-object. All of the events need to be exposed only at the top-level of your TTest component. If you have sub-property events you want to expose in the OI, you will have to propagate them accordingly, eg: unit FooBar.Reg; interface uses Classes, DesignIntf; type TTestSub = class(TPersistent) private FOnEvent: TNotifyEvent; FTest: string; public procedure Assign(Source: TPersistent); override; published property Test: string read FTest; property OnTestEvent: TNotifyEvent read FOnEvent write FOnEvent; end; TTest = class(TComponent) private FSub: TTestSub; procedure SetSub(const Value: TTestSub); function GetOnTestEvent: TNotifyEvent; procedure SetOnTestEvent(AValue: TNotifyEvent); public constructor Create(AOwner: TComponent); override; destructor Destroy; override; published property Sub: TTestSub read FSub write SetSub; property OnTestEvent: TNotifyEvent read GetOnTestEvent write SetOnTestEvent; end; procedure Register; implementation procedure Register; begin RegisterComponents('FooBar', [TTest]); end; { TTest } constructor TTest.Create(AOwner: TComponent); begin inherited; FSub := TTestSub.Create; FSub.FTest := 'Hello world'; end; destructor TTest.Destroy; begin FSub.Free; inherited; end; function TTest.GetOnTestEvent: TNotifyEvent; begin Result := FSub.OnTestEvent; end; procedure TTest.SetOnTestEvent(AValue: TNotifyEvent); begin FSub.OnTestEvent := AValue; end; procedure TTest.SetSub(const Value: TTestSub); begin FSub.Assign(Value); end; { TTestSub } procedure TTestSub.Assign(Source: TPersistent); begin FOnEvent := TTestSub(Source).OnTestEvent; end; end. I could be wrong, but I don't recall this ever being possible. Apples and Oranges. What you are asking for is simply not supported by Delphi without propagating the events manually, or maybe by writing a custom property/component editor that exposes nested events at the top level. -
How do I use a range-based for loop to sum all elements
Remy Lebeau replied to 357mag's topic in General Help
Accessing an array out of bounds is Undefined Behavior. Anything can happen. An AV/exception is not guaranteed. C++ does not have bounds checking on vanilla C-style arrays. If you want that, switch to std::array or std::vector and use their at() method. In this particular example, the first few array values are valid indexes into the array, and the remaining values are small enough that the code would exceed the bounds of the array into surrounding memory but stay within the bounds of the calling thread's stack, It's valid memory access as far as the OS is concerned, thus no AV is thrown, but it's still Undefined Behavior as far as C++ is concerned. -
TMultipartFormData issue with 12.3, but not 11.3
Remy Lebeau replied to alank2's topic in Network, Cloud and Web
Pointers are implicitly convertible to bool. A string literal is not itself a pointer, but it does decay into a pointer, which is then convertible. Note that NULL is not a pointer. It is an alias for a null pointer constant, either nullptr or integer literal 0 (depending on implementation), which can be assigned to any pointer. -
Indy in general (not just TIdSMTP specifically) indeed natively supports only up to OpenSSL 1.0.2, not OpenSSL 1.1.x and later. This is a LONG standing problem with no resolution in Indy itself at this time. But, there are a few 3rd party implementations available that add support for those versions, such as TaurusTLS: https://github.com/JPeterMugaas/TaurusTLS
-
TMultipartFormData issue with 12.3, but not 11.3
Remy Lebeau replied to alank2's topic in Network, Cloud and Web
Got an interesting reply on the ticket: He meant this deprecated method instead: procedure AddStream(const AField: string; AStream: TStream; const AFileName: string = ''; const AContentType: string = ''; AHeaders: TStrings = nil); overload; deprecated 'Use AddStream with AOwnsStream parameter'; But yeah, that makes total sense now, C++'s overload resolution would indeed prefer to implicitly convert a string literal into a bool rather than a user-defined object (ie UnicodeString), and that would explain your crash if AOwnsStream were implicitly being set to 'true' and then you try to free both streams yourself. So, do the conversion explicitly and then you will hopefully see the warning: mfd->AddStream(_D("name"), send, String(_D("value")));