Jump to content


Popular Content

Showing content with the highest reputation since 03/13/19 in all areas

  1. ByteJuggler

    Creating a "pull request" for jvcl

    Guys, while pulling updates from a remote repo is part of git (e.g. git pull from the command line for example), a "pull request" is not something intrinsically part of git, but something that github institutes, or that we agree between ourselves as developers. It literally is saying to someone else "Please {git} pull from me as I've got something you might want to review/use." It follows that in order for someone else to "pull" changes from you, that you must have some accessible place for them to pull from. Obviously users on the internet won't have access to your local repo on your developer PC, so they cannot pull from there. Nor would you normally be able to push to their repo (or their github repo) if that is where you originally pulled from (unless you're one of the project administrators/owners of course.) There therefore needs to some other repo, that must belong to you and is accessible so that someone else can pull from, that you can also first push to. (Just like there needs to be a shared SVN server, say, if you want another dev to get some changes you've made and are using subversion.) And this is where github comes in. It provides an easy to access place where you can fork and create your own remote repositories (from others) that are therefore just as easily accessible by others too. All that background is to help you understand the following: The normal process for working on github, if you want to contribute changes, is to 1.) Fork the repo of the project you want to contribute to in your github account. This creates a cheap remote repo (think "my own SVN server at github" if that helps) that belongs to you, than you can push to. 2.) Clone this fork (your own copy of this github repo) to your local PC. 3.) Do your work, commit locally. Once totally happy, git push, which obviously goes to your own remote repo (from the fork.) 4.) Now you're a few revisions ahead of the original repo, and you can then tell the original upstream repo maintainers that you'd like them to pull from your repo as you've got changes to fix some issue or whatever. In github, you do this by simply clicking "New Pull request" button in github. Hope that helps! Edit: By the by, if you've previously pulled from someone else's project directly, made some changes and now want to push this somewhere else, it's quite easy to fork the project "after the fact" and then tell git/update that "remote"/"upstream" is now else, to e.g "push" to your fork instead. (It's also possible to have multiple remotes if you want, but I digress...)
  2. Remy Lebeau

    Check for override

    To expand on Anders' comment - the TStream.Seek() method has two overloads, one for 32-bit seeks and one for 64-bit seeks. By default, the 32-bit Seek() calls the 64-bit Seek() and vice versa. Descendants must override one of the Seek() methods and the override must not call the inherited method. To avoid an endless recursive loop, the 32-bit Seek() validates that the 64-bit Seek() method has been overridden before calling it. This is the technique that it uses for that validation: procedure TAncestor.Do(); type TMethodXType = procedure of object; // must match the signature of MethodX... var Impl: TMethodXType; Base: TMethodXType; ClassTAncestor: TClass; begin Impl := MethodX; // points to descendant's implementation of MethodX... ClassTAncestor := Self.ClassType; // get object's actual class type... while (ClassTAncestor <> nil) and (ClassTAncestor <> TAncestor) do // find the TAncestor base class... ClassTAncestor := ClassTAncestor.ClassParent; Base := TAncestor(@ClassTAncestor).MethodX; // points to TAncestor's implementation of MethodX... if TMethod(Impl).Code = TMethod(Base).Code then // which MethodX implementation is the object actually using? begin // MethodX is NOT overriden... end else begin // MethodX IS overriden... end; end;
  3. There are a few things that every single one of our internal programs should do: Every dialog should be sizeable if it makes any sense at all. Delphi makes that easy with the Align and Anchor properties. Ask yourself the following questions. If you answer any of them with Yes, ... https://blog.dummzeuch.de/2019/04/03/things-that-every-desktop-program-should-do/
  4. It always depends on particular situation. Both composition and inheritance have their place. Sometimes you can use either, sometimes there is a clear distinction. Some tips that can help you decide. IS-A - inheritance - Sword IS-A Weapon so Sword should inherit Weapon HAS-A - composition or aggregation - Unit HAS-A Weapon so Unit can be composed with Weapon object With simple classes that satisfy IS-A condition plain inheritance will do. With more complex classes, you may want to use composition or delegate some behavior to other classes, especially if that behavior can be reused independently. Delegation - delegate behavior to another class when it is not an objects responsibility to implement behavior on its own Composition - when object is gone the composed objects are also gone - when Pizza is gone so are the ingredients Aggregation - class is used as a part of another class, but still exists outside that other class - when Unit dies Weapon still exists
  5. Bill Meyer

    SVG Magic released

    Having worked in Delphi since D1, and twice having had to deal with the issue of components without source, I would say that the value without source is essentially zero, as the risk factor is not worth any benefits in the short term. So I would suggest that the question as you ask it is simply wrong.
  6. dummzeuch

    Decorating read-only controls

    Not only IT-designers. It's designers <period>. Show me an unusable product and in 90% it will turn out that it was perfectly usable when the engineers finished. And then the designers ruined it. There used to be a credo "form follows function", but today it's "it doesn't matter whether it works, let's make it flashy." </rant>
  7. Just in time before April fools day 2019 there is the new GExperts release (it’s still 2019-03-30 so you are safe 😉 ). Please be aware that I mostly work with Delphi 2007, so this version can be regarded as tested quite well, followed by Delphi XE2. The others are only known to compile and new features are usually tested superficially with all versions. This is particularly true for Delphi 6/7 and 2005/2006. If you want to help by testing new versions before I release them, please contact me [...] https://blog.dummzeuch.de/2019/03/30/gexperts-1-3-13-experimental-twm-2019-03-30-released/
  8. There is a bit more to it than simply following a mantra - here is some more food for thought: https://www.thoughtworks.com/de/insights/blog/composition-vs-inheritance-how-choose
  9. dummzeuch

    What to do with unsupported components?

    I think you found all options. There are no others. I would Kick the person who bought this component without source. (Who was / is an idiot, nobody did that even back when Delphi 7 was new.) Suggest not updating to Delphi 10.3 but 10.2 (which will be rejected) Go with the DLL solution.
  10. jeanmilost

    SVG Magic released

    Hi developers, Have you ever encountered problems because your interface changes with high DPI but your images remains on the same size? Have you ever wanted to add incredible animations to your interface, but have been frustrated by the limited possibilities of the proposed image formats? So there is a library for you. SVG Magic brings the support of the Scalable Vector Graphics (SVG) image format to the C++ and Delphi VCL. Please visit: https://svgmagic.io/
  11. Remy Lebeau

    Read of address DEADBEE7. - Source of this raise?

    In some piece of code somewhere, a pointer was set to $DEADBEEF, most likely after the object it was pointing to had been freed, and then that same pointer was used afterwards by code running at address $0040CEEC trying to access a data member at offset -8 ($DEADBEE7) via that pointer. Magic addresses like $DEADBEEF are commonly used for debugging such mistakes. In this case, the code at address $0040CEEC is the System._UStrAsg() function, which is used to assign a UnicodeString to another UnicodeString. Offset -8 is the StrRec.refCount field in the UnicodeString data header, which makes sense as UStrAsg() does increment that field. In other words, some piece of code tried to assign a UnicodeString value to a dead UnicodeString variable. UStrAsg() was called by TFieldValue.SetValue(), so SetValue() was likely called on an invalid TFieldValue object inside of TGridSet.CopyRow(), which was called by TDeliverySet.UpdateFromDeliverySet() inside of TDeliveryGrid.RefreshByRouteList(). So, start in RefreshByRouteList() and work your way into UpdateFromDeliverySet() and try to figure out how it may be accessing an invalid TFieldValue object. The Operation System, when the invalid memory address $DEADBEE7 is accessed. Delphi's RTL catches that error from the OS, creates an EAccessViolation object for it, and then raises it.
  12. Stefan Glienke

    Check for override

    "Backwards compatibility" is the ultimate excuse to pile up garbage in your backyard ... It is used or ignored whenever convenient - moving forward also includes getting a compile error in your face but with a clear guide at hand how to solve it. If you ever inherited from a TDataSet and used one of its method that have TBookmark or TRecordBuffer arguments while writing code for different Delphi versions since 2010 or so you know what I mean. But some developers seem to rather want to save an hour when moving their code to a new version and waste hours or days later hunting down a bug. 😉
  13. David Heffernan

    Delphi compiler need to be opensourced

    Pretty bad reasoning. If it's for paid customers only, then there's no security in case Emba go bust. "Because we love Delphi more than you do." How to win friends and influence people.
  14. Dany Marmur

    Decorating read-only controls

    I so so agree with "In terms of UX, copying into clipboard should be taken into account." and the image. This used to work very good back when. Then - enters the designers. If it isn't Win10 native messing something up it's skins. DevExpress even have some skins that show a gray-box for readonly and some skins that do not and they refuse for years to do anything about it because it was "the vision of the designer". Such important functionality. If corrupt legislation and greed won't kill IT, designers will.
  15. Remy Lebeau

    Delphi Rio Android application.processMessages; dosent work

    Well, then you went down the wrong rabbit hole, and you need to start climbing your way out of it. Such as? You really need to stop using ProcessMessages(), and start using proper code designs. Even if you don't want to use timers/threads, there is always TThread.ForceQueue(), for instance. Anything that allows code flow to return to the main UI message loop naturally will be better than manually pumping the message queue artificially. Then file a bug report with Embarcadero. But don't litter your code with ProcessMessages() calls just to satisfy the framework. Find other alternatives. Stay away from ProcessMessages() whenever possible. That was true even in the old days of the VCL. More so now in the days of FMX on mobile.
  16. There is a possibility, but it would be difficult to apply that behavior on any TDateTime field to be converted, which could as well be a pretty unwanted side effect. Instead you can put an attribute to each field being treated this way. What you need here are two classes (well, one would do, but the second one simplifies things a lot). The first one is the interceptor: type TSuppressZeroDateInterceptor = class(TJSONInterceptor) public function StringConverter(Data: TObject; Field: string): string; override; procedure StringReverter(Data: TObject; Field: string; Arg: string); override; end; function TSuppressZeroDateInterceptor.StringConverter(Data: TObject; Field: string): string; var ctx: TRTTIContext; date: TDateTime; begin date := ctx.GetType(Data.ClassType).GetField(Field).GetValue(Data).AsType<TDateTime>; if date = 0 then begin result := EmptyStr; end else begin result := DateToISO8601(date, True); end; end; procedure TSuppressZeroDateInterceptor.StringReverter(Data: TObject; Field, Arg: string); var ctx: TRTTIContext; date: TDateTime; begin if Arg.IsEmpty then begin date := 0; end else begin date := ISO8601ToDate(Arg, True); end; ctx.GetType(Data.ClassType).GetField(Field).SetValue(Data, date); end; The second one is a special attribute: type SuppressZeroAttribute = class(JsonReflectAttribute) public constructor Create; end; constructor SuppressZeroAttribute.Create; begin inherited Create(ctString, rtString, TSuppressZeroDateInterceptor); end; Now you can decorate your class fields like this: type TDateClass = class private [SuppressZero] FHasDate: TDateTime; [SuppressZero] FNoDate: TDateTime; public constructor Create; property HasDate: TDateTime read FHasDate write FHasDate; property NoDate: TDateTime read FNoDate write FNoDate; end; As I mentioned earlier, you can omit the new attribute and use the JsonReflectAttribute directly, but that is a bit cumbersome: type TDateClass = class private [JsonReflect(ctString, rtString, TSuppressZeroDateInterceptor)] FHasDate: TDateTime; [JsonReflect(ctString, rtString, TSuppressZeroDateInterceptor)] FNoDate: TDateTime; public constructor Create; property HasDate: TDateTime read FHasDate write FHasDate; property NoDate: TDateTime read FNoDate write FNoDate; end;
  17. Stefan Glienke

    How to create a weak array?

    Not natively using [weak] attribute. You can only make a record with a [weak] IFoo field and put that into the array.
  18. Dalija Prasnikar

    Check for override

    YES, backward compatibility matters. But in cases where backward compatibility causes more trouble down the road, then it is not worth the price. In this case, maintaining backward compatibility also opened TStream and descendant classes to subtle bugs when working with streams larger than 2GB.
  19. jbg

    List of all uses clause items in the whole project

    You can use TListView in a virtual mode then it is as fast as a VirtualStringTree. OwnerData = True OnData = ListView1Data procedure TForm6.Button1Click(Sender: TObject); begin ListView1.Items.Count := 100000000; end; procedure TForm1.ListView1Data(Sender: TObject; Item: TListItem); begin Item.Caption := IntToStr(Item.Index); end;
  20. Original post: https://www.thedelphigeek.com/2019/02/design-patterns-with-delphi-book.html Hurrah, hurray, my third book is here! It’s called Hands-On Design Patterns with Delphi and (just like my first book) I wrote it for Packt Publishing. (The second book was self-published and I expect the fourth one to be, too.) As the name says, “Design Patterns with Delphi” deals with design patterns. It is a bit different from most of design pattern books and websites you will find on the Internet. Case in point A: There are no UML diagrams. I don‘t speak UML. Tried to learn it few times but for some reason the whole concept doesn‘t agree with me. If you like diagrams, don’t fear though. Any book on design patterns - and most websites covering that topic - will gladly show how any design pattern can be diagrammed. That, however, is not important and should not govern your decision to buy the book. More important is case in point B: This book speaks Delphi. All the examples are written in Delphi and language features are used to the full. I also covered few less known Delphi idioms in separate sections. You’ll still be able to follow the discussion even though you may program in a different Pascal dialect. There’s also case in point 😄 Examples make sense. I deeply dislike classical design pattern examples of the “And then we want to write this program for different toolkits and it should also be able to draw circles, not only squares” kind. Euch! I tried to find a good example for each design pattern. Admittedly, I ended with few examples that draw triangles and squares on screen (mostly because some patterns were designed specifically for solving such problems), but most of them are of a more practical nature. This book covers all three classical design pattern categories - Creational patterns, Structural patterns, and Behavioral patterns. It also discusses patterns from the newer Concurrency patterns category. At the end I threw in some borderline-pattern(ish) topics and ended with a discussion of few patterns that cannot be strictly classified as “design” patterns. In this book you’ll find: Chapter 1 An introduction to patterns. Exploration of design principles, design patterns, and idioms. A mention of anti-patterns. A short description of most important design principles. Delphi idioms: creating and destroying objects. Chapter 2 Creation patterns part 1. Singleton. Dependency injection. Lazy initialization. Object pool. Chapter 3 Creation patterns part 2. Factory method, Abstract factory, Prototype, Builder. Delphi idioms: Assign and AssignTo. Chapter 4 Structural patterns part 1. Composite. Flyweight. Marker interface. Bridge. Delphi idioms: comparers and hashers. Chapter 5 Structure patterns part 2. Adapter. Proxy. Decorator. Facade. Delphi idioms: replacing components in runtime. Also: helpers. Chapter 6 Behavioral patterns part 1. Null object. Template method. Command. State. Chapter 7 Behavioral patterns part 2. Iterator. Visitor. Observer. Memento. Delphi idioms: for .. in. Chapter 8 Concurrency patterns part 1. Locking. Lock striping. Double-checked locking. Optimistic locking. Readers-writers lock. Delphi idioms: tasks and threads. Also: bitwise operators. Chapter 9 Concurrency patterns part 2. Thread pool. Messaging. Future. Pipeline. Chapter 10 Writing Delphi programs. Event-driven programming. Actions. LiveBindings. Form inheritance. Frames. Data modules. Chapter 11 Wrapping it up. Exceptions. Debugging. Functional programming. I hope you will like this book and learn a lot from it. I know I did during the nine months I spent writing it. And if you find any bug in the code, let me know so I can correct it in the second release!
  21. jbg

    IDE Fix pack for Rio

    The newest development snapshot should fix this bug. http://andy.jgknet.de/fixpack/dev
  22. Interfaces don't have implementation, so if you want to reuse code you either have to use class inheritance or you must use composition. IS-A and HAS-A rule can help you determine whether inheritance makes sense in a first place. If IS-A rule is satisfied, then you have to see whether in that particular case you should use class inheritance or composition. When it comes to creating God objects, they break other OO principles. Composition is preferred - problem with that approach and your original question "Prefer composition over inheritance for code reuse?" is that people tend to interpret it like NEVER use inheritance. And then they go down the different rabbit hole.
  23. jeanmilost

    SVG Magic released

    This issue was fixed now, and a new version was released today. Once again, thank you for showing me this error.
  24. dummzeuch

    preventing my program from stealing the focus

    I ended up using the following code: constructor Tf_MyForm.Create(_Owner: TComponent); begin inherited; WindowState := wsMinimized; ShowWindow(Handle, SW_SHOWNOACTIVATE); end; So far it seems to work fine.
  25. jeroenp

    Unused local variables

    The best open source Delphi parser I know is DelphiAST. It is the foundation https://www.tmssoftware.com/site/fixinsight.asp which catches way more code issues than the Delphi compiler itself does. DelphiAST gets you an abstract syntax tree. Code is at https://github.com/RomanYankovsky/DelphiAST