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