Category Archives: Embarcadero Delphi

“Blazing-Fast” Data Binding for Large VCL Datasets

Version 12.1 of the DevExpress VCL controls is now available. One exciting feature that customers have been anticipating is called “Server Mode” for the VCL grid. This feature, available in the .NET grid from DevExpress, allows the control to bind to huge amounts of data and work fully featured with that data while maintaining solid performance.

I recently explored this new feature in a small sample created using Delphi XE2. To start with, I created a new table, LotsaRows, in a Microsoft SQL Server database. I then used a simple script to populate the table with one million rows.

Armed with some sample data, I created my Delphi project. The project consists of four different grid configurations:

  1. A normal TDBGrid *no sorting, grouping, filtering
  2. A TcxGrid in “Grid Mode” (View.DataController.GridMode set to True) *no sorting, grouping, filtering
  3. A “Fully Featured” TcxGrid
  4. A TcxGrid using the new “Server Mode”

The “Server Mode” feature is comprised of a few different components. There is a new TcxGrid view as well as new datasources that handle the querying of data. In my sample I used a TdxServerModeADODataSource for connecting to Microsoft SQL Server and a TcxGridServerModeTableView for my grid.

Fetching the data for the first three grids (which use traditional datasources) takes around 6 seconds for all one million rows on my setup. Binding both the TDBGrid and the TcxGrid in “Grid Mode” is nearly instant. Binding one million records to a TcxGrid setup for all features (sorting, grouping, filtering) takes around 20 seconds for me. And, with one million rows, even after loading that data the sorting and grouping can be sluggish.

The fourth configuration, the TcxGrid in “Server Mode”, is nearly instant to fetch the ADO data (compared to 6 seconds previously). In addition, binding the data to the TcxGrid control takes only 150-175 milliseconds (compared to 20 seconds). The sorting, grouping, and filtering is all much faster than the third configuration as well.

So how is this magic accomplished? Once configured, the TcxGridServerModeTableView will only request the data it needs, via the TdxServerModeADODataSource, in order to render data on screen. Initially, enough data is queried from the datasource to populate the visible rows, as well as determine things like the scrollbar position. As the user begins to make use of the features of the grid, the combination of the grid view and datasource will only query the pieces of information needed in order to perform the operation and render the results. For instance, clicking a column to sort the contents will only query those rows needed to render the results on screen, using an appropriate ORDER BY clause.

You can run a trace on SQL Server in order to see what some of these SQL queries look like:

SELECT TOP 128 "ID", "Column1", "Column2", "Column3", "Column4" FROM "LotsaRows"   ORDER BY "Column2" asc, "ID" asc
SELECT "ID" FROM (SELECT "ID", ROW_NUMBER() OVER(ORDER BY "Column2" asc, "ID" asc) as "DXROWNUMBER" FROM "LotsaRows" )DXRESULTSET WHERE DXRESULTSET.DXROWNUMBER > 395100 AND DXRESULTSET.DXROWNUMBER <= 395100 + 4151
exec sp_executesql N'SELECT "ID", "Column1", "Column2", "Column3", "Column4" FROM "LotsaRows" WHERE ("ID" IN ((@P1), (@P2), (@P3), (@P4), (@P5), ..., (@P55)))  ',N'@P1 nvarchar(38),@P2 nvarchar(38),@P3 nvarchar(38),@P4 nvarchar(38),@P5 nvarchar(38),...,@P55 nvarchar(38)',N'{6C2B027D-46C0-44E7-99FF-B60FBFB06091}',N'{477745E8-8011-45A8-AB6C-B6280E74BD87}',N'{5E49139F-67D8-4D8B-8B6C-B633698223E9}'...

You can download the Delphi source and SQL scripts for the example here.

Using XtraRichEdit to Edit HTML in VCL Applications

One request heard frequently from users of DevExpress’s VCL controls is for an HTML editing control. So far this has been deferred by the folks at DevExpress. However, they do make a bang-up .NET control called XtraRichEdit which has great HTML editing functionality. Wouldn’t it be great if we could easily embed that control in a VCL application?

It turns out this isn’t too tough using RemObjects’ Hydra product. Hydra is a plugin framework for both Delphi and .NET that lets you mix and match both managed and native hosts and plugins, visual and non-visual. This means you can make use of .NET visual controls in Delphi applications and vice-versa.

Let’s take a look at how easy this is to do (hint – very easy).

You’ll need Visual Studio, Delphi, the DevExpress WinForms controls, and Hydra all installed in the same environment. While it’s possible to do this with Delphi and Visual Studio on separate machines, it’s beyond the scope of this post.

Create a new project in Visual Studio using the “Plugin Module” template in the “RemObjects Hydra” category. Afterward, use the “Add>New Item” dialog to create a new “Visual Plugin”. Add a RichEditControl to the new design surface and dock it in its parent.

This alone is enough to yield a plugin module that can be loaded in a Delphi application and display a working RichEditControl. However, there would be no way to access the richedit’s HTML text. For this we will need to use a custom interface. This is really easy to do.

Add the following interface declaration to the top of the code-behind:

    [Guid("4033C8A9-8A7C-4DE4-864C-B8F60EFFBDD7")]
    public interface IRichEditPlugin : IHYCrossPlatformInterface
    {
        string GetHtmlText();
        void SetHtmlText(string text);
    }

This will require using RemObjects.Hydra.CrossPlatform and System.Runtime.InteropServices. Both the Guid and descending from IHYCrossPlatformInterface are required by Hydra. Finally, implement the interface:

    public partial class RichEditPlugin : VisualPlugin, IRichEditPlugin
    ...
        public string GetHtmlText()
        {
            return richEditControl1.HtmlText;
        }

        public void SetHtmlText(string text)
        {
            richEditControl1.HtmlText = text;
        }

And that’s it for the .NET side of things.

On the Delphi side of things, create a new VCL forms project. Add a THYModuleManager, TPanel, TMemo, and two TButtons.

Click the Hydra menu followed by Import Interfaces from .NET Assemblies. Browse for the assembly created above and click Import on the dialog listing the IRichEditPlugin interface. Then, click the Hydra menu followed by Hydra Package Settings. Select “Build with Hydra Core Packages” and click OK.

Adding a minimal amount of code will get the RichEditControl showing:

procedure TForm2.FormCreate(Sender: TObject);
begin
  HYModuleManager1.LoadModule('RichEditModule.dll');
  HYModuleManager1.CreateVisualPlugin('RichEditModule.RichEditPlugin', FRichEditPlugin);
  FRichEditPlugin.ShowParented(Panel1);
end;

procedure TForm2.FormDestroy(Sender: TObject);
begin
  FRichEditPlugin := nil;
  HYModuleManager1.UnloadModules;
end;

FRichEditPlugin is a private field declared as IHYVisualPlugin.

After you copy the assembly created in .NET (RichEditModule.dll in my example) to the same path as your debug executable, running the application will now show the Delphi application with the .NET RichEditControl embedded and fully functional.

Adding a bit more code will allow getting and setting the HTML text in the .NET RichEditControl using the text entered in the TMemo:

//Set button
procedure TForm2.Button1Click(Sender: TObject);
var
  RichEditPlugin: IRichEditPlugin;
begin
  if Supports(FRichEditPlugin, IRichEditPlugin, RichEditPlugin) then
    RichEditPlugin.SetHtmlText(Memo1.Text);
end;

//Get button
procedure TForm2.Button2Click(Sender: TObject);
var
  RichEditPlugin: IRichEditPlugin;
begin
  if Supports(FRichEditPlugin, IRichEditPlugin, RichEditPlugin) then
    Memo1.Text := RichEditPlugin.GetHtmlText;
end;

This new code will require adding the “_Import.pas” unit generated when you imported the .NET interface to your uses clause.

And that’s it. Press the run button and then try the Get and Set buttons along with editing text in the RichEditControl.

XtraRichEdit in a VCL App

This is pretty powerful stuff thanks to Hydra and the XtraRichEdit, and very easy to do! You can download the C# and Delphi source code here.

Accessing ExpressScheduler Recurrence Information from .NET

One challenge I’ve come up against recently is using C# to read the scheduler information saved by the DevExpress ExpressScheduler VCL control. Most of the data is fairly straight forward to read. However, there are two exceptions: recurrence information and associated resources.

This post will discuss how to read the recurrence information. This can be done directly in C#. A future post will explore how to read the associated resources. If your Delphi application only allows one resource to be associated to an event this isn’t an issue. However, if you allow multiple resources per event these are stored as Delphi variants in the DB and require Delphi to read the values out.

The recurrence information, on the other hand, is stored in a packed Delphi record which is in turn stored directly as an array of bytes in the DB field. The Delphi record is called TcxSchedulerEventRecurrenceInfoData and is defined in cxSchedulerStorage.pas:

TcxSchedulerEventRecurrenceInfoData = packed record
  Count: Integer;
  DayNumber: Integer;
  DayType: TcxDayType;
  Finish: TDateTime;
  OccurDays: TDays;
  Periodicity: Integer;
  Recurrence: TcxRecurrence;
  Start: TDateTime;
  YearPeriodicity: Integer;
  Reserved1: Byte;
  DismissDate: Integer;
end;

In order to read the recurrence information in .NET, this record and its associated types must be translated into their .NET counterparts. Here is an example of an equivalent C# struct:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
struct SchedulerEventRecurrenceInfoData
{
    public int Count;
    public int DayNumber;
    public DayType DayType;
    public double Finish;
    public Days OccurDays;
    public int Periodicity;
    public Recurrence Recurrence;
    public double Start;
    public int YearPeriodicity;
    public byte Reserved1;
    public int DismissDate;
}

The rest of the C# types can be found in the accompanying sample.

With these types in place, the only thing left is some code to convert the recurrence information from the string value stored in the DB to the SchedulerEventRecurrenceInfoData struct. This post on StackOverflow gives a simple solution for doing this:

T ByteArrayToStructure(byte[] bytes) where T: struct
{
    GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
    T stuff = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
    handle.Free();
    return stuff;
}

There is a working Delphi sample here and the .NET sample app can be found here.

UPDATE: There’s a real-world example of this technique you can find here. It is an open source project for transferring data from ExpressScheduler to XtraScheduler.

Smart Phone Style Lists with QuantumGrid

A poster on the Developer Express forums recently inquired on how to use the VCL QuantumGrid to mimic a smart phone styled list. You can see an example of the desired appearance here:

Smart Phone List Example

Notable aspects of this style are:

  • Data in a single row arranged both vertically and horizontally
  • Varying cell heights within a single row
  • Single row selection (rather than cell selection)
  • Independent cell styles
  • No column headers or cell captions

Luckily the QuantumGrid is up to the challenge. Here is an example of a smart phone styled list using the QuantumGrid and Delphi XE2:

QuantumGrid Smart Phone List

This can be accomplished using the “banded” table view in the QuantumGrid. A banded table view lets you group columns together into bands. Each band can have a variable number of vertically or horizontally stacked columns. The above example is composed of three bands and four columns: one column (with double-height) in the first band, two columns stacked vertically in the second, and a single column in the third band.

Adding and organizing bands and columns is made easy using the right-click context menu of the QuantumGrid. Starting with a simple banded table view, here is a brief video that shows how easy it is to add and layout the bands and columns necessary to achieve the above affect.

Once the banded table view has the proper bands and columns added, the following settings should be applied to the table view in the object inspector:

OptionsData.Editing = False
OptionsSelection.CellSelect = False
OptionsView.ColumnAutoWidth = True
OptionsView.GridLines = glNone
OptionsView.GroupByBox = False
OptionsView.Header = False
OptionsView.RowSeparatorColor = clGrayText
OptionsView.RowSeparatorWidth = 1
OptionsView.BandHeaders = False

With these settings in place, all that is needed is a bit of sample data and some contact thumbnails to complete the effect. You can download the source of this sample project here.

Updated 5/10/2012: DevExpress employee Alex M had this to say on the forums:

I think that making CountColumn right aligned will add a final touch to the look and feel.
TextEditProperties.Alignment.Horz := taRightJustify;
Also, I believe using a band’s context menu introduced in DevExpress VCL Build v2011 vol 2  (try once, love it forever :) ) would simplify column/band creation and arrangement shown in the video.

I’ve updated the sample and video to reflect Alex’s suggestions. Thanks Alex!

Using RemObjects Olympia Server with a Custom Session Class

Today I started playing with Olympia Server for out-of-process session management. We have a RemObjects SDK service that can currently use either in-memory or in-database session state. The in-memory option is faster, but limits our pooling options.

The various session managers in RemObjects SDK are pluggable and swappable, so adding support for Olympia Server to our service was pretty straight forward. However, I quickly ran into a limitation when using Olympia Server for session management: if you make use of a custom TROSession descendant by handling CustomCreateSession (discussed here), your custom properties will not be available after they make the trip to Olympia Server and back.

After looking into the source for TROSession and TROOlympiaSessionManager, I was able to come up with a fairly simple solution that allows you to continue using a custom TROSession descendant while also making use of Olympia for out-of-process session management.

The key is to override both SaveToStream and LoadFromStream in your custom TROSession descendant. There, serialize and deserialize your custom property values using the Values name-value pair property found on TROSession.

procedure LoadFromStream(aStream: TStream; OnlyValues: Boolean = False); override;
procedure SaveToStream(aStream: TStream; OnlyValues: Boolean = False); override;

...

procedure TMySession.LoadFromStream(aStream: TStream; OnlyValues: Boolean);
begin
  inherited;
  MyProperty := Values['MyProperty'];
  MyStrings.CommaText := Values['MyStrings'];
end;

procedure TMySession.SaveToStream(aStream: TStream; OnlyValues: Boolean);
begin
  Values['MyProperty'] := MyProperty;
  Values['MyStrings'] := MyStrings.CommaText;
  inherited;
end;

That Values property is one of the properties that will be persisted round trip with Olympia, and will allow your service to continue working as-is while making use of both a custom session class and Olympia Server.

Size a Delphi Form to fit an ExpressLayout Control’s Content

Today I was faced with the need to have some MDI child forms automatically size to fit their contents. These forms all descend from a base form that has an ExpressBars bar manager and an ExpressLayout layout control. I was surprised (though I shouldn’t be at this point) at how easy this was to achieve:

procedure TDataDetailsForm.FormShow(Sender: TObject);
begin
  inherited;
  SizeToRootLayoutContents;
end;

procedure TDataDetailsForm.SizeToRootLayoutContents;
begin
  ClientWidth := DetailsLayoutControlGroup_Root.ViewInfo.Bounds.Right -
    DetailsLayoutControlGroup_Root.ViewInfo.Bounds.Left +
    (DetailsLayoutControl.LayoutLookAndFeel.Offsets.RootItemsAreaOffsetHorz * 2);
  ClientHeight := DetailsLayoutControlGroup_Root.ViewInfo.Bounds.Bottom -
    DetailsLayoutControlGroup_Root.ViewInfo.Bounds.Top +
    (DetailsLayoutControl.LayoutLookAndFeel.Offsets.RootItemsAreaOffsetVert * 2) +
    DetailsBarManagerBar1.RealDockControl.Height;
end;

With that bit of code in place, each form now automatically size to fit its contents when shown, but can still be freely resized.

TestComplete 7 – A Killer Feature

So far I’m digging the upgrade from TestComplete 6 to 7. I’ve been a TestComplete user for several years and love the product. I’ve always been fond of AutomatedQA’s tools – we also use Automated Build Studio (in addition to FinalBuilder). Their applications are both powerful and attractive (what can I say, I’m a sucker for DevExpress user interfaces).

Recently, one of TestComplete 7’s new features has really stood out for me at work. No, it’s not keyword testing. While keyword testing has gotten most of the press and is, arguably, very cool for getting up and going with UI testing, the feature I’m loving is this: it’s no longer necessary to compile Delphi and C++Builder applications with special units in order to fully test them.

With previous versions of TestComplete, it was necessary to compile Delphi and C++Builder applications with certain units that allowed TestComplete to “see” the VCL controls rather than just the window handles and Windows controls. Running applications that were built against these units, but without TestComplete installed, resulted in a nasty error dialog. So, it was generally necessary to have scripts that built testing versions of all of our applications, placed those in a working directory, and then run our test scripts against those builds.

This is no longer necessary. Not only does this reduce the complexity of our testing process (which is A Good Thing) but, more importantly, this allows us to now test actual releases of our applications. We’ve begun rewriting our test scripts to install the same setups and updates our build process has created for our customers, and then test against those release versions. This provides us with much more accurate testing and will benefit our customers greatly, allowing us to catch bugs that may have made it into our releases but would not have been caught by testing special builds of the software.

Kudos to the team at AutomatedQA for another fine release of a great tool.

DevExpress Gems – The VCL Filter Control

Recently I was tasked with creating a visual query builder for the reporting. The existing query builder was pretty simplistic, and did not allow for grouping conditions. After talking to a few colleagues and looking into some recommended solutions, a consultant and coworker (and close friend) of mine suggested something that is now obvious, but at the time caught me off guard: why not try utilizing the same filter control shown when you customize the filter of the DevExpress VCL Quantum Grid?

Using the filter control from the Quantum Grid component would immediately carry several benefits:

  • We wouldn’t have to purchase an additional control
  • Our query builder for reports would be the same control customers already use to customize our grids
  • Our query builder for reports would visually match the rest of our application

I was optimistic about being able to reuse the filter control, but honestly thought I’d be digging into the source for the existing Quantum Grid filter customization dialog, hoping for some source I could use. Once I sat back down to my development environment, I was delighted (to say the least) to find both TcxFilterControl and TcxDBFilterControl in my tool palette. This was not the first time (nor, I suspect, the last) that I was completely surprised to find some controls in my DevExpress arsenal of which I was previously unaware.

Did these controls allow us to provide a flexible query builder capable of creating complex SQL? You betcha.

Out of the box, TcxFilterControl is meant to be wired up to something like a TcxGrid table view, while the TcxDBFilterControl is meant to be wired up to a TDataSet descendant. While I normally shy away from database-aware controls in the VCL, the TcxDBFilterControl seemed to be more suited for our needs.

To get started using a TcxDBFilterControl, you can simply drop the control on a form and hook it up to a TDataSet descendant. Immediately, the control is capable of creating complex filters, with the field selections in the filter control populated with the field definitions from the TDataSet descendant.

If you are working with a standards compliant SQL engine, using the TcxDBFilterControl to query data requires only a handful of code. Given a simple VCL project with an ADO connection to the Northwind database, a TcxDBFilterControl hooked up to the EmployeeDefsQuery component, and a grid control hooked up to the EmployeeResultsQuery component, the following code is all you need:

procedure TDemoForm.FormCreate(Sender: TObject);
begin
  EmployeeDefsQuery.SQL.Text := 'Select * From Employees Where 0 = 1';
  EmployeeDefsQuery.Open;
end;

procedure TDemoForm.FetchButtonClick(Sender: TObject);
var
  SqlStatement, WhereClause: string;
begin
  EmployeeResultsQuery.Close;
  SqlStatement := 'Select * From Employees';
  WhereClause := EmployeeFilterControl.FilterText;
  if WhereClause <> '' then
    SqlStatement := SqlStatement + ' Where ' + EmployeeFilterControl.FilterText;
  EmployeeResultsQuery.SQL.Text := SqlStatement;
  EmployeeResultsQuery.Open;
  if EmployeesTableView.ItemCount = 0 then
    EmployeesTableView.DataController.CreateAllItems;
end;

Our database engine is not fully SQL compliant, plus there were some niceties that our previous report query builder supported that had to be preserved (such as not requiring the end-user to use the % mask character with LIKE conditions). While crafting custom SQL from the filter control is not trivial, it is entirely possible and we were able to meet all of our requirements with this very useful control.

To create your own SQL from the supplied filter control, you’ll need to parse the TcxFilterControl.Criteria.Root property. The items within the criteria list can either be criteria items or additional criteria lists (TcxFilterCriteriaItem and TcxFilterCriteriaItemList). The item lists have a BoolOperatorKind property, while the criteria items have an Operator property, along with additional properties, that allow you to fully inspect the filter specified in the filter control and create your own SQL statement. While this is outside the scope of this post, feel free to contact me for more details on how to accomplish this.

I love being surprised by existing controls, new to me, that DevExpress has provided in their suites, allowing me to get my job done better and faster without additional investments in time and money. To be honest, when I thought visual query builder, I just did not think DevExpress. To me this is a showcase control (as seen from other vendors), but DevExpress’s implementation provided everything we needed to get our new report query builder going in no time.

Do You Remember Project Dionysus?

In mid-2002, Project Dionysus set out to revolutionize the Delphi developer toolset. Project Dionysus was to deliver a package of third-party solutions for Delphi that would allow a developer to augment their Delphi Professional license and – it was claimed – end up with more functionality, for a lower price, than Delphi’s Enterprise SKU.

Key players in the Project Dionysus lineup were Report Builder (reporting), RemObjects SDK (web services and remoting), ExpressQuantumGrid (grid suite), ExpressWeb Framework (ASP.NET competitor), DXSock (internet connection components), and a suite of database access layers.

Was the endeavor successful? Who knows (the companies involved most likely).

But it was a big win for myself both personally and professionally. I had already had experience with DevExpress when rumors of Dionysus first surfaced, but the project further solidified my interest in and commitment to their toolset (then VCL, now much more).

Project Dionysus was also the first time I had heard of RemObjects SDK. That was a life saver. This was, I believe, during their beta phase for version 1, and we decided to leverage RemObjects SDK for our web services at a mobile electronics startup. Without going into details, this was probably one of the single best decisions I’ve made in my professional career.

Thank you, Project Dionysus. Your hype machine exposed me to two of my favorite vendors – now two of the most relevant players – in the development tools market.

A Coming Tide

One of the projects I’ve worked on, off-and-on, for around four years, is a light-weight application framework based on the plugin framework Hydra from RemObjects and the visual controls from DevExpress (not to be confused with DevExpress’s own XAF, which blows this out of the water – maybe the term plugin framework is more fitting?).

I wouldn’t be surprised if many software developers, at some point, come to realize that a lot of the common elements between their projects could be abstracted to such a point that various products could be built on the same application framework (be it desktop software or a web application). I came to this point around five years ago, and have written at least two or tree starting-points for the project over time.

The initial project was written in Delphi, using Hydra and DevExpress’s VCL controls. The current version of this project is written in C# using Visual Studio 2008, and uses Hydra and DevExpress’s WinForms controls.

The goals for this project have evolved over the years, but are still pretty much the same as they are when it started:

  • The framework should make it very easy to expose the features of the DevExpress controls – runtime grid customization, runtime layout customization, theme and skin changes – you name it
  • The framework should be very loose, allowing pretty much any type of application to be built (adhering to a few UI guidelines and paradigms)
  • The framework should still allow for a high degree of integration between the plugins themselves and between the plugins and host
  • The plugins and host should be capable of being designed using the native designers (eg. using the DevExpress designers to design toolbars, ribbons, etc. rather than some other “description” that gets passed to the host and merged into the UI)
  • The framework should be very light – as little code and as well written as possible to get things done

This latest iteration of the project, which started a little under year ago, has been coming along well. I’ve worked on it lightly here-and-there (it’s just a hobby project really), but I’ve been happy with the results. The DevExpress WinForms controls and Hydra (along with C# and the .NET framework) have made it surprisingly easy to achieve my goals.

Currently I have a host executable and a couple of assemblies. The host doesn’t really do much of anything except display a form. Using Hydra visual and non-visual plugins, the host can be expanded with plugins for branding (company name, application name, etc.), plugins for displaying individual pages of options within the host’s settings dialog, plugins for displaying browse screens and details screens, generic dockable windows, and more.

It’s all pretty loosely coupled as I mentioned, and gives full support for (so far):

  • The Ribbon control from DevExpress – design Ribbon control in the plugins and have them merged automatically into a single ribbon at runtime in the host
  • The NavBar control from DevExpress – as with the Ribbon, design the NavBar controls and groups within the plugins at design-time and they are merged automatically into the host’s NavBar at runtime
  • The DX Ribbon StatusBar – design the StatusBar right on the plugin’s design surface and the StatusBar items are merged into the host’s StatusBar at runtime
  • XtraPrinting – return a printable object from your plugin and the host automatically supports printing that object, along with exporting to HTML, PDF, XLS, and more (available from the Ribbon application menu)
  • XtraBars Docking – visual plugins can be automatically hosted in the application as dockable windows (with customized position, caption, image, etc)
  • XtraGrid support – grid layouts are automatically saved to, and restored from, XML at runtime
  • Support for XtraLayout – layout controls parents on visual plugins automatically have their layouts saved to, and restored from, XML
  • Automatic spell checking with XtraSpellChecker – edit controls within plugins automatically get spell-checking support
  • Capable of loading Delphi plugins – by using Hydra, the host application is able to host both visual and non-visual plugins written in Delphi as well (and the DevExpress VCL components are there to give a matching look and feel)

So, what next? Now I plan on writing a Northwind DB client using the application framework. I’ll be blogging about this as the rest of the framework comes together, and eventually publish the framework with source along with the Northwind example client.

Watch here for further details.