2007-06-28

CodeGear Encore - The (non) Replays

As you may have noticed, CodeGear finally placed the replays online. Well, I'm not even going to mention that the initial plan was to have those available only to registered Delphi Customers as it was in those terms that the event took place... (Well, it seems I did mention it, but I have no problem that it's available for everyone!)

What I'm complaining here is about the lousy job done that took them 3 whole months to do!

Sure, I know that CodeGear has been busy but did they really need 3 whole months between the CodeRage Encore event and this (let's be nice) publishing of the sessions?

I mean: where are the download links? Only choice is to view online. But much worst than that, try and position the video replay cursor somewhere in the timeline: it will never be where you put it, thus completely preventing you from skimming those contents...

Three months ago, when the event took place, I saw what looked like a bug; I tried to get the presenter to repeat the steps but that didn't seem to reproduce the bug; since we had already been promised the replays before the event started, I didn't worry too much. I though: I'll wait for the replays and try and see if I did really see a bug in action and if true, I'll report it, if not, no further action will be needed.

Well, never in a million lifetimes would I think that publishing those replays would take 3 whole months and, worst, that after those 90 days, the job would still be done in a very amateurishly way...

CodeGear, this is not the way to tell us customers that one of your goals is quality: doing a bad service and taking so long to do it so bad is not what I or many others would call quality...

BTW: Should the responsible at CG want to at least fix the skimming bit, it has to do with the many files that Camtasia uses and the different ways of indicating the video size: you can't re-use them for other presentations unless they have the exact same duration, otherwise you'll end up in the mess you have managed to do...

2007-06-20

Windows Live Writer, Spell Checker, Pascal Code Formatting

September 2007 edit: Steve Dunn has updated his control, and so this no longer applies. Check my other post about using his newer version and "fixing" the used Pascal definition file.

After reading this post from Primoz Gabrijelcic, which took me to this other post from Jimmy Bergmark, my Windows Live Writer has once again the Spell check option.

In the 2nd post mentioned above, I saw a reference to another plug-in, a code-formatting plug-in, something that I wanted to add to WLW too, so I decided to check it out. I downloaded it (from here), and was a bit surprised about the lack of Pascal as a choice for language. A quick check later and I saw the different languages each had an XML file, so I thought for myself: "It can't be that hard to grab one and modify it for Pascal". And so, I started the conversion process. Unfortunately, I had placed too much faith on the recently fixed "Improved Help" of Delphi 2007: needless to say that, after a few minutes of fighting with the help, which, although improved since Delphi 2007's release as at least now it no longer renders the IDE unusable if you press F1 on a menu, I had nevertheless to give up. Finding basic things in that help is a pain in the ***, and that's putting it nicely! Be that using filters or no filters, language filters or no language filters, finding Pascal help for a list of basic types has proven to be a much greater challenge than it should have been.

So, attempt number two: Google to the rescue! I googled a bit and within seconds had found this other page, from where I could download the controls that were used by this code formatting plug-in, so, after typing a fake name and e-mail (I hate these "we want your name before you can download" type of sites!), I downloaded the free controls. Extracted the ActiproSoftware.Pascal.xml file and placed it in the code formatting plug-in Languages folder and fired up WLW.

Things didn't quite work out: no Pascal available in the language choices. A little bit more digging, and I found that the DunnHQ.Wlw.CodeFormatter.dll.config file is in fact an XML file with a list of all available languages and definitions, so, after adding the following line:

<language key="Pascal" definitionPath="./plugins/Languages/ActiproSoftware.Pascal.xml" />

and restarting WLW, I "Pasted Clipboard as Code", selected Pascal from the list of languages and got this as result:


Bugger


Humm... Something is amiss surely...


After another quick check, I found the source: the language definition XML files used in the plug-in have LanguageDefinitionVersion="3.0", while this one downloaded from ActivePro has LanguageDefinitionVersion="4.0", so, time to go check if I can find one of those for version 3...


(At this point, I can not even save a draft of this post as I get this when trying to do it:)


Another bugger


(D:\XDesk is my Desktop folder: somehow it's trying to load the language definition for the small line of XML above from the Desktop instead of from the program's start location..)


So, after a quick copy/paste of that plugins folder to my desktop, I saved, quit WLW and resumed Googling...


It turns out that the format has been significantly changed between versions 3 and 4 and that the Pascal definition was added only in version 4. Luckily, at this point I also found another code-formatting plug-in that seems to be based around v 4 as it lists Pascal in the available languages! So, after downloading and trying SyntaxColor4Writer, I was again in a dead end: it's for Beta 1 and would not work on Beta 2!


Well, I ended up clicking the "Add a Plugin..." button in WLW and downloading Code Snippet plugin for Windows Live Writer so that's what I'll try next. If it doesn't work ok, I'll update this blog post asap. Another dead end... List of supported languages:


image


Uninstall this one, try the "Add a Plugin..." button again... Another quick look finds another one that is probably based around the same source as the list of languages is identical, so, back to Google again... (I really should be working instead!)


Back to the starting idea and let's see how hard it is to retrofit v 4 Pascal definition XML into v3 controls. It turns out that it's VERY easy! All you need to do for it to start working is change both 4s in the first line of the Pascal.xml file into 3s. Like this:



<SyntaxLanguage Key="Pascal" LanguageDefinitionVersion="3.0" Secure="True" xmlns="http://ActiproSoftware/SyntaxEditor/3.0/LanguageDefinition">


So, after that it's now working with Pascal code. There are a couple things that don't look that good, namely the wrong color of keywords such as "unit", "uses" and others, but it should be easy now to fix the Pascal.xml file and simply add those keywords. So, with a little help from Delphi Basics to get what the built-in help in Delphi 2007 won't give me (a list of reserved keywords), here's how some sample Pascal code looks like:


unit uHeader;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Outlook2000, adxolFormsManager, StdCtrls;

type
TfrmHeader
= class(TadxOlForm)
lbxHeader: TListBox;
procedure adxOlFormADXSelectionChange(Sender: TObject);
private
{ Private declarations }
protected
{ Protected declarations }
public
{ Public declarations }
published
{ Published declarations }
end;

{NOTE: The adxOlForm1 variable is intended for the exclusive use
by the TadxOlFormsCollectionItem Designer.
NEVER use this variable for other purposes.
}
var
frmHeader : TfrmHeader;

implementation

{$R *.DFM}

uses MapiDefs, MapiTags, MAPIUtil;

procedure StringToList( Str: string; lstResult: TStrings );
// Convert a header string containing CR/LFs and TABs into
// a stringlist where each new property starts on a new line
var
iPos : integer;
const
CRLF
= #13#10;
begin
lstResult.Clear;
iPos :
= Pos( CRLF, Str );
while (iPos > 0) and (iPos < (Length( Str )-1) ) do begin
// If the new line starts with a Space or Tab, it's a continuation line
if (Str[iPos+2] = #9) or (Str[iPos+2] = #32) then begin
Delete( Str, iPos,
2 );
end else begin
lstResult.Add( Copy( Str,
1, Pred(iPos) ) );
Delete( Str,
1, Succ( iPos ) );
end;
iPos :
= Pos( CRLF, Str );
end;
end;

procedure TfrmHeader.adxOlFormADXSelectionChange( Sender: TObject );
var
Selection: Outlook2000.Selection;
IMail : _MailItem;
IMessage : MAPIDefs.IMessage;
PropValue: PSPropValue;
begin
lbxHeader.Items.Clear;
Selection :
= Self.ExplorerObj.Selection;
if Selection.Count > 0 then begin
try
// Try for a "normal" mail item
Selection.Item(1).QueryInterface( IID__MailItem, IMail );
if not Assigned( IMail ) then begin
// If it failed, try for a Read/Delivery Receipt item
Selection.Item(1).QueryInterface( IID__ReportItem, IMail );
end;
if not Assigned( IMail ) then begin
// I don't use Remote Mail, but for completeness this should be tested also...
Selection.Item(1).QueryInterface( IID__RemoteItem, IMail );
end;
except // Ignore exceptions
end;
if Assigned(IMail) then begin
try
if IMail.Sent then begin
IMail.MAPIOBJECT.QueryInterface(MapiDefs.IMessage, IMessage);
if Assigned(IMessage) then begin
try
PropValue :
= nil;
if HrGetOneProp(IMessage, PR_TRANSPORT_MESSAGE_HEADERS, PropValue) = S_OK then begin
StringToList( PropValue^.Value.lpszA, lbxHeader.Items );
end;
finally
MAPIFreeBuffer(PropValue);
IMessage :
= nil;
end;
end;
end;
finally
IMail :
= nil;
end;
end else begin
// If no headers found...
lbxHeader.Items.Add( 'This type of message does' );
lbxHeader.Items.Add(
'not have mail headers' );
end;
end;
end;

(* Test Comment *)
initialization
(* Another test comment
spanning 2 lines
*)
RegisterClass(TPersistentClass(TfrmHeader));
(* Another comment w/ a
{ Nested comment }
*)
finalization
{ Another test of nested comments
(* This is
another one *)
}
end.


Wrap up


Edit: Check this post for the updated files.



So, if you got kind of lost, go here to download the WLW code formatting plug-in then download this file which is my updated ActiproSoftware.Pascal.xml file and place it in the plugins\languages folder. Download this file and place it in the plugins folder overwriting the existing one (updated languages definition file for the plugin). And you're good to go!


From now on you'll be able to easily insert Pascal formatted code onto your WLW post!


If you find some syntax formatting error, let me know: I'll fix whatever needs fixing and, in a couple days, I'll send this updated file to the plugin's author so he can update his plug-in and also to the component's vendor since they're providing this for free so they too can update their component.


Have fun blogging about code... :)


Note: Somehow, either this plug-in's fault or WLW beta 2 fault, extra empty lines were added to my post, so don't be surprised if you need to delete some extra lines after publishing... :)

Also, for no good reason, even though it was displaying properly in WLW, some spaces were removed from the code, either from publishing or from my editing of this post afterwards. Just added those extra spaces and will see if they stick after re-publishing...
Update: apparently did not work! :( Still, not a big issue so I won't be spending time on it for now...


Yet another update: I'm now re-editing the post from within WLW: first time I try this!! It appears to work just fine, so I'll try to re-publish it from WLW and see if the missing spaces in the code somehow re-appear as they show nicely in WLW...


Well, it appears to be the plug-in's fault for adding the extra space: probably some style change that was not undone. As for the spaces, as long as I don't edit the post in the browser they display correctly. I'll have to get back to work, so maybe later I'll check the generated html from the code plug-in and try to find the bug. Until then, just ignore the extra spacing that makes this post look a bit ugly... :)

2007-06-15

Developing Office Add-ins the Easy Way - Part 3 of 2 (AKA: Yes, I do know how to count!)

Well, even though it's probably not the best use for my time judging from the overwhelming feedback I got on the previous 2 parts, it also doesn't take me that long to write this 3rd part of 2 so I'll do it anyway! :)

I've fixed most (all?) of the blogger screw-ups with the formatting of my post and some incorrect color coding from using Steve Trefethen's Syntax Highliting page, and now I decided to add a couple files for easier download. Here you can find the zip file with nothing but the source code and the Extended Mapi units, and here you can find a nice setup made with InnoSetup in a few minutes that will install the compiled add-in, register it, create a source subfolder with the source code in it and allow you to uninstall all this at any time should you want to. Just remember that you need to restart Outlook to have it acknowledge the newly installed add-in.

Because I know that Blogger will again mess up my formating, I'm instead placing here a prt-scr of the InnoSetup script used for creating the installer: most of it was done through the wizard...

Inno

On a different note, Part 3 of Delphi in a Radical Build will be postponed for a while: my available time has dropped considerably and whenever I pick up on that 3rd part I'll have to redo the 1st two parts as I've recently had some data loss while trying to repartition my external HDD using a re-partitioning utility that had not let me down before... So, the amount of work involved in creating that part 3 of 3 would largely surpass my free time for a lot longer. Not all is lost however as at least I can read my own articles and recreate it: that's one nice side-effect of blogging about something! :)

On another different note, is it my impression or the Windows Live Writer beta 2 (which I installed after finishing the previous 2 posts), lost the spell checker?? I could swear there was an option to spell check in the previous beta!

2007-06-14

Developing Office Add-ins the Easy Way - Part 2 of 2 (AKA: The tutorial stuff...)

If you haven't read Part 1, I'd advise you to do so. In it you'll find some more information on these components and, more importantly, your 20% discount coupon redeemable until the end of June 2007...

Step 1: Running the new Add-In Wizard

  1. Fire up Delphi and choose File->New->Other, Delphi Projects->Add-In Express VCL->ADX Outlook Add-in.
  2. Click Next and, for the project name, I'm using Insider and coInsider for the coClass Name. The first is used, guess what?, for the Project's name and the 2nd is used in Outlook's COM Addins dialog (Tools->Options->Other->Advanced Options)
  3. Clicking next will show you the "Option Pages" step which is optional.
    • For this addin we'll just hit next again. For a more complex add-in, this would be where you'd create your own option pages. You can have option pages displayed as another tab on the Options dialog or by right-clicking all or some folders in outlook, say one for Inbox, other for Outbox: they are different types of dialogs serving different purposes and you can add as many as you like.
  4. Hit next again and we'll be in the "Outlook 2007 Task Panes"; again, not of interest to us here so move along.
  5. Click Next, Finish and we're done here.

Step 1.5: More blah, blah, blah...

We now have a basic project that we'll add some meat to in order for it to do what we set out to. We could easily add an explorer or inspector command bar, but we don't need them for this project. An explorer command bar is one that is displayed on Outlook; an inspector command bar is displayed when you double-click some outlook item and "inspect" it in it's own window. Say, when you double click an e-mail message and another window pops up. You can have the inspector command bars only display for certain types of folders by simply setting a property, say, create an e-mail inspector bar that is displayed only when inspecting a mail message but not when viewing an appointment. And, of course, you can add as many as you want and add buttons, menus and other controls to them at will.

Among other cool objects you can use (not needed for this add-in), are the TADX<AppNameHere>AppEvents, such as TADXOutlookAppEvents from where you can add your own handlers. Here's the list of OutlookAppEvents (these are global events: other components have their own events as well, but these are events that don't relate to a particular button being pressed or hotkey being used):

  • OnItemSend
  • OnNewMail
  • OnNewMailEx
  • OnQuit
  • OnReminderFire
  • OnStartup

BTW: Thanks to blogger messing up my formatting big-time, I had to shorten the list to just a few sample items so as not to have a whole lot of space wasted. Maybe I'll take a prt-scr later and update this...

Step 2: Adding some components and code

  1. What we are now going to add is an "ADX Outlook Form" which is a small pane where we will be displaying the headers of the selected message, so go to File->New->Other, Delphi Projects->Add-In Express VCL and double click "ADX Outlook Form".
  2. Save the form (I used uHeader for the unit name).
  3. Add a TListBox, call it lbxHeader and set it to fill the form.
  4. We need another component to control creation of these panes. Go on to the main project form (should be empty) and add a "TadxOlFormsManager".
  5. In this component's events, add the following code to the "OnADXBeforeFormInstanceCreateEx" event:
    1 if args.FolderObj.EntryID = OutboxEntryID then begin
    2 args.Cancel := true;
    3 end;
  6. Let's add that OutboxEntryID as a protected property to the form (TAddInModule) of type string:
    1 property OutboxEntryID: string read FOutboxEntryID;
  7. And the corresponding internal field to the private section of TAddInModule:
    1 FOutboxEntryID: string;
  8. And a method to set the value in the protected section (not a setter method though!):
       1 procedure SetOutboxEntryID;
      2
      3 procedure TAddInModule.SetOutboxEntryID;
      4 var
      5 nameSpace : Outlook2000.NameSpace;
      6 outboxFolder: Outlook2000.MAPIFolder;
      7 begin
      8 try
      9 nameSpace := OutlookApp .GetNamespace ( 'MAPI' );
      10 outboxFolder := nameSpace .GetDefaultFolder( olFolderOutbox );
      11 FOutboxEntryID := outboxFolder.EntryID;
      12 finally
      13 nameSpace := nil;
      14 outboxFolder := nil;
      15 end;
      16 end;
    • Now click the form and enter the following code to it's "OnAddInInitialize" event:
      1 SetOutboxEntryID();
    • Finally, let's give the TadxOlFormsManager something to manage: double click it and add a new item. Set the following properties for that item:
      1. ExplorerItemTypes->expMailItem, set to True as we want this form displayed on mail folders only; leave all others to false.
      2. ExplorerLayout set to elTopSubpane; (you can play around with it later if you want!)
      3. And finally, let's link it to the form we created above: set FormClassName to our form created above. It will be available on the drop down as soon as you go into File->Use Unit and select our uHeader unit.

    If you build the project, register it and launch outlook, you'll see a blank new pane displayed: Sorry for the large, dimmed and blurred image: it's from my main outlook... :)

    Also, if you notice, so far most of the code was related to adding an exception, that is, we wanted our form to display on mail folders, unless that folder is Outbox.

    Now it's time to add our real meat into this.

    Step 3: Adding our application logic

    1. Lets go back to our uHeader unit and add the following code to the onADXSelectionChange event:
       1 procedure TfrmHeader.adxOlFormADXSelectionChange( Sender: TObject );
      2 var
      3 Selection: Outlook2000.Selection;
      4 IMail : _MailItem;
      5 IMessage : MAPIDefs.IMessage;
      6 PropValue: PSPropValue;
      7 begin
      8 lbxHeader.Items.Clear;
      9 Selection := Self.ExplorerObj.Selection;
      10 IMail := nil;
      11 if Selection.Count > 0 then begin
      12 try // Try for a "normal" mail item
      13 Selection.Item(1).QueryInterface( IID__MailItem, IMail );
      14 if not Assigned( IMail ) then begin
      15 // If it failed, try for a Read/Delivery Receipt item
      16 Selection.Item(1).QueryInterface( IID__ReportItem, IMail );
      17 end;
      18 if not Assigned( IMail ) then begin
      19 // I don't use Remote Mail, but for completeness this should be tested also...
      20 Selection.Item(1).QueryInterface( IID__RemoteItem, IMail );
      21 end;
      22 except// Ignore exceptions
      23 // QueryInterface may throw up an exception, but I don't recall under what condition it was
      24 // It was for some non->relevant item, i.e., one that we're not processing here
      25 // That's the bad thing of writing something and not documenting it properly when it happens!
      26 end;
      27 if Assigned(IMail) then begin
      28 try
      29 if IMail.Sent then begin
      30 IMail.MAPIOBJECT.QueryInterface(MapiDefs.IMessage, IMessage);
      31 if Assigned(IMessage) then begin
      32 try
      33 PropValue := nil;
      34 if HrGetOneProp(IMessage, PR_TRANSPORT_MESSAGE_HEADERS, PropValue) = S_OK then begin
      35 StringToList( PropValue^.Value.lpszA, lbxHeader.Items );
      36 end;
      37 finally
      38 MAPIFreeBuffer(PropValue);
      39 IMessage := nil;
      40 end;
      41 end;
      42 end;
      43 finally
      44 IMail := nil;
      45 end;
      46 end else begin // If no headers found...
      47 lbxHeader.Items.Add( 'This type of message does' );
      48 lbxHeader.Items.Add( 'not have mail headers' );
      49 end;
      50 end;
      51 end;
    2. Now let's add the MAPI units to our project and to the uses clause in this form:
      1 uses MapiDefs, MapiTags, MAPIUtil;
    3. Now all that is left is to add that StringToList function I used to process the semi-colon formatted mail headers into a more readable list:
       1 procedure StringToList( Str: string; lstResult: TStrings );
      2 // Convert a header string containing CR/LFs and TABs into
      3 // a stringlist where each new property starts on a new line
      4 var
      5 iPos : integer;
      6 const
      7 CRLF = #13#10;
      8 begin
      9 lstResult.Clear;
      10 iPos := Pos( CRLF, Str );
      11 while (iPos > 0) and (iPos < (Length( Str )-1) ) do begin
      12 // If the new line starts with a Space or Tab, it's a continuation line
      13 if (Str[iPos+2] = #9) or (Str[iPos+2] = #32) then begin
      14 Delete( Str, iPos, 2 );
      15 end else begin
      16 lstResult.Add( Copy( Str, 1, Pred(iPos) ) );
      17 Delete( Str, 1, Succ( iPos ) );
      18 end;
      19 iPos := Pos( CRLF, Str );
      20 end;
      21 end;

    And we're done!

    Just build again, and re-launch outlook and you'll have something like this:

    Final thoughts and notes:

    1. Don't forget that you can regsvr32 dlllname.dll or regsvr32 -u dllname.dll and any installer will do that for you if you mark the dll as self-registering.
    2. Don't forget that you'll need to close the application you're testing/compiling your add-in for, before you can compile it as the dll will be in use! :)
    3. If you look back, you'll see that you pratically never knew you were handling COM objects and that most of the code was for the application logic with part of the complexity in that arising from using Extended Mapi because Outlook's object model is a bit limited in some places... Creating Excel add-ins is even easier as you don't have to deal with Extended Mapi! ;) You will require some knowledge of the application's Object Model, but that comes out of the box in the form of some VBA help files that you can install with your Office.
    4. I didn't show in this simple demo two other easy to implement features, mostly out of lazyness: adding toolbars/buttons/menus and option pages. Trust me (or don't trust and instead try for yourself!): those are very easy to implement!
    5. Don't forget to take advantage of the 20% discount coupon (see Part 1), and have fun Developing Office Add-ins the Easy Way!
    6. Syntax highlighting done using Steve Trefethen's Syntax Highlighter and then manually tweaked the generated HTML to fix some coloring bugs.

    Developing Office Add-ins the Easy Way - Part 1 of 2 (AKA: Blah, Blah, Blah...)

    Well, I first started thinking of doing this post in April, then, earlier in May, I thought of contacting the component vendor asking them for a special discount coupon that I could give you, the reader of this blog. They promptly gave me one that was good until the end of May, but, as you may suspect by now, I didn't have the time to make the post. Well, things are a bit easier now with Windows Live Writer, so I'll try to make this post today (edit: I finished this several "todays" after starting!). (And don't worry, I talked with them and they extended the coupon's validity to the end of June!...)

    So, how does one create an Office Add-in the easy way? Well, you cheat! :)
    Actually, it's no more cheating than using database access components to access a, (you guessed!) database... I've been using AfalinaSoft's Add-In Express components in the last 18 months or so, and all I can say is that it's child's play doing any office Add-In development, be that Word, Excel, PowerPoint, Publisher, Visio, etc... I've created some Excel add-ins for my own use just because it was so easy to do them, rather than coding in VBScript! Outlook is very well represented in this lot with very cool features available for it as you'll see later in this post. Some new features added in the 2007 version allow you to add new form regions allowing you to create some great outlook add-ins with very little effort! (Note: that's 2007 version of the components, not of Office! All the features and the tutorial in the next part work the same from Office 2000 to 2007!)

    Today's Add-In (I don't imply I'll be adding more, but one never knows as it's really easy to do them!), is a small Outlook Add-in that will show a collapsible pane in the messages list to show you the full Internet headers of the selected e-mail. You can shrink/expand/collapse this pane at will and, due to the way things work in Outlook, it's available for all mail folders except the Outbox. I've had to explicitly exclude that one after I found out that, if I select a message pending delivery, it would cancel delivery of that message: kind of what happens if you double click a message in the outbox and don't hit send again. No big deal: after a mail to the excellent Afalina support, I had a simple way of excluding just that folder (or any other I could want to exclude).

    So, what do you gain by using Afalina's Add-In Express instead of doing it the hard way?

    1. A very well though out and tested component suite.
    2. You can easily follow a couple steps in a wizard, add a few lines of code and have an add-in ready in minutes, not hours.
    3. For the most part (there are a couple minor things to take into consideration), you get not to worry if your add-in is going to be used in Office 2000/XP/2003/2007 and wether or not those are running the default install or SP1 or SP2 or whatever.
    4. If you plan on going the .NET way in the future, they have the exact same components available for .NET.
    5. Deploying your add-in for non-.NET versions is easy: if you don't use packages, all get's compiled onto your main project (DLL), so it's a simple file to distribute/register/whatever.
    6. Many examples of different add-ins for different office applications are available.
    7. If you purchase the higher version (Premium), you get the full source code, including designers and wizards.
    8. Again, for the highest version you can even have instant messaging access to the developers; for other versions, normal e-mail and web-forum based support is provided and still they answer questions promptly.

    Now, before you read any further, I must point out three flaws of this component suite, even though they are minor flaws as I'll explain later:

    1. No trial version
    2. Requires Activation
    3. No help file

    Why do I say they are minor?

    1. You have a no questions asked 30 day money back guarantee (for the non-source versions) : I recommend you start with Standard version or Basic if you're on a short budget, and later, after you decide you will keep it, contact them for upgrade pricing for the source-code versions. I started with Basic myself, over 18 months ago, and have since upgraded to the Premium for the source code and added support.
    2. In the Premium version you get the whole source, even for the designers and wizards, so even if they somehow get out of business, you are not prevented from installing these components; also, you can install these on up to three machines, so you can install it on a Virtual Machine to have ready as a fallback procedure.
    3. They provide an easy to follow start up manual, they also provide both in the installer and in their website a plethora of demo add-ins, they have a very active and friendly forum, and tech support is among the best I've found for any component suite. In fact, should you get the Premium package, you can even contact them through instant messaging!

    As for the coupon code, if you purchase the Basic or Standard versions (no source code included), you can use this coupon for a 20% discount until the end of June 2007: ADFXM20

    Remember that, even using this coupon, you will still have the 30 days from date of purchase to return the product for the price paid should you not be happy with it.

    You will need the Standard version if you want to take advantage of the advanced forms feature as described in the next post. As for later, once you decide you want to keep these components and no longer need to take advantage of the money back guarantee, I'd recommend you to upgrade to either Pro or even better, Premium, not only for the full source code but also the added support. Contact them and they'll upgrade your license for the difference between the purchased and wanted versions.

    Now, with a very lengthy post already, it's time to start explaining how easy it is to create an outlook add-in to display the selected message's headers in another pane. When I started trying to create this demo application, I needed access to some message properties that I wasn't finding through the outlook object model, so I e-mailed them my question and very promptly (next day, IIRC), they sent me, not only the answer to my question, but a few Pascal units with the translated Extended MAPI and a sample project that addressed my problem! I received similar help from them later on when I couldn't find a way to exclude just one folder (outbox) from the folders where the add-in's pane would show and I mailed them the project with my question and they returned me the updated project with a few lines of code added and a short explanation of what was done. It's not as instant as a help file, but it sure is a lot more flexible!

    I was thinking of doing a Video, but not only I'm on a short budget now and the free solutions I tried didn't inspire me, but it's also easier to copy/paste this and print it out for reference, should you want to follow along!

    Part 2, which I'm writing right now, will be posted a few seconds after part one: I decided to split it so it's not such a big article and because you can thus print that 2nd part and use as a follow along should you want to try it out.

    2007-06-13

    "Font smoothing, anti-aliasing, and sub-pixel rendering" - Joel on Software

    Well, after reading this post, and since I couldn't find a way to comment on that, I opted for the easy comment option: blog about it! :)

    In fact, not much to say here, rather than in this particular aspect, I do favor Microsoft's call rather than Apple's one. Why? Well, surely being used to it also helps making that call, but I'd like to believe that reasoning has something to do with it too! :)

    When you spend so much time staring at a computer screen (12+ hours a day), which one would you favor: readability (read: clear, crisp, non-eye-straining text), or paper-similarity (read: fuzzier but more truer to print text)?

    If only one to choose from, I go with readability, the way MSFT did (hey! I'm actually sticking on MSFT's side on something! :)); It could be nice to have an option to have a more paper-like preview, but for the most part, and for a programmer who spends a lot of time staring at code, paper similarity is nothing compared to the ease on his eyes from reading crisper text...

    If I were to do a vote, I believe most people would agree with me for two reasons alone: most readers of my blog are Windows users and most are programmers, so they would easily go for the MSFT way in this particular context.

    Of course, when we get to the insanely high DPI displays, affordable displays that can show 300+ DPI, then this question could be raised again. Until then, I'll stick with MSFT's way...

    Delphi 2007 Update - Take 3

    I wasn't very fond of InstallAware, not as it's used by the Delphi installer, but now I'm even lesser of a fan: so much bloat and so much file messing around from here to there back here then a new there... Is it really necessary? Can't the Delphi installer be a bit more (read: a LOT more!) streamlined?

    I've attempted to update my clean Delphi 2007 image and the process stalled. I read somewhere that some people achieved good results by disabling all their startup programs, only I will rather reformat my PC than I start disabling software just so I can upgrade or install something...

    Luckily, both in that clean Delphi VM and in my main machine, "upgrading" using the now available ISO image went just fine. And I say "upgrading" as it's really a complete uninstall followed by a new install, not really an update... The only good thing is that component registration is left intact so you don't need to re-install them all again.

    Well, after all that, all that was left was testing the update on the tweaked install that I've blogged about earlier. Even though my main dev machine is a variation of that setup, I wanted to test on the same configuration used for that article. Took me a while as I had to redo that image as I recently tried repartitioning my external HDD and good 'ol Murphy stepped in ruining everything in it, but eventually I found enough time to follow the step by step instructions on my own article and redo that image. Oddly enough, upgrading went fine when it had failed on the non-tweaked and clean VM! Just a couple notes for those updating that version:

    1. To be on the safe side, export HKCU\Software\Classes and HKCU\Software\Borland from the account used and import on the install user account;
    2. After the install is done, repeat those steps in the other direction
      (Note: I did it without using these steps and it appears to have worked fine, but if you want to be 100% sure, do these two operations as they won't take much time)

    Also, when asked for the missing files, be sure to enter the {ABE...} folder in the Install user's local settings\application data used for the original install. And don't check the "Clear cache" option!

    The installer works in very weird ways: first, a new GUID is used to cache the files ({2EB...}); then it clears almost everything from the old install cache ({ABE...}), leaving only around 60 MB there. In the end, it copies some files back there, so the end cache space used is around 420 MB in {ABE...} and 770 MB in {2EB...}. Which ones will it use when you use update 2? I have no idea!! Just guessing, and judging from the files and sizes, I'd say that the cached files are in {ABE...} and the uncompressed cached files are in {2EB...}. However, the Setup.exe and related files are together with the uncompressed files, so I really have no clue what the 7z files are needed for... Will all those files be sufficient to install on a new machine? I don't know nor have tested yet. Maybe later but no promises...

    If you really want to be on the safe side, I'd download the ISO since it's the option that installed fine for me in a couple tests where the update would fail. In that case, just click the option to delete the cache. Now, if CodeGear would smarten up a bit and use a decent installer...

    2007-06-08

    My Second impressions of the Delphi 2007 Update 1

    Well, this time, even though I have the ISO I downloaded last night, I choose to try the auto-updater. So, I fired up my Delphi VM and, as I write this, it's been 2 hours since it said the updates were ready to install and started installing them... No clue as to how many more and, unlike Nick said of slow hard-disks, I'll hardly think this to be a HD problem as neither my physical HD light nor the virtual HD light from the VM seem busy: they hardly flash at all!

    I'll check back every couple hours or so to update the progress...

    EDIT: Almost 4 hours into it and in the same spot: that is surely stalled. I'll leave it running a bit more as Nick says it will "eventually finish", but after dinner, I'll check again and most likely will try again. If it fails once more, then I'll try with the ISO image...

    My first impressions of the Delphi 2007 Update 1

    + Update went well very smoothly (didn't time it as I used the time for having breakfast!)

    + Disk space required after the full install was more or less the same used previously: a couple MB less in some places a few more in others, but overall was only around 10 MB more.

    + Pressing F1 on a IDE menu will no longer render the IDE unusable

    - It still doesn't show the help page for that menu though ("No help available for context")

    + New filters available on the Help Index, including "Language: Delphi"

    - Interestingly, integer, array, and several other keywords I tried, don't seem to be part of the "Language: Delphi"! :)

    - Pressing F1 over those keywords in the editor (and some others such as uses, private, program and more), will either show the infamous "No help found for context" or will point me to C++ only information;

    - An empty help filter option (Dinkumware) was left in the shipped version that should not be there;

    - There's still C# and VB.NET help offered for some keywords instead of the proper Delphi version of those keywords (try pressing F1 over "implementation"). I wonder if Codegear wants to sell us on MSFT tools! :)

    That's all for the first few minutes. I thought of going through my Quality Central reports and see which ones had been addressed (if any), but seeing so many still in the un-opened state after over 2 months of them being reported kind of made me lost interest in doing that check.
    In fact, that's one reason, if not the major one, behind my lost of interest in helping out on QC in the latest months... That and seeing clear, concise and easy to replicate reports being left un-opened for years, kind of makes me think that it's a waste of time QCing at all... Sure, it's all fine and dandy using volunteers to pre-process QC, but leaving so many reports un-opened does not add to the overall quality they (CodeGear) are trying to achieve. I'd guess this is one area where they'll need and want to make some changes...

    And now another week is ending and I've yet to make a couple promised posts... :(

    I'll try to make at least one of those either today or tommorrow at most, since that one involves a discount coupon on a set of components and the time is ticking on that coupon... Stay tuned.

    CodeGear: All customers are equal but some are (no longer) more equal than others

    For those who missed a small subtlety with the latest Delphi 2007 update, there is now an ISO available for download from the registered users area!

    It's a 4.16 GB file and after a couple small problems I finally managed to download it. Just beware that, using the FTP link, it will incorrectly show as only 160 or so MB file but it seems to download the whole file anyway. In the end, I had to use the Borland Download Manager and I'd recommend you to do the same because continuing the FTP download will fail due to the incorrectly displayed size should you run into any network problem during the download.

    As usual, I'll be doing some installations/tests/updates and I'll blog a bit about it later!

    For now, and even before installing, I'd like to publicly thank CodeGear for two things: making the ISO available to all customers and having an option to delete the cache. Now, if only they added a way to not use that cache at all and instead use the DVD or downloaded cache instead, now that finally would be a decent installer!

    2007-06-05

    Easier to browse list of incoming Fixes in Delphi 2007

    That's what one gets to do when having a few minutes left: not enough to do some coding, but enough to do some text find/replace and blog about it! :) I did it for myself, but maybe others will find this useful too as it's far easier to browse than the full QC post here... For the more curious, just took some 10 minutes or so to manually process that list using UltraEdit: then a couple more to paste it in excel to find a couple exceptions missed and fix them, then copy/paste them into Windows Live Writer after going through UltraEdit again to add some table formating code... (List sorted by Area then Description)

    [EDIT: added links for valid QC reports]

    [EDIT 2: I'm still fighting with blogger to get it to re-display the table properly without placing so much empty space between the text and the table!]

    [EDIT 3: Found the problem: apparently blogger doesn't like it when I paste back some HTML with extra CR/LFs as I used to make each table row in it's own line; removed all CR/LFs, pasted back and it's working again!]

    QC#AreaShort Description
    42627ActiveX->IDE->Implementation file management TLB is not renamed if project that contains a TLB is renamed using save as.
    40156Compatibility->Previous -> Current Custom Action developed in Delphi 7 blocks BDS2006 when form viewed
    44731Compiler dcc32.exe reports E2029 error incorrectly
    34298Compiler->Delphi Compiler allows *static* class methods to be passed as value of method pointer variable.
    45896Compiler->Delphi Compiler generates internal error on compiling attached project
    41751Compiler->Delphi->Code Generation/Optimization Property with inlined function and Data type conversion produces wrong code
    41285Compiler->Delphi->Code Generation/Optimization using self in a class method of a class helper causes an av
    32786Compiler->Delphi->Errors - Warnings BTInner class cannot get access to strict protected virtual method of outer class
    43943Compiler->Delphi->Interaction with UI IDE disappears when opening D7 forms.pas
    45336Compiler->Delphi->Language->Overloading cannot implicitly cast records to Float type
    22878Database InterBase Blob output params of StoredProcs truncated in D2006
    42824Database->DBExpress->TSQLConnectionDBX4 TSQLConnection Memory Leak and Debugger Fault Notification
    42673Database->DBExpress->TSQLConnection Memory leak in TSQLConnection.Open
    45565Database->dbExpressCore Create constructor of DBXDynalink.DBXDriverLoader or of third party driver never called
    43141Database->dbExpressCore mixing DBX3 and DBX4 drivers leads to crash in IDE and code
    43125Debugger->Evaluator->Delphi Default display for PChars is "Character"
    34555Debugger->Multi-process cannot switch the active project when a process is being debugged
    38658Debugger->Stepping using f7 to step into a method causes bds to lockup with 100% cpu use
    42423Documentation Help for TStream.Seek is incorrect
    21202Documentation Missing Help for AlignWithMargin
    44320Documentation Unable to overload shift operators
    16261Documentation->IDE Help Contexts Component | Import Type Library missing
    39516Documentation->IDE Help Contexts Help missing for TDBGrid.Anchor properties
    39517Documentation->IDE Help Contexts Help missing for TDBGrid.Constraints
    39857Documentation->IDE Help Contexts Help missing for the following TDBGrid.TitleFont properties
    39856Documentation->IDE Help Contexts Help topic missing for the following TDBGrid.Style properties
    27348Documentation->IDE Help Contexts TCustomListView.TopItem Property help file has conflicting instructions
    13801Documentation->IDE Help Contexts There is no context sensitive help for the EllipsisPosition property on a TLabel
    31928Documentation->Online Help Clipped Help re: dynamic arrays
    9957Documentation->Online Help Many VCL indexed properties documented incorrect
    20522Documentation->Online Help TControl.Margins help topic not helpful
    39569Documentation->Online Help->Main help AllocMem function is not present in Online Help
    30552Documentation->Online Help->Main help Help for the TEventStatus Enum Has Duplicated Text
    34061Documentation->Online Help->Object Pascalincomplete list of fundamental types
    36354Documentation->Online Help->Object Pascal Delphi help doesn't say about Iterators for interfaces, but feature is implemented.
    34676Documentation->Online Help->Object Pascal Delphi help doesn't say about Iterators for records, but feature is implemented.
    39761Documentation->Online Help->Object Pascal Links in Ceil, Floor, and Trunc help don't work.
    42767Documentation->Online Help->Object Pascal Warning/error confusion in FOR and FOR IN documentation
    38647Documentation->Online Help->VCL TCheckBox does not fire OnKeyDown for arrow keys, as help suggests
    33417Documentation->Online Help->VCL TCollectionItem.Create is not described as virtual
    38801Documentation->Online Help->VCL THandleObject.WaitFor is not documented
    42285Documentation->Online Help->VCL The documentation for TMenuItem.Hint Property is incorrect.
    43092IDE BDS does not show on Task Manager applications listSB: XP only
    43477IDE editor or welcome page has incorrect size after maximize, minimize and restore
    32650IDE IDE Exception dialog: Call stack should be included with copy to clipboard
    33315IDE->Code Browsing ctrl+shift+up/down command doesn't work in some classes with nested types.
    40744IDE->Code Editor Caret positioned one character further left of compiler error position
    44894IDE->Code Editor->Error Insight Delphi 2007 IDE suddenly disappears while typing
    43597IDE->Code Editor->Help Insight Help insight 'Object reference not set' errors with dotted filenames on search path
    42808IDE->Code Templates Automated Incident Report
    32108IDE->Desktop Layouts Resizing maximized editor window causes erratic behaviour
    43130IDE->Desktop Layouts Under undocked mode the main Delphi window is improperly sized after a minimize/restore
    40821IDE->Dialogs Confirmation dialog to add BPL path to the PATH environment variable is wrongly translated
    43097IDE->Dialogs Text display problems on Tools->Options
    44770IDE->Dialogs->Project Options Linker output option resets after closing & reopening project
    42948IDE->Dialogs->Project Options Record Field Alignment Option not saved
    40074IDE->Dialogs->Project Options should remove "Windows Forms designer" from the Tools | Options dialog
    42338IDE->File Handling When using Ctrl+Enter in the code editor to open a file, the IDE is not able to open an INC file
    41681IDE->Form Designer Minimising D2007 whilst in undocked mode leaves forms visible
    41917IDE->Help DEXPLORE.EXE not closed upon exit
    42640IDE->Help Garbled characters within a help topics selection dialog
    42237IDE->Help Help by F1 Doesn't work at all in object inspector for Modelling projects!!!
    219029IDE->History Viewwhen project is reopen, on History view, code pane ( bottom pane ) is grayed out
    41079IDE->Memory Issues using safemm, changing selected unit in the ide causes a read-AV
    43475IDE->Project Management Automatic conversion of .bdsproj to .dproj fails to convert $Z (DCC_MinimumEnumSize)
    44777IDE->Project Management Child forms are not recreated together with the main form when MainFormOnTaskbar is True
    43569IDE->Project Management Environment variables not expanded/recognized at compile time.
    43052IDE->Project Management Switching between Debug and Release doesn't cause a recompile when project is run
    21953IDE->ToDoList Priority information in To-Do List is lost
    42529IDE->Tool Palette Icon scrambling and unpredictible error messages in palette.
    43021IDE->Unit Testing->Test Case Wizard Catastrophic failure when creating unit test
    45149IDE->Unit Testing->Test Case Wizard No task bar entity for test case app
    40818Install Delphi does not work without installing Database Features
    42602Install EPackageRegistrationException in module sanctuarylib.dll
    44514Install->Files Enterprise instead of Professional in field ProductName in the version info resource of bds.exe of the Professional edition
    44662Install->Files TeePrevi.dfm is missing in ->lib
    42247Install->Registry settings Package load errors on startup when de-selecting some internet packages
    42403International->Truncation [STRING CORRUPTION]First phrase in installer is too long in French
    43114Internet->Indy Default browsing path for Indy is incorrect
    43986Midas->TClientDataSet Blob fields truncated in TClientDataSet
    22253Modeling->IDE Integration Added units do not show up in model view
    21228Modeling->Printing Overview in documentation generation is just a black box
    3910RTL->Delphi->Other RTL AccessViolation in TBucketList and TObjectBucketList DeleteItem
    45532RTL->Delphi->Other RTL Bug in ObjAuto.pas affects CreateMethodPointer functionality
    43199RTL->Delphi->WinAPI HelpShowTableOfContents gives error 'Unable to find a Table of Contents.'
    38342SOAP->WSDL Importer WSDL Importer renames "name" to "name_"
    37537VCL Form.ScreenSnap handling is wrong if Windows Taskbar is docked to left or top of the screen
    43331VCL Taskbar button is duplicated when restarting Explorer.exe
    45745VCL Vista Modal Dialog flashing broken in Update Patch
    36283VCL->Additional Controls->Action Bar Controls TCustomizeDlg is not localized
    43334VCL->Core VCL Classes IDE keeps focus if project MainFormOnTaskBar is False
    46202VCL->Core VCL Classes->TApplication Application.BringToFront not working as expected
    44910VCL->Core VCL Classes->TApplication BDS 2006 compiled applications do not get their taskbar button selected on startup with the latest vcl bpl files for Delphi 2007
    42374VCL->Core VCL Classes->TApplication Hiding main form changes the caption of the task bar icon
    43007VCL->Core VCL Classes->TApplication Wrong taskbar focus behaviour in IDE
    43984VCL->Core VCL Classes->TForm Application set to start minimized will behave erratically if MainFormOnTaskbar := True for non-Vista Windows
    43333VCL->Core VCL Classes->TWinControl A control whose parent's FShowing is false will not hide
    44401VCL->Dialog Controls Open and Save dialogs don't return FilterIndex under Vista
    46134VCL->Dialog Controls->TOpenDialog TOpenDialog under Vista Breaks doShareAware
    42610VCL->Graphics gifimg unit might display modal error dialog in initialization
    42867VCL->Win 32 Controls->TImageList Image list never grows its internal bitmap