<?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>VCL Developer</title>
	<atom:link href="http://vcldeveloper.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://vcldeveloper.com</link>
	<description>Ali Keshavarz&#039;s Website</description>
	<lastBuildDate>Fri, 04 Nov 2011 23:40:16 +0000</lastBuildDate>
	<language>fa</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>Boolean and BOOL</title>
		<link>http://vcldeveloper.com/tips-tricks/boolean-and-bool/</link>
		<comments>http://vcldeveloper.com/tips-tricks/boolean-and-bool/#comments</comments>
		<pubDate>Fri, 04 Nov 2011 23:40:16 +0000</pubDate>
		<dc:creator>Ali Keshavarz</dc:creator>
				<category><![CDATA[Tips & Tricks]]></category>
		<category><![CDATA[Boolean]]></category>
		<category><![CDATA[Delphi]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://vcldeveloper.com/?p=530</guid>
		<description><![CDATA[It took me an hour to fix an Access Violation in one of my source codes tonight. The AV caught my eyes when I thought everything was done correctly, and it is ready for committing changes and hit the bed! It was a vague AV, giving me just a few NT OS functions in call [...]]]></description>
			<content:encoded><![CDATA[<p>It took me an hour to fix an Access Violation in one of my source codes tonight. The AV caught my eyes when I thought everything was done correctly, and it is ready for committing changes and hit the bed!</p>
<p>It was a vague AV, giving me just a few NT OS functions in call stack trace, and stopping on any line containing Result (as the return value for a property getter). I reviewed the code several times, everything seemed OK, and I had only changed tens of lines of code, so I was really confused where the hell this AV came from; I mean, I knew which property getter method was causing the error, and the method was not lengthy or complicated, but I had no clue how come it was causing such an AV  &gt;-(</p>
<p>Eventually while I was reviewing the changed codes again and again, I noticed something; there was a Windows API call which required a PBOOL parameter, and I had called it twice in the function code. One call was written a while ago, and the other was written tonight. The problem was, for the second call I had defined the parameter as Boolean rather than defining it as BOOL (passing its address using @ operator). That&#8217;s a shame!</p>
<p>So here&#8217;s a personal note for myself: Do not code at 2 AM, specially when you are kinda sleepy. If you did, make sure your eyes can distinguish between BOOL, and Boolean <img src='http://vcldeveloper.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://vcldeveloper.com/tips-tricks/boolean-and-bool/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Update 1 for RAD Studio XE2 is available</title>
		<link>http://vcldeveloper.com/news/update-1-for-rad-studio-xe2-is-available/</link>
		<comments>http://vcldeveloper.com/news/update-1-for-rad-studio-xe2-is-available/#comments</comments>
		<pubDate>Wed, 28 Sep 2011 08:08:52 +0000</pubDate>
		<dc:creator>Ali Keshavarz</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Delphi]]></category>
		<category><![CDATA[Delphi XE2]]></category>
		<category><![CDATA[Embarcadero]]></category>
		<category><![CDATA[RAD Studio]]></category>
		<category><![CDATA[RAD Studio XE2]]></category>
		<category><![CDATA[دلفی]]></category>

		<guid isPermaLink="false">http://vcldeveloper.com/?p=525</guid>
		<description><![CDATA[Today,  just less than a month of releasing the original XE2 product, Embarcadero published the first update of a series of frequent updates for RAD Studio XE2 (including Delphi XE2 and C++ Builder XE2). Update 1 contains 120 bug fixes in FireMonkey, VCL Styles, compiler, and IDE. This update is mandatory for installing the future [...]]]></description>
			<content:encoded><![CDATA[<p>Today,  just less than a month of releasing the original XE2 product, Embarcadero published the first update of a series of frequent updates for RAD Studio XE2 (including Delphi XE2 and C++ Builder XE2). Update 1 contains 120 bug fixes in FireMonkey, VCL Styles, compiler, and IDE. This update is mandatory for installing the future updates. Here is the official announcement: <a href="http://edn.embarcadero.com/article/41650" target="_blank">Update 1 for Delphi XE2, C++Builder XE2 and RAD Studio XE2</a> . Make sure to read Release Notes for Update 1 before installing it, because Update 1 requires a full uninstall of original XE2 installation and is not a simple upgrade. You can also see a list of all bug fixes in this update here: <a href="http://edn.embarcadero.com/article/41649" target="_blank">Delphi XE2 and C++Builder XE2 Update 1 Bug Fix List</a> .</p>
<p>As I checked the bugs list, at least one bug regarding BiDi support (QC # 97965) is fixed in VCL Styles. No other BiDi related bugs are fixed in this update. Embarcadero staff mentioned in Embarcadero newsgroups that the company is planning to release monthly updates for XE2 product, so we should wait to see if any of the BiDi related bugs will be fixed in the coming updates or not.</p>
]]></content:encoded>
			<wfw:commentRss>http://vcldeveloper.com/news/update-1-for-rad-studio-xe2-is-available/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Enumerating Windows services</title>
		<link>http://vcldeveloper.com/tips-tricks/enumerating-windows-services/</link>
		<comments>http://vcldeveloper.com/tips-tricks/enumerating-windows-services/#comments</comments>
		<pubDate>Tue, 13 Sep 2011 14:30:28 +0000</pubDate>
		<dc:creator>Ali Keshavarz</dc:creator>
				<category><![CDATA[Tips & Tricks]]></category>
		<category><![CDATA[Delphi]]></category>
		<category><![CDATA[Delphi XE2]]></category>
		<category><![CDATA[Services]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[دلفی]]></category>

		<guid isPermaLink="false">http://vcldeveloper.com/?p=504</guid>
		<description><![CDATA[A while ago, I had to enumerate all Windows services for a project. I was browsing the source code today, and thought maybe it would be a good idea to talk about this matter in a blog post, and publish a sample source code to achieve this. The easiest way to enumerate Windows services is [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">A while ago, I had to enumerate all Windows services for a project. I was browsing the source code today, and thought maybe it would be a good idea to talk about this matter in a blog post, and publish a sample source code to achieve this.</p>
<p style="text-align: justify;">The easiest way to enumerate Windows services is using WMI. Of course using WMI requires some basic knowledge of MS COM technology which is tricky, but thanks to the great tool. <a href="http://code.google.com/p/delphi-wmi-class-generator/" target="_blank">Delphi WMI Class Generator</a> by <a href="http://www.theroadtodelphi.wordpress.com/" target="_blank">Rodrigo Ruz</a>, you can have a ready Delphi class for obtaining information about installed services on a Windows machine without even writing a single line of code. All you have to know is that WMI class for Windows services is Win32_Service under root\CIMV2 namespace. Delphi WMI Class Generator will generate a unit named uWin32_Service.pas which contains a class named TWin32_Service. This class returns info about a single service for you. If you need to enumerate all installed services, you need to write a couple of codes to call its GetCollectionCount to retrieve number of available services, and SetCollectionIndex to set current item index for the class. Here is a sample code to retrieve names of all installed services on the local machine using TWin32_Service class:</p>
<pre class="brush: delphi; title: ; notranslate">
var
  i: Integer;
begin
  with TWin32_Service.Create do
  try
    for i := 0 to GetCollectionCount - 1 do
    begin
      Writeln(DisplayName);
      SetCollectionIndex(i);
    end;
  finally
    Free;
  end;
end;
</pre>
<p style="text-align: justify;">However, WMI is slow, and it relays on WMI service. If you need a faster way to enumerate Windows services, or if for whatever reason WMI service is disabled or not working on your target machine; then you have to relay on Windows API. Using Windows API for this purpose is not as easy as using the automatically generated TWin32_Service class. I am not aware of a single Windows API function that can enumerate Windows services for you and give you all the detailed information which WMI returns for each service. You have to call roughly a dozen of API functions to enumerate Windows services and retrieve some nice information for each service.</p>
<p style="text-align: justify;">First you need to open a handle to service manager on the target machine by calling <a href="http://msdn.microsoft.com/en-us/library/ms684323%28v=vs.85%29.aspx" target="_blank">OpenSCManager</a> function, then you should call <a href="http://msdn.microsoft.com/en-us/library/ms682640%28VS.85%29.aspx" target="_blank">EnumServicesStatusEx</a> function to enumerate available services, and retrieve their names and status. If you just need service names and status, you are done, but if you need to retrieve description and configuration for each service too, then you should open a handle for each service using <a href="http://msdn.microsoft.com/en-us/library/ms684330%28v=vs.85%29.aspx" target="_blank">OpenService </a>function by giving it service name which you obtain through EnumServicesStatusEx call , and then call <a href="http://msdn.microsoft.com/en-us/library/ms684932%28v=vs.85%29.aspx" target="_blank">QueryServiceConfig</a> and <a href="http://msdn.microsoft.com/en-us/library/ms684935%28v=vs.85%29.aspx" target="_blank">QueryServiceConfig2</a> functions to get the required configurations. At the end you should make sure you free all the allocated buffers, and close all handles. Delphi installation does not provide header translation for some of these API functions (particularly EnumServicesStatusEx and QueryServiceConfig2), but they are translated and available for Delphi by well-known Project JEDI, and their JEDI Windows API Headers which contain the majority of Windows headers. If you are a Delphi developer and have not heard about them yet (That would be weird!!), you can download the package from <a title="JEDI Windows API Header" href="http://blog.delphi-jedi.net/jedi-api-headers/" target="_blank">this link</a>.</p>
<p style="text-align: justify;">Anyways, in the source code below, I wrapped all of those API calls into a class named TAkServices. This class holds an internal list containing information for each Windows service installed on a given machine. I tested it on both Delphi 2010 (Win32) and Delphi XE2 (Win64):</p>
<p style="text-align: justify;"><span id="more-504"></span></p>
<pre class="brush: delphi; title: ; notranslate">
{*******************************************************************************
/// &lt;author&gt; Ali Keshavarz (vcldeveloper@gmail.com) &lt;/author&gt;
/// &lt;date&gt; 09/13/2011 &lt;/date&gt;
/// &lt;license&gt;
///  This work is licensed under the Creative Commons Attribution 3.0 Unported
///  License. To view a copy of this license, visit
///  http://creativecommons.org/licenses/by/3.0/
///  or send a letter to Creative Commons, 171 Second Street, Suite 300,
///  San Francisco, California, 94105, USA.
/// &lt;/license&gt;
*******************************************************************************}

unit uAkServices;

interface

uses
 Generics.Collections;

type
 /// Service status values; these items are defined in Windows SDK. For more
 /// info refer to MSDN.
 TAkServiceState = (SERVICE_STOPPED          = $۰۰۰۰۰۰۰۱,
 SERVICE_START_PENDING    = $۰۰۰۰۰۰۰۲,
 SERVICE_STOP_PENDING     = $۰۰۰۰۰۰۰۳,
 SERVICE_RUNNING          = $۰۰۰۰۰۰۰۴,
 SERVICE_CONTINUE_PENDING = $00000005,
 SERVICE_PAUSE_PENDING    = $۰۰۰۰۰۰۰۶,
 SERVICE_PAUSED           = $۰۰۰۰۰۰۰۷ );

 /// Service startup mode values; these items are defined in Windows SDK. For
 /// more info refer to MSDN.
 TAkServiceStartMode = (SERVICE_BOOT_START,
 SERVICE_SYSTEM_START,
 SERVICE_AUTO_START,
 SERVICE_DEMAND_START,
 SERVICE_DISABLED );

 /// &lt;summary&gt;
 /// Service information structure. This structure is used by TAkServiceList
 /// class to save info for each individual service.
 /// &lt;/summary&gt;
 TAkServiceInfo = record
 public
 /// A path to service executable file.
 BinaryPath : string;
 /// Current service state.
 CurrentState : TAkServiceState;

 Description : string;
 /// User-friendly name of service
 DisplayName : string;
 /// Service flags. It can be either zero or SERVICE_RUNS_IN_SYSTEM_PROCESS.
 Flags : Integer;
 /// Actual name of service which is also used as service key name in Registry.
 Name : string;
 /// Process identifier for a running service. If the service is not running
 /// or it is running in System process, then ProcessID will be zero.
 ProcessID : Cardinal;
 /// Startup mode of service.
 StartMode : TAkServiceStartMode;
 /// Username by which service logged into system.
 StartName : string;
 end;

 /// Holds a list of TAkServiceInfo reccords as the list of Windows services.
 TAkServiceList = TList&lt;TAkServiceInfo&gt;;

 TAkServiceInfoEnumerator = TEnumerator&lt;TAkServiceInfo&gt;;

 /// &lt;summary&gt;
 /// Provides a list of installed Windows services on a given machine.
 /// &lt;/summary&gt;
 TAkServices = class
 private
 FLastUpdateTime : TDateTime;
 FList : TAkServiceList;
 FMachineName : string;
 function GetCount: Integer;
 function GetItem(Index: Integer): TAkServiceInfo;
 procedure GetServiceConfig(hSCManager: Cardinal; var Service: TAkServiceInfo);
 procedure SetMachineName(const Value: string);
 protected
 procedure InitializeList; virtual;
 procedure InternalRefresh; virtual;
 public
 /// &lt;summary&gt;
 /// Constructor for TAkServices.
 /// &lt;/summary&gt;
 /// &lt;param name=&quot;AMachineName&quot;&gt;
 ///  (in) Name of the machine which its services should be listed. Default = ''
 /// &lt;/param&gt;
 /// &lt;param name=&quot;.&quot;&gt;&lt;/param&gt;
 constructor Create(const AMachineName: string = '');
 destructor Destroy; override;
 function GetEnumerator: TAkServiceInfoEnumerator;
 /// &lt;summary&gt; Updates list of services. &lt;/summary&gt;
 procedure Refresh;
 /// &lt;summary&gt;
 /// Indicates number of services. If the list is not updated yet, it will be
 /// updated first.
 /// &lt;/summary&gt;
 property Count: Integer read GetCount;
 /// &lt;summary&gt;
 /// Returns item at the Index position of the list of services.
 /// If the list is not updated yet, it will be updated first.
 /// &lt;/summary&gt;
 property Item[Index: Integer]: TAkServiceInfo read GetItem; default;
 /// &lt;summary&gt;
 /// Indicates last update time for the list. It will be updated each time
 /// Refresh method is called.
 /// &lt;/summary&gt;
 property LastUpdateTime: TDateTime read FLastUpdateTime;
 /// &lt;summary&gt;Name of the machine which its services should be listed. &lt;/summary&gt;
 property MachineName: string read FMachineName write SetMachineName;
 end;

implementation

uses
 SysUtils,
 Windows,
 JwaWinNT,
 JwaWinType,
 JwaWinSvc,
 JwaWinError;

{ TAkServices }

constructor TAkServices.Create(const AMachineName: string);
begin
 inherited Create;
 FMachineName := AMachineName;
end;

destructor TAkServices.Destroy;
begin
 System.TMonitor.Enter(Self);
 try
 FList.Free;
 FList := nil;
 finally
 System.TMonitor.Exit(Self);
 end;

 inherited;
end;

function TAkServices.GetCount: Integer;
begin
 InitializeList;
 Result := FList.Count;
end;

function TAkServices.GetEnumerator: TAkServiceInfoEnumerator;
begin
 InitializeList;
 Result := FList.GetEnumerator;
end;

function TAkServices.GetItem(Index: Integer): TAkServiceInfo;
begin
 InitializeList;
 Result := FList[Index];
end;

procedure TAkServices.InitializeList;
begin
 if not Assigned(FList) then
 begin
 System.TMonitor.Enter(Self);
 try
 FList := TAkServiceList.Create;
 InternalRefresh;
 finally
 System.TMonitor.Exit(Self);
 end;
 end;
end;

procedure TAkServices.GetServiceConfig(hSCManager: Cardinal; var Service: TAkServiceInfo);
var
 dwBufNeeded: Cardinal;
 dwBufSize: Cardinal;
 hService : Cardinal;

 /// &lt;summary&gt;
 /// Retrieves service binary path, start mode, and user name.
 /// &lt;/summary&gt;
 procedure GetRequiredConfig(var Service: TAkServiceInfo);
 var
 lpServiceConfig : LPQUERY_SERVICE_CONFIG;
 begin
 dwBufSize := 0;
 dwBufNeeded := 0;
 /// Retrieve required buffer size.
 QueryServiceConfig(hService, nil, dwBufSize, dwBufNeeded);
 if GetLastError &lt;&gt; ERROR_INSUFFICIENT_BUFFER then
 RaiseLastOSError;

 /// Alocate enough buffer size.
 dwBufSize := dwBufNeeded;
 lpServiceConfig := AllocMem(dwBufSize);
 try
 /// Get service configuration
 if not QueryServiceConfig(hService, lpServiceConfig, dwBufSize, dwBufNeeded) then
 RaiseLastOSError;

 /// Save configuration data in the record.
 Service.BinaryPath := lpServiceConfig.lpBinaryPathName;
 Service.StartMode := TAkServiceStartMode(lpServiceConfig.dwStartType);
 Service.StartName := lpServiceConfig.lpServiceStartName;
 finally
 FreeMem(lpServiceConfig);
 end;
 end;

 /// &lt;summary&gt;
 /// Retrieves service description.
 /// &lt;/summary&gt;
 procedure GetOptionalConfig(var Service: TAkServiceInfo);
 var
 lpServiceDescBuff : LPSERVICE_DESCRIPTION;
 begin
 dwBufSize := 0;
 dwBufNeeded := 0;
 /// Retrieve required buffer size.
 QueryServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, nil, dwBufSize, dwBufNeeded);
 if GetLastError &lt;&gt; ERROR_INSUFFICIENT_BUFFER then
 RaiseLastOSError;

 /// Alocate enough buffer size.
 dwBufSize := dwBufNeeded;
 lpServiceDescBuff := AllocMem(dwBufSize);
 try
 /// Retrieve service description
 if not QueryServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION,
                            PByte(lpServiceDescBuff), dwBufSize, dwBufNeeded) then
   RaiseLastOSError;
  /// Save service description in the record.
  if Assigned(lpServiceDescBuff.lpDescription) then
   SetString(Service.Description,
             lpServiceDescBuff.lpDescription,
             StrLen(lpServiceDescBuff.lpDescription));
   finally
     FreeMem(lpServiceDescBuff);
   end;
 end;

begin
  Assert(hSCManager &gt; 0, 'Service manager is not initialized.');

  /// Open a service handle to be used by QueryServiceConfig() and QueryServiceConfig2() functions.
  hService := OpenService(hSCManager,PChar(Service.Name),SERVICE_QUERY_CONFIG);
  if hService = 0 then
    RaiseLastOSError;
  try
    GetRequiredConfig(Service);
    GetOptionalConfig(Service);
  finally
    CloseServiceHandle(hService);
  end;
end;

procedure TAkServices.InternalRefresh;
var
  dwBufNeeded: Cardinal;
  dwBufSize: Cardinal;
  dwNumOfServices: ULONG;
  hSCM: SC_HANDLE;
  lpResumeHandle: Cardinal;
  NewItem : TAkServiceInfo;
  pBuf: PBYTE;
  pInfo: LPENUM_SERVICE_STATUS_PROCESS;
  i: Integer;
begin
  Assert(Assigned(FList),'Internal list is not assigned yet!');

  System.TMonitor.Enter(FList);
  try
   dwBufSize := 0;
   dwBufNeeded := 0;
   dwNumOfServices := 0;
   lpResumeHandle := 0;
   FList.Clear;

   /// We need an open service manager handle to be able to enumerate services.
   hSCM := OpenSCManager(PChar(FMachineName), nil,
   SC_MANAGER_ENUMERATE_SERVICE or SC_MANAGER_CONNECT);
   if (hSCM = 0) then
     RaiseLastOSError;

   try
     /// First check how much buffer is needed by passing dwBufSize as zero,
     /// and pBuf as nil.
     EnumServicesStatusEx(hSCM, SC_ENUM_PROCESS_INFO, SERVICE_WIN32,
                          SERVICE_STATE_ALL, nil, dwBufSize, dwBufNeeded,
                          dwNumOfServices, lpResumeHandle, nil);
     if (dwBufNeeded &lt; 1) then
       RaiseLastOSError;

     /// Alocate enough space for the buffer.
     dwBufSize := dwBufNeeded;
     pBuf := AllocMem(dwBufSize);
     try
       /// Retrieve services list
       if not EnumServicesStatusEx(hSCM, SC_ENUM_PROCESS_INFO, SERVICE_WIN32,
                                   SERVICE_STATE_ALL, pBuf, dwBufSize, dwBufNeeded,
                                   dwNumOfServices, lpResumeHandle, nil) then
         RaiseLastOSError;

       /// Type casting pBuf to LPENUM_SERVICE_STATUS_PROCESS record is necessary
       ///  so that we can access each service info in the buffer as a record.
       pInfo := LPENUM_SERVICE_STATUS_PROCESS(pBuf);
       /// Write services list
       for i := 0 to dwNumOfServices-1 do
       begin
         NewItem.Name := pInfo.lpServiceName;
         NewItem.DisplayName := pInfo.lpDisplayName;
         NewItem.Flags := pInfo.ServiceStatusProcess.dwServiceFlags;
         NewItem.ProcessID := pInfo.ServiceStatusProcess.dwProcessId;
         NewItem.CurrentState := TAkServiceState(pInfo.ServiceStatusProcess.dwCurrentState);
         GetServiceConfig(hSCM, NewItem);
         FList.Add(NewItem);

         /// Go to next record in the buffer. Compiler will increment pInfo pointer
         ///  according to size LPENUM_SERVICE_STATUS_PROCESS record.
         Inc(pInfo);
       end;
       FLastUpdateTime := Now;
    finally
       FreeMem(pBuf);
    end;
  finally
    CloseServiceHandle(hSCM);
  end;
  finally
     System.TMonitor.Exit(FList);
  end;
end;

procedure TAkServices.Refresh;
begin
 /// If FList is not created yet, InitializeList will create it and calls InternalRefresh
 /// automatically, but if the list is already created, just calling InternalRefresh
 /// is enough.
 if not Assigned(FList) then
 InitializeList
 else
 InternalRefresh;
end;

procedure TAkServices.SetMachineName(const Value: string);
begin
 if not SameText(FMachineName, Value) then
 begin
    FMachineName := Value;
    Refresh;
  end;
end;

end.
</pre>
<p style="text-align: justify;">Here is also a demo Delphi application using TAkServices class to enumerate Windows services on the local machine, and show them in a ListView control. Download link for the source files (including uAkServices.pas and all required JEDI API header translations) is available at the end of this article:</p>
<div id="attachment_507" class="wp-caption aligncenter" style="width: 310px"><a href="/wp-content/uploads/2011/09/WinServicesDemo.png"><img class="size-medium wp-image-507" title="WinServicesDemo" src="http://vcldeveloper.com/wp-content/uploads/2011/09/WinServicesDemo-300x218.png" alt="" width="300" height="218" /></a><p class="wp-caption-text">Demo application in action; enumerating Windows services using Windows API</p></div>
<h3>Download:</h3>
<p class="download"><a href="/downloads/Enum_Win_Services_Demo.zip">Source code plus the demo app</a></p>
<p><strong>P.S.</strong> Oops, it seems my code highlighter is not keen on indentation in longer source codes. If you see the code without proper indentation, you can use <a href="http://pastebin.com/777VN9RU">this pastebin link</a> to see the source formatted properly, or download the source file. I&#8217;m sorry for the inconvenience.</p>
]]></content:encoded>
			<wfw:commentRss>http://vcldeveloper.com/tips-tricks/enumerating-windows-services/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>ProcessInfo 1.5 is released with Win64 support</title>
		<link>http://vcldeveloper.com/news/processinfo-1-5-is-released-with-win64-support/</link>
		<comments>http://vcldeveloper.com/news/processinfo-1-5-is-released-with-win64-support/#comments</comments>
		<pubDate>Sun, 11 Sep 2011 22:14:29 +0000</pubDate>
		<dc:creator>Ali Keshavarz</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Components]]></category>
		<category><![CDATA[Delphi]]></category>
		<category><![CDATA[Freeware]]></category>
		<category><![CDATA[ProcessInfo]]></category>
		<category><![CDATA[TAppInfo]]></category>
		<category><![CDATA[TProcessInfo]]></category>
		<category><![CDATA[دلفی]]></category>
		<category><![CDATA[کامپوننت]]></category>

		<guid isPermaLink="false">http://vcldeveloper.com/?p=499</guid>
		<description><![CDATA[ProcessInfo 1.5 is released. The changes in this release are: Added support for Win64 and Delphi XE2. Added TProcessItem.CloseProcess method to close a process normally (not forcefully). Added TProcessItem.CurrentProcess property. This property always refers to the current process in the list of running processes. Added PrivateWorkingSetSize property to TProcessItem.MemoryInfo. Added global  ProcessInformation function. This function [...]]]></description>
			<content:encoded><![CDATA[<p>ProcessInfo 1.5 is released. The changes in this release are:</p>
<ul>
<li>Added support for Win64 and Delphi XE2.</li>
<li> Added TProcessItem.CloseProcess method to close a process normally (not forcefully).</li>
<li> Added TProcessItem.CurrentProcess property. This property always refers to the current process in the list of running processes.</li>
<li>Added PrivateWorkingSetSize property to TProcessItem.MemoryInfo.</li>
<li> Added global  ProcessInformation function. This function returns a global instance of TProcessInfo. The instance will be freed when the application is terminating.</li>
<li> Fixed a few minor bugs.</li>
</ul>
<p>To download ProcessInfo 1.5, please go to <a href="/products/products-components/process-info/">ProcessInfo</a> page.</p>
]]></content:encoded>
			<wfw:commentRss>http://vcldeveloper.com/news/processinfo-1-5-is-released-with-win64-support/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>FireMonkey and support for bi-directional text &#8211; Part 2</title>
		<link>http://vcldeveloper.com/news/firemonkey-and-support-for-bi-directional-text-2/</link>
		<comments>http://vcldeveloper.com/news/firemonkey-and-support-for-bi-directional-text-2/#comments</comments>
		<pubDate>Sun, 11 Sep 2011 09:51:04 +0000</pubDate>
		<dc:creator>Ali Keshavarz</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Delphi]]></category>
		<category><![CDATA[Delphi XE2]]></category>
		<category><![CDATA[FireMonkey]]></category>
		<category><![CDATA[RAD Studio]]></category>
		<category><![CDATA[RAD Studio XE2]]></category>

		<guid isPermaLink="false">http://vcldeveloper.com/?p=479</guid>
		<description><![CDATA[Last month when RAD Studio XE2 was still in Beta phase, I wrote a weblog post about bi-directional (BiDi) text support in KSDev VGScene (ancestor of FireMonkey), questioning FireMonkey support for BiDi text, and why it is important to support it. As I mentioned in a post-script update, Andreano Lanusse commented on my post, and [...]]]></description>
			<content:encoded><![CDATA[<p>Last month when RAD Studio XE2 was still in Beta phase, I wrote<a title="FireMonkey and support for bi-directional text" href="/news/firemonkey-and-support-for-bi-directional-text/" target="_blank"> a weblog post</a> about bi-directional (BiDi) text support in KSDev VGScene (ancestor of FireMonkey), questioning FireMonkey support for BiDi text, and why it is important to support it. As I mentioned in a post-script update, <a href="http://www.andreanolanusse.com/" target="_blank">Andreano Lanusse</a> commented on my post, and told us BiDi text would not be supported in the initial version of FireMonkey. Now it is been around a couple of weeks that the official RAD Studio XE2 is released, and its trial version is available for download. I decided to test BiDi support in the official FireMonkey using the trial version, and write the second part of my  investigation on BiDi text support in FireMonkey.</p>
<p>First of all I should mention that I didn&#8217;t expect any BiDi support in this version, so my initial intention was to highlight the bugs for BiDi support in FireMonkey and report them to be hopefully fixed in the future releases. The first impression was that FireMonkey is not as bad as VGScene in supporting BiDi text. It was a surprise because I didn&#8217;t really expect any BiDi support after reading Andreano&#8217;s comment. There is very limited and half baked support for BiDi text in the initial release and it still has a long way to go for fully supporting BiDi text. Here I am going to discuss support for BiDi text in FireMonkey version 1.0, highlighting the bugs which should be fixed regarding this support, and the QC report regarding each bug.</p>
<p>Before I discuss BiDi support, I should mention that according to Michael Swindell, Senior vice president of marketing and product management at Embarcadero, FireMonkey will be updated frequently. The first update is expected before the end of September, and the other updates will be published more often than quarterly [<a title="Will Firemonkey be updated outside of regular product updates? " href="https://forums.embarcadero.com/thread.jspa?threadID=60400" target="_blank">Source</a>]. That means, we will see several updates for FireMonkey before the new version of RAD Studio is published next year. That is really exciting and makes me very hopeful that all or at least many of the bugs mentioned here might be fixed before the next major release of RAD Studio in 2012. It is important to be hopeful about evolution of a product, and feel that your feedbacks are really considered by its developers. Years ago many of my friends tried to notify Borland about some of the existing bugs in VCL regarding BiDi and right-to-left languages support, but they never got fixed, and many of those guys migrated to .NET, abandoning Delphi. I myself stopped reporting any new bug to QC when Embarcadero deleted my EDN account just because my country in my profile was mentioned as Iran. Now I feel the team listens more to user feedbacks. It doesn&#8217;t really matter if I am Iranian or American or whatever when I am reporting a bug or when I am discussing some technical stuff. Anyways, that is another story and I discussed that in <a title="Embarcadero and Iran Embargo" href="/news/embarcadero-and-iran-embargo/" target="_blank">an older blog post</a>. Let&#8217;s go back to FireMonkey and its support for BiDi text:</p>
<p><span id="more-479"></span></p>
<p>The first thing that I noticed in FireMonkey regarding BiDi support was a new BiDiMode property added to FireMonkey forms. This property determines if the whole form is right-to-left or left-to-right. When it is set to bdRightToLeft, it changes TextAlign property of the child controls inside the form, and set the text inside them aligned right to left. It also enables BiDi reading in the text for many of the controls so that a text containing a mixture of Latin and a right-to-left language (e.g. Arabic, Persian, Hebrew) characters is read correctly. If you remember from the older post on this subject, VGScene lacked such a feature. Having this effect makes FireMonkey a little more useful in right-to-left applications. At least in many cases your users will be able to read the text shown to them properly.</p>
<p>However the idea of having a single BiDiMode property to govern all the child controls inside a form is not practically appealing, because it is very common for a right-to-left from to contain Latin or numeric elements which should be laid out left-to-right rather than  right-to-left. Actually all FireMonkey controls should have a BiDiMode property governing the layout of that particular control and its children; something similar to BiDiMode property in VCL controls.</p>
<p>Another problem that is visible when BiDiMode of a form is set to bdRightToLeft is in the form title; the title is not BiDi-aware so if it contains a mixture of Latin and right-to-left characters, it will show the text incorrectly. Also layout of the title is not right; in a right-to-left window the default coordinates system starts from the upper right corner, form icon is on the right side of the title bar, form title is next to it, and window buttons (min, max, close) are on the left side of the form, that means mirroring the position of title bar elements. Right now the title bar for right-to-left forms are aligned the same way as left-to-right forms which is wrong:</p>
<div id="attachment_485" class="wp-caption aligncenter" style="width: 504px"><a href="/wp-content/uploads/2011/09/RTL_FireMonkey_Title.png"><img class="size-full wp-image-485" title="RTL FireMonkey Title" src="http://vcldeveloper.com/wp-content/uploads/2011/09/RTL_FireMonkey_Title.png" alt="RTL FireMonkey Title" width="494" height="29" /></a><p class="wp-caption-text">BUG: FireMonkey form title does not change when BiDiMode is bdRightToLeft </p></div>
<p>VCL forms have the same problem. It gets even more irritating when you use a right-to-left VCL form with Ribbon controls; Ribbon application button overlaps with Close button, making it very hard for the user to click on Close button.</p>
<p>Now let&#8217;s see how child controls react when BiDiMode is set to bdRightToLeft. First of all, I checked TEdit control. It is the common control for receiving text input. There are two type of textual edit controls in FireMonkey; TEdit, and TClearingEdit. The latter has a button at the end of the control which clears the text inside the control, when clicked:</p>
<div id="attachment_486" class="wp-caption aligncenter" style="width: 266px"><a href="/wp-content/uploads/2011/09/RTL_FireMonkey_EditBox.png"><img class="size-full wp-image-486" title="RTL FireMonkey EditBox" src="http://vcldeveloper.com/wp-content/uploads/2011/09/RTL_FireMonkey_EditBox.png" alt="RTL FireMonkey EditBox" width="256" height="95" /></a><p class="wp-caption-text">Right-to-left edit boxes in FireMonkey have a couple of minor visual bugs.</p></div>
<p>As you can see in the picture above, BiDi text is shown correctly in those edit controls, but they have two other bugs; first of all, when an edit control receives focus, the cursor remains on the left side of the edit box, blinking. The cursor should be at the right corner of the edit box when the control is set right-to-left. Even when an edit box is focused and input language is changed, if the input language is right-to-left, the cursor should jump to the right side of the box.  This false behavior is not exclusive to TEdit, actually all controls that receive text input (e.g. CombBoxes, Memos, etc.) have the same problem with their cursor position. The other problem is with TClearingEdit control; clear button inside the control should be positioned on the left side when text is right-to-left, and on the right side when text is left-to-right.</p>
<p>ComboBoxes have an additional bug beside the other one I mentioned for edits; the items in the drop down list are left-aligned and not BiDi-aware (i.e. mixing Latin and right-to-left characters destroys proper text reading):</p>
<div id="attachment_487" class="wp-caption aligncenter" style="width: 225px"><a href="/wp-content/uploads/2011/09/RTL_FireMonkey_ComboBox.png"><img class="size-full wp-image-487" title="RTL FireMonkey ComboBox" src="http://vcldeveloper.com/wp-content/uploads/2011/09/RTL_FireMonkey_ComboBox.png" alt="RTL FireMonkey ComboBox" width="215" height="115" /></a><p class="wp-caption-text">BUG: Items are left-aligned and item texts are not BiDi-aware.</p></div>
<p>Unfortunately right-to-left Memo is useless in FireMonkey. This memo control is really buggy, even when it is not right-to-left. Anyways, as you can see in the picture below, a right-to-left memo does not show the text at all. The text is there as the cursor is blinking where the text is ended, but no text is visible:</p>
<div id="attachment_488" class="wp-caption aligncenter" style="width: 256px"><a href="/wp-content/uploads/2011/09/RTL_FireMonkey_Memo.png"><img class="size-full wp-image-488" title="RTL FireMonkey Memo" src="http://vcldeveloper.com/wp-content/uploads/2011/09/RTL_FireMonkey_Memo.png" alt="RTL FireMonkey Memo" width="246" height="112" /></a><p class="wp-caption-text">BUG: Right-to-left text disappears in FireMonkey Memo control.</p></div>
<p>TreeView in FireMonkey acts similar to TreeView in VGScene, the items are right-aligned, but the arrow icon indicating each node sub-items, and the indentation for each sub-item are drawn on the left-side, making the right-to-left TreeView looking weird. The only improvement here is in BiDi text reading; as you can see in the picture, BiDi text is read correctly when Latin and right-to-left characters are mixed together:</p>
<div id="attachment_490" class="wp-caption aligncenter" style="width: 220px"><a href="/wp-content/uploads/2011/09/RTL_FireMonkey_TreeView1.png"><img class="size-full wp-image-490" title="RTL FireMonkey TreeView" src="http://vcldeveloper.com/wp-content/uploads/2011/09/RTL_FireMonkey_TreeView1.png" alt="RTL FireMonkey TreeView" width="210" height="141" /></a><p class="wp-caption-text">BUG: Arrow icon and indentations for the sub-items remain on the left side.</p></div>
<p>As I mentioned in the first part of this investigation, it is been so many years that TreeView in VCL has problem with right-to-left too. I hope we see it fixed someday soon too.</p>
<p>TabControl in FireMonkey isn&#8217;t any better than PageControl in VCL; they both ignore right-to-left setting, and remain left-aligned:</p>
<p style="text-align: center;">
<div id="attachment_491" class="wp-caption aligncenter" style="width: 222px"><a href="/wp-content/uploads/2011/09/RTL_FireMonkey_TabControl.png"><img class="size-full wp-image-491 " title="RTL_FireMonkey_TabControl" src="http://vcldeveloper.com/wp-content/uploads/2011/09/RTL_FireMonkey_TabControl.png" alt="RTL FireMonkey TabControl" width="212" height="148" /></a><p class="wp-caption-text">BUG: Tabs are shown left-to-right rather than right-to-left</p></div>
<p>Now the menus; both FireMonkey and VCL have problem in showing right-to-left menus properly. They both draw the menu (either main menu or popup menu) left-aligned, so that the icon is shown on the left side of each menu item rather than the right side. FireMonkey has two additional bugs in its menu; first of all, BiDi text reading in the menu is not implemented, so mixing Latin and right-to-left characters in a text makes the text unreadable. Beside that, menu items in the main menu are always started from left to right:</p>
<div id="attachment_492" class="wp-caption aligncenter" style="width: 244px"><a href="/wp-content/uploads/2011/09/RTL_FireMonkey_MainMenu.png"><img class="size-full wp-image-492" title="RTL_FireMonkey_MainMenu" src="http://vcldeveloper.com/wp-content/uploads/2011/09/RTL_FireMonkey_MainMenu.png" alt="RTL FireMonkey MainMenu" width="234" height="72" /></a><p class="wp-caption-text">BUG: Menus have no BiDi support and is left-aligned.</p></div>
<p>The last control I investigated was TStringGrid; TDBGrid in VCL was one of the rare controls which had nice right-to-left support, but such a nice support does not exist in FireMonkey; TStringGrid in FireMonkey can be attached to a dataset thanks to the new Live Binding feature, but columns are always drown left-to-right. What&#8217;s more, having separate BiDiMode property for each column is more important here, because each column might have right-to-left, Latin, or numerical data, and we cannot expect all such data to be aligned either left-to-right or right-to-left:</p>
<div id="attachment_494" class="wp-caption aligncenter" style="width: 254px"><a href="/wp-content/uploads/2011/09/RTL_FireMonkey_Grid.png"><img class="size-full wp-image-494" title="RTL_FireMonkey_Grid" src="http://vcldeveloper.com/wp-content/uploads/2011/09/RTL_FireMonkey_Grid.png" alt="RTL FireMonkey Grid" width="244" height="148" /></a><p class="wp-caption-text">BUG: Grid columns are always laid out left-to-right</p></div>
<h2>Conclusion</h2>
<p>With all these bugs in right-to-left support, is FireMonkey 1.0 really usable for right-to-left applications? The short answer is, No. The longer answer is; there is some basic support for reading BiDi text, so at least you can have some single-lined text in your application. With this basic support you can create some limited demo applications or some trivial fun stuff, but not really any serious business application. However, as I mentioned earlier, the good news is that FireMonkey is supposed to be updated frequently, so we can be hopeful that many of these bugs might be fixed in the coming months.</p>
<p>In this article I mentioned many VCL bugs regarding right-to-left support too, I hope Embarcadero consider these old VCL bugs too, and fix them eventually.</p>
<p>Anyways, here is a list of QC reports regarding the bugs I mentioned in this article. If you need proper right-to-left support in your Delphi or C++ Builder applications, please take a few minutes, and vote for these reports in Quality Central, so that Embarcadero would deal with them more seriously:</p>
<ul>
<li>QC <a href="http://qc.embarcadero.com/wc/qcmain.aspx?d=98647" target="_blank">#98647</a>: BiDi support in FireMonkey is broken.</li>
<li>QC <a href="http://qc.embarcadero.com/wc/qcmain.aspx?d=98604" target="_blank">#97604</a>: Cursor position always left with BidiMode = bdRightToLeft.</li>
<li>QC <a href="http://qc.embarcadero.com/wc/qcmain.aspx?d=98644" target="_blank">#98644</a>: All FireMonkey controls should have BiDiMode property.</li>
<li>QC <a href="http://qc.embarcadero.com/wc/qcmain.aspx?d=98638" target="_blank">#98638</a>: TMemo does not render BiDi text.</li>
<li>QC <a href="http://qc.embarcadero.com/wc/qcmain.aspx?d=98770" target="_blank">#98770</a>: Clear button is positioned incorrectly when BiDiMode is set to bdRightToLeft.</li>
<li>QC <a href="http://qc.embarcadero.com/wc/qcmain.aspx?d=98771" target="_blank">#98771</a>: ComboBox has no proper BiDi support.</li>
<li>QC <a href="http://qc.embarcadero.com/wc/qcmain.aspx?d=98772" target="_blank">#98772</a>: TreeView is not properly right aligned when BiDiMode is set to bdRightToLeft.</li>
<li>QC <a href="http://qc.embarcadero.com/wc/qcmain.aspx?d=98773" target="_blank">#98773</a>: TTabControl is not right aligned when BidiMode is set to bdRightToLeft.</li>
<li>QC <a href="http://qc.embarcadero.com/wc/qcmain.aspx?d=98774" target="_blank">#98774</a>: Both main menu and popup menu have serious problems in supporting bi-directional text.</li>
<li>QC <a href="http://qc.embarcadero.com/wc/qcmain.aspx?d=98775" target="_blank">#98775</a>: TStringGrid has no proper support for bi-directional text.</li>
</ul>
<p>BTW, here is a request in Delphi UserVoice website demanding better support for bidirectional user interfaces in Delphi. Please vote for this one too:</p>
<ul>
<li><a href="http://delphi.uservoice.com/forums/4432-general/suggestions/2231089-better-support-for-bidirectional-user-interfaces?ref=title" target="_blank">Better support for Bidirectional user interfaces</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://vcldeveloper.com/news/firemonkey-and-support-for-bi-directional-text-2/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>RAD Studio XE2 is released!</title>
		<link>http://vcldeveloper.com/news/rad-studio-xe2-is-released/</link>
		<comments>http://vcldeveloper.com/news/rad-studio-xe2-is-released/#comments</comments>
		<pubDate>Thu, 01 Sep 2011 19:57:13 +0000</pubDate>
		<dc:creator>Ali Keshavarz</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Delphi]]></category>
		<category><![CDATA[Delphi XE2]]></category>
		<category><![CDATA[RAD Studio]]></category>
		<category><![CDATA[RAD Studio XE2]]></category>
		<category><![CDATA[XE2]]></category>

		<guid isPermaLink="false">http://vcldeveloper.com/?p=476</guid>
		<description><![CDATA[Eventually RAD Studio XE2 is RTMed and ready for download. There is a good article in the online documentation wiki about what&#8217;s new in Delphi and C++ Builder XE2. You can also view the features matrix for different editions here. And here  is download link for the 30-days trial version from Embarcadero. Before installing the [...]]]></description>
			<content:encoded><![CDATA[<p>Eventually RAD Studio XE2 is RTMed and ready for download. There is a good article in the online documentation wiki about <a href="http://docwiki.embarcadero.com/RADStudio/en/What%27s_New_in_Delphi_and_C%2B%2BBuilder_XE2" target="_blank">what&#8217;s new in Delphi and C++ Builder XE2.</a> You can also view the features matrix for different editions <a href="http://edn.embarcadero.com/article/images/41566/RAD_Studio_XE2_Feature_Matrix.pdf" target="_blank">here</a>.</p>
<p>And here  is <a href="https://downloads.embarcadero.com/free/rad_studio" target="_blank">download link</a> for the 30-days trial version from Embarcadero. Before installing the final version, if you already have XE2 beta installed, make sure you uninstall it completely and remove all of its folders which might remain undeleted; otherwise, you might have to deal with weird installation issues.</p>
<p>I hope this will be a new start for Delphi <img src='http://vcldeveloper.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://vcldeveloper.com/news/rad-studio-xe2-is-released/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>FireMonkey and support for bi-directional text</title>
		<link>http://vcldeveloper.com/news/firemonkey-and-support-for-bi-directional-text/</link>
		<comments>http://vcldeveloper.com/news/firemonkey-and-support-for-bi-directional-text/#comments</comments>
		<pubDate>Tue, 16 Aug 2011 02:52:00 +0000</pubDate>
		<dc:creator>Ali Keshavarz</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Delphi]]></category>
		<category><![CDATA[FireMonkey]]></category>
		<category><![CDATA[RAD Studio]]></category>
		<category><![CDATA[RAD Studio XE2]]></category>

		<guid isPermaLink="false">http://vcldeveloper.com/news/firemonkey-and-support-for-bi-directional-text/</guid>
		<description><![CDATA[If you are following Delphi news, you probably know that Delphi XE2 is supposed to be released very soon, and it has many exciting features. One of the important new features introduced in Delphi XE2 is its GPU-accelerated, vector-based GUI framework; FireMonkey. I talked about XE2 and FireMonkey in the previous post, but since it [...]]]></description>
			<content:encoded><![CDATA[<p>If you are following Delphi news, you probably know that Delphi XE2 is supposed to be released very soon, and it has many exciting features. One of the important new features introduced in Delphi XE2 is its GPU-accelerated, vector-based GUI framework; FireMonkey. I talked about XE2 and FireMonkey in the <a href="http://vcldeveloper.com/news/waiting-for-delphi-xe2-with-excitement/" target="_blank">previous post</a>, but since it is not officially released yet, I am not sure if FireMonkey will have any support for bi-directional (BiDi) text and Right-to-Left languages. A few days ago, I asked Andreano Lanusse in his <a href="http://www.andreanolanusse.com/en/video-delphi-xe2-and-firemonkey-app-on-windows-mac-and-ios/" target="_blank">blog post</a> about this, but I received no reply. Well, I knew FireMonkey is based on existing KSDev <a href="http://www.ksdev.com/wiki/index.php?title=VGScene" target="_blank">VGScene</a> component which was purchased by Embarcadero earlier this year. I had played with VGScene a while ago; however, I couldn’t remember if it had any support for bi-directional text. Anyhow, I decided to install a copy of the last published version of VGScene (4.2) on Delphi XE to see what kind of support for BiDi text languages it provides.</p>
<p>Before I describe my experience with VGScene, let me explain what supporting bi-directional text really means, why is it important, and what kind of support for it exists in MS Windows…</p>
<p><span id="more-468"></span></p>
<h3>What is support for BiDi , and why is it important?</h3>
<p>First of all, you probably know that, not all languages in the world are written from left to right; a few languages including Arabic, Persian, Urdu, Hebrew, and Maldivian are written from right to left. Some languages like Chinese can be written in any direction; left to right, right to left, or top to down.</p>
<p>Displaying a right-to-left text in computers is not as simple as flipping the screen order, because in some cases, your right-to-left text may contain left-to-right character too. That way, either the left-to-right or the right-to-left characters would be displayed incorrectly. Such a text which is a mixture of left-to-right and right-to-left characters is called Bi-directional (BiDi) text, and supporting bi-directional text in computer means displaying and inputting BiDi text correctly. You can read more about it in <a href="http://en.wikipedia.org/wiki/Bi-directional_text" target="_blank">Wikipedia</a>.</p>
<p>But why is BiDi important?</p>
<p>Right-to-left languages are widespread in Middle East, North Africa, and Central Asia. <a href="http://en.wikipedia.org/wiki/Arabic_language" target="_blank">Arabic</a> has the third largest population of official usages in the world, after English and French, with 26 countries using it as their official language, and more than 280 million people speaking it as their first language. It is also language of Quran (Koran), the holly Muslims’ book. Quran and Islamic prayers are read in Arabic, so every Muslim in the world should have a basic knowledge of Arabic to say his/her daily prayers. Islam is the second largest religion in the world with more than 1.5 billion followers all over the world, and the one with the fastest pace of growth.</p>
<p><a href="http://en.wikipedia.org/wiki/Persian_language" target="_blank">Persian</a> is the official language in 3 countries with more than 100 million population. <a href="http://en.wikipedia.org/wiki/Urdu" target="_blank">Urdu</a> is the official language in Pakistan, with more than 60 million speakers. <a href="http://en.wikipedia.org/wiki/Hebrew_language" target="_blank">Hebrew</a> is the Jewish language, and language of Torah. There are more than 13 million Jews around the world.</p>
<p>Summing all of these, more than <strong><span style="text-decoration: underline;">400 million people in 30 countries</span></strong> all over the world are using a right-to-left language as their first language, and more than 1.5 billion people are using a right-to-left language as their religious language.</p>
<p>From software development point of view, if you are writing a software targeting any market in Middle East, Central Asia, or North Africa, or writing a religious software for Muslims or Jews; you <strong><em>need</em></strong> BiDi support in your software.</p>
<h3>BiDi support in Windows</h3>
<p>Win32 always have had adequate support for right-to-left languages. Currently Windows supports Arabic and Hebrew scripts. Persian uses Arabic alphabet, so supporting Arabic is enough to support Persian too. Since Windows 2000, Windows started to fully support Unicode, which made supporting displaying and inputting right-to-left text in Windows easier. Win32 also supports right-to-left layout for controls and windows using some extended styles. Particularly, Win32 provides four <a href="http://msdn.microsoft.com/en-us/library/ff700543" target="_blank">extended styles</a> regarding BiDi support in Windows controls:</p>
<ul>
<li>
<div><strong>WS_EX_LAYOUTRTL</strong><br />
Arabic and Hebrew versions of Windows 98/Me, Windows 2000/XP: Creates a window whose horizontal origin is on the right edge. Increasing horizontal values advance to the left.</div>
</li>
<li>
<div><strong>WS_EX_LEFTSCROLLBAR</strong><br />
If the shell language is Hebrew, Arabic, or another language that supports reading order alignment, the vertical scroll bar (if present) is to the left of the client area. For other languages, the style is ignored.</div>
</li>
<li>
<div><strong>WS_EX_RIGHT</strong><br />
The window has generic &#8220;right-aligned&#8221; properties. This depends on the window class. This style has an effect only if the shell language is Hebrew, Arabic, or another language that supports reading-order alignment; otherwise, the style is ignored. Using the WS_EX_RIGHT style for static or edit controls has the same effect as using the SS_RIGHT or ES_RIGHT style, respectively. Using this style with button controls has the same effect as using BS_RIGHT and BS_RIGHTBUTTON styles.</div>
</li>
<li>
<div><strong>WS_EX_RTLREADING</strong><br />
If the shell language is Hebrew, Arabic, or another language that supports reading-order alignment, the window text is displayed using right-to-left reading-order properties. For other languages, the style is ignored.</div>
</li>
</ul>
<p>Using these styles, you can have right-to-left windows and child controls with proper BiDi text displaying and input. Microsoft provided the same support for BiDi in .NET WinForms, and WPF windows too.</p>
<h3>BiDi support in Delphi VCL</h3>
<p>In Delphi, BiDi support is basically provided in TControl class by exposing <a href="http://docwiki.embarcadero.com/VCL/e/index.php/Controls.TControl.BiDiMode" target="_blank">BiDiMode</a> property which specifies four different modes of displaying and layouting controls for left-to-right or right-to-left text. Beside that, TWinControl class provides <a href="http://docwiki.embarcadero.com/VCL/e/index.php/Controls.TWinControl.FlipChildren" target="_blank">FlipChildren</a> method which flips children of a container control from left to right or vice versa. Also TApplication class has two properties; BiDiKeyboard, and NonBiDiKeyboard which specify keyboard layout which should be loaded automatically based on a BiDiMode value of a control when user focuses on that particular control. For example, you can specify Arabic layout code for Application.BiDiKeyboard, and English layout code for Application.NonBiDiKeyboard in your source code, and whenever the user focuses on a right-to-left control in any of application forms, the active input keyboard changes to Arabic, and when he/she focuses a left-to-right control, the active input keyboard changes to English. Take note that Application.NonBiDiKeyboard and Application.BiDiKeyboard are kinda useless in Windows Vista and Windows 7, because they call <a href="http://msdn.microsoft.com/en-us/library/ms646305%28v=vs.85%29.aspx" target="_blank">LoadKeyboardLayout</a> API function every time a control is focused, instead of <a href="http://msdn.microsoft.com/en-us/library/ms646289%28v=vs.85%29.aspx" target="_blank">ActiveKeyboardLayout</a> API, and in such versions of Windows that causes a big delay which makes the forms load slower, and flicker when focus is changed; but that is another story.</p>
<p>There are some other methods and functions in VCL that can help you to write a BiDi-enabled application. You can read more about BiDi support in VCL in RAD Studio <a href="http://docwiki.embarcadero.com/RADStudio/en/Including_Bi-directional_Functionality_in_Applications" target="_blank">documentation</a>.</p>
<p>As you can see, BiDi support is built into VCL deep from its base class for all controls. The problem is that, not all controls in VCL hierarchy implement this feature properly; that means, there are many different controls that while being created or being drawn, do not take BiDi support into consideration, so changing their BiDiMode property have no effect on them, or in some cases brings up unexpected behaviors. For example, attaching a right-to-left DBGrid to ClientDataset will draw the grid totally useless:</p>
<table border="0" cellspacing="0" cellpadding="2" width="663">
<tbody>
<tr>
<td width="310" valign="top"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; float: left; padding-top: 0px; border-width: 0px;" title="LTR_Grid_VCL" src="http://vcldeveloper.com/wp-content/uploads/2011/08/LTR_Grid_VCL_thumb.png" border="0" alt="LTR_Grid_VCL" width="240" height="38" align="left" />Left-to-right DBGrid with BiDi text.</td>
<td width="351" valign="top"><a href="http://vcldeveloper.com/wp-content/uploads/2011/08/RTL_Grid_VCL.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="RTL_Grid_VCL" src="http://vcldeveloper.com/wp-content/uploads/2011/08/RTL_Grid_VCL_thumb.png" border="0" alt="RTL_Grid_VCL" width="240" height="38" /></a><br />
Right-to-Left DBGrid attached to ClientDataset</td>
</tr>
</tbody>
</table>
<p>Setting BiDiMode for Delphi Ribbon, or PageControl, or TreeView control has no effect on them. PageControl and TreeView are standard Windows controls with support of right-to-left layout, but they are not wrapped properly in VCL:</p>
<table border="0" cellspacing="0" cellpadding="2" width="665">
<tbody>
<tr>
<td width="320" valign="top"><a href="http://vcldeveloper.com/wp-content/uploads/2011/08/RTL_Tab_VCL.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="RTL_Tab_VCL" src="http://vcldeveloper.com/wp-content/uploads/2011/08/RTL_Tab_VCL_thumb.png" border="0" alt="RTL_Tab_VCL" width="229" height="68" /></a><br />
<span style="font-size: x-small;">VCL: BiDiMode is set to bdRightToLeft, but PageControl is still left-tot-right.<br />
</span></td>
<td width="343" valign="top"><a href="http://vcldeveloper.com/wp-content/uploads/2011/08/RTL_Tab_WinForms.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="RTL_Tab_WinForms" src="http://vcldeveloper.com/wp-content/uploads/2011/08/RTL_Tab_WinForms_thumb.png" border="0" alt="RTL_Tab_WinForms" width="244" height="60" /></a><br />
WinForms: TabControl is properly set to right-to-left alignment.</td>
</tr>
<tr>
<td width="320" valign="top"><a href="http://vcldeveloper.com/wp-content/uploads/2011/08/RTL_TreeView_VCL.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="RTL_TreeView_VCL" src="http://vcldeveloper.com/wp-content/uploads/2011/08/RTL_TreeView_VCL_thumb.png" border="0" alt="RTL_TreeView_VCL" width="264" height="116" /></a><br />
<span style="font-size: x-small;">VCL: BiDiMode is set to bdRightToLeft, but TreeView, and CategoryButtons are still left-tot-right.<br />
</span></td>
<td width="343" valign="top"><a href="http://vcldeveloper.com/wp-content/uploads/2011/08/RTL_TreeView_WinForms.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="RTL_TreeView_WinForms" src="http://vcldeveloper.com/wp-content/uploads/2011/08/RTL_TreeView_WinForms_thumb.png" border="0" alt="RTL_TreeView_WinForms" width="244" height="133" /></a><br />
WinForms: TreeView is properly set to right-to-left alignment.</td>
</tr>
</tbody>
</table>
<p>Sometimes setting BiDiMode for a control to bdRightToLeft makes its text BiDi-enabled, but the control itself is not layouted right-to-left:</p>
<table border="0" cellspacing="0" cellpadding="2" width="665">
<tbody>
<tr>
<td width="323" valign="top"><a href="http://vcldeveloper.com/wp-content/uploads/2011/08/RTL_Menu_VCL.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="RTL_Menu_VCL" src="http://vcldeveloper.com/wp-content/uploads/2011/08/RTL_Menu_VCL_thumb.png" border="0" alt="RTL_Menu_VCL" width="164" height="184" /></a><br />
<span style="font-size: x-small;">BiDiMode is set to bdRightToLeft, but main menu control is aligned left-to-right. </span></td>
<td width="340" valign="top"><a href="http://vcldeveloper.com/wp-content/uploads/2011/08/RTL_Menu_WinForms.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="RTL_Menu_WinForms" src="http://vcldeveloper.com/wp-content/uploads/2011/08/RTL_Menu_WinForms_thumb.png" border="0" alt="RTL_Menu_WinForms" width="164" height="184" /></a><br />
WinForms: Menu is properly set to right-to-left alignment.</td>
</tr>
</tbody>
</table>
<p>BiDi support in third-party components is not consistent either; some components like <a href="http://www.fast-report.com/en/products/" target="_blank">FastReport</a> have very nice support for BiDi text. <a href="http://www.raize.com/devtools/rzcomps/" target="_blank">Raize components</a> are usually good in right-to-left layout thanks to their custom rendering methods. <a href="http://www.delphi-gems.com/index.php?option=com_content&amp;task=view&amp;id=12&amp;Itemid=38" target="_blank">VirtualTreeView</a> and <a href="http://www.ehlib.com/" target="_blank">EhLib</a> have nice BiDi support too. I like TMS components a lot, specially their <a href="http://www.tmssoftware.com/site/advsmoothcontrols.asp" target="_blank">Smooth Controls</a>, but BiDi support in <a href="http://www.tmssoftware.com/site/products.asp?t=vcl" target="_blank">TMS components</a> is weak, except their grid component. I don’t use <a href="http://www.devexpress.com/Products/VCL/" target="_blank">DevExpress</a> components, but I heard their components are quiet good in handling BiDi.</p>
<h3>BiDi support in KSDev VGScene</h3>
<p>OK, examining this one was the main reason of writing this blog post; the truth is, unfortunately, VGScene has no BiDi support, yes you read it right, NO support. I checked properties in VGScene controls several times; no such BiDiMode, or RightToLeft, or RTL property exists. VGScene is not able to render BiDi text properly, or set proper right-to-left alignment for its controls.</p>
<p>There is a property called TextAlign in some controls, at first I thought that is the property I was looking for, but later on I found out it just aligns text in the control to either left or right side, but does not set text direction accordingly, that means no BiDi support!</p>
<p>If you don’t know Persian, you might think text in the pictures below is drawn correctly; however, if you look carefully, you will notice the dot (.) character at the beginning of the right-to-left text in VGScene screenshot. You may also notice that text shown in VGScene is not the same as the text in WPF.Actually the text in WPF screenshot means “This is a Test”, and Test is written in English while the rest of it is written in Persian. The text in VGScene screenshot is meaningless; that is because VGScene has no sense of BiDi, and when you mix a Latin character or punctuation symbol with your right-to-left characters, it draws the whole text as a mess.</p>
<table border="0" cellspacing="0" cellpadding="2" width="400">
<tbody>
<tr>
<td width="52" valign="top"><a href="http://vcldeveloper.com/wp-content/uploads/2011/08/RTL_TextBox_VGScene.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="RTL_TextBox_VGScene" src="http://vcldeveloper.com/wp-content/uploads/2011/08/RTL_TextBox_VGScene_thumb.png" border="0" alt="RTL_TextBox_VGScene" width="224" height="184" /></a><br />
VGScene</td>
<td width="348" valign="top"><a href="http://vcldeveloper.com/wp-content/uploads/2011/08/RTL_TextBox_WPF.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="RTL_TextBox_WPF" src="http://vcldeveloper.com/wp-content/uploads/2011/08/RTL_TextBox_WPF_thumb.png" border="0" alt="RTL_TextBox_WPF" width="224" height="184" /></a><br />
WPF</td>
</tr>
</tbody>
</table>
<p>Well VGScene is not able to properly change layout of a control to right-to-left either. The screenshot below shows two TreeView controls in VGScene, in the left control TextAlign is set to left, and in the right control it is set to right. As you can see, when you right-align a treeview item, its text goes to the right side, but the arrow icon and children indentation remain on the left-side, making the TreeView to look something like a simple ListBox:</p>
<p><a href="http://vcldeveloper.com/wp-content/uploads/2011/08/RTL_TreeView_VGScene.png"><img style="background-image: none; margin: 0px 12px 0px 0px; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="RTL_TreeView_VGScene" src="http://vcldeveloper.com/wp-content/uploads/2011/08/RTL_TreeView_VGScene_thumb.png" border="0" alt="RTL_TreeView_VGScene" width="414" height="184" /></a></p>
<p>Even if TextAlign property was supposed to be a property to define BiDi mode, Unlike BiDiMode in VCL or RightToLeft in WinForms or FlowDirection in WPF, it does not affect other controls hierarchically; that means, you should set it for every control separately, even in TreeView case, for every tree node.</p>
<p>For VGScene to support BiDi mode properly, it needs to add a property similar to BiDiMode in VCL in the base control class, and it should change the code for drawing a control or its text according to the value of this new property. How WPF implemented support for BiDi mode in the user interface can be a good template for modifying VGScene (or FireMonkey) to properly support BiDi text. You can read more about BiDi support in WPF here: <a href="http://msdn.microsoft.com/en-us/library/aa350685.aspx" target="_blank">Bidirectional features in WPF overview.</a></p>
<h3>Conclusion</h3>
<p>It is obvious that BiDi support was not a goal in VGScene design. VGScene is not in development anymore. It is sold to Embarcadero, and now its sequel is called FireMonkey. As I mentioned earlier, it is not clear whether FireMonkey will bring proper support for BiDi text or not. I am personally doubtful about it; because some of the new VCL controls are designed with no BiDi support in mind, and many obvious BiDi-related bugs in the older controls are remained unfixed for years. To me that is an indication that such a support is not a big concern for Embarcadero developers. What’s more, Andreano Lanusse somehow ignored answering my question regarding this support in FireMonkey, which can be another indication that such a support does not exist. I really hope my doubt is proved wrong, because if BiDi support in FireMonkey is the same as what I saw in VGScene, this tool will be useless in BiDi environments.</p>
<h3><span style="color: #ff0000;">Update (08/24/2011)<br />
</span></h3>
<p style="text-align: justify; padding-left: 30px;">As you can read in the comment; <a href="http://www.andreanolanusse.com/" target="_blank">Andreano Lanusse</a> from Embarcadero confirmed that FireMonkey in RAD Studio XE2 will not have BiDi support, but they included it in their RoadMap. The roadmap is not  published yet, thus we gotta wait for it and see when is BiDi support supposed to be included in FireMonkey. I hope they do it in an update pack for XE2 rather than postponing it to future releases of RAD Studio. Here I also should appreciate Andreano&#8217;s efforts for informing me and trying to include this feature in their roadmap.</p>
]]></content:encoded>
			<wfw:commentRss>http://vcldeveloper.com/news/firemonkey-and-support-for-bi-directional-text/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Waiting for Delphi XE2 with excitement</title>
		<link>http://vcldeveloper.com/news/waiting-for-delphi-xe2-with-excitement/</link>
		<comments>http://vcldeveloper.com/news/waiting-for-delphi-xe2-with-excitement/#comments</comments>
		<pubDate>Sat, 06 Aug 2011 20:41:00 +0000</pubDate>
		<dc:creator>Ali Keshavarz</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Delphi]]></category>
		<category><![CDATA[FireMonkey]]></category>
		<category><![CDATA[RAD Studio]]></category>
		<category><![CDATA[RAD Studio XE2]]></category>
		<category><![CDATA[XE2]]></category>

		<guid isPermaLink="false">http://vcldeveloper.com/news/waiting-for-delphi-xe2-with-excitement/</guid>
		<description><![CDATA[Delphi world is full of good news these days. Delphi XE2 is announced officially a couple of days ago, and it is supposed to bring some lovely features It was obvious that XE2 will bring 64-bits support to Delphi, along with supporting Mac OS as a new target platform. Mac OS support was supposed to [...]]]></description>
			<content:encoded><![CDATA[<p align="justify">Delphi world is full of good news these days. Delphi XE2 is announced officially a couple of days ago, and it is supposed to bring some lovely features <img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://vcldeveloper.com/wp-content/uploads/2011/08/wlEmoticon-smile.png" /></p>
<p align="justify">It was obvious that XE2 will bring 64-bits support to Delphi, along with supporting Mac OS as a new target platform. Mac OS support was supposed to be added to Delphi XE, but it was postponed to this release. Although 64-bits and Mac OS support are cool, they were both expected. The big news was FireMonkey!</p>
<p align="justify">When Embarcadero announced their plan for adding Mac OS support, the original plan was a continuation of the old CLX framework which was based on Qt. The difference was, the new CLX was supposed to bring just cross-compiling for Mac OS (and later on Linux), not like original CLX which had a Linux-based IDE (Kylix) for compiling the same source code for Linux. However the plan changed, Embarcadero bought <a href="http://www.ksdev.com/" target="_blank">KSDev</a> company, creator of <a href="http://www.ksdev.com/wiki/index.php?title=VGScene" target="_blank">VGScene</a> and <a href="http://www.ksdev.com/wiki/index.php?title=DXScene" target="_blank">DXScene</a> components, and hired its programmer. They decided to provide a vector-based, GPU accelerated, cross-platform GUI framework based on the recently bought KSDev products; and that is <strong>FireMonkey</strong>.</p>
<div align="justify"><span id="more-446"></span></div>
<p align="justify">FireMonkey is the new cross-platform GUI framework for Delphi. You can create Windows (32-bits, 64-bits), Mac OS (32-bits), and iOS (32-bits) applications using FireMonkey in Delphi XE2. <a href="http://en.wikipedia.org/wiki/IOS_%28Apple%29" target="_blank">iOS</a> addition was a surprised, and I didn’t expect it; although it is not a direct compilation to ARM code. Actually you have to export your iOS code to a <a href="http://en.wikipedia.org/wiki/Xcode" target="_blank">XCode</a> project, and compile it with XCode, to be able to run it on your iPhone or iPad devices. Also, 64-bits support for Mac is not ready yet. It seems they are still working on it.</p>
<p align="justify">On Windows platform, FireMonkey uses <a href="http://en.wikipedia.org/wiki/Direct2D" target="_blank">Direct2D</a> for 2D renderings, <a href="http://en.wikipedia.org/wiki/Direct3D" target="_blank">Direct 3D</a> for 3D renderings; and OpenGL on Mac OS. If Direct2D is not available, FireMonkey will fall back to GDI+ to render the GUI.</p>
<p align="justify">Here is a video by <cite><a href="http://www.andreanolanusse.com">Andreano Lanusse</a></cite> demoing 3D capabilities of FireMonkey on Windows, Mac OS, and iOS :</p>
<div style="padding-bottom: 0px; padding-left: 0px; width: 448px; padding-right: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-top: 0px" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:02c9f24e-3a9e-4a72-9c8a-9cfaa595db59" class="wlWriterEditableSmartContent">
<div><object width="448" height="252"><param name="movie" value="http://www.youtube.com/v/JtFIw2YpuQc?hl=en&amp;hd=1"></param><embed src="http://www.youtube.com/v/JtFIw2YpuQc?hl=en&amp;hd=1" type="application/x-shockwave-flash" width="448" height="252"></embed></object></div>
<div style="width:448px;clear:both;font-size:.8em">Delphi XE2 and FireMonkey Application on Windows, Mac OS, and iOS</div>
</div>
<p>&#160;</p>
<p align="justify">You can also read more about FireMonkey on Andreano’s weblog (Do not miss the comments) :</p>
<p align="justify"><a href="http://www.andreanolanusse.com/en/a-little-bit-about-firemonkey-and-delphi-xe2/" target="_blank">A little bit about FireMonkey and Delphi XE2</a></p>
<p align="justify">However that is not the whole story; in XE2 we don’t need to deal with a separate set of components as data-aware components. Now in XE2 we will have Live Binding. It means we can bind any data source to any visual control. If you are familiar with .NET controls, you probably saw this binding property. Now the same thing exists in Delphi too.</p>
<p align="justify">What’s more, DataSnap and DBX are also enhanced; for DataSnap, AFAIK, proxy class generators are added for many platforms (i.e. Android, iOS, JavaScript, .NET, BlackBerry, etc.). Also I heard some features are added for deployment to could.&#160; For DBX, it seems a driver for ODBC is added.</p>
<p align="justify">Beside all of these new features, the popular reporting tool, <a href="http://www.fast-report.com/en/products/developer_tools_for_borland.html" target="_blank">FastReport</a>, will be shipped by default with Delphi XE2 too.</p>
<p align="justify">There must be many enhancements and additions to Delphi RTL too, but I haven’t heard anything about them yet. So we have to wait for other <a href="http://www.embarcadero.com/world-tour" target="_blank">worldwide tours</a> Embarcadero is conducting in August to get more detail information about this exciting release. </p>
<p align="justify">It seems XE2 might be the most significant Delphi release in the past decade. It is not officially announced when XE2 will be released, but I can guess it will be some time in September.</p>
]]></content:encoded>
			<wfw:commentRss>http://vcldeveloper.com/news/waiting-for-delphi-xe2-with-excitement/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Implementing Singleton pattern in Delphi</title>
		<link>http://vcldeveloper.com/tips-tricks/implementing-singleton-pattern-in-delphi/</link>
		<comments>http://vcldeveloper.com/tips-tricks/implementing-singleton-pattern-in-delphi/#comments</comments>
		<pubDate>Fri, 03 Jun 2011 21:49:23 +0000</pubDate>
		<dc:creator>Ali Keshavarz</dc:creator>
				<category><![CDATA[Tips & Tricks]]></category>
		<category><![CDATA[Delphi]]></category>
		<category><![CDATA[Singleton]]></category>

		<guid isPermaLink="false">http://vcldeveloper.com/?p=421</guid>
		<description><![CDATA[There are several ways to implement Singleton pattern in Delphi. Most of the publicly available source codes that I saw use old techniques to keep backward compatibility with older versions of Delphi (e.g. Delphi 7). In such techniques usually a global variable or a writable const is used to keep a reference to the singleton [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">There are several ways to implement <a title="Singleton pattern" href="http://en.wikipedia.org/wiki/Singleton_pattern" target="_blank">Singleton pattern</a> in Delphi. Most of the publicly available source codes that I saw use old techniques to keep backward compatibility with older versions of Delphi (e.g. Delphi 7). In such techniques usually a global variable or a writable const is used to keep a reference to the singleton instance; because in those old versions of Delphi, there were no way to define a class variable.</p>
<p style="text-align: justify;">Also many of them try to hide the constructor under protected visibility, assuming it would prohibit users from instantiating the class, and forcing them to use the defined method for accessing the singleton instance. I can’t realize what was the rationale behind hiding the constructor, because all Delphi classes are inherited from <a title="TObject" href="http://docwiki.embarcadero.com/VCL/en/System.TObject" target="_blank">TObject</a>, and it already has a default Create constructor defined as public, so a user can always call that Create method to instantiate a new object and getting around your singleton implementation.</p>
<p style="text-align: justify;">A few months ago when I was looking for a singleton implementation in Delphi which does not use old writable consts or global variables; I found <a title="Implementing the Singleton Design Pattern in Delphi without Global Variables" href="http://www.yanniel.info/2010/10/singleton-pattern-delphi.html" target="_blank">a blog post</a> by Yanniel Alvarez Alfonso, implementing Singleton pattern using class variables, but there was still the problem of hiding constructors, so I wrote a comment there, telling him that hiding the constructor is not a good idea; and instead of that, he should override TObject.NewInstance method. He appreciated the note, and changed his code to reflect that.</p>
<p style="text-align: justify;">Today I needed to implement Singleton again, but I was too lazy to write it, so I searched for it in my source codes, but didn’t find my own code! I tried my favorite modeling tool; <a title="ModelMaker" href="http://www.modelmakertools.com/modelmaker/index.html" target="_blank">ModelMaker</a>, but their Singleton pattern implementation was the same old-style writable const technique (even in the new ModelMaker 11). Eventually I decided to write it again, and save it as a code template in ModelMaker to use it later when I need it and I am not in the mood of writing it again and again <img class="wlEmoticon wlEmoticon-smile" style="border-style: none;" src="http://vcldeveloper.com/wp-content/uploads/2011/06/wlEmoticon-smile.png" alt="Smile" /></p>
<p><span id="more-421"></span></p>
<h2>Singleton Implementation</h2>
<p>Here is my implementation of a singleton class:</p>
<pre class="brush: delphi; title: ; notranslate">
unit uSingleton;

interface

uses
  Windows;

type
  TSingleton = class sealed(TObject)
  strict private
    class var
      _Instance: TSingleton;
    /// This lock assures us that our singleton instance will be
    /// created only once in a multi-threaded environment.
    CreationLock: RTL_CRITICAL_SECTION;
    class function GetInstance: TSingleton; static; inline;
  private
    procedure InitInstanceFields;
  public
    class constructor ClassCreate;
    constructor Create;
    class destructor ClassDestroy;
    destructor Destroy; override;
    class function NewInstance: TObject; override; final;
    class property Instance: TSingleton read GetInstance;
  end;

implementation

{ TSingleton }
class constructor TSingleton.ClassCreate;
begin
  InitializeCriticalSection(CreationLock);
end;

constructor TSingleton.Create;
begin
  inherited;

end;

class destructor TSingleton.ClassDestroy;
begin
  /// If singleton instance is not destroyed by user, destroy it automatically.
  if Assigned(_Instance) then
  begin
    _Instance.Free;
    _Instance := nil;
  end;
  DeleteCriticalSection(CreationLock);
end;

destructor TSingleton.Destroy;
begin
  /// Make the singleton instance nil before destroying it.
  /// This way, next time Instance property is accessed, a
  /// new instance will be created.
  _Instance := nil;
  inherited;
end;

class function TSingleton.GetInstance: TSingleton;
begin
  Result := Self.Create;
end;

procedure TSingleton.InitInstanceFields;
begin
  { TODO : Initialize your instance here}
end;

class function TSingleton.NewInstance: TObject;
begin
  /// New instance is called when a new instance is being created.
  /// We first check if the singleton instance is assigned, if
  /// it is not assigned yet, we let NewInstance assign a new
  /// instance; Otherwise, we make it to return our already assigned
  /// singleton object.
  /// This way we will always have a single instance of the class
  /// even if user calls Create() method of our class.
  if not Assigned(_Instance) then
  begin
    EnterCriticalSection(CreationLock);
    try
      _Instance := inherited NewInstance as Self;
      _Instance.InitInstanceFields;
    finally
      LeaveCriticalSection(CreationLock);
    end;
  end;

  Result := _Instance;
end;

end.
</pre>
<p style="text-align: justify;">The important piece of this code is overriding <a title="TObject.NewInstance" href="http://docwiki.embarcadero.com/VCL/XE/en/System.TObject.NewInstance" target="_blank">TObject.NewInstance</a> method. TObject.NewInstance is defined as a virtual class function. It is responsible for allocating memory for an instance of a class and returning a pointer to the allocated memory. NewInstance is called by all constructors automatically. So, if you override NewInstance method, you can control how instances of a class are allocated. What we do here is to make sure NewInstance allocates memory for our class instances only once, and if an instance is already created, it returns a pointer to that instance rather than allocating new memory. This way, we do not need to hide our constructors, because even if you call constructor of your class, it relays on NewInstance for its memory allocation, and will always return the same singleton instance.</p>
<blockquote>
<p style="padding-left: 30px; text-align: justify;"><span style="text-decoration: underline;"><strong>WARNING</strong></span>: Take note that if you have any initialization code in your constructor, calling it more than once will execute those initialization codes again, so you’d better take care of that in your constructor; otherwise, you might end up having memory leaks or losing the data stored in that singleton instance! To avoid that, I added a new method called InitInstanceFields which is called by NewInstance whenever the singleton instance is being assigned. You can put your initialization codes in that method.</p>
</blockquote>
<p style="text-align: justify;">As it is obvious, this code won’t compile in older version of Delphi, because we are using class constructor\destructor, strict private visibility, and class var.  You need Delphi 2010 or newer versions to compile this code. Class constructors and class destructors were introduced in Delphi 2010 as an object-oriented replacement for unit <a title="unit initialization" href="http://www.delphibasics.co.uk/RTL.asp?Name=Unit&amp;ExpandCode1=Yes" target="_blank">initialization</a> and <a title="unit finalization" href="http://www.delphibasics.co.uk/RTL.asp?Name=Unit&amp;ExpandCode1=Yes" target="_blank">finalization</a> sections. They work almost the same as initialization and finalization sections, but have a big advantage over those old unit sections; a unit initialization or finalization section is always executed, either you use the corresponding classes or not. On the other hand, a class constructor or destructor is executed only if you use a class or one of its instances in your code. If you do not use the class, its class constructor or destructors won’t execute. That is how (along with <a title="Libraries and Packages (Delphi)" href="http://docwiki.embarcadero.com/RADStudio/en/Libraries_and_Packages" target="_blank">DLL delay loading</a>) Delphi team added gesture support to existing Delphi controls without such a big overhead in Delphi 2010. You can read more about class constructors and destructors in <a title="Class Constructors. Popping the hood." href="http://blogs.embarcadero.com/abauer/2009/09/04/38899" target="_blank">this blog post</a> by Allen Bauer.</p>
<h2>ModelMaker Code Template</h2>
<p style="text-align: justify;">OK, now that we have the code, we can change it a little to turn it in to a <a title="ModelMaker" href="http://www.modelmakertools.com/modelmaker/index.html" target="_blank">ModelMaker</a> code templates. Code templates are custom patterns which can be defined by the user, and applied on an element in ModelMaker. Our template is simple, the only change we need to make is using <em>&lt;!ClassName!&gt;</em> macro. This macro will be expanded automatically to the actual class name by ModelMaker. Once our code is ready, we can open ModelMaker, go to <em>View | Patterns</em> menu (Shift + F7), and once Patterns dialog is open, right-click on an empty area of the dialog, and select <em>Register Code Template</em> from the context menu. ModelMaker will ask for the template source file. We will give it address of our template source file, and a template name (I used “<em>Singleton Class</em>”). That’s it! Now our new template is registered and available in <em>Templates</em> tab of Patterns dialog. Select a class in your model, and open Patterns dialog, go to <em>Templates</em> tab, and click on your template button. ModelMaker will automatically apply it to your class, making your class a singleton class.</p>
<p><img class="alignnone" title="Singleton class in ModelMaker" src="/wp-content/uploads/2011/06/Singleton.png" alt="Singleton class in ModelMaker" width="160" height="217" /></p>
<p>Here is my ModelMaker template:</p>
<pre class="brush: delphi; title: ; notranslate">
unit Singleton;

interface

uses Windows;

type
  TCodeTemplate = class sealed(TObject)
  strict private
    class var _Instance: &lt;!ClassName!&gt;;
    class var CreationLock : RTL_CRITICAL_SECTION;
    class function GetInstance: &lt;!ClassName!&gt;; static; inline;
  private
    procedure InitInstanceFields;
  public
    constructor Create;
    destructor Destroy; override;
    class constructor ClassCreate;
    class destructor ClassDestroy;
    class function NewInstance: TObject; override; final;
    class property Instance: &lt;!ClassName!&gt; read GetInstance;
  end;

implementation

constructor TCodeTemplate.Create;
begin
  inherited;

end;

destructor TCodeTemplate.Destroy;
begin
  _Instance := nil;
  inherited;
end;

class constructor TCodeTemplate.ClassCreate;
begin
  InitializeCriticalSection(CreationLock);
end;

class destructor TCodeTemplate.ClassDestroy;
begin
  if Assigned(_Instance) then
  begin
    _Instance.Free;
    _Instance := nil;
  end;
  DeleteCriticalSection(CreationLock);
end;

class function TCodeTemplate.GetInstance: &lt;!ClassName!&gt;;
begin
  Result := Self.Create;
end;

procedure TCodeTemplate.InitInstanceFields;
begin
  { TODO : Initialize your instance here}
end;

class function TCodeTemplate.NewInstance: TObject;
begin
  if not Assigned(_Instance) then
  begin
    EnterCriticalSection(CreationLock);
    try
      _Instance := inherited NewInstance as Self;
      _Instance.InitInstanceFields;
    finally
      LeaveCriticalSection(CreationLock);
    end;
  end;

  Result := _Instance;
end;

end.
</pre>
<p>Have fun</p>
<p><em><strong><span style="text-decoration: underline;">Update 1</span></strong></em>: <em>I added a critical section to make the implementation thread-safe  (refer to David&#8217;s comment). The code for creating a new singleton  instance is protected by a critical section to make sure multiple  threads will not create multiple instances of the class if they are  accessing Instance property for the first time simultaneously.</em></p>
<p><em><strong><span style="text-decoration: underline;">Update 2</span></strong></em>: <em>There were some flaws in the sample source code and a bug in initializing instance fields. I updated the source code to fix those issues (Refer to Arthur&#8217;s comment and my reply to him).</em></p>
<p><em><br />
</em></p>
]]></content:encoded>
			<wfw:commentRss>http://vcldeveloper.com/tips-tricks/implementing-singleton-pattern-in-delphi/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>دانلود از مارکت آمازون برای اندروید</title>
		<link>http://vcldeveloper.com/tips-tricks/download-from-amazon-appstore-for-android/</link>
		<comments>http://vcldeveloper.com/tips-tricks/download-from-amazon-appstore-for-android/#comments</comments>
		<pubDate>Wed, 13 Apr 2011 15:21:06 +0000</pubDate>
		<dc:creator>Ali Keshavarz</dc:creator>
				<category><![CDATA[Tips & Tricks]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[Farsi]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[فارسی]]></category>

		<guid isPermaLink="false">http://vcldeveloper.com/?p=408</guid>
		<description><![CDATA[در این نوشته قصد دارم درباره چگونگی دانلود از مارکت آمازون برای اندروید بنویسم… حدود یک ماهی میشه که شرکت آمازون یک فروشگاه آنلاین برای نرم افزارهای سیستم عامل اندروید افتتاح کرده. هر چند این فروشگاه به اندازه فروشگاه اندروید مارکت گوگل نرم افزار نداره، و به اندازه اون هم همه گیر نیست، اما با [...]]]></description>
			<content:encoded><![CDATA[<div dir="rtl">
<p style="text-align: justify;" dir="rtl">در این نوشته قصد دارم درباره چگونگی دانلود از مارکت آمازون برای اندروید بنویسم…</p>
<p style="text-align: justify;" dir="rtl">حدود یک ماهی میشه که شرکت آمازون یک فروشگاه آنلاین برای نرم افزارهای سیستم عامل اندروید افتتاح کرده. هر چند این فروشگاه به اندازه فروشگاه اندروید مارکت گوگل نرم افزار نداره، و به اندازه اون هم همه گیر نیست، اما با توجه به عظمت شرکت آمازون، و تخصص آن در فروشگاه های آنلاین، و محتوای متنوعی که این شرکت ارائه میکنه، و توجه روز افزون این شرکت به تبلت ها؛ میشه امیدوار بود که این فروشگاه به زودی به عنوان رقیبی برای اندروید مارکت شرکت گوگل تبدیل بشه، و مانعی بر سر راه انحصار طلبی تدریجی گوگل در بازار اندروید بشه. در حال حاضر، آمازون هر روز یک نرم افزار تجاری را به طور رایگان در اختیار کاربرانش قرار میده، که همین خودش تبلیغ خوبی برای این سرویس هست.</p>
<p style="text-align: justify;" dir="rtl">مارکت آمازون از دو طریق وب سای و همچنین از طریق نرم افزار اختصاصی این شرکت در دسترس هست. کاربر میتونه از طریق وب سایت آمازون یا نرم افزار مارکت آمازون لیست نرم افزارها را مرور کنه، و نرم افزار دلخواه اش را خریداری کنه. در این حالت، نرم افزار مربوطه به لیست آنلاین نرم افزارهای کاربر در سایت آمازون افزوده میشه، و کاربر میتونه از طریق نرم افزار مارکت آمازون بر روی دستگاه اندروید خود، نرم افزار های خود را دانلود کرده و بر روی دستگاه نصب کنه. مارکت فعلی امکان جستجو در لیست نرم افزارها، مشاهده دسته بندی نرم افزار، مشاهده صد نرم افزار رایگان و تجاری برتر، ایجاد Wish List، و ارائه لیست نرم افزارهای پیشنهادی بر اساس علایق شما را فراهم میکنه. البته متاسفانه نرم افزار مارکت آمازون که بر روی دستگاه نصب میشه، امکان شناسایی نرم افزارهای نصب شده فعلی را نداره، و اگر بخواید نسخه جدیدی از یکی از نرم افزارهای فعلی تان را نصب کنید، آمازون قبل از نصب نسخه جدید، نسخه قبلی را حذف میکنه، اما بعد از اینکه یک بار نرم افزار مربوطه با مارکت آمازون نصب شد، دفعات بعد، می تونید بدون مشکل آن نرم افزار را توسط مارکت آمازون آپدیت کنید.</p>
<p style="text-align: justify;" dir="rtl"><span id="more-408"></span></p>
<p style="text-align: justify;" dir="rtl">
<h2 style="text-align: justify;" dir="rtl">محدودیت فعلی دانلود</h2>
<p style="text-align: justify;" dir="rtl">بزرگترین مشکل فعلی مارکت آمازون برای اندروید، محدود کردن کاربران آن به کاربران آمریکایی هست؛ یعنی فعلا به طور رسمی، مارکت آمازون فقط به کاربرانی که در آمریکا زندگی می کنند، سرویس ارائه میکنه، و کاربرانی که قصد دانلود از سایر نقاط جهان را داشته باشند، قادر نخواهند بود که از این مارکت دانلود کنند. در این حالت، برای ما کاربران ایرانی اندروید، فرق خاصی بین مارکت گوگل و آمازون وجود نخواهد داشت؛ در هر دو حالت، امکان دانلود نرم افزار برای ما فراهم نیست.</p>
<p style="text-align: justify;" dir="rtl">اما برخلاف گوگل، شرکت آمازون کنترل خاصی بر روی دستگاه های اندروید فروخته شده نداره، و به اندازه گوگل هم محدودیت برای کاربران ایجاد نمیکنه. در واقع دانلود نرم افزار مارکت آمازون برای اندروید توسط هر کاربری حتی ایرانی امکان پذیر هست، و ثبت نام در سایت آمازون هم آزاد هست؛ اما در هنگام دانلود، آمازون از شما میخواد که اطلاعات مربوط به بخش ۱-Click Purchase را در خصوصیات کاربری خودتان وارد کنید. این اطلاعات شامل آدرس شما، و اطلاعات کارت اعتباری شما میشه، و اگر اطلاعات معتبری برای کارت اعتباری وارد نکنید، یا آدرس شما خارج از ایالات متحده آمریکا باشه، امکان دانلود برای شما فراهم نخواهد شد.</p>
<p style="text-align: justify;" dir="rtl">
<h2 style="text-align: justify;" dir="rtl">چگونگی دور زدن محدودیت دانلود</h2>
<p style="text-align: justify;" dir="rtl">همانطور که گفتم، آمازون به اطلاعات معتبر یک کارت اعتباری، و یک آدرس معتبر در داخل آمریکا نیاز داره، تا به شما اجازه دانلود بده. خب اگر یک کارت اعتباری معتبر آمریکایی داشته باشید، مشکلی نیست؛ می تونید هم نرم افزارهای رایگان و هم نرم افزارهای تجاری را از مارکت آمازون دانلود کنید. اما اگر کارت اعتباری آمریکایی نداشته باشید، چطور؟</p>
<p style="text-align: justify;" dir="rtl">در واقع شرکت آمازون فقط اعتبار کارت اعتباری را با بررسی الگوی اعداد به کار رفته در شماره کارت اعتباری بررسی میکنه، و اگر شما الگویی از اعداد را به عنوان شماره کارت اعتباری وارد کنید که مشابه یکی از الگوهای استفاده شده توسط شرکت های معتبر کارت اعتباری باشه، آمازون شماره کارت اعتباری شما را قبول میکنه. البته این به معنی آن نیست که با همچین شماره کارت اعتباری می تونید از آمازون خرید کنید، بلکه در زمان خرید یک محصول تجاری، صحت اطلاعات کارت اعتباری شما بررسی میشه، و در اون صورت، شماره جعلی شما جواب نخواهد داد، اما این بررسی فقط برای دانلود نرم افزارهای تجاری صورت میگیره، پس اگر بخواید نرم افزارهای رایگان را دانلود کنید، با همین شماره کارت جعلی هم می تونید این کار را انجام بدید. البته دقت داشته باشید که اگر آمازون متوجه استفاده از شماره کارت جعلی بشه، حساب آمازون شما مسدود خواهد شد!</p>
<p style="text-align: justify;" dir="rtl">نرم افزارها و سایت هایی هستند که می تونند برای شما شماره های کارت اعتباری به ظاهر صحیح تولید کنند، یکی از این سایت ها، سایت fakenamegenerator.com هست، که میتونه برای شما نام، آدرس، شماره تلفن، و شماره کارت اعتباری به ظاهر معتبر، ولی در واقع جعلی تولید کنه. دقت داشته باشید که سئولیت استفاده از اینگونه ابزارها با خودتان خواهد بود.</p>
<p style="text-align: justify;" dir="rtl">بعد از به دست آوردن یک شماره کارت اعتباری و  آدرس، می تونید با این نام و آدرس در سایت آمازون ثبت نام کنید. بعد از ثبت نام در سایت آمازون، به صفحه مربوط به Appstore for Android برید، و در گوشه بالا سمت راست، در کادر Get Sarted، آدرس ایمیل خود را وارد کنید. و بر روی دکمه Go کلیک کنید. با این کار، لینک دانلود Appstore برای شما ایمیل میشه، و می تونید از طریق اون لینک، فایل apk مربوطه را دریافت، و در دستگاه خودتان نصب کنید.</p>
<p style="text-align: justify;" dir="rtl">بعد از نصب برنامه در دستگاه اندریود خود، به سایت آمازون برگردید؛ و به صفحه Your Account برید، و در بخش Settings، گزینه ۱-Click Settings را انتخاب کنید. در این صفحه، از شما اطلاعات کارت اعتباری، آدرس، و تلفن شما درخواست میشه. اطلاعات کارت اعتباری که از طریق سایت fakenamegenerator به دست آوردید را در فیلدهای مربوطه وارد کنید. آدرس خود، شامل کشور، ایالت، شهر، و نام خیابان، را در فیلدهای مربوطه وارد کنید. اگر پس از ثبت آدرس، آمازون از آدرس وارد شده برای خیابان ایراد گرفت، می تونید یک آدرس واقعی در همان شهر را به راحتی با جستجو برای نام آن شهر پیدا کنید، مثلا سایت های مشاور املاک متعددی وجود دارند که آدرس خانه ها و ویلاهای آماده فروش یا کرایه را درج می کنند، یا شرکت های مختلف حاضر در شهر، آدرس خود را در سایت شان درج می کنند. پس می توانید به راحتی یک آدرس معتبر در داخل شهر و ایالت مورد نظر پیدا کنید. اگر آمازون به شما پیشنهاد داد که شاید ZIP Code وارد شده، اشتباه باشه، و منظور شما فلان آدرس هست، همان آدرس پیشنهادی آمازون را  قبول کنید. شماره تلفن جعلی که در مرحله قبل به دست آوردید را هم در کادر مربوط به شماره تلفن وارد کنید، فقط دقت کنید که حتما در ابتدای شماره تلفن، عبارت ۱+ که کد تلفن کشور آمریکا هست، را قید کنید، وگرنه امکان دانلود برای شما فراهم نخواهد شد!</p>
<p style="text-align: justify;" dir="rtl">با ذخیره کردن تنظیمات بالا، می توانید در دستگاه اندروید خود برنامه Appstore را اجرا کرده، و در سایت آمازون لاگین کنید، و لیست نرم افزارها را مرور کنید. هر نرم افزاری <strong>رایگانی </strong>که مایل به دانلود آن هستید را انتخاب کرده، و گزینه Get app را کلیک کنید. با این کار، فرایند دریافت آن فایل شروع خواهد شد. ابتدا آمازون یک فاکتور خرید برای شما ایمیل می کند، و سپس دانلود نرم افزار بر روی دستگاه شروع خواهد شد. بعد از اتمام دانلود، نرم افزار بر روی دستگاه شما نصب می شود.</p>
<p style="text-align: justify;" dir="rtl">
<h3 style="text-align: justify;" dir="rtl">دانلود با استفاده از کارت اعتباری معتبر غیر آمریکایی</h3>
<p style="text-align: justify;" dir="rtl">اگر یک کارت اعتباری معتبر، ولی غیر آمریکایی دارید، و قصد خرید محصولات تجاری از مارکت آمازون برای اندروید را دارید، در این مرحله می توانید اطلاعات کارت اعتباری واقعی خودتان را در تنظیمات حساب کاربری خودتان وارد کنید، و از طریق آن به خرید بپردازید؛ چون ظاهرا بررسی آمریکایی بودن آدرس شما فقط یک بار انجام میشه، و تغییر آدرس و شماره کارت اعتباری در مراحل بعدی، تاثیری بر امکان دانلود یا خرید شما نخواهد داشت.</p>
<p style="text-align: justify;" dir="rtl">
<p style="text-align: justify;" dir="rtl">خوش بگذره <img class="wlEmoticon wlEmoticon-smile" style="border-style: none;" src="http://vcldeveloper.com/wp-content/uploads/2011/04/wlEmoticon-smile.png" alt="Smile" /></p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://vcldeveloper.com/tips-tricks/download-from-amazon-appstore-for-android/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic
Page Caching using disk: enhanced
Database Caching using disk: basic
Object Caching 1309/1402 objects using disk: basic

Served from: vcldeveloper.com @ 2012-05-19 01:08:38 -->
