<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Art of Delphi Programming &#187; Delphi</title>
	<atom:link href="http://www.uweraabe.de/Blog/category/delphi/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.uweraabe.de/Blog</link>
	<description>Opinions, thoughts and ideas mostly related to Delphi Programming</description>
	<lastBuildDate>Sun, 24 Mar 2013 18:05:29 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>When, What, Why!</title>
		<link>http://www.uweraabe.de/Blog/2013/03/24/when-what-why/</link>
		<comments>http://www.uweraabe.de/Blog/2013/03/24/when-what-why/#comments</comments>
		<pubDate>Sun, 24 Mar 2013 18:05:29 +0000</pubDate>
		<dc:creator>Uwe Raabe</dc:creator>
				<category><![CDATA[Delphi]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.uweraabe.de/Blog/?p=279</guid>
		<description><![CDATA[A common pattern seen in Delphi code is the &#8220;code inside an event handler&#8221; syndrome. Lines and lines of code are placed inside an event handler. Not enough, these event handlers are often called directly from other places in the &#8230; <a href="http://www.uweraabe.de/Blog/2013/03/24/when-what-why/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>A common pattern seen in Delphi code is the &#8220;code inside an event handler&#8221; syndrome. Lines and lines of code are placed inside an event handler. Not enough, these event handlers are often called directly from other places in the code &#8211; just because the code inside it needs to be executed. Take that as a big sign of code smell!</p>
<p>You know what? The event handler is not the right place for that code.</p>
<p><a href="http://docwiki.embarcadero.com/RADStudio/XE3/en/Extract_Method">Extract</a> it into a separate method &#8211; or probably more of them. Name those methods so that the name describes what the code executed is supposed to do. (It is probably not doing that, but that is a case for debugging.)</p>
<p>You can give some extended description in a comment to the method. If you have <a href="http://www.devjetsoftware.com/products/documentation-insight/">Document Insight</a> (you should have the Express version with any recent Delphi), use it to display this comment wherever you hover the mouse over that method name.</p>
<p>Place the method calls into the event handlers. May be, you can write a little comment that explains why you are calling these methods. Don&#8217;t reword the method names here.</p>
<p><strong>Remember:</strong> The event handler names tell you <em>when</em> that code is executed, the method names tell you <em>what</em> is executed and the comments tell you <em>why</em> it is executed.</p>
<p>BTW: Don&#8217;t try to be clever and rename the event handler so that its name resembles the <em>what</em>. You will have a hard time to find out the <em>when!</em> It would only be stored in the event wiring of the DFM and needs the Object Inspector to see it. It only makes the code harder to read. Keep the event handler names as given when possible. In case it is wired to multiple events, name it according to its usage (like <em>DataSetsAfterPost</em>), not its purpose.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.uweraabe.de/Blog/2013/03/24/when-what-why/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>18 Years of Delphi Programming</title>
		<link>http://www.uweraabe.de/Blog/2013/02/15/18-years-of-delphi-programming/</link>
		<comments>http://www.uweraabe.de/Blog/2013/02/15/18-years-of-delphi-programming/#comments</comments>
		<pubDate>Thu, 14 Feb 2013 23:29:45 +0000</pubDate>
		<dc:creator>Uwe Raabe</dc:creator>
				<category><![CDATA[Delphi]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.uweraabe.de/Blog/?p=276</guid>
		<description><![CDATA[Some weeks after I got my Delphi 1 I had some contract work for a CAD/CAM system at a company located in my home town. After discussing a specific problem with their chief programmer (he was on C++) for the &#8230; <a href="http://www.uweraabe.de/Blog/2013/02/15/18-years-of-delphi-programming/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Some weeks after I got my Delphi 1 I had some contract work for a CAD/CAM system at a company located in my home town. After discussing a specific problem with their chief programmer (he was on C++) for the whole morning I was not able to convince him that my proposed solution will work.</p>
<p>During lunch break I went home, started Delphi and just wrote a prototype for proof. When I came back only about an hour after I left and showed him the working sample, he couldn&#8217;t believe it &#8211; always trying to find out how I did manage to cheat.</p>
<p>A few months later he quit&#8230;</p>
<p>Happy Birthday Delphi!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.uweraabe.de/Blog/2013/02/15/18-years-of-delphi-programming/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Do you know Build Groups?</title>
		<link>http://www.uweraabe.de/Blog/2013/01/07/do-you-know-build-groups/</link>
		<comments>http://www.uweraabe.de/Blog/2013/01/07/do-you-know-build-groups/#comments</comments>
		<pubDate>Mon, 07 Jan 2013 09:33:16 +0000</pubDate>
		<dc:creator>Uwe Raabe</dc:creator>
				<category><![CDATA[Delphi]]></category>

		<guid isPermaLink="false">http://www.uweraabe.de/Blog/?p=211</guid>
		<description><![CDATA[Can you make a build in one step? (It is #2 in The Joel Test, but that is not a main topic of this article.) If you can, you have probably set up a clean build system for doing daily &#8230; <a href="http://www.uweraabe.de/Blog/2013/01/07/do-you-know-build-groups/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Can you make a build in one step? (It is #2 in <a title="The Joel Test" href="http://www.joelonsoftware.com/articles/fog0000000043.html" target="_blank">The Joel Test</a>, but that is not a main topic of this article.) If you can, you have probably set up a clean build system for doing daily builds (#3 of The Joel Test) or even continuous builds based on a source control system (#1 of The Joel Test) and some of the many really useful tools available. The build system (hopefully) takes care to make sure that your sources are at least compilable for the different platforms and different build configurations as they are available in more recent Delphi versions.</p>
<p>You also do <a title="Smoke Testing" href="http://en.wikipedia.org/wiki/Smoke_testing#Software_development" target="_blank">Smoke Testing</a> before you check in, don&#8217;t you? There is no reason to break the build just for being lazy. But here things may become somewhat complicated, at least when you are developing for different platforms and some of the target platforms are currently not available in your working environment. But the least thing you can do before checking in is to make sure it will compile &#8211; for all platforms and all build configurations and whatever combination of those is feasible!</p>
<p><a href="http://www.uweraabe.de/Blog/2013/01/07/do-you-know-build-groups/nerd/" rel="attachment wp-att-255"><img class="wp-image-255 alignright" alt="Nerd" src="http://www.uweraabe.de/Blog/wp-content/uploads/2013/01/Nerd.png" width="358" height="355" /></a></p>
<p>The Delphi IDE actually provides the necessary buttons to change the platform and build configuration for all projects in the current project group with only a few mouse clicks, but even that might sum up to plenty of clicks and actions, which is as tedious as it is error prone. Here <em>Build Groups</em> come to the rescue.</p>
<p>Build Groups are a lesser known part of the Project Manager. They are useful to compile, build or clean selected projects of a project group  for different platforms and build configurations in one step.</p>
<p>To make use of them you have to click on<img class="alignnone" title="Show Build Groups Pane" alt="ShowBuildGroups.bmp" src="http://docwiki.embarcadero.com/images/RADStudio/XE3/e/thumb/1/12/ShowBuildGroups.bmp/29px-ShowBuildGroups.bmp.png" width="29" height="26" /> Show Build Groups Pane inside the Project Manager. This will attach a new window inside the Project Manager where you can manage your build groups.</p>
<p><a href="http://www.uweraabe.de/Blog/2013/01/07/do-you-know-build-groups/buildgroupspane1/" rel="attachment wp-att-252"><img class="alignnone" alt="BuildGroupsPane1" src="http://www.uweraabe.de/Blog/wp-content/uploads/2013/01/BuildGroupsPane1.png" width="461" height="437" /></a><a href="http://www.uweraabe.de/Blog/2013/01/07/do-you-know-build-groups/buildgroupspane1/" rel="attachment wp-att-252"><br />
</a></p>
<p>For illustrations I am using the DataSnapDemos sample from Delphi here, but this should work with every project group.</p>
<p>First thing to do is create a new build group. Click the appropriate button <img alt="CreateBuildGroup.bmp" src="http://docwiki.embarcadero.com/images/RADStudio/XE3/d/thumb/e/e0/CreateBuildGroup.bmp/23px-CreateBuildGroup.bmp.png" />, enter a decent name and you end up with a list of all available projects from the current project group. By default each project comes with its current build configuration and platform.</p>
<p><a href="http://www.uweraabe.de/Blog/2013/01/07/do-you-know-build-groups/buildgroupspane2/" rel="attachment wp-att-259"><img class="alignnone size-full wp-image-259" alt="BuildGroupsPane2" src="http://www.uweraabe.de/Blog/wp-content/uploads/2013/01/BuildGroupsPane2.png" width="452" height="146" /></a><br />
<a href="http://www.uweraabe.de/Blog/2013/01/07/do-you-know-build-groups/selectconfigurations/" rel="attachment wp-att-260"><img class="alignright" alt="SelectConfigurations" src="http://www.uweraabe.de/Blog/wp-content/uploads/2013/01/SelectConfigurations.png" width="318" height="256" /></a></p>
<p>Now click into the Configurations column of the DelphiDataSnapServer project. A second click will switch to edit mode which unveils an ellipsis button. Click it. From the configurations available for this project select the ones that should go into this build group.</p>
<p>Do the same for the Platforms column. You are prompted with a list of all platforms for the selected project.<a href="http://www.uweraabe.de/Blog/2013/01/07/do-you-know-build-groups/selectplatforms/" rel="attachment wp-att-261"><img class="size-full wp-image-261 alignleft" alt="SelectPlatforms" src="http://www.uweraabe.de/Blog/wp-content/uploads/2013/01/SelectPlatforms.png" width="255" height="201" /></a></p>
<p>After selecting the required configurations and platforms for each project in the group, you can compile, build or clean the whole pack with only one click. Very handy to make sure your changes actually compile when you are working with lots of {$IFDEF Debug}.</p>
<p>&nbsp;</p>
<p>Oh, btw: You can have multiple build groups for different purposes or to target only part of the projects. Just select the projects you need.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.uweraabe.de/Blog/2013/01/07/do-you-know-build-groups/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>DataSnap in the Cloud</title>
		<link>http://www.uweraabe.de/Blog/2012/09/24/datasnap-in-the-cloud/</link>
		<comments>http://www.uweraabe.de/Blog/2012/09/24/datasnap-in-the-cloud/#comments</comments>
		<pubDate>Mon, 24 Sep 2012 09:22:46 +0000</pubDate>
		<dc:creator>Uwe Raabe</dc:creator>
				<category><![CDATA[Delphi]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.uweraabe.de/Blog/?p=219</guid>
		<description><![CDATA[Last weekend I spoke at the Delphi Tage in Heidelberg about DataSnap In The Cloud and I promised to provide the referenced data for download. So here it is: DataSnap in the Cloud (PDF) The slides from the presentation. I omitted &#8230; <a href="http://www.uweraabe.de/Blog/2012/09/24/datasnap-in-the-cloud/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Last weekend I spoke at the Delphi Tage in Heidelberg about <strong>DataSnap In The Cloud</strong> and I promised to provide the referenced data for download. So here it is:</p>
<p><a href="http://www.uweraabe.de/Blog/2012/09/24/datasnap-in-the-cloud/datasnap-in-the-cloud-pdf/" rel="attachment wp-att-222">DataSnap in the Cloud (PDF)</a></p>
<p style="padding-left: 30px;">The slides from the presentation. I omitted those slides serving transition effects only.</p>
<p><a href="http://www.uweraabe.de/Blog/2012/09/24/datasnap-in-the-cloud/fishfacts-projekt/" rel="attachment wp-att-223">FishFacts (Project)</a></p>
<p style="padding-left: 30px;">The modified FishFacts project. The console application project is called <em>FishFactsServer</em>.  It contains the changes to make it work with SQL Database in Azure as well as the patched Data.DBXMSSQLMetaDataReader.pas (XE2) to make it work with SQL (Azure) Database.</p>
<p><a href="http://www.uweraabe.de/Blog/2012/09/24/datasnap-in-the-cloud/azure-cloud-service/" rel="attachment wp-att-224">Azure Cloud Service</a></p>
<p style="padding-left: 30px;">The Azure Cloud Services Project. You have to copy the FishFactsServer.exe into the WorkerRole folder after compilation and before making the package.</p>
<p><a href="http://www.uweraabe.de/Blog/2012/09/24/datasnap-in-the-cloud/dbdemos-sql-script/" rel="attachment wp-att-225">DbDemos SQL Script</a></p>
<p style="padding-left: 30px;">SQL Script for DbDemos Database. Executing this script in SQL Managment Studio will create and populate the complete dbdemos database in a format suitable for SQL (Azure) Database.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.uweraabe.de/Blog/2012/09/24/datasnap-in-the-cloud/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Connecting to SQL Azure with dbExpress</title>
		<link>http://www.uweraabe.de/Blog/2012/04/03/connecting-to-sql-azure-with-dbexpress/</link>
		<comments>http://www.uweraabe.de/Blog/2012/04/03/connecting-to-sql-azure-with-dbexpress/#comments</comments>
		<pubDate>Tue, 03 Apr 2012 12:18:42 +0000</pubDate>
		<dc:creator>Uwe Raabe</dc:creator>
				<category><![CDATA[Delphi]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.uweraabe.de/Blog/?p=203</guid>
		<description><![CDATA[Did you notice that there is a free trial of SQL Azure? Well, I stepped into it &#8211; just to gain experience. As the database behind SQL Azure is just SQL Server 2008 R2, there should be a possibility to &#8230; <a href="http://www.uweraabe.de/Blog/2012/04/03/connecting-to-sql-azure-with-dbexpress/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Did you notice that there is a free <a title="SQL Azure Free Trial" href="https://www.windowsazure.com/en-us/pricing/free-trial/?vwo=maincta" target="_blank">trial</a> of SQL Azure? Well, I stepped into it &#8211; just to gain experience.<span id="more-203"></span></p>
<p>As the database behind SQL Azure is just SQL Server 2008 R2, there should be a possibility to access that thing with the dbExpress driver for MSSQL that ships with Delphi Enterprise, Ultimate and Architect.</p>
<p>What should I say, the first attempt just failed!</p>
<p>Although I have been aware that SQL Azure won&#8217;t work with Windows Authentication, simply changing the host name and giving the user credentials didn&#8217;t work out of the box.</p>
<p>Googling didn&#8217;t reveal much, but a <a href="http://www.da-soft.com/blogs/delphi-sql-azure-support.html" target="_blank">post</a> from da-soft pushed me into the right direction:</p>
<blockquote>
<ul>
<li>
<div>You have to use &#8220;<strong>tcp:</strong>&#8221; prefix in Server parameter. This is because only TCP/IP protocol is supported by SQL Azure.</div>
</li>
<li>You have to use &#8220;<strong>@server</strong>&#8221; suffix in User_Name parameter. This is probably because the farm has a lot of users from other SQL Azure accounts.</li>
</ul>
</blockquote>
<p>A sample host name looks like: <em>tcp:a1b2c3d4e5.database.windows.net</em> where <em>a1b2c3d4e5</em> is your Azure host.</p>
<p>The corresponding user name should then look like: <em>&lt;user&gt;@a1b2c3d4e5</em></p>
<p>Don&#8217;t forget to disable OSAuthentication!</p>
<p>Worth to mention that despite stated otherwise in the blog post, it is indeed possible to use plain dbExpress with SQL Azure.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.uweraabe.de/Blog/2012/04/03/connecting-to-sql-azure-with-dbexpress/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A DUnit Folder Iterator Extension</title>
		<link>http://www.uweraabe.de/Blog/2012/03/17/a-dunit-folder-iterator-extension/</link>
		<comments>http://www.uweraabe.de/Blog/2012/03/17/a-dunit-folder-iterator-extension/#comments</comments>
		<pubDate>Sat, 17 Mar 2012 15:51:03 +0000</pubDate>
		<dc:creator>Uwe Raabe</dc:creator>
				<category><![CDATA[Delphi]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.uweraabe.de/Blog/?p=195</guid>
		<description><![CDATA[You have unit tests, don&#8217;t you? Or at least you run some tests to make sure your recent changes broke something? These regression tests are vital to any serious software development. What would your customers say when they get a &#8230; <a href="http://www.uweraabe.de/Blog/2012/03/17/a-dunit-folder-iterator-extension/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>You have unit tests, don&#8217;t you? Or at least you run some tests to make sure your recent changes broke something?</p>
<p>These regression tests are vital to any serious software development. What would your customers say when they get a new version breaking their day to day work? Well, at least I can&#8217;t afford that &#8211; and be it just that I&#8217;m not keen to fix those problems at a customer under high pressure. So I have regression tests.<span id="more-195"></span></p>
<p>Writing those tests for a long standing program can be quite time consuming, but you have to start somewhere. In this case it came out that my application takes an input file and produces an output file from that. So I asked my customers to send me plenty of their input files. The amount of files I got was &#8211; well, let&#8217;s say unexpected.</p>
<p>I took each file and produced the corresponding output file as a reference. The regression tests also take each input file, produce the output file and compares it with the reference file. If anything is different the test fails and I have to take a look why it fails. Sometimes the fail is intended and I have to update the reference file.</p>
<p>The big challenge was to write the unit tests for all these input files (&gt; 1000). My first attempt was to put a loop into a test case that iterates over all files. That worked but had a major drawback: when one file failed, the complete test failed at that file and the remaining files were not checked at all.</p>
<p>Writing one test case for each file looked far less comfortable, so I wrote a little extension to DUnit that dynamically creates test cases for each file found in a given folder.</p>
<p>The extension introduces two new classes: <em>TFileTestCase</em> derived from <em>TTestCase</em> and <em>TFolderTestSuite</em> derived from <em>TTestSuite</em>.</p>
<p>To make use of these you derive a test case from <em>TFileTestCase</em> and implement any test methods as published just as you do for a normal test case. The current file for the test case can be taken from the new property <em>TestFileName.</em></p>
<p>The critical part is to override the class method <em>Suite</em>, which returns an ITestSuite interface. Here you create an instance of TFolderTestSuite with some appropriate parameters. The required first parameter for TestClass can simply be given with <em>self</em>, which in a class method gives the current class type.</p>
<p>Here is the code for the extension unit:</p>
<p></p><pre class="crayon-plain-tag">unit TestFrameworkExt;

interface

uses
  TestFramework;

type
  TFileTestCaseClass = class of TFileTestCase;
  TFileTestCase = class(TTestCase)
  private
    FTestFileName: string;
  public
    constructor Create(const AMethodName, ATestFileName: string); reintroduce; overload; virtual;
    function GetName: string; override;
    property TestFileName: string read FTestFileName;
  end;

  TFolderTestSuite = class(TTestSuite)
  private
    FBaseFolder: string;
    FFileMask: string;
    FRecursive: Boolean;
  protected
    procedure AddMethodTests(TestClass: TTestCaseClass; const NameOfMethod: string); overload; virtual;
    procedure ProcessFile(Suite: ITestSuite; TestClass: TFileTestCaseClass; const NameOfMethod, FileName: string); virtual;
    procedure ProcessFolder(Suite: ITestSuite; TestClass: TFileTestCaseClass; const NameOfMethod, Path, FileMask: string;
        Recursive: Boolean); overload; virtual;
    procedure ProcessBaseFolder(Suite: ITestSuite; TestClass: TFileTestCaseClass; const NameOfMethod: string); virtual;
  public
    constructor Create(TestClass: TFileTestCaseClass; const ABaseFolder, AFileMask: string; ARecursive: Boolean); overload;
    procedure AddTests(testClass: TTestCaseClass); override;
    property BaseFolder: string read FBaseFolder;
    property FileMask: string read FFileMask;
    property Recursive: Boolean read FRecursive;
  end;

implementation

uses
  Types, IOUtils;

constructor TFolderTestSuite.Create(TestClass: TFileTestCaseClass; const ABaseFolder, AFileMask: string; ARecursive:
    Boolean);
begin
  FBaseFolder := ABaseFolder;
  FFileMask := AFileMask;
  FRecursive := ARecursive;
  inherited Create(TestClass);
end;

procedure TFolderTestSuite.AddMethodTests(TestClass: TTestCaseClass; const NameOfMethod: string);
var
  suite: ITestSuite;
begin
  if TestClass.InheritsFrom(TFileTestCase) then begin
    suite := TTestSuite.Create(NameOfMethod);
    AddSuite(suite);
    ProcessBaseFolder(suite, TFileTestCaseClass(TestClass), NameOfMethod);
  end
  else begin
    AddTest(TestClass.Create(NameOfMethod));
  end;
end;

procedure TFolderTestSuite.AddTests(testClass: TTestCaseClass);
var
  MethodIter     :  Integer;
  NameOfMethod   :  string;
  MethodEnumerator:  TMethodEnumerator;
begin
  { call on the method enumerator to get the names of the test
    cases in the testClass }
  MethodEnumerator := nil;
  try
    MethodEnumerator := TMethodEnumerator.Create(testClass);
    { make sure we add each test case  to the list of tests }
    for MethodIter := 0 to MethodEnumerator.Methodcount-1 do begin
      NameOfMethod := MethodEnumerator.nameOfMethod[MethodIter];
      AddMethodTests(testClass, NameOfMethod);
    end;
  finally
    MethodEnumerator.free;
  end;
end;

procedure TFolderTestSuite.ProcessBaseFolder(Suite: ITestSuite; TestClass: TFileTestCaseClass; const NameOfMethod:
    string);
begin
  ProcessFolder(Suite, TestClass, NameOfMethod, BaseFolder, FileMask, Recursive);
end;

procedure TFolderTestSuite.ProcessFile(Suite: ITestSuite; TestClass: TFileTestCaseClass; const NameOfMethod, FileName:
    string);
begin
  suite.AddTest(TestClass.Create(NameOfMethod, FileName));
end;

procedure TFolderTestSuite.ProcessFolder(Suite: ITestSuite; TestClass: TFileTestCaseClass; const NameOfMethod, Path,
    FileMask: string; Recursive: Boolean);
var
  list: TStringDynArray;
  S: string;
  tmp: ITestSuite;
begin
  list := TDirectory.GetFiles(Path, FileMask);
  for S in list do
    ProcessFile(suite, TestClass, NameOfMethod, S);
  if Recursive then begin
    list := TDirectory.GetDirectories(path);
    for S in list do begin
      tmp := TTestSuite.Create(TPath.GetFileName(S));
      suite.AddSuite(tmp);
      ProcessFolder(tmp, TestClass, NameOfMethod, S, FileMask, true);
    end;
  end;
end;

constructor TFileTestCase.Create(const AMethodName, ATestFileName: string);
begin
  FTestFileName := ATestFileName;
  inherited Create(AMethodName);
end;

function TFileTestCase.GetName: string;
begin
  result := TPath.GetFileNameWithoutExtension(TestFileName);
end;

end.</pre><p></p>
]]></content:encoded>
			<wfw:commentRss>http://www.uweraabe.de/Blog/2012/03/17/a-dunit-folder-iterator-extension/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Windows 7 Previews &#8211; the Delphi Way</title>
		<link>http://www.uweraabe.de/Blog/2011/06/01/windows-7-previews-the-delphi-way/</link>
		<comments>http://www.uweraabe.de/Blog/2011/06/01/windows-7-previews-the-delphi-way/#comments</comments>
		<pubDate>Wed, 01 Jun 2011 12:42:59 +0000</pubDate>
		<dc:creator>Uwe Raabe</dc:creator>
				<category><![CDATA[Delphi]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.uweraabe.de/Blog/?p=165</guid>
		<description><![CDATA[In the ancient days of Windows XP and Delphi 7 I used to provide a preview of the proprietary file content inside the file open dialog of one of my applications. This was accomplished by deriving from TOpenDialog, just like &#8230; <a href="http://www.uweraabe.de/Blog/2011/06/01/windows-7-previews-the-delphi-way/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>In the ancient days of Windows XP and Delphi 7 I used to provide a preview of the proprietary file content inside the file open dialog of one of my applications. This was accomplished by deriving from <em>TOpenDialog</em>, just like the <em>TOpenPictureDialog</em> does that comes with Delphi itself.</p>
<p>The drawback was that since Windows Vista this was no way to go when you wanted to use the new Vista style dialogs. This was an even more nuisance as the new dialogs already come with a preview ability &#8211; so why not use it directly?<span id="more-165"></span></p>
<p>Googling a bit reveiled that others have to fight with the same problem, but no one seemed to have bitten the bullet to make a nice Delphi wrapper around the usual hurdles encountered when programming directly against the operating system. Looks like it was my turn to volunteer and here are the results. A simple implementation of a preview handler the Delphi way can be written in 45 lines:</p><pre class="crayon-plain-tag">unit MyPreviewHandler;

interface

uses
  PreviewHandler, Classes, Controls, StdCtrls;

const
  CLASS_MyPreviewHandler: TGUID = '{64644512-C345-469F-B5FB-EB351E20129D}';

type
  TMyPreviewHandler = class(TFilePreviewHandler)
  private
    FTextLabel: TLabel;
  public
    constructor Create(AParent: TWinControl); override;
    procedure DoPreview(const FilePath: string); override;
    property TextLabel: TLabel read FTextLabel;
  end;

implementation

uses
  SysUtils;

constructor TMyPreviewHandler.Create(AParent: TWinControl);
begin
  inherited;
  FTextLabel := TLabel.Create(AParent);
  FTextLabel.Parent := AParent;
  FTextLabel.AutoSize := false;
  FTextLabel.Align := alClient;
  FTextLabel.Alignment := taCenter;
  FTextLabel.Layout := tlCenter;
  FTextLabel.WordWrap := true;
end;

procedure TMyPreviewHandler.DoPreview(const FilePath: string);
begin
  TextLabel.Caption := GetPackageDescription(PWideChar(FilePath));
end;

initialization
  TMyPreviewHandler.Register(CLASS_MyPreviewHandler, 'bplfile', 'BPL Binary Preview Handler', '.bpl');
end.</pre><p>This is all that must be done to display the description of a BPL file in the preview pane, whereas most of the work is actually setting up a <em>TLabel</em> do display it nicely. </p>
<p>Overriding <strong>DoPreview</strong> is obiligatory as the inherited declaration is abstract. If you refuse to override it, you actually don&#8217;t want to write your own preview handler, so stop reading further and mind your own business. </p>
<p>The overridden constructor <strong>Create</strong> is the place to establish the needed controls for the preview and connect it to the passed parent. You can easily place a derived TFrame instance onto the parent control, which allows the use of the visual form designer for your preview. Be aware that the constructor has to be declared as <em>override</em>.</p>
<p>Overriding the <strong>Unload</strong> method is optional in case you have to clear the preview and/or free some resources. It just didn&#8217;t make sense in this example, unless you want to clear the label caption. (and it would have increased the line count to 51)</p>
<p>Don&#8217;t forget to <strong>register</strong> your preview handler in the initialization part of the unit using a fresh GUID. <em>(Pre-emptive comment: No, class constructors are not the way to go here)</em></p>
<p>Of course the compiled DLL has to be registered with <em>regsvr32</em>. Make sure to run it <em>as Administrator</em>.</p>
<p>OK, I admit that the overall benefit of this preview handler is somewhat limited, but it does serve well as an example. I also admit that I suppressed the project file, which in turn is quite simple.</p><pre class="crayon-plain-tag">library MyPreviewHandlerLib;

uses
  ComServ,
  PreviewHandler in 'PreviewHandler.pas' {PreviewHandler: CoClass},
  MyPreviewHandler in 'MyPreviewHandler.pas';

exports
  DllGetClassObject,
  DllCanUnloadNow,
  DllRegisterServer,
  DllUnregisterServer,
  DllInstall;

{$R *.RES}

begin
end.</pre><p>I tried to get rid of the {PreviewHandler: CoClass} entry in the uses clause, but the IDE insisted to put it in again. So, be it&#8230;</p>
<p>The real work (as usual) is done under the hood in unit <em>PreviewHandler.pas</em>, which I will explain shortly in the following. </p>
<p>The interface section declares a base class <em>TPreviewHandler</em> and two derived classes <em>TStreamPreviewHandler</em> and <em>TFilePreviewHandler</em>.</p><pre class="crayon-plain-tag">type
  TPreviewHandler = class abstract
  public
    constructor Create(AParent: TWinControl); virtual;
    class function GetComClass: TComClass; virtual; abstract;
    class procedure Register(const AClassID: TGUID; const AName, ADescription, AFileExtension: string);
    procedure Unload; virtual;
  end;

  TStreamPreviewHandler = class abstract(TPreviewHandler)
  public
    procedure DoPreview(Stream: TStream); virtual; abstract;
    class function GetComClass: TComClass; override; final;
  end;

  TFilePreviewHandler = class abstract(TPreviewHandler)
  public
    procedure DoPreview(const FilePath: String); virtual; abstract;
    class function GetComClass: TComClass; override; final;
  end;</pre><p>Microsoft recommends to implement the stream based preview handler as it will also work for previews, say, inside a zip file, but there are cases when a file based preview handler is just a bit more handy. You would have difficulties to implement the sample preview handler from above on a stream with the same simplicity. There is indeed a third possibility to implement a preview handler based on an <em>IShellItem</em>, but let&#8217;s say I left the implementation as an exercise.</p>
<p>You may have noticed that <em>TPreviewHandler</em> is derived from <em>TObject</em> instead of <em>TComObject</em>, which actually was my first approach. I decided to separate the COM stuff from the preview implementation to get a lean inheritance and small base classes not cluttered with methods you better shouldn&#8217;t know about. The actual COM class is retrieved from the virtual class function <em>GetComClass</em>, which is overriden in both of the derived preview handler classes. The declaration of the derived function as <em>final</em> ensures that no one can override this function in a descendant class. This is necessary because the underlying factory assumes that the COM class descends from a specific private class (I&#8217;m open for suggestions on that). If you are going to implement your own COM classes you should better implement your own complete preview handler framework at all. For anyone else, just ignore the <em>GetComClass</em> function.</p>
<p>The implementing COM classes resemble the file/stream structure of the preview handler classes, just because they have to implement either <a href="http://msdn.microsoft.com/en-us/library/bb761818%28v=vs.85%29.aspx">IInitializeWithFile</a> or <a href="http://msdn.microsoft.com/en-us/library/bb761810%28v=VS.85%29.aspx">IInitializeWithStream</a>. The base class <em>TComPreviewHandler</em> is responsible for most of the internal stuff and the implementation is mostly straight forward. The mapping to the Delphi type <em>TWinControl</em> properties is made with a class helper just to bundle all that stuff (and to make it harder to port it to older Delphi versions). </p>
<p>The <em>TComPreviewHandlerFactory</em> class is responsible for updating the various registry entries needed to make Windows aware of the preview handler. It also takes care of doing the right things to use a 32-bit handler in a 64-bit environment. The code to check for this situation is taken from <a href="http://www.delphidabbler.com">www.delphidabbler.com</a> and I expanded it a little bit so that it hopefully will also work with the <a href="http://www.embarcadero.com/products/delphi/64-bit">upcoming 64-bit Delphi compiler</a>.</p>
<p>As a gimmick you get a <em>TStream</em> implementation that maps to an <a href="http://msdn.microsoft.com/en-us/library/aa380034%28v=VS.85%29.aspx">IStream</a> interface with the <em>TIStreamAdapter</em> class. The other way round is already available in Delphi, but it didn&#8217;t fit in here very well.</p>
<p>The sources for Delphi XE can be downloaded here: <a href='http://www.uweraabe.de/Blog/wp-content/uploads/2011/06/PreviewHandler.zip'>PreviewHandler.zip</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.uweraabe.de/Blog/2011/06/01/windows-7-previews-the-delphi-way/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>On Upgrading Delphi</title>
		<link>http://www.uweraabe.de/Blog/2011/05/14/on-upgrading-delphi/</link>
		<comments>http://www.uweraabe.de/Blog/2011/05/14/on-upgrading-delphi/#comments</comments>
		<pubDate>Sat, 14 May 2011 10:34:53 +0000</pubDate>
		<dc:creator>Uwe Raabe</dc:creator>
				<category><![CDATA[Delphi]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.uweraabe.de/Blog/?p=160</guid>
		<description><![CDATA[Back from Delphi Developer Days (Kudos to Marco and Cary) and after cleaning up the mess in my inbox I would like to share some thought I had during one of the sessions named &#8220;Delphi: Today and Tomorrow&#8221;. Some of &#8230; <a href="http://www.uweraabe.de/Blog/2011/05/14/on-upgrading-delphi/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Back from <a title="Delphi Developer Days" href="http://www.delphideveloperdays.com/">Delphi Developer Days</a> (Kudos to Marco and Cary) and after cleaning up the mess in my inbox I would like to share some thought I had during one of the sessions named &#8220;Delphi: Today and Tomorrow&#8221;.</p>
<p>Some of the attendants mentioned they were still working with older Delphi versions and even if the newer versions were laying around they refused to make the step migrating their applications to the current Delphi XE. One argument from a fellow developer working still with Delphi 2007 actually alerted myself as he rated the step from Delphi 2007 to Delphi 2009 a very big one regarding the Unicode migration, but the step from Delphi 2010 to Delphi XE seems rather small, which makes himself unsure wether to make the migration to Delphi XE now or wait for the next version to come.</p>
<p>Honestly, I don&#8217;t get that. There already <em>is</em> a large step from Delphi 2007 to Delphi XE. Why making it even larger? What about &#8220;divide and conquer&#8221;? Do you really expect the migration to XE2 being easier than that to XE?<span id="more-160"></span></p>
<p>The big step, at least for some of us, may indeed be from Delphi 2007 to Delphi 2009. For myself it was merely waiting for the third party libraries to keep up or to replace some of them with those currently supported (OK, that has been some work). The steps to Delphi 2010 and Delphi XE were simply opening the project, compile and start using the new features.</p>
<p>Since migrating to Delphi 2009 I have been able to make use of all the new and exciting features that made it into the product since then. My code and my coding has improved a lot. I learned a whole bunch of new technologies and new techniques that makes my programming life easier. Staying with Delphi 2007 would have been a huge loss of time. Time to work with new technologies and gain experience.</p>
<p>When Delphi XE2 will be delivered I can concentrate on what is new in that version. I am eager to make my applications compile for the Mac (remembers me that I have to buy one before). I can&#8217;t even imagine to bother with Unicode, Generics and Anonymous Methods at that time.</p>
<p>IMHO not keeping up with the current Delphi is similar to not using version control, only the other way round. While using version control allows you to revert to a previous version of your application easily, staying up-to-date with your Delphi version allows you to create the future versions of your applications much easier.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.uweraabe.de/Blog/2011/05/14/on-upgrading-delphi/feed/</wfw:commentRss>
		<slash:comments>28</slash:comments>
		</item>
		<item>
		<title>Synchronize and Queue with Parameters</title>
		<link>http://www.uweraabe.de/Blog/2011/01/30/synchronize-and-queue-with-parameters/</link>
		<comments>http://www.uweraabe.de/Blog/2011/01/30/synchronize-and-queue-with-parameters/#comments</comments>
		<pubDate>Sun, 30 Jan 2011 14:40:30 +0000</pubDate>
		<dc:creator>Uwe Raabe</dc:creator>
				<category><![CDATA[Delphi]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.uweraabe.de/Blog/?p=135</guid>
		<description><![CDATA[In Delphi&#8217;s TThread class there is Synchronize to call a method in the context of the GUI thread. This is necessary in case, for example, you want to update a progressbar or a status label in a form, because the &#8230; <a href="http://www.uweraabe.de/Blog/2011/01/30/synchronize-and-queue-with-parameters/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>In Delphi&#8217;s <em>TThread</em> class there is <em>Synchronize</em> to call a method in the context of the GUI thread. This is necessary in case, for example, you want to update a progressbar or a status label in a form, because the VCL is not thread safe. While <em>Synchronize</em> is a blocking method (i.e. the thread code continues when the GUI thread has finished the method call), recent versions of Delphi introduced a non-blocking <em>Queue</em> method.</p>
<p>The drawback of using <em>Synchronize</em> is that it is very cumbersome to handle parameters during such a call. The standard solution is to use fields in the <em>TThread</em> descendant holding the parameters during <em>Synchronize</em>, but this won&#8217;t work properly with <em>Queue</em>. <span id="more-135"></span>As <em>Queue</em> is non-blocking there might be multiple calls to <em>Queue</em> waiting to be processed, which often cannot share the same field. Worse, using <em>Queue</em> access to these fields have to be thread safe, too. The queuing thread may just set this field for the next call to <em>Queue</em> while a previous <em>Queue</em> call is executed in the main thread just using this field. As this problem doesn&#8217;t exist with <em>Synchronize</em>, switching from <em>Synchronize</em> to <em>Queue</em> just has to be done more careful.</p>
<p>One way to deal with parameters for <em>Synchronize</em> is the use of <em>Anonymous Methods</em>. There is an overloaded version of <em>Synchronize</em> and <em>Queue</em> taking a <em>TThreadProcedure</em> as parameter:</p><pre class="crayon-plain-tag">TThreadMethod = procedure of object;
TThreadProcedure = reference to procedure;

procedure Queue(AMethod: TThreadMethod); overload;
procedure Synchronize(AMethod: TThreadMethod); overload;
procedure Queue(AThreadProc: TThreadProcedure); overload;
procedure Synchronize(AThreadProc: TThreadProcedure); overload;</pre><p>A simple example for a parametrized call to <em>Synchronize</em> could be like this:</p><pre class="crayon-plain-tag">type
  TMyProgressEvent = procedure(PercentComplete: Integer) of object;

  TMyThread = class(TThread)
  private
    FOnMyProgress: TMyProgressEvent;
  protected
    procedure CallMyProgress(PercentComplete: Integer);
    procedure Execute; override;
  public
    property OnMyProgress: TMyProgressEvent
      read FOnMyProgress
      write FOnMyProgress;
  end;

procedure TMyThread.CallMyProgress(PercentComplete: Integer);
begin
  if GetCurrentThreadId = MainThreadID then begin
    if Assigned(FOnMyProgress) then
      FOnMyProgress(PercentComplete);
  end
  else begin
    Synchronize(
      procedure
      begin
        CallMyProgress(PercentComplete);
      end);
  end;
end;

procedure TMyThread.Execute;
var
  I: Integer;
begin
  for I := 0 to 100 do begin
    CallMyProgress(I);
    Sleep(10);
  end;
end;</pre><p>The magic is that the <em>Anonymous Method</em> captures the value of the <em>PercentComplete</em> variable. Thus it will be totally safe to use <em>Queue</em> instead of <em>Synchronize</em> here.</p>
<p>I&#8217;m using a little trick here to ensure that the critical code is called inside the GUI thread without having a separate method. The ID of the GUI thread is stored in <em>MainThreadID</em>, so I just check if the result of the function <em>GetCurrentThreadID</em> matches this value and call <em>Synchronize</em> otherwise.</p>
<p>One note using <em>Queue</em>: when the thread is freed, all pending <em>Queue</em> calls are removed. So if your code depends on all these calls being handled in the GUI thread you have to make sure that the thread instance lives at least that long.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.uweraabe.de/Blog/2011/01/30/synchronize-and-queue-with-parameters/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>The Visitor Pattern &#8211; Part 4</title>
		<link>http://www.uweraabe.de/Blog/2010/08/17/the-visitor-pattern-part-4/</link>
		<comments>http://www.uweraabe.de/Blog/2010/08/17/the-visitor-pattern-part-4/#comments</comments>
		<pubDate>Tue, 17 Aug 2010 13:17:43 +0000</pubDate>
		<dc:creator>Uwe Raabe</dc:creator>
				<category><![CDATA[Delphi]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.uweraabe.de/Blog/?p=105</guid>
		<description><![CDATA[The interface approach introduced in Part 2 of this series and extended in Part 3 did cover most of our needs. But there is nothing that can&#8217;t be done better with the right tools. I&#8217;ve been using this approach for &#8230; <a href="http://www.uweraabe.de/Blog/2010/08/17/the-visitor-pattern-part-4/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>The interface approach introduced in Part 2 of this series and extended in Part 3 did cover most of our needs. But there is nothing that can&#8217;t be done better with the right tools.<br />
<span id="more-105"></span><br />
I&#8217;ve been using this approach for a couple of years and it made my life a lot easier. You need an export as DXF? No problem! Displaying in OpenGL? I&#8217;ll write a new visitor!</p>
<p>Writing the additional interfaces was easy done with the help of a customized code template, so that has never been a pain. The only thing that bothered me over time was that I could only apply the Visitor Pattern to classes I have control of. I just wasn&#8217;t able to visit, say, all the components of a TForm in a descent fashion (i.e. not queueing <em>if component is something then &lt;typecast&gt;</em>).</p>
<p>While digging through the new features of Delphi 2010 I discovered a solution which is as clean, lean, flexible and elegant as it could be. A little RTTI and some decent naming convention did the trick. Here is the code:</p><pre class="crayon-plain-tag">unit uVisitor;

interface

type
  TVisitor = class
  public
    procedure Visit(Instance: TObject); virtual;
  end;

implementation

uses
  Rtti;

procedure TVisitor.Visit(Instance: TObject);
var
  context: TRttiContext;
  currentClass: TClass;
  params: TArray&lt;TRttiParameter&gt;;
  paramType: TRttiType;
  selfMethod: TRttiMethod;
  S: string;
begin
  context := TRttiContext.Create;
  currentClass := Instance.ClassType;
  repeat
    S := currentClass.ClassName;
    Delete(S, 1, 1); // remove &quot;T&quot;
    for selfMethod in context.GetType(self.ClassType).GetMethods('Visit' + S) do begin
      params := selfMethod.GetParameters;
      if (Length(params) = 1) then begin
        paramType := params[0].ParamType;
        if ParamType.IsInstance and (ParamType.AsInstance.MetaclassType = currentClass)then begin
          selfMethod.Invoke(Self, [Instance]);
          Exit;
        end;
      end;
    end;
    currentClass := currentClass.ClassParent;
  until currentClass = nil;
end;

end.</pre><p>And here is a visitor capable of handling some VCL controls on a form together with an example of its usage:</p><pre class="crayon-plain-tag">type
  TMyVisitor = class(TVisitor)
  public
    procedure VisitButton(Instance: TButton);
    procedure VisitLabel(Instance: TLabel);
    procedure VisitEdit(Instance: TEdit);
    procedure VisitMemo(Instance: TMemo);
  end;

procedure TMyVisitor.VisitButton(Instance: TButton);
begin
  Instance.Caption := 'a button';
end;

procedure TMyVisitor.VisitEdit(Instance: TEdit);
begin
  Instance.Text := 'an edit';
end;

procedure TMyVisitor.VisitLabel(Instance: TLabel);
begin
  Instance.Caption := 'a label';
end;

procedure TMyVisitor.VisitMemo(Instance: TMemo);
begin
  Instance.Lines.Clear;
  Instance.Lines.Add('a memo');
end;

procedure TForm40.Button1Click(Sender: TObject);
var
  I: Integer;
  visitor: TMyVisitor;
begin
  visitor := TMyVisitor.Create;
  try
    for I := 0 to ComponentCount - 1 do
      visitor.Visit(Components[I]);
  finally
    visitor.Free;
  end;
end;</pre><p>If you need to visit some class, just introduce a new method with a suitable name and signature and you are done. No new interfaces, no fiddling around with classes. It just works right out of the box.</p>
<p>I&#8217;m still visualizing some possible scenarios where this approach can be useful, too. Stay tuned.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.uweraabe.de/Blog/2010/08/17/the-visitor-pattern-part-4/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
