September 30, 2006
Enhanced Delphi DBImage replacement (handles wmf, emf and jpg)
Sebastian Mayora has created an excellent replacement for the DBImage control. EDBImage handles all the image formats that DBImage does PLUS jpg, wmf and emf as well. Download it here.
Posted by daen at 09:19 AM | Comments (0)
Catching dataset updates in Delphi
When you navigate away from an inserted or edited record in a DataSet in Delphi, an implicit post will occur before the navigation. Sometimes, it's useful to be able to trap that and handle it in different ways. For example, you might want to ask the user if they want to save or discard the changes, or cancel the navigation and keep making changes to the current record (they might just have hit the wrong key or clicked on the wrong spot with the mouse). The bad news is that it's far from clear how to do this in the Delphi documentation. The good news is that it turns out to be pretty simple to do.
The trick lies in using a special exception called EAbort (defined along with a load of other exceptions in SysUtils). EAbort is special because it doesn't display a dialog message in the default exception handler - it's "silent". The place to do this is in the DataSet's BeforePost event handler. Throwing the EAbort simply pulls the rug from under the whole record update machinery. There's a handy procedure called Abort which will throw EAbort for you.
procedure TForm1.CDSBeforePost(DataSet: TDataSet);
begin
with DataSet as TClientDataSet do
begin
if DataSet.Modified then
begin
case MessageDlg('Save (yes) discard (no)'+
'or continue editing (cancel)?',
mtWarning,mbYesNoCancel,0) of
mrNo:
begin
Cancel;
Abort;
end;
mrCancel:
begin
Abort;
end;
end;
end;
end;
end;
There's one extra twist (not shown here) where implicit posts (generated by navigation and insert/delete events) need to be handled differently from explicit posts. This requires a boolean ExplicitPost flag that is set anytime before you call DataSet.Post from your code, and in the DBNavigator.BeforeAction event handler for the nbPost button. The flag is cleared in a transition to dsEdit or dsInsert which can be done in DataSource.OnStateChange. Then, in the DataSet.BeforePost event handler, the flag is checked and if set, the warning message is not displayed. This is not so clean, because you need to remember to set this flag before every explicit Post.
Thanks to Zarko Gajic at delphi.about.com for writing the article that put me on the right track.
Posted by daen at 08:47 AM | Comments (0)
August 15, 2006
MDL Draw control tips in Delphi
... although it should work generally. Note I'm using Viatcheslav V. Vassiliev's Managed VCL components for Delphi 7 ...
Assume you have configured a TClrControl and set the AssemblyName property to MDL.Draw.Renderer, Version=1.4.1000.20, Culture=neutral, PublicKeyToken=e922e3fd683b3777 (although the MDL.Draw.Renditor assembly will also do), and the ControlName property to MDL.Draw.Renderer.Renderer (although the MDL.Draw.Renditor.Editor control will also do).
Assume that you've read a molfile into variable MolFileString. You can set the molfile property of the Renderer control using the following code:
ClrControl1.ClrObject.DispProperty['MolFileString']:= MolFileString
Assume you also have a TImage instance available that you want to capture the Renderer image into as a bitmap. You can easily do it like this:
ClrControl1.ClrObject.DispProperty['MolFileString']:=
ClientDataSet1.FieldByName('ConvMolfileString').AsString;
Image1.Picture.Bitmap.Handle:=
ClrControl1.ClrObject.DispProperty['Image'].GetHBitmap;
Posted by daen at 02:39 PM | Comments (0)
June 01, 2006
Rendering ChemDraw image as metafile in Delphi TImage control
Assume you've already set the ChemDraw control with SMILES/MOL etc and you also have a TImage on the form already called Image1 ...
procedure TForm1.ButtonRenderClick(Sender: TObject); var WMFData: array of byte; MemStream: TMemoryStream; begin WMFData:=CSChemDrawCtl1.Data['image/x-wmfs']; MemStream:=TMemoryStream.Create; MemStream.WriteBuffer(WMFData[0],Length(WMFData)); MemStream.Seek(0,soFromBeginning); Image1.Picture.Metafile.LoadFromStream(MemStream); MemStream.Free; end;
Posted by daen at 09:04 PM | Comments (0)
November 21, 2005
Delphi 7 help amusing spelling gaffe
ProcessPath procedurearses a file name into its constituent parts.
Posted by daen at 12:15 PM
September 07, 2005
DAPUG workshop 6-7 September
I'm back from a two day workshop organised by DAPUG (the Danish Database Application Programmers Users Group). These workshops are held once or twice per year. The venue this time is Hotel Hessellet, which has been the location for many of these workshops over the last ten years. Hessellet is a four-star hotel situated by the beach at Nyborg, just over the Storebælt from Sjælland. The accomodation is sumptuous, the food is absolutely delicious and the location is wonderful. This workshop was titled "Using In-Memory Data Stores: Featuring ClientDataSets and .NET DataSets" and was expertly presented by Cary Jensen, long-time Delphi and database guru. I have quite a few ideas now as to how to use TClientDataSet in new ways, thanks to Cary. The next workshops are provisionally booked for May 2-3 and August 29-30 2006.
Here are some photos of the workshop and Hotel Hessellet.
Posted by daen at 11:26 PM
August 03, 2005
ClientDataSet and nested data sets, and general Delphi bling
TClientDataSet is a wrapper for a minimal portable database implementation known as MIDAS. Client data sets allow you to populate them with fields and data from other databases, or you can create your own schema at design or runtime. Data can be streamed into a proprietary binary file format (.CDS) or XML (although the XML schema is proprietary). What's really cool is that fields in a client data set can themselves be data sets, allowing master-detail relationships to be created relatively easily. I stress the relatively, because it isn't entirely clear from the Delphi documentation how to do it. Which is why people like Cary Jensen, Marco Cantu, Ray Konopka, Bob Swart, Charlie Calvert, Steve Teixeira (recently defected to MS, boo hiss!), Xavier Pacheco and all those TeamB people and other Delphi experts who post their knowledge where all and sundry can find it deserve medals. Cary Jensen is singled out in this post for his excellent and comprehensive article on nested data sets using TClientDataSet.
Posted by daen at 03:29 AM
June 18, 2005
Delphi, Web Services and statefulness ...
Advanced Web Services (Deepak Shenoy)
Posted by daen at 11:38 AM
May 07, 2005
Borland BDP, IIS and Oracle : more questions than answers?
It's not so straightforward to access Oracle using the Borland Data Provider (BDP) through IIS ... I kept getting "BdpException: Connection open failed". Turns out it's a permissioning problem, and it's far from resolved in my mind. I've currently granted full access to the entire Oracle hierarchy to the local ASPNET, IUSR... and IWAM... users (the Oracle DB is running on the same box as IIS). That works. This is actually a general problem relating to Oracle access through IIS (I googled up lots of articles on ADO.NET, ODBC, OleDB etc etc, all tackling the same problem).
But hmmm.
I think only the ASPNET user needs access, and read only (maybe execute?) permissions at that. I will try to remove access to the other accounts and see what happens. I also want to get ECO II working - I believe it should be fairly plain sailing now my ASP.NET app can see the database.
But, how, then, do you get access to an Oracle DB on another Windows box? Or, for that matter, one running on a Linux box?
Questions, questions ...
Links and a definitive resolution to these puzzles will follow ... I hope.
Posted by daen at 03:51 PM
March 17, 2005
Delphi 2005 Update 2
Delphi 2005 Update 2 now available ...
Posted by daen at 11:28 PM
February 21, 2005
Delphi 8 update 3 fixes .NET Framework 1.1 SP1 problems
Out-of-the-box, Delphi 8 VCL.NET projects do not compile under .NET framework 1.1 SP1. Period. It's taken me half a day to track down the official Borland fix for this, which is in Delphi 8 update 3. Bad bad bad.
Posted by daen at 01:42 PM
September 24, 2004
Unofficial Newsletter of Delphi Users
The Unofficial Newsletter of Delphi Users
See Grahame Marsh's series on Drag & Drop (eg Sep 99 - COM Interface based Drag and Drop Part 9 – Starting a Drag Source Operation and COM Interface-based Drag and Drop - Part 10).
Posted by daen at 12:43 AM
September 02, 2004
Thierry Coq's homepage - TP LEX and YACC
"Site personnel de Thierry/Thierry's Personal site"
Posted by daen at 10:51 PM
July 12, 2004
JNI array parameter issues
According to Matthew Mead (author of the JNI port for Delphi), it is entirely possible that the helper function ArgsToJValues doesn't work correctly for some types and some JVMs. The solution is to use the JNI array handling functions. This article on starting a JVM from C shows how to do this from within C.
Here's some example Delphi code, with the relevant array handling bits in bold:
program JavaFromDelphi;
{$APPTYPE CONSOLE}
uses
SysUtils, JNI;
var
Options: array [0..4] of JavaVMOption;
VM_args: JavaVMInitArgs;
JavaVM: TJavaVM;
JNIEnv: TJNIEnv;
Cls: JClass;
Mid: JMethodID;
Errcode: Integer;
Obj: JObject;
DelphiIntArray: array [0..8] of Integer;
JavaIntArray: JIntArray;
Loop: Integer;
begin
try
// Create the JVM (using a wrapper class)
JavaVM := TJavaVM.Create;
// Set the options for the VM
Options[0].optionString := '-Djava.class.path=.';
Options[1].optionString := '-Xcheck:jni';
VM_args.version := JNI_VERSION_1_4;
VM_args.options := @Options;
VM_args.nOptions := 2;
// Load the VM
Errcode := JavaVM.LoadVM(VM_args);
if Errcode < 0 then
begin
WriteLn(Format('Error loading JavaVM, error code = %d', [Errcode]));
Exit;
end;
// Create a Java environment from the JVM's Env (another wrapper class)
JNIEnv := TJNIEnv.Create(JavaVM.Env);
// Create the Java array of integers
JavaIntArray := JNIEnv.NewIntArray(9);
// Quit if this fails
if JavaIntArray = nil then
begin
WriteLn('Can''t get int array');
Exit;
end;
// Fill the Delphi array with some values
for Loop:=0 to 8 do
begin
DelphiIntArray[Loop]:=(Loop*Loop);
end;
// Set the Java int array with the values in the Delphi int array
JNIEnv.SetIntArrayRegion(JavaIntArray,0,9,@DelphiIntArray);
// Find the class in the file system. This is why we added
// the current directory to the Java classpath above.
Cls := JNIEnv.FindClass('TestApp');
if Cls = nil then
begin
WriteLn('Can''t find class: TestApp');
Exit;
end;
// Get its default constructor
Mid := JNIEnv.GetMethodID(Cls, '', '()V');
if Mid = nil then
begin
WriteLn('Can''t get default constructor for class');
Exit;
end;
// Create the object
obj := JNIEnv.NewObjectA(Cls, Mid, nil);
// Fail if we can't
if Obj = nil then
begin
WriteLn('Can''t get get object');
Exit;
end;
// Get method
Mid := JNIEnv.GetMethodID(Cls, 'test', '([I)V');
if Mid = nil then
begin
WriteLn('Can''t find method: test');
Exit;
end;
// Finally, call the method with the Java int array ...
JNIEnv.CallObjectMethodA(obj, Mid, PJValue(@JavaIntArray));
except
on E : Exception do
WriteLn('Error: ' + E.Message);
end;
end.
The TestApp.java source is here:
public class TestApp
{
void test(int[] params)
{
System.out.println("params.length="+params.length);
for (int i=0; i<e;params.length; i++)
{
System.out.println("params["+i+"]="+params[i]);
}
}
}
Posted by daen at 02:27 PM
June 13, 2004
JNI and Delphi
Using the Java Native Interface with Delphi
Posted by daen at 12:45 AM
April 25, 2004
PCA/chemical components for Delphi
Epina and Software Development Lohninger
Posted by daen at 01:24 AM
February 29, 2004
Delphi RTTI library
Posted by daen at 11:56 PM
February 20, 2004
Use the Source Luke ...

Project JEDI's JVCL consists of over 300 open source Mozilla Public License (MPL) components for use in Delphi.
Posted by daen at 12:24 AM
January 12, 2004
How to get an enum's name in Delphi
In this article (Under The Hood With Dr.Bob - How to Get an Enum's Name) the inestimable Bob Swart describes how to get an enum value as a string.

Posted by daen at 03:35 PM
December 22, 2003
Building DLLs with G++ for Delphi
Building DLL with G++
testfn.c
__declspec(dllexport) int testfn(int i, int j)
{
return i+j;
}
Compiling
g++ -x c -c testfn.c
Linking DLL
dllwrap --dllname=tst.dll testfn.o
Using in Delphi
function testfn(i: integer; j: integer): integer; cdecl; external 'tst.dll';
Posted by daen at 09:51 PM



