-
Content Count
1071 -
Joined
-
Last visited
-
Days Won
23
Everything posted by aehimself
-
Long story short - if you don't have to, don't. I am forced to use it at work and the only positive thing I can say about it is even XE7 runs on it without issues.
-
Build time affected with an updated component...
aehimself replied to Ian Branch's topic in General Help
Antivirus exclusion? If only specific bds.exe-s are set (not the whole Program Files\Embarcadero\Studio folder) your real time scanner can and will affect build times. -
I personally used MySQL for my projects and a bit of MsSQL server. I advise against FireBird and Oracle, my personal experience shows you'll have extra issues to keep an eye on. On Windows servers my suggestion is MsSQL, on Linux MariaDB. That way updates / patches are included in the regular process.
-
AppWatcher - Remote Application Management for Delphi Developers
aehimself replied to maumsti's topic in I made this
Unfortunately that is true. If the old version running, it will stay that way until it is closed. At least you can make sure that the new instances are the updated version :) -
AppWatcher - Remote Application Management for Delphi Developers
aehimself replied to maumsti's topic in I made this
I'm not sure because we are talking about a network share, but renaming the file and placing the new .exe (with the same name) might still work. A lot of us use this technique in updating our applications. -
AppWatcher - Remote Application Management for Delphi Developers
aehimself replied to maumsti's topic in I made this
With this I completely agree. Meaningful attacks (and their mitigation) are out of the scope of this project however (especially if we are somewhat "controlling" endpoints) we should do our part in cybersecurity :) -
AppWatcher - Remote Application Management for Delphi Developers
aehimself replied to maumsti's topic in I made this
Include some security. The first glance there's nothing stopping me from shutting down all your programs if I get into your network. Are you sure you need to keep a TCP connection up with each agent? UDP would be a lot more practical, plus you could do the discovery with a simple broadcasted message. -
Multithread and thread-safe TClientDataSet?
aehimself replied to snodev's topic in RTL and Delphi Object Pascal
The only benefit I see here is the usage of data aware controls. A Dataset descendant is never going to be as efficient in storage or manipulation as arrays are. Also keep in mind that you are doubling the resources used every time you are cloning a Dataset, which - by your own words - is already pretty large. To simplify/standardize I would create my custom data storage class with thread safe access and then look into DataBinding or writing my own helpers to display the data in this storage. If speed is not an issue you also can use an indexed TFileStream to cut back on memory requirements.- 5 replies
-
- delphi
- tclientdataset
-
(and 1 more)
Tagged with:
-
I'd strongly advise against UPX especially in production executables. I had my fair share of after-the-last-moment struggle because of it
-
It's "normal". The same happens in my home project which has 10-ish frames only. At least the fix is easy 🙂
-
Borland had a pascal "IDE" and compiler called Turbo Pascal - with that you could only develop console applications - as there was no Windows at that time yet. Delphi was born in reaction to this, this was it's magic as you could target the brand-new shiny platform. Delphi is and was always designed in the RAD fashion: events firing here and there and you react to these events - let it be a click of a button or the closing of a form. My opinion is this is why books start off with GUI applications. If you have an amphibious car, you'll mainly show it off on water as every other car can drive on the road already. An other thing is if you code in the RAD way you only have to write and maintain only a small portion of code as the majority is handled by the framework. You'll also have more sense of success (and therefore the will to continue to learn) as you can recreate a fully functional notepad clone with 10 lines of written code. These are just my 2 cents though but based on these it makes sense to introduce Delphi this way. And if this was (at least the part of) the reason I'd also advise to start this way. Throw some controls on the form, make them do something you fancy. With time, you'll eventually meet the necessity to separate UI and business logic but when you reach that point you probably will have enough expertise to create the backend.
-
You can add a message pump to any thread, VCL or not. If you need window messages, you can call AllocHwnd. Just because we are talking about console it doesn't mean these things do not work.
-
Hello all, I have an issue with some of our components in the application we support where an event handler simply disappears (gets unlinked, code stays in .pas) when a frame is opened. The main container is a frame which is the 3rd or 4th descendant of a simple TFrame (with 2-3 levels of visual inheritance included). The event handler is the OnDataChange event of a custom TDataSource descendant component. This frame has ~50 of these datasources, but only 2 are affected. No other datasources / frames have the same issue (which we have hundreds, if not thousands). When you open the file in Delphi, the tab indicator already shows that it is modified and can be saved. Upon saving the event handler is simply unlinked, leaving the actual code in the .pas file. Restoration is easy, just double-click the handler in object inspector so it gets linked back which you can save perfectly... until next time someone forgets to check the modifications and roll back the removals; which already happened at least 5 times in the past half a year. inherited frmCustom: TfrmCustom [...] object dtsMyDTS: TCustomDataSource [...] OnDataChange = dtsMyDTSDataChange <-- this line disappears [...] end [...] end I bet it will be some rare edge case but it already caused lots of headaches and it would be a blessing if it could be fixed. I am not able to share the sources as they are proprietary plus you'd need the whole custom component package as well to be able to open it 🙂 I'm simply looking for indicators, what I can try, what I can check to find the root cause. Anyone saw something like this? Cheers!
-
Long story short, the issue was in the custom component itself. Someone wanted to have a constant OnDataChange code to run every single time and - as TDataSource is an INSANELY bad component with no overridable methods whatsoever - this is how they solved it: TCustomDataSource = class(TDataSource) protected procedure Loaded; override; private FOnDataChangeDesigned: TDataChangeEvent; end; procedure TCustomDataSource.Loaded; begin inherited; FOnDataChangeDesigned := OnDataChange; OnDataChange := DataChangeDef; end; In the moment the component was successfully streamed (run- or design time) the event handler was "saved" and reset, only to be called from the internal method. But since it's a private method the Object Inspector could not access it, therefore clearing the event handler alltogether. Saving only wrote this inconsistent state back to the disk. And yes, it seems all of the TCustomDataSources were affected, the event handler just disappeared so long ago that noone seemed to realize it. After fixing it and relinking all DataChange events found in the entire application... it seems to be working properly now.
-
The datasource is on the last frame not on an ascendant (object dtsMyDTS instead of inherited dtsMyDTS). Inheritance only plays a role here if Delphi bugs out due to the long frame chain I think.
-
By the first look... nothing seems different, that's my issue. The create order is an excellent idea, I'll doublecheck that tomorrow!
-
Unfortunately I do not remember the 10.4 era, but this definitely happened under Delphi 11.2 and now Delphi 12. The project (and probably this frame) originally was created with Delphi 7 but was slowly upgraded to the most recent version. The source of said component is in Browsing path, Library path points to the precompiled DCU. All frame files (including the first one inherited from TFrame) is a part of the project. We have ~1500 frames with at least 20-50 of these custom datasources on each and this problem only occures on one frame, two datasources (always the same 2). This makes me believe that fixing it won't be something generic - e.g. on component or project level.
-
Hello everyone, While keeping an eye on other mediums I decided that a post here wouldn't hurt either. As the company I currently work for is going through a leadership change - as the title mentions - I am currently looking for new (remote) opportunities home or abroad. I'm aiming for something long-term in the EU-region and while others are not excluded, some agreement will be needed due to time zone differences. The first time I met Pascal was about 29 years ago. As time progressed I upgraded that knowledge to Delphi and it quickly became the go-to solution for repetative tasks at work. Currently on Delphi 12 but I have hands-on experience with 7 and every minor and major release since Seattle. Currently maintaining a big codebase (~1,5M LOC) plus custom components mostly derived from DevExpress. After getting rid of all the memory leaks I alone converted all this to a 64-bit compatible source and - probably due to my affection towards the language - Delphi version updates became my responsibility as well. Right next to Delphi I'm also using C# and have additional knowledge in T-SQL, C, C++, HTML, JS, CSS, Perl, Assembly and PHP. Being a sysadmin for 13 years I welcome windows batch as an old friend with Bash gaining traction lately. I'm not native but English is not an issue. If anyone knows someone looking for a reliable and passionate Delphi dev just forward the posting to me 🙂
-
Hello, I have a pagecontrol descendant, where I overridden the DoDrag method to show the picture of the dragged tab: Procedure TPageControl.DoStartDrag(Var DragObject: TDragObject); Var tab: TRect; bmp, tabbmp: TBitMap; Begin inherited; If DragObject <> nil Then Exit; // Create a bitmap of the tab button under cursor tab := Self.TabRect(Self.ActivePage.TabIndex); bmp := TBitmap.Create; bmp.Canvas.Lock; tabbmp := TBitmap.Create; Try bmp.Height := Self.Height; bmp.Width := Self.Width; tabbmp.Height := tab.Height; tabbmp.Width := tab.Width; Self.PaintTo(bmp.Canvas.Handle, 0, 0); tabbmp.Canvas.CopyRect(tabbmp.Canvas.ClipRect, bmp.Canvas, tab); DragObject := TPageControlExtraDragObject.Create(tabbmp); Finally bmp.Canvas.Unlock; FreeAndNil(tabbmp); FreeAndNil(bmp); End; End; When the user clicks on one of the tabs I'm manually initiating the dragging process by Self.BeginDrag(False);. When I went into BeginDrag, I saw that if you do not specify a dragging threshold, it takes this value from Mouse.DragThreshold, which is 5 pixels. This - to me - means that the dragging is NOT initiated unless the button is still down, and the cursor went at least 5 pixels away from the initiating position. What happens now is that the DoStartDrag event fires immediately, the bitmap is taken and is drawn as a fly-out immediately. Even it I am just switching tabs, which is kind of annoying. So the question is... if my logic is right (and the DoStartDrag should be fired based on distance) why it is firing immediately? If not, is there a simple setting I forgot to add or I manually have to handle this by MouseMove? I'm using Delphi 10.4.1, but the "issue" was present in 10.4 and 10.3 as well.
-
DataEvent is a method of the link, not the grid itself: Type TMyGridDataLink = Class(TGridDataLink) protected Procedure DataEvent(Event: TDataEvent; Info: NativeInt); Override; End; TDBGrid = Class(Vcl.DBGrids.TDBGrid) protected Function CreateDataLink: TGridDataLink; Override; End; implementation Procedure TMyGridDataLink.DataEvent(Event: TDataEvent; Info: NativeInt); Begin inherited; // Call your public method of (Self.Grid As TDBGrid) to update it's captions // Use Event and Info to make conditions if necessary End; Function TDBGrid.CreateDataLink: TGridDataLink; Begin Result := TMyGridDataLink.Create(Self); End; As for alignment I used a different approach: _ownerpanel := TPanel.Create(Self.Parent); _ownerpanel.Top := Self.Top; _ownerpanel.Left := Self.Left; _ownerpanel.Height := Self.Height; _ownerpanel.Width := Self.Width; _ownerpanel.Anchors := Self.Anchors; _ownerpanel.Align := Self.Align; _ownerpanel.BevelOuter := bvNone; _ownerpanel.Parent := Self.Parent; _ownerpanel.Constraints.Assign(Self.Constraints); _statusbar := TStatusBar.Create(_ownerpanel); _statusbar.Parent := _ownerpanel; _statusbar.SimplePanel := True; _statusbar.ShowHint := True; Self.Constraints.MaxHeight := 0; Self.Constraints.MaxWidth := 0; Self.Constraints.MinHeight := 0; Self.Constraints.MinWidth := 0; Self.Align := alClient; Self.Parent := _ownerpanel; Correct. You can play around your component in runtime but to reflect your changes in design time you will need a component installed in the Delphi IDE itself.
-
TPanel.Create(TDBGrid(AOwner)); The owner of the grid is usually the container (form, frame, etc). Typecasting to the wrong type might cause access violations - simply leave it out. It's unnecessary. The main difference is how the object will be freed. When passing nil as the owner the object has to be freed up manually. Otherwise, it's automatically freed when the owner is freed. I'd suggest using Self (the grid) as the owner of the panel so you can leave out .Free in the destructor. P.s.: When I made a similar component I think I ended up putting the count update logic to the DataChange event but I have to doublecheck...
-
Double, default value
aehimself replied to Skrim's topic in Algorithms, Data Structures and Class Design
That's exactly what I meant. If no exceptions are thrown, the string was successfully converted and the return value will initialize the variable correctly. As the snipplet above contained no Try..Except or Try...Finally blocks it doesn't matter what would use the variable in question afterwards as it never gets executed. -
Double, default value
aehimself replied to Skrim's topic in Algorithms, Data Structures and Class Design
That is correct. All local variables are uninitialized and might contain complete garbage until the first assignment. Without checking the source, StrToFloat has two options: either throw an exception or to return a value. The line after this assignment is only executed if no exception was thrown, therefore the local variable holds an actual value. Therefore, the variable := 0 is unnecessary in this case. -
Help needed in testing emulated GetTickCount32/64
aehimself replied to Kas Ob.'s topic in Algorithms, Data Structures and Class Design
Found it! The code I used could not be more simple... program Project1; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils; function GetTickCount64Emu: UInt64; const KUSER_BASE_ADDRESS = $7FFE0000; //KUSER_BASE_ADDRESS_KERNEL_MODE =$FFFFF78000000000; //in case it is needed begin Result := (PUInt64(KUSER_BASE_ADDRESS + $320)^ * PCardinal(KUSER_BASE_ADDRESS + $4)^) shr 24; end; begin try WriteLn(GetTickCount64Emu); ReadLn; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. And it resulted 5283539281 with 61 days, 3.5 hours of uptime on a 32-bit Windows Server 2003 R2: -
Help needed in testing emulated GetTickCount32/64
aehimself replied to Kas Ob.'s topic in Algorithms, Data Structures and Class Design
@Kas Ob. The VM is now at 61 days of uptime. I'm having a bit of trouble compiling an EXE which actually executes on Windows 2003... I remember having to change something somewhere in the IDE / project options. If you know the solution let me know - it might be quicker than me attempting to research.