-
Content Count
1053 -
Joined
-
Last visited
-
Days Won
23
Everything posted by aehimself
-
Custom component ParentBackground property resets to false
aehimself posted a topic in Delphi IDE and APIs
Hello, We have a custom component derived from Delphi's standard TPanel. What I realized is that the ParentBackground property resets to False each time the form is opened in the Delphi IDE (no saving is required, it automatically updates the DFM). There are no mentions / changes made to this property in the component's code and the situation does not change even if I add this published property: property ParentBackground stored true default True; I found an old topic about OldCreateOrder behaving the same way, but the proposed solution (remove the ParentBackground = False from the DFM with a text editor) only works until the form is reopened again - then it will automatically reset to False and update the DFM immediately without saving. I'll keep digging and investigating but if anyone has experience with this please do not hesitate to share the solution 🙂 Thanks! -
Custom component ParentBackground property resets to false
aehimself replied to aehimself's topic in Delphi IDE and APIs
So, the issue had nothing to do with the panel, but a label on it... and by replacing it from TLabel to TcxLabel to be precise. There was a section in the constructor which looked like this: With TLabel.Create Do Begin // [...] If criteria Then Color := clRed; End; This was fine but in the moment someone changed it with cxLabel (which has no public .Color property) that one line immediately turned ParentBackground off on the panel as it changed it's color instead of the labels. This is one reason I hate With blocks 😞 -
Hello, I just finished rewriting a method which now only lists font names useable by TSynEdit. The theory is easy; while enumerating Screen.Fonts I'm passing them to the exact same check as TSynEdit does (SynDWrite.pas, IsFontMonospacedAndValid). If it returns true, I add it to the list. The issue is, there is a CheckOSError call in said method which break the execution of the program way too many times if it is run from the IDE. The current implementation is as follows: function IsFontMonospacedAndValid(Font: TFont): Boolean; var LogFont: TLogFont; DWFont: IDWriteFont; begin try Assert(GetObject(Font.Handle, SizeOf(TLogFont), @LogFont) <> 0); CheckOSError(TSynDWrite.GDIInterop.CreateFontFromLOGFONT(LogFont, DWFont)); Result := (DWFont as IDWriteFont1).IsMonospacedFont; if (FontFamilyName(DWFont) <> Font.Name) and (fsBold in Font.Style) then Font.Style := Font.Style - [fsBold]; except Exit(False); end; end; I can put the EOSError exception type as a globally ignored one in Tools / Options but understandably it is not an ideal solution. I also could copy and paste this check, removing the CheckOSError but if I do I have to keep an eye on the official implementation to make sure to update my version if the original changes. Is there a compiler directive which will ignore a specific exception type within a block of code? Thanks!
-
@Steven Kamradt An important rule of writing maintainable software is that you are not changing the code in any external components. Doing that will come to bite you in the back later on; especially if you try to update said component.
-
I solved this issue by changing my icons to Material Designs Webfont and providing them to my application using Icon Fonts Image list. When the style changes I just update the .FontColor property of the image list to TStyleManager.ActiveStyle.GetStyleFontColor(sfWindowTextNormal). This way I can be certain that whatever is selected, my toolbar and popup menu icons are always visible. As an extra, if you are fine with the monochrome look, you can spare the fee of the designer.
-
How does CurrentControlSet differ from HKEY_CURRENT_USER
aehimself replied to Tom F's topic in Windows API
I'd doublecheck every registry operation and make sure every .OpenKey has a .CloseKey, and every TRegistry.Create has a .Free in the Finally block. I had my share of issues when I wanted to reuse the same TRegistry object within a method to perform different writes. I ended up creating it and freeing it up after each "task". -
Types incompatibles : 'string' et 'Extended'
aehimself replied to abdellahmehdi's topic in Algorithms, Data Structures and Class Design
*** Screams in JavaScript *** -
Hello, I have a pretty basic update mechanism in my applications which gets the job done - but it has it's limitations. It would be nice to have "dev" and "stable" channels, messages to be shown to the users (e.g. if there's a yet unfixed bug with a workaround), going back to a previous version, delta updates only, etc. So I started to rework the thing as it is but I am simply stuck on the design stage... I can not agree with myself on how it should be done properly. My base theory is one file in one update archive, the application determines what it needs to update and download only those archives to minimize network traffic. - Put a static JSON with all version information, this gets refreshed each time a version is deployed? This is how the current system works: easy to implement but... - Just put the ready archive with the new version in the folder and have a service explore the changes and rebuild the static JSON accordingly? This option sounds the best to avoid any lingering files / entries (e.g. archive is placed but changed were not placed in the DB or vice versa) but where the changelog is coming from in this case? - Store everything in a database and use a PHP script to query and assemble the reply JSON? My PHP knowledge is really limited, so I'd prefer not to have this option. Although, a dynamic list is crucial to minimize traffic (why to download version information for different products, or changelogs for versions below the current one?) So my question is... are there any readily available update platforms for Delphi (server and client side too) which I can simply implement in my applications and forget about this matter? I'm also open to suggestions on how the thing should work, on all possible levels: - Backend. Is a database really needed or overkill? - Static vs dynamic update definitions. Dynamic is better from many perspectives but does it really worth the extra effort? - Protocol. Should I really stick to HTTP, or is there a better / create my own? - How the information is translated and sent, including how the application should know if a new file is added to the distribution? Cheers!
-
WinSock (Indy) select() doesn't return on network
aehimself posted a topic in Network, Cloud and Web
Hello, We have an application built on Delphi 10.4.1 / 10.4.2 which is communicating with a server using the Indy TidHttp component. It works perfectly, but there is one particular call when the result can arrive in 1-1,5 hours... and this is where things get strange. The request is sent with idHttp.Post (using a stream as an outgoing and an incoming data buffer) and if the reply arrives in 30 minutes, all is fine. Somewhere between 30 minutes and one hour, the underlying WinSock .select never returns. Data is sent out, received by the server, processed and the data is sent out - but never received by the client. Using WireShark it can be seen that the moment the server sends the reply, the client issues a TCP retransmission... maybe it thinks that the data was lost but was unable to use the channel while waiting for data? Then the reply arrives, channel gets free and it sends the retransmission but discards the data received? These are just guesses, I'm not very familiar with this low-level functionality of WinSock. Oh, one more thing... this issue is NOT present if the server and the client is on the same machine; connecting to localhost makes a difference. Stack trace where the application stops is as follows: :772729dc ntdll.ZwWaitForSingleObject + 0xc :74417555 ; C:\WINDOWS\SysWOW64\mswsock.dll :751c5f1e WS2_32.select + 0xce IdStackWindows.TIdSocketListWindows.FDSelect(???,???,nil,???) IdStackWindows.TIdSocketListWindows.SelectRead(-2) IdSocketHandle.TIdSocketHandle.Select(???) IdSocketHandle.CheckIsReadable(???) IdSocketHandle.TIdSocketHandle.Readable(-2) IdIOHandlerStack.TIdIOHandlerStack.Readable(???) IdIOHandler.TIdIOHandler.ReadFromSource(True,-2,False) IdIOHandler.TIdIOHandler.ReadLn(#$A,-1,16384,TIdASCIIEncoding($1A138AD4) as IIdTextEncoding) IdIOHandler.TIdIOHandler.ReadLn(nil) IdHTTP.TIdCustomHTTP.InternalReadLn IdHTTP.TIdCustomHTTP.DoRequest(???,'http://10.0.2.53:12345/BIN',$2E6D75A0,$2E6D73A0,(...)) IdHTTP.TIdCustomHTTP.Post('http://10.0.2.53:12345/BIN',$14E0F58,$2E6D73A0) Before you say anything, I know this is a bad design. We shouldn't wait on long lasting operations but to poll for it on HTTP. What I'd like to know is what happens and why it happens so I can get an insight if patching the mess worth it or just jump straight to refactoring. Cheers! -
WinSock (Indy) select() doesn't return on network
aehimself replied to aehimself's topic in Network, Cloud and Web
Aren't these supposed to be services (like Apple's or Google's notification service) or websockets...? -
WinSock (Indy) select() doesn't return on network
aehimself replied to aehimself's topic in Network, Cloud and Web
Honestly, I don't know if it would make any sense. It's your decision at the end. Would have made my implementation easier (and error-free the first try 🙂) but our implementation is clearly wrong here. In normal operation the HTTP protocol should work in "bursts": request something, get an answer, repeat until all done. If someone else needs a TCP-level keep-alive in HTTP instead of fixing the real issue (like in my case) these 3 lines of extra code seems very well deserved. Plus the solution is now publicly accessible in this thread. -
WinSock (Indy) select() doesn't return on network
aehimself replied to aehimself's topic in Network, Cloud and Web
I decided to implement both. Upon enabling the TCP keepalive if a handle is allocated SetKeepAliveValues is called but there is now an OnSocketAllocated handler which checks if the keepalive was enabled and if yes, calls SetKeepAliveValues. This way the exception disappeared; your guess was right, there was no handle allocated after the DoRequest call. As I could not reproduce the freezing of the application I can not confirm whether that disappears or not... guess time will tell sooner or later. Thank you! -
WinSock (Indy) select() doesn't return on network
aehimself replied to aehimself's topic in Network, Cloud and Web
@Remy Lebeau Just yesterday a new issue was reported which is in direct connection with the solution in this thread. The code is fairly simple: procedure TCustomActionCallerThread.Execute; begin V_CONNECTION.IndyHttpClient.Socket.Binding.SetKeepAliveValues(True, FTCPKeepAlive, FTCPKeepAlive); Try try V_CONNECTION.DoRequest(FActionName, FRequestXml, FResult); except on E: Exception do FResultException := Exception(AcquireExceptionObject); end; Finally V_CONNECTION.IndyHTTPClient.Socket.Binding.SetKeepAliveValues(False, 0, 0); End; end; The DoRequest (where the HTTP communication actually takes place) is quick (less than a second) but the code in the finally block (to disable the keepalive) throws an exception: Socker Error # 10038 Socket operation on non-socket. To make things more interesting, if the application is built with Delphi 10.4.1, it completely freezes. 10.4.2 only throws the exception but the operation finishes successfully. Do you have an idea why this error might appear? We use HTTP keepalive, so the socket should still exist after the DoRequest call. Is there a check which I can use as a condition to prevent this from happening? Also, do you happen to know in any difference between the Indy versions in 10.4.1 and 10.4.2? I can not really find a logical explanation in the behavior difference. Thank you! -
A while ago we managed to create one like this. You'll also find an installable component version in the comments.
-
Nice fix from a standard Windows application error 🙂 Where can I report more and how? 🙂 One demo locks up the application, 3 other causes it to crash completely.
-
Windows Defender. I know what sites to visit and what to download / execute 🙂 Spot on. Win10 Pro x64. No idea. I have an on-board Intel 620 and an additional Radeon R5 M430. The last time I used my PC for gaming was when I quit WoW about 10 years ago so I'm kinda rusty in these things 🙂 Intel's driver is 30.0.101.1960, Radeon is at 27.20.20904.4000 if it makes any sense. When I first started your demo there was a moment of DOS prompt and then nothing. No worries if my laptop cannot run it, it's not a workhorse. I just got a tidy bit worried, questioning my life decisions and uploading the executable on VirusTotal. Handle your exceptions if you can, please 🙂
-
Warning: serious bug in XE10.4.2/DCC64
aehimself replied to Alexander Sviridenkov's topic in RTL and Delphi Object Pascal
This code seems to work on a fully patched 10.4.2: procedure TForm2.FormCreate(Sender: TObject); Var x: Int64; begin x := Int64.MaxValue; If x <> Test Then Raise Exception.Create('Fail'); end; function TForm2.Test: Int64; begin Result := Int64.MaxValue; end; Checked with TFileStream too: procedure TForm2.FormCreate(Sender: TObject); Var fs: TFileStream; tb, r: TBytes; a: Int64; b: Integer; begin SetLength(tb, 1024 * 1024); // 1 MByte For a := Low(tb) To High(tb) Do tb[a] := a Mod 255; fs := TFileStream.Create('C:\Users\xxx\test.tmp', fmCreate); Try For a := 0 To 4 * 1024 Do fs.Write(tb, Length(tb)); finally fs.Free; End; SetLength(r, Length(tb)); fs := TFileStream.Create('C:\Users\xxx\test.tmp', fmOpenRead); Try Repeat b := fs.Read(r, Length(r)); If b > 0 Then If (b <> Length(tb)) Or Not CompareMem(@r[0], @tb[0], Length(tb)) Then Raise Exception.Create('Read error, read ' + b.ToString + ' bytes'); Until b = 0; finally fs.Free; End; end; Runs and works properly. Am I missing something? -
Faulting application name: GVExamples.exe, version: 0.0.0.0, time stamp: 0x62940977 Faulting module name: KERNELBASE.dll, version: 10.0.19041.1706, time stamp: 0x458acb5b Exception code: 0xc06d007e Fault offset: 0x0000000000034fd9 Faulting process id: 0x2bd8 Faulting application start time: 0x01d8752529d9b09b Faulting application path: C:\Users\xxx\Downloads\GVExamples\GVExamples.exe Faulting module path: C:\WINDOWS\System32\KERNELBASE.dll Report Id: ac240234-13c0-439c-88d1-1d9bdbdcb991 Faulting package full name: Faulting package-relative application ID:
-
I wanted to do this for a really long time so I started to extract the core improvements of Delphi's TDBGrid into a separate component. This includes: - New public BeginUpdate / EndUpdate methods, which can disconnect the dataset and keep the previous image on the component. This is useful if you are doing opens / posts / anything in a background thread but don't want to show emptiness until - Automatic and manual fitting of columns which considers the column and the content width but won't let a column be wider than half it's size - Vertical scrollbar now works properly, not only 3 positions and is not visible when not needed - Grid properly handles mouse wheel scrolling - Content is shown as the scrollbar is dragged (not only updating when the mouse is released) - If there is no connected dataset or it is not active, the two empty cells won't be shown - Every second row has a slightly different background, out-of-focus selection is now drawn with a separate shade of grey, so you can see that the grid is not in focus. This considers VCL styles. - If TitleClick or TitleHotTrack is enabled, the cursor changes to a hand instead of the pointers It might get more updates later on when I see what code can be generally used from my heavily customized one. Feel free to grab it / check how things were done. Tried to put comments everywhere.
-
You either manually set the position on the form's OnResize event or set the proper anchors after creating the components.
-
TDBGrid is doing a really crappy job in sizing it's columns and however I didn't meet the issue you describe, I simply consider it to this "feature". Have a look at this snipplet for a possible fix; I started mine based on this too.
-
Something like this: Var pbar: TProgressBar; lbl: TLabel; a: Integer; Begin TProgressBarInStatusBar.CreateIn(StatusBar1, pbar, lbl); For a := 0 To 1000 Do Begin pbar.Position := a Div 10; lbl.Caption := 'Working ' + a.ToString + '...'; Application.ProcessMessages; // Don't do this. It's just pseudocode. Sleep(500); End; End;
-
I create my progress bars in the first panel of the status bar, with a label on it to show some meaningful information on the progress... like "30 of 999 items processed". Yes, it won't work if you resize the panel, needs some adjustments if you want to create it in the 3rd, but this is the code I use: Unit uProgressBarInStatusBar; Interface Uses Vcl.ComCtrls, Vcl.StdCtrls; Type TProgressBarInStatusBar = Class public Class Procedure CreateIn(Const inStatusBarPanel: TStatusPanel; Var outProgressBar: TProgressBar; Var outLabel: TLabel); End; Implementation Uses Vcl.Controls, System.Classes; Class Procedure TProgressBarInStatusBar.CreateIn(Const inStatusBarPanel: TStatusPanel; Var outProgressBar: TProgressBar; Var outLabel: TLabel); Var statusbar: TStatusBar; Begin statusbar := inStatusBarPanel.Collection.Owner As TStatusBar; outProgressBar := TProgressBar.Create(statusbar); outProgressBar.Parent := statusbar; outProgressBar.Top := 2; outProgressBar.Left := 1; outProgressBar.Width := inStatusBarPanel.Width - 3; outProgressBar.Height := statusbar.ClientHeight - 3; outLabel := TLabel.Create(outProgressBar); outLabel.Parent := outProgressBar; outLabel.Align := alClient; outLabel.AutoSize := False; outLabel.Alignment := taCenter; End; End. The small sacrifice of having it in the first panel makes up to it with no custom drawings / hacks needed at all. And it looks good enough:
-
Hello, We just met a strange issue and was wondering if anyone can explain why it is happening. The below code throws a stack overflow, as the compiler doesn't make a difference between TDateTime and Integer and keeps calling the first method: program Project1; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, System.DateUtils; function GetDay(dt: TDateTime): string; Overload; begin Result := GetDay(DayOfTheWeek(dt)); end; function GetDay(i: Integer): string; Overload; const LDays: array[1..7] of string = ('H', 'K', 'S', 'C', 'P', 'S', 'V'); begin Result := LDays[I]; end; begin WriteLn(GetDay(Today)); end. It works perfectly if you turn it to a dummy class and publish these methods as class functions: Type x = Class class function GetDay(dt: TDateTime): string; Overload; class function GetDay(i: Integer): string; Overload; End; It also works if you push these two methods in a separate unit with proper Interface section: unit Unit1; interface function GetDay(dt: TDateTime): string; overload; function GetDay(i: Integer): string; overload; implementation I guess it'll have something to do on how overloads are interpreted in the implementation area...? Delphi 10.4, 10.4.2 and 11 are producing the same symptom.
-
WinSock (Indy) select() doesn't return on network
aehimself replied to aehimself's topic in Network, Cloud and Web
I can confirm that wrapping the long lasting call in a Try...Finally block and enabling / disabling the KeepAlive function via SetKeepAliveValues solves the problem. Thank you, Remy!