New option in Delphi Help Expert to open in web browser

 Delphi  Comments Off on New option in Delphi Help Expert to open in web browser
Jan 012019
 

Prompted by a suggestion from Peter Aschbacher I just added a new feature to my Delphi Help Expert:

You can now force it to use the default web browser instead of the Welcome Page for web URLS.

This is a global setting.

I also fixed a bug I recently introduced which resulted in the Welcome Page of Delphi 2007 no longer being found.

Discussion about this post in the international Delphi Praxis forum.

 Posted by on 2019-01-01 at 14:55

You can now follow me on Diaspora

 blog, Delphi  Comments Off on You can now follow me on Diaspora
Dec 312018
 

I created an account on Pluspora (I’m dz@pluspora.com *1).

If the WordPress plugin I just installed works as expected, all blog posts will be available there. And if I understand correctly how Diaspora works, it should be possible to follow me on other Diaspora Pods too.

(*1 dummzeuch@pluspora.com was blocked for whatever reason, It’s quite possible that I registered it before and deleted that account later. I don’t remember doing that though.)

 Posted by on 2018-12-31 at 19:25

Delphi Known IDE Packages Manager updated to Delphi 10.3 Rio

 Delphi  Comments Off on Delphi Known IDE Packages Manager updated to Delphi 10.3 Rio
Dec 292018
 

A while ago, after my post on Known IDE Packages in Delphi I wrote a the KnownIdePackagesManager tool which lists those packages, allows to disable and enable some of them and also set the package description for those packages that don’t have a meaningful description.

Today, I updated the tool to support Delphi 10.3 Rio.

Discussion about this post in the international Delphi Praxis forum.

 Posted by on 2018-12-29 at 19:38

Delphi Custom Container Pack updated for Delphi 10.3 Rio

 Delphi  Comments Off on Delphi Custom Container Pack updated for Delphi 10.3 Rio
Dec 292018
 

I have just updated the Delphi Custom Container Pack sources to support Delphi 10.3 Rio. This time it required than creating the packages for the new version and adding the latest version of the Delphiversions.inc file. When loading the designtime package an EAssertionFailed exception was raised. It turned out that the category sCategoryDelphiNewFiles no longer exists. I have added two fall back categories: sCategoryDelphiIndividualFiles and sCategoryDelphiNew. One of them will hopefully continue to work.

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

Discussion about this post in the international Delphi Praxis forum.

 Posted by on 2018-12-29 at 17:49

TDbf packages for Delphi 10.3 Rio

 Delphi  Comments Off on TDbf packages for Delphi 10.3 Rio
Dec 262018
 

TDbf is an open source library to access Dbase tables. It’s released under the LGPL license (which makes in impractical for most commercial Delphi development). It is also used in Lazaraus (I haven’t checked the license there, but apparently you can develop commercial programs with it.)

The project seems to be rather dead though. Apparently nobody noticed that it failed to compile with many Delphi versions, starting with Delphi 2009 and also including Delphi 10.2.

Today I wanted to simply add packages to support Delphi 10.3 and ran into these compile errors. I fixed them and also committed the packages. Be warned though, that I have not tested the functionality. It compiles but may still be broken.

Discussion about this post in the international Delphi Praxis forum.

 Posted by on 2018-12-26 at 14:06

GExperts 1.3.12 experimental twm 2018-12-22 released

 Delphi  Comments Off on GExperts 1.3.12 experimental twm 2018-12-22 released
Dec 222018
 

It’s time for a gift to all Delphi developers, a new Release of GExperts. Happy Holidays! (But do spend some time with your family rather than testing GExperts. 😉 )

I blogged about the new features already. There were also several bug fixes.

Please be aware that I mostly work with Delphi 2007, so this version can be regarded as tested quite well, followed by Delphi XE2. The others are only known to compile and new features are usually tested superficially with all versions. This is particularly true for Delphi 6/7 and 2005/2006.

Head over to the Experimental GExperts page to download the latest release.

Discussion about this post in the international Delphi Praxis forum.

 Posted by on 2018-12-22 at 18:04

Register and use a custom clipboard format in Delphi

 Delphi  Comments Off on Register and use a custom clipboard format in Delphi
Dec 182018
 

I just now had the need to transmit GPS (WGS 84) coordinates from one program to another. First, I simply copied longitude and latitude separately using the clipboard, which works fine but is really time consuming when you have to do that very often.

I could have just copied both values as text to clipboard using e.g. <tab> as the separator, but that would have required some code on both sides anyway, so I thought, why not use a custom clipboard format? I had never done that before and I wanted to learn how to do it.

Windows allows all programs to register custom clipboard formats by calling the RegisterClipboardFormat Windows API function. It simply takes a PChar (PAnsiChar / PWideChar, depending on which variant you call) and returns a handle for the new format. This handle can then be used to read and write entries of that format to and from the clipboard.

  MyClipFormat := RegisterClipboardFormat(PChar('MyClipFormat'));

The name of the clipboard format must be unique for that format, so e.g. you could prefix it with your company’s domain name to be sure. Multiple programs can register the same format if they know how to read and write it and can then exchange data this way.

Once such a format has been registered, it can be used with the standard Clipboard.HasFormat method.

  if Clipboard.HasFormat(MyClipFormat) then begin
    // Yes! There is something for us on the clipboard.
  end;

Actually writing and reading a custom format involves calls to the Windows API function GlobalAlloc, GlobalLock and GlobalUnlock as well as using the Clipboard.SetAsHandle and Clipboard.GetAsHandle methods.

But first, we need to define that format. In my case I decided to transfer the GPS coordinates as an AnsiString in the following format:

'WGS84'#9 + LongitudeString + #9 + LatitudeString
So, I use a fixed prefix followed by a tab character and then the longitude and latitude as strings, again separated by a tab character. I could simply have transferred the binary representation of e.g. two doubles but I wanted to use a format that was easy to debug. Since this is the clipboard of a single computer, I don’t care about the decimal separator. It should be the same on both sides, the writer and the reader.

Writing is the more complicated part, so let’s implement that first.

procedure WriteMyClipFormat(_Longitude, _Latitude: double);
var
  s: AnsiString;
  MemHandle: HGLOBAL;
  MemPtr: Pointer;
begin
  s := AnsiString(Format('WGS84'#9'%.5f'#9'%.5f', [_Longitude, _Latitude]));
  // Get a moveable memmory handle.
  // (according to the Windows API documentation of
  // SetClipboardData it must be moveable.)
  MemHandle := GlobalAlloc(GMEM_MOVEABLE, Length(s) + 1);
  // To be able to write to such a handle, we must convert it to a pointer.
  MemPtr := GlobalLock(MemHandle);
  try
    StrCopy(MemPtr, PAnsiChar(s));
  finally
    GlobalUnlock(MemHandle);
  end;
  // Now we call SetAsHandle to write it to the clipboard.
  Clipboard.SetAsHandle(MyClipFormat, MemHandle);
  // Since the memory is now stored in the clipboard,
  // we can not free it. So don't call GlobalFree here!
end;

That takes care of the writing part. Now for reading.

function TryReadMyClipFormat(out _Longitude, _Latitude: double): boolean;
var
  MemHandle: THandle;
  MemPtr: Pointer;
  WgsCoords: string;
  s: string;
begin
  Result := Clipboard.HasFormat(MyClipFormat);
  if not Result then begin
    // There is nothing in that format on the clipboard.
    Exit; //==&amp;gt;
  end;

  Clipboard.Open;
  try
    // Get the content.
    MemHandle := Clipboard.GetAsHandle(MyClipFormat);
    // Convert the memory handle to a pointer so we can access it.
    MemPtr := GlobalLock(MemHandle);
    // It's a PAnsiChar, so we can simply assign it to a string,
    // converting it from AnsiString to String on the way
    WgsCoords := string(PAnsiChar(MemPtr));
    GlobalUnlock(MemHandle);
  finally
    Clipboard.Close;
  end;
  // WgsCoords now contains the coordinates encoded in the
  // way described above.
  // We now use ExtractStr (from my u_dzStringUtils unit)
  // to get the three parts and convert the numbers to float.
  s := ExtractStr(WgsCoords, #9);
  Result := (s = 'WGS84');
  if not Result then begin
    // Something went wrong. It is supposed to have this prefix.
    Exit; //==&amp;gt;
  end;

  s := ExtractStr(WgsCoords, #9);
  Result := TryStrToFloat(s, _Longitude);
  if not Result then begin
    // The longitude could not be converted to a float.
    Exit; //==&amp;gt;
  end;

  s := ExtractStr(WgsCoords, #9);
  Result := TryStrToFloat(s, _Latitude);
end;

That takes care of the reading part.

As mentioned above, we could have simply transfered the a memory block containing the binary representation of two doubles instead. I just like my code complex and unreadable. 😉

Also, it would easily be possible to wrap all this into a class which registers the custom clipboard format in its constructor and has a Write and TryRead Method. We could even have multiple classes for different clipboard data types.

Discussion about this in the international Delphi Praxis forum.

 Posted by on 2018-12-18 at 18:13