Archive for the ‘Delphi 2007’ Category

Custom Variant Wrapper for TDataset - Part 4

Friday, January 1st, 2010

In Part 3 we discussed clearing and copying our custom variant.  Next I am going to show you how to implement dynamic properties for our TDataset wrapper.  If you remember from the introduction to this series of articles, I wanted to be able to get the value of a dataset’s fields’ values using the name of the field as the property name.  Like this: variant.field_name.

(more…)

Custom Variant Wrapper for TDataset - Part 3

Thursday, December 31st, 2009

In Part 2 I explained how to initialize a custom variant’s data structure and how to create a TCustomVariantType descendant to implement the methods required to make the variant useful.  Now I will start to explain which methods need to be implemented, what they do and how they do it.  In this part we will discuss clearing your variant and copying your variant to another variant.

(more…)

Custom Variant Wrapper for TDataset - Part 2

Thursday, December 31st, 2009

In Part 1 of this series we discussed the data structure needed to hold your custom variant data.  In this article we will discuss the code needed to create an instance of your custom variant.

(more…)

Custom Variant Wrapper for TDataset - Part 1

Wednesday, December 30th, 2009

This is the first in a series of articles that will attempt to document the process of creating a Delphi custom variant.  In this article I will cover the data structure required to define a custom variant.  Later articles will address the classes and methods that need to be implemented in order for you custom variant to be able to do any useful work.

(more…)

Custom Variants in Delphi

Wednesday, December 30th, 2009

I was watching one of the CodeRage presentations the other day.  It was the one about domain specific languages by Marco Cantu.  In it he shows how custom variants can be used to implement a domain specific language in Delphi.  While I found the presentation interesting, I didn’t see much benefit to inventing one and using it in the type of programming that I do.  However, I can see a lot of applications for custom variants.

Unfortunately, Marco didn’t go into a lot of detail about exactly how custom variants are implemented.  So I started reading the Delphi Developers Guide.  It covers the necessary material but I found the explanations to be insufficient and I didn’t have the eureka moment that made everything clear enough to start implementing a custom variant.  So I went to the old standby, Google.  I didn’t find much there either.  One fairly length article that I did find basically parroted the Delphi documentation and examples and wasn’t much help either.

Anyway, I took the information that I could find and the VCL source code and dove in.   As a first project, I decided to implement a custom variant wrapper for the TDataset component that would allow me to access the dataset’s field’s values without have to use the excessively wordy and cumbersome dataset.FieldByName(”field_name“).Value syntax.  I wanted to be able to get a field’s value by using the field’s name as a property, like this, datasetVariant.field_name.  Where field_name is the name of the field in the database.

In a series of articles to follow, I am going to try to document my experiences and discoveries in the hope that; (1) it will serve as a memory aid to me if I ever have to do this again and (2) it will help someone else along the road to their own custom variant.  Wish me luck.

Part 1 - Variant Data Structures
Part 2 - Initializing the Variant
Part 3 - Copying and Clearing the Variant
Part 4 - Implementing Dynamic Properties
Part 5 - Casting the Variant to a Different Data Type
Part 6 - Implementing Dynamic Functions and Procedures

DestroyHandle and Delphi 2007

Wednesday, November 18th, 2009

Back in the good old days, when Windows 98 was king of the desktop, it didn’t matter how much memory your system had there was a hard limit on the number of resources (like window handles) that could be active at any one time.  This caused me problems with some of my larger applications.  They kept maxing out the active resources.

To get around this problem, there as a little trick that you could use with Delphi 5 to free the resources used by a window that was not visible.  To free the resources you used TWinControl.DestroyHandle to free the handles for the window that was about to be hidden and all of its child windows.  So this code went into all of my larger programs 10 or 11 years ago and everything was golden.  I even forgot that I had put the resource saving code into the programs.

So, skip forward 10 or 11 years and I am merrily porting my programs from Delphi 5 to Delphi 2007.  All of a sudden I start to encounter strange problems.  For example, I had a ComboBox on a page in a page control.  If I left the page containing the ComboBox and then returned to that page, the ComboBox’s drop down list was cleared.  I spent many hours debugging this to absolutely no avail. Until I finally stumbled across my little resource saving fiddle.  I removed that code from the program and now everything works as it should.  Fortunately, since Windows 98 is long dead (or should be) this code is no longer necessary so removing it isn’t going to cause me any heartache (I hope).

Codegear (now Embarcadero) obviously changed something in the implementation of the DestroyHandle method.  No wonder I am sick of programming. :(

How to Create an Active Form in Delphi 2007

Wednesday, November 11th, 2009

I spent a couple of hours frustrating myself today trying to remember how to create an active form using Delphi 2007.  I knew that I had done it before, but do you think I could remember how?  No way! So to avoid future frustrations I decided to write it down.

Before you can create an active form, you first need to create a new project by selection File | New | Other | Activex | Activex Library.  Once that step is done, you can create the active form by selecting File | New | Other | Activex | Active Form.  Leaving out the first step will cause you to slowly go crazy while you search all of the Delphi project item categories for the active form wizard without finding it.

Indy “Connection Closed Gracefully” Errors

Monday, October 5th, 2009

I was being plagued by “Connection closed gracefully” errors in an application that uses the Indy TIdHttp component to communicate with a remote server.  Periodically, I would get one of these exceptions.  Basically, this should be no big deal.  It just means that the remote server closed the connection before the transaction was complete.  i.e. I had sent the request but before I got the response, the remote server closed the connection.  So, just close the connection and try again after a suitable interval you say.  Well that is what I thought, but calling TIdHttp.Disconnect, waiting a bit and sending the request again just resulted in the same error over and over and over and over …

It turns out, that if there is any data left in Indy’s input buffer simply calling disconnect doesn’t actually get rid of the connection.  The connection lingers on until the input buffer is emptied.  In order to get rid of the connection completely you need to flush the input buffer by calling TIdHttp.IOHandler.InputBuffer.Clear after calling TIdHttp.Disconnect.  Completely inobvious and  not documented at all as far as I can tell.

Using HtmlHelp in a Delphi Active Form

Tuesday, June 16th, 2009

I stumbled across a bug in the Delphi HtmlHelpViewer unit yesterday.  I had written an ActiveX control based on a Delphi form (active form) and I wanted to display the contents of an HtmlHelp file.  Sounded easy enough, just put HtmlHelpViewer in the uses list.  And that worked insofar as I could display the required help pages. But (isn’t there always a but) if the user didn’t display any help pages the application would hang when it tried to close.

Googling provided some hints as to what the problem might be but no solution to the problem.  It turns out there is a bug in Delphi’s HtmlHelpViewer unit.  It only calls HtmlHelp using the HH_INITIALIZE command if you try to display a help page.  Sounds reasonable, why would you want to initialize the help engine if you aren’t going to display any help, right?  Unfortunately, HtmlHelpViewer calls HtmlHelp using the HH_CLOSE_ALL command unconditionally when the application shuts down.  That means that it tries to close all open help windows without ever having initialized the Html help system.  In a normal application, this doesn’t cause any problems but if you try to do this from an ActiveX control, the application will hang.

After much messing around I finally found a workaround.  I simply put a call to HtmlHelp using the HH_INITIALIZE command in my ActiveX control’s start up code and the problem is gone.

There are references to this problem in Embarcadero’s Quality Central but they don’t seem to have done anything about it yet.

PS

This turned out to be not quite so easy as I thought.  In addition to placing an HH_INITIALIZE command in the active form’s OnCreate event handler (DO NOT put this in the initialization section of the unit because it won’t work) I also had to copy the HmtlHelpViewer to my project directory, add it to my project and make the following change:

procedure THtmlHelpViewer.SoftShutDown;
begin
if (FInitialized) then  // Only call HH_CLOSE_ALL if we are initialized
HtmlHelp(0, nil, HH_CLOSE_ALL, 0);
end;

For reasons that elude me neither fix on its own solves the problem but it you use both then it seems to work.

Delphi Compiling All Delphi Sources When a User Project is Compiled

Wednesday, February 25th, 2009

Strange things just seem to happen to me.  I was experimenting with dynamically loaded run time packages and I wanted to include patched versions of some of Delphi’s units in my run time package.  So, I removed vcl.dcp from the Requires list and added the various Delphi units that I needed to the Contains list for the package.  Everything worked just the way I wanted.  My run time package used all of the Delphi run time units except for vcl.bpl.  Unfortunately, from this point on, every time I tried to compile one of my other projects, Delphi insisted on compiling all of the Delphi units in addition to my own.  Turns out, sometime during my attempts to force patched versions of the Delphi source to be used by my run time package, ($BDS)\source\win32\vcl got added to the IDE’s library path.  Once I removed that from the libaray path, everything went back to normal.  Weird!!