Leaderboard
Popular Content
Showing content with the highest reputation on 01/31/19 in Posts
-
Fixed download links: IDEFixPackD103RegDev.7z fastdccD103vDev.7z
-
The attached IDEFixPack development snapshot fixes this TCustomListBox IDEFixPack bug. IDEFixPackD103Reg64.7z
-
Hi everyone, I've ported Casbin to delphi and created Casbin4D open source project. Please check it here: https://github.com/casbin4d/Casbin4D Please feel free to comment, fork, report issues, etc. Thanks
-
I've let my enterprise subscription expire yesterday. It breaks my heart after two decades of working with Delphi but as many others I just lost all confidence in emba/idera. IMHO complaining but at the same time keep paying ridiculously high subscription fee (compared to other development environments) sends them the wrong message. I'll gladly resubscribe if things turn around or when Delphi eventually gets auctioned off to a better care-taker.
-
Should my record be a class instead?
David Schwartz replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
When you eat something, you need to prepare it (maybe cook it, or order it, or unwrap it), then you need to clean up afterwards. When you get in your car to go somewhere, you need to start it up; when you arrive at your destination, you need to shut it off. When you walk into a room, you may need to open the door and perhaps turn on a light; when you leave, you may need to shut the light off and close the door. Most things in life require some kind of setup, then you do something, then you clean up after yourself. Tell me it really bothers you having to deal with this constantly in your life ... or if you're like most people, you don't ever give any of it a second thought. Objects work the same way. The fallacy in your logic (and people who claim to dislike creating and freeing things) is that just because there's nothing named "constructor" or "destructor" that you're not initializing things first and cleaning up afterwards. Variables often need to be initialized and cleaned-up, regardless of their scope. By default, the compiler clears out globals automatically for you by setting them to zero, but it's risky to depend on default behaviours like that from your environment. Constructors are simply methods used for INITIALIZING an object's state. They're usually just a bunch of assignment statements. They may also create other objects required inside of the object. Simple objects that don't inherit from a parent class with a constructor that needs to be called don't need constructors. Destructors are for cleaning up when you're finished using the object. For simple classes, they're often not necessary. But if you allocate anything from the heap within the class, then they're required if you want to avoid memory leaks. However, it's a good practice to always have constructors and destructors defined, even if they're empty. And if they ARE empty, the compiler optimizes them out. The nice thing about them is they're called automatically, unlike your existing code that needs to be called explicitly. So don't tell me you dislike creating things! Classes with constructors and destructors require less code than what you're doing now ... guaranteed. Even if you're working with a bunch global variables, any nontrivial application has code that initializes groups of related variables, and breaks them down when you're finished. One of the biggest hurdles functional programmers need to overcome when learning OOP is that all of those global variables need to be collected into closely-related groups, and those groups are called "classes". Then you move the code that's already there that's used to initialize those variables into the class' constructor, and any code that's already there for cleaning up into the class' destructor. Then you want to hide the variables themselves ("encapsulation") by defining properties so if the underlying implementations change, you don't have to change every single place they're referenced. Trust me ... after you've been using OOP principles correctly for a while, it becomes second-nature, and you'll wonder how you managed to keep your sanity dealing with everything splattered all over the place with no organization whatsoever. -
Object destroyed too soon?
Attila Kovacs replied to Primož Gabrijelčič's topic in RTL and Delphi Object Pascal
I'd say thats why: property Result: TOmniValue read GetResult write SetResult; A Record property. -
Finally the Quality Central issues statuses begin to update. And what do you think? RSP-21645 (Editor tabs do not show icons) - closed. Resolution: Works As Expected 🙁 . Really, that is how they at Embarcadero see it. RSP-21636 (Active editor tab is not highlighted when IDE theming is disabled) - closed. Resolution: Won't Fix. Given this stupid attitude (and obvious intentions to further force the themed IDE despite all its glitches) I highly doubt that I'll renew my subscription when it expires this March. I thank David Millington for personally contacting me but I do not want to further waste my hard earned money for another round of cosmetic IDE changes instead of bug fixing.
-
Should my record be a class instead?
Fritzew replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
One of the best explanations I ever read..... Thanks for write this. -
I did a CodeRage 9 talk on a topic that might help: https://www.youtube.com/watch?v=qqKx8fQTTfI
-
Is it really good practice to create Forms only as needed? Always?
David Schwartz replied to Mike Torrettinni's topic in VCL
Generally speaking, I don't auto-create any forms that aren't required to be around for the entire duration of the program's execution. So there's the Main form, any DataModules that are used by other forms (bad practice, but very common), and any other forms that are simply easier to leave around to hang onto values that would otherwise need to be saved somewhere else. Everything else is created as-needed and freed when I'm done using it. As far as your 50-tabbed notebook ... it must take forever to open that form in Delphi! At some point, I'd change that from a tabbed notebook to a panel where I loaded up an embedded form (created on-the-fly) from a combobox selection. -
Another IDEFixPack development snapshot that fixes the IDEFixPack bug RSP-23405 that was reported to Embarcadero. Changelog: - Fixed: With CompilerSpeedPack64 the Win64 compiler generated broken code for asm-blocks
-
Should my record be a class instead?
Uwe Raabe replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
This is an class approach. The benefit is the full encapsulation of the private parts inside the implementation section. unit uGlobalData; interface type TGlobalData = class type TValue = record ValName: string; ValInProject: boolean; end; public { these should probably be properties instead } Id: Integer; RecName: string; Values: TArray<TValue>; procedure PrepareGlobalRec; virtual; abstract; end; function GlobalData: TGlobalData; implementation type TGlobalDataImpl = class(TGlobalData) private type TLocalRec = record LocalRecStr: string; // ... end; procedure LocalProc1; procedure LocalProc2; var LocalStrVar: string; LocalRecVar: TLocalRec; public procedure PrepareGlobalRec; override; end; procedure TGlobalDataImpl.LocalProc1; begin end; procedure TGlobalDataImpl.LocalProc2; begin end; procedure TGlobalDataImpl.PrepareGlobalRec; begin // prepare GlobalRec data LocalStrVar := 'local test'; LocalRecVar.LocalRecStr := 'test'; LocalProc1; LocalProc2; end; var GlobalDataInstance: TGlobalData = nil; function GlobalData: TGlobalData; begin if GlobalDataInstance = nil then begin GlobalDataInstance := TGlobalDataImpl.Create; end; Result := GlobalDataInstance; end; initialization finalization GlobalDataInstance.Free; GlobalDataInstance := nil; end. -
Object destroyed too soon?
Primož Gabrijelčič replied to Primož Gabrijelčič's topic in RTL and Delphi Object Pascal
This works, but requires lots of code if I would want to implement it with the original (very rich) `TOmniValue` record: IOmniValueFwd = interface; TOmniValue = record private FOwnedObject: IAutoDestroyObject; function GetAsOwnedObject: TObject; procedure SetAsOwnedObject(const Value: TObject); public class operator Implicit(const ov: TOmniValue): IOmniValueFwd; property AsOwnedObject: TObject read GetAsOwnedObject write SetAsOwnedObject; end; IOmniValueFwd = interface ['{4CCE0702-1CBF-4467-8185-8C38C37BA624}'] function GetAsOwnedObject: TObject; function GetValue: TOmniValue; procedure SetAsOwnedObject(const Value: TObject); property AsOwnedObject: TObject read GetAsOwnedObject write SetAsOwnedObject; property Value: TOmniValue read GetValue; end; TOmniValueFwd = class(TInterfacedObject, IOmniValueFwd) strict private FOmniValue: TOmniValue; strict protected function GetAsOwnedObject: TObject; function GetValue: TOmniValue; procedure SetAsOwnedObject(const Value: TObject); public constructor Create(const ov: TOmniValue); property AsOwnedObject: TObject read GetAsOwnedObject write SetAsOwnedObject; property Value: TOmniValue read GetValue; end; IWorkItem = interface ['{7C583FC8-90DD-46A5-81B9-81B911AA1CBE}'] function GetResult: IOmniValueFwd; procedure SetResult(const Value: IOmniValueFwd); property Result: IOmniValueFwd read GetResult write SetResult; end; I can then use: procedure Test(const workItem: IWorkItem); begin workItem.Result.AsOwnedObject := TTestObj.Create; end; or: procedure Test(const workItem: IWorkItem); var ov: TOmniValue; begin ov.AsOwnedObject := TTestObj.Create; workItem.Result := ov; end; And both work fine. full code here -
Is [weak] available in win32/win64
Cristian Peța replied to pyscripter's topic in RTL and Delphi Object Pascal
Yes, for interfaces, like article says. What help are you reading? Maybe it was not revised. -
High-level abstractions - Difficulties in choosing and using appropriate strategies for solving my task.
Primož Gabrijelčič replied to Shrinavat's topic in OmniThreadLibrary
You have: Renderer := Parallel.ParallelTask.NumTasks(numTasks).NoWait .Execute( procedure begin workItem := RenderQueue.Next; ... end); and then: for iTask := 0 to numTasks-1 do begin TileSource := workItem.Data['TileSource' + iTask.ToString]; RenderQueue.Add(TOmniValue.Create([iTask, TileSource])); end; If you change only the parameter to `ParallelTask.NumTasks`, some tasks won't ever get data because you'll schedule only `numTasks` items to `RenderQueue`. -
High-level abstractions - Difficulties in choosing and using appropriate strategies for solving my task.
Primož Gabrijelčič replied to Shrinavat's topic in OmniThreadLibrary
`workItem.Result` is a record property. Because of that, this code: workItem.Result.AsOwnedObject := TBitmap32.Create(256,256); is equivalent to running: var tmp: TOmniValue; tmp := workItem.Result; tmp.AsOwnedObject := TBitmap32.Create(256,256); And that fails. You should change the code to: var tmp: TOmniValue; tmp.AsOwnedObject := TBitmap32.Create(256,256); workItem.Result := tmp; I'll see if I can change the implementation of `IOmniWorkitem` to prevent such problems. -
@Alexander Elagin Just in case you need the icons because of change indicators, you can try https://sites.google.com/site/kryvich/kryvichs-editor-status-bars. Works without IDE theming too.
-
High-level abstractions - Difficulties in choosing and using appropriate strategies for solving my task.
Primož Gabrijelčič replied to Shrinavat's topic in OmniThreadLibrary
Indeed, if you set `workItem.Result` as owned object, it gets destroyed immediately after the `Asy_Execute` exits. This is the minimal code that reproduces the problem: procedure TfrmBackgroundWorkerImageFactory.Asy_Factory(const workItem: IOmniWorkItem); begin if not workItem.CancellationToken.IsSignalled then workItem.Result.AsOwnedObject := TBitmap32.Create(256,256); end; At the moment, don't use `OwnsObject` or `AsOwnedObject` at that point. I'll dig in to see what's going on. -
Using dxgettext on Windows 10
Sue King replied to dummzeuch's topic in Tips / Blogs / Tutorials / Videos
I've asked on the Nexus forum about this, posting this call stack from the debugger. gnugettext.TGnuGettextInstance.LoadResString($676444) gnugettext.LoadResStringW($676444) nxllUtils.nxRaiseLastOSError(True,0) nxtwWinsockTransport.TnxWinsockClientConnection.DoRecv((no value),32) nxtwWinsockTransport.TnxWinsockClientConnection.Read((nxptBasePooledTransport.TnxBasePooledTransport.btMessageReceived,$7E790030)) nxptBasePooledTransport.TnxBaseCallbackThread.InnerExecute nxllThread.TnxInternalInitThread.DoExecute nxllThread.TnxThread.Execute nxptBasePooledTransport.TnxBaseCallbackThread.Execute :0047a030 ThreadProc + $4C :00409e7e ThreadWrapper + $2A :76d1fe09 KERNEL32.BaseThreadInitThunk + 0x19 :77d0662d ntdll.RtlGetAppContainerNamedObjectPath + 0xed :77d065fd ntdll.RtlGetAppContainerNamedObjectPath + 0xbd This sequence is repeated for each time through the endless loop. The translated text first time through is '[unknown]'. If I don't actually The suggestion was that maybe there is something in LoadResString that causes issues when called in the context of a different thread. The Nexus code I'm trying to use has multiple threads involved so maybe there is a race condition somewhere. -
Using dxgettext on Windows 10
Sue King replied to dummzeuch's topic in Tips / Blogs / Tutorials / Videos
I've spent some hours in the debugger trying to see what is going on. Unfortunately the Nexus code is multi-threaded and it makes it hard to follow what is going on. Before I go back to them, I've played around with the code inTGnuGettextInstance.dgettext. It seems as though calling utf8encode, and then utf8decode can trigger the looping, but it may be that something is happening that I don't understand. That is, changing to code to add var lResult: UnicodeString; lUTF8String: UTF8String; begin ... end else begin lUTF8String := utf8encode(szMsgId); lResult := UTF8Decode(lUTF8String); Result := szMsgId; ... causes the loops. While running, if I jump over the utf8decode in the debugger (4 times), it then completes. If utf8decode is not called it works fine. I noticed that while it is looping, the message is [unknown]. When I skip the utf8decode with the debugger, it shows [Operation aborted] the first 2 times through, and then '[unknown]' the next 2 times, and then doesn't need to call it again as it has completed whatever it is doing successfully. If this doesn't give you any clues, then I'll talk to Nexus. I wanted to do all I could before raising it with them. At the moment, I've think I reached the end of my knowledge with trying to debug this. The call stack in the debugger doesn't appear helpful. Thanks for looking at this.