{"id":208,"date":"2008-08-19T22:34:44","date_gmt":"2008-08-19T10:34:44","guid":{"rendered":"https:\/\/www.deltics.co.nz\/blog\/?p=208"},"modified":"2008-08-20T10:51:27","modified_gmt":"2008-08-19T22:51:27","slug":"when-typenames-collide","status":"publish","type":"post","link":"https:\/\/www.deltics.co.nz\/blog\/posts\/208\/","title":{"rendered":"When Type(name)s Collide"},"content":{"rendered":"<span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\">4<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span><p>It&#8217;s funny how this happens.\u00a0 I was already intending to write about the way I have exploited like-type names to my advantage, and then noticed that the same subject cropped up recently in the <a href=\"https:\/\/forums.codegear.com\/category.jspa?categoryID=12\" target=\"_blank\">re-invented Delphi forums<\/a>.\u00a0 In that instance, the issue though was a <span style=\"text-decoration: underline;\">problem<\/span>, and one that I&#8217;m sure many will be familiar with:\u00a0 <a href=\"https:\/\/forums.codegear.com\/message.jspa?messageID=3331&amp;tstart=0\" target=\"_blank\">When is a TBitmap not a TBitmap<\/a>?<\/p>\n<p>In my case, the question is: <em>When is a TForm not TForm<\/em>?<\/p>\n<p><!--more--><\/p>\n<h3>Keeping The VCL At Arms Length<\/h3>\n<p>A very large number of moons ago I was briefly involved in a <a href=\"http:\/\/en.wikipedia.org\/wiki\/PowerBuilder\" target=\"_blank\">PowerBuilder<\/a> project (anybody else remember when 4GL&#8217;s were going to save the software development industry from itself?).<\/p>\n<p>When OO reached PowerBuilder it brought with it an extensible component model &#8211; the PowerBuilder equivalent of the VCL &#8211; the PFC (<em>PowerBuilder Foundation Class<\/em> library).\u00a0 The team I was working with had learned from experience to keep the PFC at arms length.<\/p>\n<p>Objects in the application were <em><span style=\"text-decoration: underline;\">never<\/span><\/em> instances of PFC classes, but of derived classes, even if the class derived added or changed nothing in the base class.<\/p>\n<p>The reason being of course that if ever a problem was later discovered in the PFC class, or if some new behaviour or feature were desirable in the foundation classes, the additional class between the application and the PFC gave the developers an opportunity to make changes that would instantly propogate into all corners of their project, without having to modify the PFC itself, protecting themselves to an extent from changes in future versions of the PFC.<\/p>\n<p>In Delphi terms this would mean for example never using a <strong>TButton<\/strong>, but instead declaring a <strong>TMyButton<\/strong> class and always using that as the &#8220;fundamental base class&#8221; for <span style=\"text-decoration: underline;\">all<\/span> buttons (and button classes) in your projects.<\/p>\n<p>Adopting a comprehensive layer of intermediate classes to sit between an application and the VCL is obviously a huge, and largely pointless, task &#8211; the VCL is a very different beast than the PFC ever was.<\/p>\n<p>But in the case of <strong>TForm<\/strong> an intermediate class could be useful, adding capabilities to forms that are widely, if not universally, useful.<\/p>\n<p>The <strong>TBitmap<\/strong> problem identifies the mechanism to make an intermediate class instantly useful.\u00a0 The two <strong>TBitmap<\/strong> types caused problems because they were actually very different types and utterly incompatible.\u00a0 But having the same name wasn&#8217;t, itself, a problem.\u00a0 Just unfortunate.<\/p>\n<p>With a little care, we can make like-names work <em>for<\/em> us.<\/p>\n<h3>A New TForm<\/h3>\n<p>To avoid the problems that occur with <strong>TBitmap<\/strong> we need to be careful to make any new <strong>TForm<\/strong> compatible with the VCL original.\u00a0 But isn&#8217;t that exactly what OO gives us?\u00a0 (One of the things anyway).<\/p>\n<p>Consider this declaration:<\/p>\n<pre class=\"delphi\">  unit Deltics.Forms;\r\n\r\ninterface\r\n\r\n  uses\r\n    Forms;\r\n\r\n  type\r\n    TForm = class(Forms.TForm)\r\n    end;\r\n\r\nimplementation\r\n\r\nend.<\/pre>\n<p>This new <strong>TForm<\/strong> is compatible with <strong>TForm<\/strong> &#8211; it is a direct descendant.  Anywhere that a <strong><em>Forms<\/em>.TForm<\/strong> can be referenced, a <strong><em>Deltics.Forms<\/em>.TForm<\/strong> is also sure to be perfectly valid because, unlike in the case of that <strong>TBitmap<\/strong> example, it <em><span style=\"text-decoration: underline;\">is<\/span><\/em> in fact a <strong>Forms.TForm<\/strong>.<\/p>\n<p>It also happens to have exactly the same name, so any existing &#8211; or, more importantly, automatically generated &#8211; code that doesn&#8217;t know about my new form class can be made to use it simply by ensuring that the unit containing it is in scope.<\/p>\n<p>Note that I am <span style=\"text-decoration: underline;\">not<\/span> talking about visual form inheritance here.<\/p>\n<h3>Now We Have It, What To Do With It?<\/h3>\n<p>Before going too far, let us first see how we incorporate this new <strong>TForm<\/strong> into our applications by looking at the boiler-plate code generated by the IDE when we create a new form in our projects:<\/p>\n<pre class=\"delphi\">  unit Unit1;\r\n\r\ninterface\r\n\r\nuses\r\n  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,\r\n  Dialogs;\r\n\r\ntype\r\n  TForm1 = class(TForm)\r\n    procedure FormCreate(Sender: TObject);\r\n  private\r\n    { Private declarations }\r\n  public\r\n    { Public declarations }\r\n  end;<\/pre>\n<p>All we need to do is add the <strong>Deltics.Forms<\/strong> unit to the <strong>uses<\/strong> list in such a way that the <strong>TForm<\/strong> in that unit &#8220;hides&#8221; the <strong>TForm<\/strong> in the <strong>Forms<\/strong> unit.\u00a0 This means adding it <em>after<\/em> the <strong>Forms<\/strong> unit:<\/p>\n<pre class=\"delphi\">uses\r\n  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,\r\n  Dialogs,\r\n  Deltics.Forms;<\/pre>\n<p>That&#8217;s it.\u00a0 (We could of course just replace <strong>Forms<\/strong> with <strong>Deltics.Forms<\/strong> but there are other things in the <strong>Forms<\/strong> unit that we will likely want to refer to).<\/p>\n<p>Either way, the <strong>TForm<\/strong> that the <strong>TForm1<\/strong> class derives from is now <strong><em>Deltics.Forms.<\/em>TForm<\/strong>.<\/p>\n<p>Still, this doesn&#8217;t achieve very much other than to play a harmless little prank on the VCL.\u00a0 But what it does is provide us with an opportunity &#8211; we can now introduce things into <strong>TForm<\/strong>, or make changes using normal OO techniques.<\/p>\n<p>For now let&#8217;s just add a fairly trivial new feature &#8211; a property that we can manipulate at runtime to provide our forms with a <a href=\"https:\/\/www.deltics.co.nz\/blog\/?p=193\" target=\"_blank\">size grip<\/a> if we wish (design-time properties are a whole different ball game when it comes to forms).<\/p>\n<p>Again, this is so trivial a download is a bit much, so here&#8217;s the entire unit:<\/p>\n<pre class=\"delphi\">  unit Deltics.Forms;\r\n\r\ninterface\r\n\r\n  uses\r\n    Forms,\r\n    Deltics.Controls.SizeGrip;\r\n\r\n  type\r\n    TForm = class(Forms.TForm)\r\n    private\r\n      fHasSizeGrip: Boolean;\r\n      fSizeGrip: TSizeGrip;\r\n      procedure set_HasSizeGrip(const aValue: Boolean);\r\n      procedure CreateSizeGrip;\r\n    protected\r\n      procedure CreateWnd; override;\r\n      procedure DestroyWnd; override;\r\n    public\r\n      property HasSizeGrip: Boolean read fHasSizeGrip write set_HasSizeGrip;\r\n    end;\r\n\r\nimplementation\r\n\r\n  uses\r\n    SysUtils;\r\n\r\n  procedure TForm.CreateSizeGrip;\r\n  begin\r\n    if NOT HandleAllocated then\r\n      EXIT;\r\n\r\n    fSizeGrip := TSizeGrip.Create(self);\r\n    fSizeGrip.Parent := self;\r\n  end;\r\n\r\n  procedure TForm.CreateWnd;\r\n  begin\r\n    inherited;\r\n    if HasSizeGrip then CreateSizeGrip;\r\n  end;\r\n\r\n  procedure TForm.DestroyWnd;\r\n  begin\r\n    FreeAndNIL(fSizeGrip);\r\n    inherited;\r\n  end;\r\n\r\n  procedure TForm.set_HasSizeGrip(const aValue: Boolean);\r\n  begin\r\n    if (fHasSizeGrip = aValue) then\r\n      EXIT;\r\n\r\n    fHasSizeGrip := aValue;\r\n\r\n    if HasSizeGrip then CreateSizeGrip else FreeAndNIL(fSizeGrip);\r\n  end;\r\n\r\nend.<\/pre>\n<h3>Just The Tip of The TIceBerg<\/h3>\n<p>The <strong>Deltics.Forms<\/strong> unit actually started out with a different purpose and incorporates much more than a few trivial additions to <strong>TForm<\/strong>.<\/p>\n<p>The <strong>Application<\/strong> object gets some attention, and <strong>TForm<\/strong> gets a significant further work-out, a lot of it in the name of <a href=\"http:\/\/www.installationexcellence.com\/articles\/VistaWithDelphi\/Original\/Index.html#Wheres_My_Induction\" target=\"_blank\">Creating Windows Vista Ready applications<\/a>.\u00a0 Since the Vista readiness changes hinge on the <strong>Application<\/strong> object, I shall look at how I achieved that next.<\/p>\n","protected":false},"excerpt":{"rendered":"<p><span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\">4<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span> It&#8217;s funny how this happens.\u00a0 I was already intending to write about the way I have exploited like-type names to my advantage, and then noticed that the same subject cropped up recently in the re-invented Delphi forums.\u00a0 In that instance, the issue though was a problem, and one that I&#8217;m sure many will be familiar [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":[]},"categories":[4],"tags":[292,42,41,40,43],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1TKYv-3m","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":244,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/244\/","url_meta":{"origin":208,"position":0},"title":"Generic Methods and Type Inferencing","date":"25 Aug 2008","format":false,"excerpt":"In the new Delphi forums recently, Barry Kelly responded to a question about lambda expression syntax in Tibur\u00f3n with this observation: This syntax needs type inference. Our compiler was not originally written to support type inference, but work to support type inference is orthogonal to supporting anonymous methods. ...\u00a0 you'll\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":222,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/222\/","url_meta":{"origin":208,"position":1},"title":"More Deltics.Forms Magic","date":"24 Aug 2008","format":false,"excerpt":"Last time I introduced a bit of skullduggery with my Deltics.Forms unit as a way to easily \"inject\" a new TForm class into my projects.\u00a0 We used this new class to add public property that we could use to add a size grip control to any form. This time we\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":295,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/295\/","url_meta":{"origin":208,"position":2},"title":"Making A Splash","date":"04 Sep 2008","format":false,"excerpt":"OK, so who hasn't done this a million times - adding a splash screen to a Delphi application.\u00a0 I've seen any number of \"easy\" ways to do this but during a session at Tech Ed '08 this week I saw the latest in splash screen technology from Microsoft:\u00a0 A SplashScreen\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":193,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/193\/","url_meta":{"origin":208,"position":3},"title":"Resizing a Non-Resizable Form","date":"17 Aug 2008","format":false,"excerpt":"One control that I have not seen in the line-up of new controls in the VCL for Tibur\u00f3n is a size grip. Most people may not even realise that this control exists, even though it is part of Windows itself and is really quite useful.\u00a0 Fortunately, implementing it ourselves is\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1938,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1938\/","url_meta":{"origin":208,"position":4},"title":"Menu Items, APIs, Crackers and Hackers","date":"16 Oct 2013","format":false,"excerpt":"Francois Piette recently posted a solution to obtaining the screen position of a menu item involving using a \"hacker\" class. There is however a safer, more direct mechanism which I hope Francois won't mind me sharing and a far less safe related hacking technique that his post brought to mind.\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1593,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1593\/","url_meta":{"origin":208,"position":5},"title":"Learning Valuable Lessons","date":"14 Sep 2013","format":false,"excerpt":"Iztok has been at it again, making comments that prompt another post. :) He expresses his view that there are only two viable options for mobile development. The first is essentially the web-based technology approach (HTML\/JS\/PhoneGap etc) and the other is the platform native tool chains, Eclipse\/AndroidStudio\/Xcode etc. He may\u2026","rel":"","context":"In &quot;Android&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/208"}],"collection":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/comments?post=208"}],"version-history":[{"count":5,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/208\/revisions"}],"predecessor-version":[{"id":213,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/208\/revisions\/213"}],"wp:attachment":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/media?parent=208"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/categories?post=208"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/tags?post=208"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}