Windows 7 マシンで Delphi XE4 を実行しています。CSIDL と KNOWFOLDERID のどちらを使用するかを認識できる 1 つのコード ベースが必要です。
{$IFDEF XXXXXX) を使用して、uses セクションでさまざまなファイルを条件付きでコンパイルし、Windows XP 以前に基づいてさまざまな関数を呼び出す方法はありますか?
Windows 7 マシンで Delphi XE4 を実行しています。CSIDL と KNOWFOLDERID のどちらを使用するかを認識できる 1 つのコード ベースが必要です。
{$IFDEF XXXXXX) を使用して、uses セクションでさまざまなファイルを条件付きでコンパイルし、Windows XP 以前に基づいてさまざまな関数を呼び出す方法はありますか?
これに条件付きコンパイルを使用したくない可能性が非常に高いです。これを行うと、オペレーティング システムのバージョンごとに異なる実行可能ファイルを出荷する必要があります。これにより、インストールが非常に複雑になります。
このシナリオに対処するための通常のアプローチは、条件付きコンパイルではなくランタイム ブランチを使用することです。したがって、次のようなコードを記述します。
if IsWindowsVistaOrGreater then
DoKnownFolderIDVersion
else
DoCSIDLVersion;
重要なことの 1 つは、これらの if ステートメントをできるだけ低いレベルに保つ必要があるということです。これらの詳細を高レベル コードから隠す必要があります。高レベル コードの観点からは、特定のフォルダーの場所を要求する必要があります。高レベル コードには、バージョンに基づく分岐が含まれていてはなりません。
複雑なのは、サポートされている古いプラットフォームには存在しない可能性がある API 関数を使用するブランチには、ロード時のリンクを使用できないことです。そのため、読み込み時のリンクではなく、実行時のリンクを使用してください。これを実現するにはさまざまな方法がありますが、システム API の場合、Delphi の最新バージョンでは、遅延読み込みが優れたオプションです。
個人的には、MS がすぐに機能を削除するとは思わないので、今でも CSIDL ベースの API を使用することを嫌いではありません。しかし、CSIDL を使用するかどうかの決定は、明らかにあなた次第です。これらの API をもう使用したくないという気持ちは確かに理解できます。Microsoft があなたにそうしてほしくないことは明らかです。
Windows バージョンのサポートを確認する場合は、新しいバージョンのヘルパー API を使用する必要があります。Delphi に同梱されている Windows ユニットにそれらが含まれていることを今知っています。おそらくそれらは最新のものですが、それらを持たないバージョンを持っている可能性があります. その場合、これらを使用できます:
function IsWindowsVersionOrGreater(wMajorVersion, wMinorVersion, wServicePackMajor: Word): Boolean;
function IsWindowsXPOrGreater: Boolean;
function IsWindowsXPSP1OrGreater: Boolean;
function IsWindowsXPSP2OrGreater: Boolean;
function IsWindowsXPSP3OrGreater: Boolean;
function IsWindowsVistaOrGreater: Boolean;
function IsWindowsVistaSP1OrGreater: Boolean;
function IsWindowsVistaSP2OrGreater: Boolean;
function IsWindows7OrGreater: Boolean;
function IsWindows7SP1OrGreater: Boolean;
function IsWindows8OrGreater: Boolean;
function IsWindows8Point1OrGreater: Boolean;
....
const
VER_EQUAL = 1;
VER_GREATER = 2;
VER_GREATER_EQUAL = 3;
VER_LESS = 4;
VER_LESS_EQUAL = 5;
VER_AND = 6;
VER_OR = 7;
_WIN32_WINNT_WINXP = $0501;
_WIN32_WINNT_VISTA = $0600;
_WIN32_WINNT_WIN7 = $0601;
_WIN32_WINNT_WIN8 = $0602;
_WIN32_WINNT_WINBLUE = $0603;
function VerSetConditionMask(dwlConditionMask: ULONGLONG; dwTypeBitMask: DWORD; dwConditionMask: Byte): ULONGLONG; stdcall; external kernel32;
function VerifyVersionInfo(var lpVersionInfo: TOSVersionInfoEx; dwTypeMask: DWORD; dwlConditionMask: DWORDLONG): BOOL; stdcall; external kernel32 name 'VerifyVersionInfoW';
function IsWindowsVersionOrGreater(wMajorVersion, wMinorVersion, wServicePackMajor: Word): Boolean;
var
osvi: TOSVersionInfoEx;
dwlConditionMask: DWORDLONG;
begin
osvi := Default(TOSVersionInfoEx);
osvi.dwOSVersionInfoSize := SizeOf(osvi);
osvi.dwMajorVersion := wMajorVersion;
osvi.dwMinorVersion := wMinorVersion;
osvi.wServicePackMajor := wServicePackMajor;
dwlConditionMask := VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
dwlConditionMask := VerSetConditionMask(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
dwlConditionMask := VerSetConditionMask(dwlConditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
Result := VerifyVersionInfo(osvi, VER_MAJORVERSION or VER_MINORVERSION or VER_SERVICEPACKMAJOR, dwlConditionMask);
end;
function IsWindowsXPOrGreater: Boolean;
begin
Result := IsWindowsVersionOrGreater(HiByte(_WIN32_WINNT_WINXP), LoByte(_WIN32_WINNT_WINXP), 0);
end;
function IsWindowsXPSP1OrGreater: Boolean;
begin
Result := IsWindowsVersionOrGreater(HiByte(_WIN32_WINNT_WINXP), LoByte(_WIN32_WINNT_WINXP), 1);
end;
function IsWindowsXPSP2OrGreater: Boolean;
begin
Result := IsWindowsVersionOrGreater(HiByte(_WIN32_WINNT_WINXP), LoByte(_WIN32_WINNT_WINXP), 2);
end;
function IsWindowsXPSP3OrGreater: Boolean;
begin
Result := IsWindowsVersionOrGreater(HiByte(_WIN32_WINNT_WINXP), LoByte(_WIN32_WINNT_WINXP), 3);
end;
function IsWindowsVistaOrGreater: Boolean;
begin
Result := IsWindowsVersionOrGreater(HiByte(_WIN32_WINNT_VISTA), LoByte(_WIN32_WINNT_VISTA), 0);
end;
function IsWindowsVistaSP1OrGreater: Boolean;
begin
Result := IsWindowsVersionOrGreater(HiByte(_WIN32_WINNT_VISTA), LoByte(_WIN32_WINNT_VISTA), 1);
end;
function IsWindowsVistaSP2OrGreater: Boolean;
begin
Result := IsWindowsVersionOrGreater(HiByte(_WIN32_WINNT_VISTA), LoByte(_WIN32_WINNT_VISTA), 2);
end;
function IsWindows7OrGreater: Boolean;
begin
Result := IsWindowsVersionOrGreater(HiByte(_WIN32_WINNT_WIN7), LoByte(_WIN32_WINNT_WIN7), 0);
end;
function IsWindows7SP1OrGreater: Boolean;
begin
Result := IsWindowsVersionOrGreater(HiByte(_WIN32_WINNT_WIN7), LoByte(_WIN32_WINNT_WIN7), 1);
end;
function IsWindows8OrGreater: Boolean;
begin
Result := IsWindowsVersionOrGreater(HiByte(_WIN32_WINNT_WIN8), LoByte(_WIN32_WINNT_WIN8), 0);
end;
function IsWindows8Point1OrGreater: Boolean;
begin
Result := IsWindowsVersionOrGreater(HiByte(_WIN32_WINNT_WINBLUE), LoByte(_WIN32_WINNT_WINBLUE), 0);
end;
function IsWindowsServer: Boolean;
var
osvi: TOSVersionInfoEx;
dwlConditionMask: DWORDLONG;
begin
osvi := Default(TOSVersionInfoEx);
osvi.dwOSVersionInfoSize := SizeOf(osvi);
osvi.wProductType := VER_NT_WORKSTATION;
dwlConditionMask := VerSetConditionMask(0, VER_PRODUCT_TYPE, VER_EQUAL);
Result := not VerifyVersionInfo(osvi, VER_PRODUCT_TYPE, dwlConditionMask);
end;
{$IFDEF VISTA_UP}
// use modern APIs
{$ELSE}
// fallback
{$ENDIF}
ターゲットが Vista+ の場合、次のように条件付きシンボルをどこかVISTA_UP
に定義します。
-Dxxx
コマンドライン コンパイラ スイッチの使用$DEFINE VISTA_UP
別の$INCLUDE
-d ファイルでライブラリ ユニットの DCU を保持することはできません。ターゲットを切り替えるたびに再構築する必要があります。