Меня интересует отображение диалога открытия файла в старом стиле (то есть такого, который не действует как проводник Windows) в приложении C#. Я нашел этот пример для вызова устаревшей функции GetOpenFileName через [DllImport]
и extern
. Однако, чтобы на самом деле получить поведение, отличное от Explorer, на странице GOFN указано, что мне также нужно установить перехватчик:
Windows продолжает поддерживать диалоговое окно «Открыть» старого стиля для приложений, которым требуется поддерживать пользовательский интерфейс в соответствии со старым пользовательским интерфейсом. Чтобы отобразить диалоговое окно «Открыть» в старом стиле, включите процедуру-перехватчик OFNHookProcOldStyle и убедитесь, что флаг OFN_EXPLORER не установлен.
Я изменил пример и создал приведенную ниже функцию как обратный вызов OFNHookProcOldStyle, который, если я правильно читаю документацию по таким обратным вызовам, не должен менять никакого поведения, просто всегда возвращая 0 (обрабатывать сообщение). Наличие такого набора перехватчиков должно отключить поведение Explorer при отсутствии флага OFN_EXPLORER для его повторного включения.
public static UIntPtr SimpleOfnHookProcOldStyle(
[In] IntPtr hdlg, [In] uint uimsg, [In] UIntPtr wParam, [In] IntPtr lParam)
{
return UIntPtr.Zero;
}
Я установил флаг OFN_ENABLEHOOK следующим образом:
int OFN_ENABLEHOOK = (int)new Int32Converter().ConvertFromString("0x00000020");
ofn.flags = OFN_ENABLEHOOK;
Однако мне также нужно установить фактический обратный вызов перехвата, то есть IntPtr
. Как я могу получить IntPtr
для моего SimpleOfnHookProcOldStyle
метода, чтобы я мог установить его как крючок?
Почему бы просто не поставить const int OFN_ENABLEHOOK = 0x00000020
?
@Дай, я не знал int
поддерживает прямое присвоение шестнадцатеричных значений, спасибо!
Вам нужно
public delegate UIntPtr Delegate_type(IntPtr hdlg, uint uimsg, UIntPtr wParam, IntPtr lParam);
public static Delegate_type native_callback = SimpleOfnHookProcOldStyle;
GCHandle handle = GCHandle.Alloc(native_callback);
IntPtr funcPtr = Marshal.GetFunctionPointerForDelegate(native_callback);
handle.Free()
после закрытия диалога, чтобы не утечь память.Приятно знать, что мне не нужны закрепленные. Я не использовал его в своей версии C++/CLI, и этот ответ заставил меня задуматься, не является ли это несчастным случаем, ожидающим своего часа.
информация о том, почему не нужно закреплять делегата stackoverflow.com/a/19866119/15649230
Вы посмотрели новые улучшения взаимодействия в .NET5+, в нем есть примеры, которые могут быть полезны, т. е. базовый сценарий использования управляемого обратного вызова в собственную функцию без UnmanagedCallersOnlyAttribute будет выглядеть так...