Safe event hooking and unhooking (for Delphi IDE plugins)

 Delphi, GExperts  Comments Off on Safe event hooking and unhooking (for Delphi IDE plugins)
Oct 122015

In the comments to my Google+ post announcing my blog post on Hacking the Delphi 10 Project Options dialog Ondrej Kelle said:

If two or more plugins hijack the same global event handler then they must restore the previous (from their point of view) handler in reverse order, however this is not guaranteed and therefore this technique is likely to cause trouble.


API should be written, safe for plugins to use instead of the event handlers

to which Heinz Toskano added

This scenario remembers me when I wrote interrupt handlers for DOS. The civilized way was to hook and return the original handler, except when you replace the interrupt, in that case you was obliged to expose the original interface, just to not broke something else. Something similar must be done with IDE plugins, otherwise it will become bad coding.

I did a quick Google search but found no existing standard so I decided to simply describe one and publish it in the hope that others will find it useful and adhere to it.

I have moved the code and description to it’s own static page. I will improve it as I go along and blog about these improvements.

I post a link to this article on Google+. If you want to leave any comments, use this post.

How to disable update checking in TortoiseSVN?

 TortoiseSVN, Windows  Comments Off on How to disable update checking in TortoiseSVN?
Oct 122015

The latest 1.9.x versions of TortoiseSVN no longer support Windows XP (1.8.12 was the last one that did). Since some of the computers I work with are stuck with XP there isn’t much sense in having it check for updates automatically.

Older versions of TortoiseSVN used to have a check box on the settings “General” page, but that apparently was removed later. Now, it is on the “Advanced” page and called “VersionCheck”. Setting it to “false” disables the check.

TortoiseSVN Settings Advanced VersionCheck

Hacking the Delphi 10 Project Options dialog

 Delphi, GExperts  Comments Off on Hacking the Delphi 10 Project Options dialog
Oct 112015

Today I wanted to do something I did before: Add a drop file handler to an edit control in a dialog of the Delphi IDE. The dialog in question is the the Project Options dialog.

I thought it would be pretty simple to do that:

  1. Get the dialog instance from Screen.Forms list.
  2. Get the edit control using the form’s FindComponent method
  3. Attach a drop file handler to it.

Pretty standard for somebody who has written IDE plugins for Delphi before and is somewhat acquainted with its internals. Little did I know how difficult it would become.

First, the Project Options dialog is created dynamically (many other dialogs are created at program start). So, how do I access it?

It turns out that the global Screen object has got a useful event for this: Screen.OnActiveFormChange which is called every time the active form in the IDE changes. So my plugin could just assign an event handler to it and wait for the Project Options form to become the active one. This works, but there are two pitfalls:

  1. The IDE internally uses this event.
  2. How do I know which form is the one I am looking for?

To solve the first I have to hook it and call the original event handler.

To solve the second, I had to enhance my Delphi IDE Explorer to dynamically update its display. It also hooks Screen.OnActiveFormChange for this. This gave me the name and class of the Project Options dialog:

DelphiProjectOptionsDialog: TDelphiProjectOptionsDialog

So, now I had the dialog instance and needed the edit control for the debugging host application. Again, using the IDE explorer, I found its name and class name:

SourcePathInput: THistoryPropComboBox

So, it’s just a matter of calling FindComponent, check the class type to make sure it is the correct control and be done with it, right?

Not so, the Dialog also contains some frames that own their controls rather than the form. So I had to traverse the control hierarchy in order to find the control. It looks like this:

DelphiProjectOptionsDialog: TDelphiProjectOptionsDialog
  [3] Panel2: TPanel
    [1] PropertySheetControl1: TPropertySheetControl
      [0] : TDebuggerLocalPage
        [2] Panel1: TPanel
          [0] HostAppGroupBox: TGroupBox
            [0] HostAppInput: THistoryPropComboBox
          [2] CDWGroupBox: TGroupBox
            [0] CWDInput: THistoryPropComboBox
          [3] SourcePathGroupBox: TGroupBox
            [0] SourcePathInput: THistoryPropComboBox

      [2] : TDebuggerSymbolTablePage
        [1] gbSymbolTables: TGroupBox
          [1] ddDebugSymbolSearchPath: THistoryPropComboBox
          [4] cbLoadAllSymbols: TCheckBox
          [3] Panel1: TPanel
            [0] ListViewPanel: TPanel
              [0] SymbolTablesListView: THintListView

The numbers in front of the controls are its index in the parent’s Controls array.

The last challenge was the control’s class: THistoryPropComboBox. Whatever it is, it is not a TCombobBox but at least it derives from TCustomComboBox, so I could typecast it to that. But how do I access the Text property to fill it with the name of the file dropped on it? It is a protected field in TCustomComboBox. I took a gamble and assumed that it just publishes this field like TComboBox does and hard type casted it to TComboBox. It worked.

So, after several hours of hacking I can now drop an executable from the Windows Explorer on the Host application input field and its filename will automagically appear there.

As you can seen from the table above, there are some other interesting input fields for drop file support. They will come next, but for today, one is enough.

Entry Point Not Found in dbkdebugide220.bpl

 Delphi, GExperts  Comments Off on Entry Point Not Found in dbkdebugide220.bpl
Oct 112015

Note to self: If you encounter the error

bds.exe Entry Point Not Found

bds.exe – Entry Point Not Found
The procedure entry point
could not be located in the dynamic link library

while trying to debug an IDE Expert for Delphi 10 Seattle:

  1. Check the host application you put into the Run -> Parameters dialog! Chances are you are calling the Delphi XE8 IDE there rather than Delphi 10 Seattle.
    Project Options for GExpertsRS10 release
  2. If that looks fine, check that you looked in the right place. Did you really look in the Debug Win32 configuration?
    Project Options for GExpertsRS10 debug

Experimental GExperts Version 1.38 2015-10-10 released

 Delphi, GExperts  Comments Off on Experimental GExperts Version 1.38 2015-10-10 released
Oct 102015

There is nothing new about the formatter code. But there are two new GExpert functions and I also improved several GExperts dialogs:

The first new functionality is hiding the navigation bar in Delphi 10 Seattle. The code was kindly donated by Achim Kalwa. You can find the option in the GExperts configuration dialog on the Code Editor tab:

GExperts Configuration: Hide Navigation Bar

The second new functionality is for all supported Delphi versions(*). It enables auto complete and dropping directories from the explorer in the edit control used for adding directories to a search path. To enable it, set the corresponding check box in the GExperts configuration dialog on the IDE tab:

GExperts Configuration: enhance search paths

This dialog is used in several places in the IDE, e.g. the search path in project options, the library path and the browsing path in the general options.

(*) Actually the dialog is also used in several other places where it does not manage search path’s but something else, so I had to filter for the dialog caption in addition to the dialog class. I am sure it works with the English Delphi versions but there might be French and German versions with a different dialog caption than the one I check for. I would also have liked to support the Japanese version, but nobody from Japan answered me when I asked for the dialog captions on Google+. So, if it does not work for you, head for the linked G+ post and add the caption of your dialog there. I’ll add those new captions to the next release.

I also added auto complete and file/directory drop support from the explorer to the following GExperts dialogs:

  • Configuration dialog, “General” tab, for VCL source directory, GExperts storage directroy and Help file.
  • Grep Search, the directory to search in when doing a directory search
  • Backup Project for additional files and directories; Also, the corresponding configuration dialog got an enhanced input for the directory where to save the files.
  • Clean Directory for additional directories and file extensions
  • Code Librarian Options for the Code Librarian Storage Location

There are probably other dialogs to enhance. I will get to them given time.

If you have been using my previous experimental version with Delphi 10 Seattle, you will have to uninstall it from the IDE first before installing the new version, because the dll name has changed. Erik decided to simply call it GExpertsRS10.dll.

Head over to the Experimental GExperts page to download it.

Batch wizardry: Finding a subdir in all parent dirs

 Batch, Windows  Comments Off on Batch wizardry: Finding a subdir in all parent dirs
Oct 042015

As an addition to Using my buildtools here is a batch subroutine to find a subdirectory in any of the parent directories of a script:

@rem search all parent directories for a subdir and return
@rem the full path to that directory in %result%
set parentdir=%1%
set subdir=%2%
call :GetDir %parentdir%
set parentdir=%result%
if exist %parentdir%\%subdir% goto found
goto loop
endlocal & set result=%parentdir%\%subdir%
goto :eof

rem extract path
set result=%~dp1%
rem remove any quotes
set result=%result:"=%
rem add quotes
set result="%result%"
rem remove \ before the closing quote
set result=%result:\"="%
rem remove any quotes
set result=%result:"=%
endlocal & set result=%result%
goto :eof

To use it, you first have to copy it to the script that wants to use it. (You could probably also put it into its own file an call that file but for my purpose that would not work.) Then you call it like this:

call :FindInParents %0% buildtools
@rem The result is returned in the %result% environment variable.

As you can see, it needs two parameters. The first one is the directory from where to start searching. Lazy bastard™ that I am I just take the %0% implicit parameter of the batch file that contains its name. While that actually is a file name and not a directory it will work nonetheless because %0%\buildtools does not exist. The second parameter is the name of the subdirectory to find. So the above looks for a subdirectory called “buildtools” in any of the directories contained in the full filename of the current batch file. Don’t forget to add a

goto :eof

to the end of the main batch code so it will not execute the subroutine as well.

The full batch file I use in GExperts to call a central doBuildProject.cmd script located in the buildtools directory looks like this:

@rem Searches the parent dirctories for the buildtools and calls the doBuildProject.cmd there
@echo off
call :FindInParents %0% buildtools
call %result%\doBuildProject.cmd
goto :eof

@rem search all parent directories for a subdir and return
@rem the full path to that directory in %result%
set parentdir=%1%
set subdir=%2%
call :GetDir %parentdir%
set parentdir=%result%
if exist %parentdir%\%subdir% goto found
goto loop
endlocal & set result=%parentdir%\%subdir%
goto :eof

rem extract path
set result=%~dp1%
rem remove any quotes
set result=%result:"=%
rem add quotes
set result="%result%"
rem remove \ before the closing quote
set result=%result:\"="%
rem remove any quotes
set result=%result:"=%
endlocal & set result=%result%
goto :eof

Using my buildtools

 Delphi, dzLib  Comments Off on Using my buildtools
Sep 262015

My buildtools for Delphi have been available on SourceForge for quite a while. I use them in all my projects, including – slightly modified – in GExperts. Just in case somebody else is interested, I’ll outline how to use them in a project.


First, your project has to follow the following structure:


Notice that the main project directory should have the same name as your project, so if the project is called MyProject, the directory should have the same name (Exceptions are possible, see below). Also, the project files should be in a subdirectory called src (this cannot easily be changed).


If these requirements are met, you can just add the build tools as an svn:external to a subversion project like this:


This will create a subdirectory buildtools to the project’s main directory.

If your main project directory name is different from your project name, create a __SetProjectName.cmd script that sets the environment variable PROJECT to your project name:

set PROJECT=MyProject

All scripts will try to call this in order to get the project name. If it does not exist, the project name will be assumed to be the same as the main project directory.

The first step should now be to execute the script __CopyTemplates.cmd located in buildtools\templates. It will do the following:

  • Copy _BuildProject.cmd, _OpenInIde.cmd and _AutoBuildCheck.cmd to the project directory
  • Copy to src\
  • Copy template_icon.rc to src\%project%_icon.rc if it does not exist
  • Copy template_version.ini to src\%project%_version.ini if it does not exist.
  • open src\%project%_version.ini in notepad to be adjusted for the given project

src\%project%_version.ini is an ini file that maintains the version info of the project. The Delphi IDE (since Delphi 2005 and up until recently) notoriously mishandled the version information, so at some point I grew tired of it and moved the handling of version information to an external tool. More on that later. The format of the INI file should be familiar to all who have used Delphi 7 or earlier. The Version info in the .dof file there was in the same format.

The build tools assume that the project uses Delphi 2007 since that is the version with which I (have to) do most of my development work. If your project uses a different version, create a __DelphiVersion.cmd file with the following content:

set DelphiVer=XE2 

Replace the XE2 with your Delphi version:
6, 7, 2005, 2006, 2007, 2009, 2010, XE, XE2 … XE8 (I have yet to add Delphi 10 Seattle)

Now you should be able to open the project in the Delphi IDE by executing the _OpenInIDE.cmd script, do a commandline build by executing the _BuildProject.cmd script.

That’s the general preparation, now for the actual advantages of using these tools:

Version Information, Icon and Manifest
Up to Delphi 7 you could enter the version information into the projects settings dialog, check the “auto inc build number” option and let the IDE do everything else. The information was stored in the project.dof file. There was the disadvantage that the project.res file changed with every build but most people didn’t mind that much. If you deleted the .res file, it would be recreated with the correct version info, all you lost was the icon. Unfortunately a command line build using dcc32 did not increment the build number. Then Borland jumped on the dotNET wagon and created a new IDE. This new IDE botched the handling of the version info vs. the project.res file completely. Now, the master version information was stored in the project.res file and the IDE updated the project.bdsproj file (and later the project.dproj file) from there. The command line compiler still did not increment the build number.

At that point I got fed up and wrote dzPrepBuild. It is a small tool that can read and modify .dof, .bdsproj, .dproj and .ini files. But the most important function is creating a .rc file with the version information that can be compiled to a .res file which in turn can be used by Delphi to add version information to the executable. It also creates a manifest file for Windows Vista and later, containing the version information.

So, in order to use it, do the following:

  • Disable version information in your project
  • Add the following Pre-Build event (Delphi 2007 and up):
    call ..\buildtools\prebuild.cmd $(PROJECTPATH)
  • Add the following Post-Build event (Delphi 2007 and up):
    call ..\buildtools\postbuild.cmd $(OUTPUTDIR)$(OUTPUTNAME)
  • In the project.dpr file remove the {$ *.res} line
  • and add the following lines
      {$R *_version.res}
      {$R *_icon.res}
      {$R *_manifest.res}

If you use a Delphi version older than Delphi 2007, you must find another way to call the prebuild and postbuild scripts, because Pre- and Post-Build events were only introduce with Delphi 2007.

So, what does prebuild.cmd do?

  • It increments the build number in src\%project%_version.ini
  • Writes a src\%project%_version.rc from this information
  • If src\ exists, writes a src\%project%.manifest and a corresponding src\%project%_manifest.rc
  • Calls brcc32 to compile src\%project%_version.rc to a .res file
  • If src\%project%_manifest.rc exists, calls brcc32 to compile it to a .res file
  • If src\%project%_icon.rc exists, calls brcc32 to compile it to a .res file

Oh, I haven’t mentioned the %project%_icon.rc file yet: It’s a text file that only contains one line:


You should adapt it to point to the .ico file you want to use for your project. Alternatively you can delete the .rc file if you don’t want to have an icon. In this case you also must remove the {$R *_icon.res} line from the project.dpr file. Here is a hint on creating icons from multiple png files.

Regarding the manifest: Newer versions of Windows (starting with Vista) have the (I think) annoying habit of virtualizing access to the registry and some file system folders to which a program does not have write access. If you don’t tell Windows to not do that, you will not even notice your programming errors. To tell Windows to go and play somewhere else, you need a manifest. A manifest is an xml file that is added to the executable as a resource. That’s what the project_manifest.rc file does. Windows looks into that xml file in order to find out whether the program is compatible to a particular Windows version. The file in buildtools\templates contains the following text:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  This manifest tells Windows Vista (and Windows 7/8) not to virtualize any file
  or registry access. Also, it disables themes support.
  <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity version=""
    name="template from dzlib build tools"
<!-- We do not want themes support
    <assemblyidentity type="win32"
      language="*" processorarchitecture="*">
  <description>This application was built using buildtools from dzlib</description>
  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
      <!-- We support Windows Vista -->
      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
      <!-- We support Windows 7 -->
      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
      <!-- We support Windows 8 -->
      <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
      <!-- We support Windows 8.1 -->
      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
      <!-- We support Windows 10 -->
      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">

Apart from claiming compatibility to Windows Vista, 7, 8, 8.1 and 10 this manifest also disables theming (you might want to change that) and tells Windows to not run with any elevated privileges. MSDN has some more information on manifests.

Please note that the manifest also contains the version information. The prepbuild tool will read src\ and create src\%project%.manifest, overwriting the latter if it exists. So in order to change the manifest, you should edit src\

JclDebug Information and Translation

The postbuild.cmd file’s job is to do the following:

  • Append JclDebug information to the executable by calling the AppendJclDebug.cmd script, which in turn calls the makejcldbg executable
  • Append translations for dxGetText to the executable by calling AppendTranslations.cmd which in turn calls the dxgettext tools.

I have written a separate blog post on Using JclDebug in your program. See there for an introduction on how it works. For the above to work, you should enable a full map file in the project’s Linker options.

AppendTranslation.cmd assumes that you use GNU Gettext for Delphi and C++ Builder (dxgettext) for translating your projects. It expects translations for German, English and French in subdirectories of translations:


The translation files themselves are called default.po and can be created with either the explorer extensions that come with dxgettext or by copying the _ExtractTranslations.cmd script from builtools to the main project directory and executing it there.

The .po files are compiled to binary .mo files which are created in the corresponding directory under locale:


You must create these directories for the AppendTranslation.cmd script to work. (Edit: A new script in buildtools PrepareForTranslation.cmd can do that for you. — 2015-10-4 twm)

That’s it for now. I hope this short overview isn’t too confusing for somebody who hasn’t used the buildtools before. If you like them, feel free to use them. If you have suggestions, please contact me through my Google+ profile.

Delphi7Help4BDS updated for Delphi XE7 to 10 Seattle

 Delphi  Comments Off on Delphi7Help4BDS updated for Delphi XE7 to 10 Seattle
Sep 252015

I have just updated my Delphi7Help4BDS expert to support Delphi XE7, XE8 and 10 Seattle.

It allows to reconfigure F1 + any of the modifier keys Shift, Ctrl, Alt and Alt+Ctrl to call either a help file (you will need the old winhelp viewer that Microsoft dropped with (Vista?)), chm file or internet url. It comes preconfigured with a few example internet urls for searching with Google, Bing, the Embarcadero docwiki or MSDN.

This shows the result of Alt+F1 when the cursor was on the keyword "Integer":


To install it, get the sources from SourceForge, open the package for your Delphi version, compile and install it. You should then find a new entry in the IDE’s Help menu called “Configure Delphi7HelpForBds” which gets you a dialog where you can configure the actions for each of the key combinations.


Delphi Custom Container Pack updated for Delphi 10 Seattle

 none  Comments Off on Delphi Custom Container Pack updated for Delphi 10 Seattle
Sep 252015

I just updated the Custom Container Pack sources to support Delphi 10 Seattle. It was mostly a matter of creating the packages for the “new” version. I also added Delphi 10 Seattle to the file.

It now compiles and installs. I have not tested it extensively.

Custom Containers Pack (CCPack) is an integrated tool and component mini-library to produce and maintain composite controls (or simply “composites”) and other containers (forms, data modules and frames). The process of building composite components looks like ActiveForm and Frame creating, but the result is the native VCL component. You can create new composites just as usual forms.

Here is the original documentation in RTF format.

It was originally developed by Sergey Orlik who posted the source code to code central