При разработке приложений для Windows на Delphi и Free Pascal часто возникает необходимость использовать API-функции, типы данных и константы, которые доступны только в определенных версиях операционной системы. В этой статье мы рассмотрим, как правильно работать с такими элементами и какие подходы можно использовать для информирования разработчиков о требованиях к версии Windows.
Проблема совместимости версий Windows
Многие функции Windows API, такие как VirtualAlloc2, доступны только начиная с определенных версий ОС. Например, VirtualAlloc2 работает только в Windows 10 версии 1607 и выше. Если разработчик использует такую функцию в коде, приложение не будет работать на более старых версиях Windows.
// Пример функции, доступной только в Windows 10+
function VirtualAlloc2(
Process: THandle;
BaseAddress: Pointer;
Size: SIZE_T;
AllocationType: DWORD;
PageProtection: DWORD;
ExtendedParameters: PMEM_EXTENDED_PARAMETER;
ParameterCount: ULONG
): Pointer; stdcall; external kernel32 name 'VirtualAlloc2';
Текущие решения в FPC/Delphi
1. Использование директивы deprecated
В Free Pascal можно использовать директиву deprecated с сообщением:
function VirtualAlloc2(...): Pointer; stdcall;
external kernel32 name 'VirtualAlloc2' deprecated 'Требуется Windows 10 версии 1607 или выше';
Недостаток этого подхода в том, что deprecated подразумевает устаревание функции, что не всегда соответствует действительности.
2. Условная компиляция
Можно использовать условные директивы для проверки версии Windows:
{$IFDEF WINDOWS}
{$IFDEF WIN10_SPECIFIC}
function VirtualAlloc2(...): Pointer; stdcall; external kernel32 name 'VirtualAlloc2';
{$ELSE}
// Альтернативная реализация или сообщение об ошибке
{$ENDIF}
{$ENDIF}
3. Проверка версии во время выполнения
Более надежный способ - проверять версию Windows при запуске программы:
function IsWindows10OrGreater: Boolean;
var
osvi: TOSVersionInfoEx;
dwlConditionMask: DWORDLONG;
begin
ZeroMemory(@osvi, SizeOf(osvi));
osvi.dwOSVersionInfoSize := SizeOf(osvi);
osvi.dwMajorVersion := 10;
osvi.dwMinorVersion := 0;
osvi.wServicePackMajor := 0;
osvi.wServicePackMinor := 0;
dwlConditionMask := VerSetConditionMask(
VerSetConditionMask(
VerSetConditionMask(
VerSetConditionMask(
0, VER_MAJORVERSION, VER_GREATER_EQUAL),
VER_MINORVERSION, VER_GREATER_EQUAL),
VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL),
VER_SERVICEPACKMINOR, VER_GREATER_EQUAL);
Result := VerifyVersionInfoW(
osvi,
VER_MAJORVERSION or VER_MINORVERSION or
VER_SERVICEPACKMAJOR or VER_SERVICEPACKMINOR,
dwlConditionMask) <> False;
end;
Предлагаемое решение: директива advice
Как альтернативу можно предложить введение новой директивы advice, которая будет работать аналогично deprecated, но без подтекста устаревания:
function VirtualAlloc2(...): Pointer; stdcall;
external kernel32 name 'VirtualAlloc2' advice 'Требуется Windows 10 версии 1607 или выше';
Такой подход: 1. Не вводит в заблуждение (в отличие от deprecated) 2. Позволяет включать/выключать предупреждения отдельно 3. Дает четкую информацию разработчику
Практические рекомендации
Документируйте требования - всегда указывайте в комментариях, какая версия Windows требуется:
// Требуется Windows 10 версии 1607 (Anniversary Update) или выше
function VirtualAlloc2(...): Pointer; stdcall; external kernel32;
Используйте динамическую загрузку для функций, которые могут отсутствовать:
var
_VirtualAlloc2: function(...): Pointer; stdcall;
procedure LoadVirtualAlloc2;
var
hModule: HMODULE;
begin
hModule := GetModuleHandle(kernel32);
if hModule = 0 then Exit;
_VirtualAlloc2 := GetProcAddress(hModule, 'VirtualAlloc2');
end;
Предоставляйте альтернативы для старых версий Windows:
function MyVirtualAlloc(...): Pointer;
begin
if Assigned(_VirtualAlloc2) then
Result := _VirtualAlloc2(...)
else
Result := VirtualAlloc(...); // Стандартная реализация
end;
Заключение
Работа с API, специфичным для определенных версий Windows, требует внимательного подхода. Использование директив компилятора, проверок во время выполнения и динамической загрузки функций позволяет создавать приложения, которые корректно работают в разных версиях Windows. Предлагаемая директива advice могла бы стать удобным инструментом для информирования разработчиков о требованиях к версии ОС без нежелательных побочных эффектов.
При разработке кросс-версионных приложений всегда учитывайте целевую аудиторию и минимальные системные требования, чтобы найти баланс между использованием современных API и совместимостью.
Описание работы с функциями, типами и константами, доступными только в современных версиях Windows, в Delphi и Pascal, включая методы проверки совместимости и альтернативные решения.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.