Я работаю с некоторым кодом, который использует Microsoft.WindowsAPICodePack, чтобы предоставить оболочку C# для общих диалоговых окон в стиле Vista (IFileOpenDialog, IFileSaveDialog). Я хочу добавить проверку выбранного элемента в обратном вызове события OnFileOk, и это в основном работает, но одним из его аспектов является извлечение HWND диалогового окна для использования в качестве родительского элемента для отображаемого окна сообщения. Microsoft предоставляет документацию о том, как это сделать:
The calling process can use the window handle of the dialog itself as the parent of the UI. That handle can be obtained by first calling IOleWindow::QueryInterface and then calling IOleWindow::GetWindow with the handle as shown in this example.
(https://msdn.microsoft.com/en-us/library/windows/desktop/bb776913(v=vs.85).aspx)
Я добавил в код определение интерфейса IOleWindow:
[ComImport,
Guid(ShellIIDGuid.IOleWindow),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IOleWindow
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void ContextSensitiveHelp(
[In] bool fEnterMode);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
IntPtr GetWindow();
}
...
internal const string IOleWindow = "00000114-0000-0000-C000-000000000046";
Когда я передаю IFileDialog, переданный в OnFileOk, в IOleWindow (в последнее время я не так много работал с COM-взаимодействием, но это завершает вызов QueryInterface в базовом мире COM, верно?), Ошибки не возникает, и ссылка IOleWindow не null. Но когда я звоню GetWindow, кажется, что всегда возвращается IntPtr.Zero. Я попытался объявить метод с параметром out вместо возвращаемого значения и получил тот же результат: без ошибок, но всегда IntPtr.Zero.
Кто-нибудь видит, что я делаю не так ?? Я ничего плохого не делаю, но просто иногда не получается получить ручку окна ??
Большое спасибо! Пробую прямо сейчас.
Как я уверен, вы уже знали, что именно в этом и заключалась проблема. Если вы чувствуете, что хотите отправить ответ, даже если «Порядок методов в COM-интерфейсе важен, а порядок в вашем объявлении IOleWindow неправильный», я буду счастлив отметить это как ответ. :-)





Ответ @Hans Passant был уже в носу. Порядок методов в COM-интерфейсе важен, и у меня был неправильный порядок, вот и все. Я получил заказ из документации, которая была отсортирована по алфавиту, а не из фактического IDL. :-П
Неправильный порядок, только для человеческого глаза:
Правильный порядок, фактический IDL:
(Я не знаю, кто такой @tpn на GitHub, эта ссылка может сломаться, но если это так, просто найдите IOleWindow в файле OleIdl.idl из Windows SDK. :-))
Подходящим объявлением IOleWindow является доступно здесь. Получение методов в неправильном порядке довольно фатально.