Quantcast
Channel: Planet Object Pascal
Viewing all articles
Browse latest Browse all 1725

The Wiert Corner - irregular stream of stuff: jpluimers

$
0
0

As I wrote before, I’m with the Delphi with haters camp, and this is why:

Using the with statement in Delphi makes your code less future proof.

The below code example is just one of many. I show it because I recently bumped into doing some long overdue code porting to Delphi XE3.

Since I’ve been bitten by using with a couple of times before, it didn’t take me long to find the cause.

Example code where FIConData is of type NOTIFYICONDATAW that used to compile fine:

    with FIconData do
    begin
      cbSize := SizeOf(FIconData);
      Wnd := Self.Handle;
      uID := $DEDB;
      uFlags := NIF_MESSAGE or NIF_ICON or NIF_TIP;
      hIcon := Application.Icon.Handle;
      uCallbackMessage := WM_CAS400NTIcon;
      StrCopy(szTip, PChar(Caption));
    end;

Well, as of Compiler Version 20, it doesn’t compile any more.

The reason is that the _NOTIFYICONDATAW got changed, because the underlying Windows API NOTIFYICONDATA structure changed to accommodate new Windows Vista features.

But because of backward compatibiliy, you cannot pass the full new structure when you are running on Windows versions prior to Windows Vista.

Hence this piece of code to calculate the right structure size in the ShellApi unit as of Delphi 2009:

class function _NOTIFYICONDATAW.SizeOf: Integer; static;
begin
  if Win32MajorVersion >= 6 then
    // Size of complete structure
    Result := System.SizeOf(_NOTIFYICONDATAW)
  else
    // Platforms prior to Vista do not recognize the fields guidItem and hBalloonIcon
    Result := System.SizeOf(_NOTIFYICONDATAW) - System.SizeOf(TGUID) - System.SizeOf(Winapi.Windows.HICON);
end;

SizeOf is a perfectly good name for this, but it clashes when you use the with statement.

Three other SizeOf functions got added. This is the complete list of four:

  • Unit Windows:
    • class function tagNONCLIENTMETRICSA.SizeOf: Integer;
    • class function tagNONCLIENTMETRICSW.SizeOf: Integer;
  • Unit CommCtrl:
    • class function MCHITTESTINFO.SizeOf: Integer;
  • Unit ShellApi:
    • class function _NOTIFYICONDATAW.SizeOf: Integer; static;

You are tempted to rewrite the with like this:

    with FIconData do
    begin
{$if CompilerVersion >= 20}
      cbSize := SizeOf();
{$else}
      cbSize := SizeOf(FIconData);
{$ifend CompilerVersion >= 20}
      Wnd := Self.Handle;
      uID := $DEDB;
      uFlags := NIF_MESSAGE or NIF_ICON or NIF_TIP;
      hIcon := Application.Icon.Handle;
      uCallbackMessage := WM_CAS400NTIcon;
      StrCopy(szTip, PChar(Caption));
    end;

But you should in fact rewrite it like this, so you are sure from which entity each value comes:

{$if CompilerVersion >= 20}
    FIconData.cbSize := FIconData.SizeOf();
{$else}
    FIconData.cbSize := SizeOf(FIconData);
{$ifend CompilerVersion >= 20}
    FIconData.Wnd := Self.Handle;
    FIconData.uID := $DEDB;
    FIconData.uFlags := NIF_MESSAGE or NIF_ICON or NIF_TIP;
    FIconData.hIcon := Application.Icon.Handle;
    FIconData.uCallbackMessage := WM_CAS400NTIcon;
    StrCopy(FIconData.szTip, PChar(Caption));

–jeroen


Filed under: Delphi, Delphi 1, Delphi 2005, Delphi 2006, Delphi 2007, Delphi 2009, Delphi 2010, Delphi 3, Delphi 4, Delphi 5, Delphi 6, Delphi 7, Delphi XE, Delphi XE2, Delphi XE3, Development, Software Development

Viewing all articles
Browse latest Browse all 1725

Trending Articles