Главное, что я вижу неправильно в этом коде, и я действительно изучил вызов SHChangeNotification_Lock
, это то, что вы безоговорочно звоните GetLastError
.
Документация для этой функции API неадекватна, поскольку в ней не указано, как сообщать об ошибках. Тем не менее, я бы сильно ожидал, что об ошибках сообщит функция, возвращающая NULL
. Поскольку в документации ничего не говорится о вызове GetLastError
, вполне возможно, что функция API не устанавливает последнее значение ошибки. Неважно, даже если вы можете быть уверены, что GetLastError
может быть вызван, вы должны делать это только после сбоя, т.е. если вызов SHChangeNotification_Lock
возвращает NULL
. Если вы позвоните GetLastError
после успешного вызова API, вы получите код ошибки для самого последнего неудачного вызова API, который не связан с текущим вызовом.
Суть в том, что я уверен, что WParam
содержит все 4 байта, и что ваша проблема не в этой части процесса.
Результатом всего этого является то, что я твердо верю, что SHChangeNotification_Lock
успешен, но вызов SHGetPathFromIDList
терпит неудачу. Вы не проверяете возвращаемое значение для этого. Бьюсь об заклад, он возвращает FALSE
.
Взгляните на объявления C ++ для двух функций.
SHChangeNotification_Lock
возвращает список идентификаторов в параметре, набранном вот так:
PIDLIST_ABSOLUTE **pppidl
SHGetPathFromIDList
получает список идентификаторов в параметре, набранном вот так:
PCIDLIST_ABSOLUTE pidl
Я не знаю, как выглядит ваше объявление SHChangeNotification_Lock
, но тот, который представлен в моей версии Delphi (XE2), выглядит неправильно. Этот параметр объявлен так:
out pppidl: array of PItemIDList
Честно говоря, я не вижу, как функция Windows API может возвращать открытый массив Delphi в качестве параметра out. Я думаю, что это должно быть объявлено так:
out pppidl: PPItemIDList
и вам может потребоваться объявить PPItemIDList
равным ^PItemIDList
.
Теперь pppidl
- это массив. Он указывает на первый элемент массива PItemIDList
. Таким образом, вы получите путь к первому элементу, вызвав:
SHGetPathFromIDList(pppidl^, @psi1);
Я полагаю, это реальная проблема, с которой вы столкнулись.
Наконец, я не могу понять, почему вы проверяли бы успех с hNotifyLock > 0
. Правильный тест - hNotifyLock <> 0
. Теперь я знаю, что некоторые типы Delphi изменились в последних версиях, но если бы THandle
было значением со знаком в вашей версии Delphi, то ваш код был бы неправильным. Независимо от того, что правильный логический тест - <>0
.