Wpf: получение содержащего HwndSource пользовательского элемента управления

#.net #wpf #hwnd

#.net #wpf #hwnd

Вопрос:

Я пишу пользовательский элемент управления Wpf, и мне нужно как можно скорее получить ссылку на HwndSource содержащего окна. Это должно быть 1) в конструкторе моего элемента управления, если возможно, или 2) в момент добавления элемента управления в иерархию отображения.

Как я могу определить, когда / доступен ли HwndSource? Я планирую получить ссылку, используя такой код, как следующий:

 var source = HwndSource.FromVisual(this) as HwndSource;
  

Ответ №1:

Вы можете использовать метод AddSourceChangedHandler от PresentationSource для прослушивания изменений PS (HwndSource является производным PS).

http://msdn.microsoft.com/en-us/library/system.windows.presentationsource.addsourcechangedhandler.aspx

Ответ №2:

Насколько я понимаю, элементы управления WPF не являются Windows. Только окно в приложении wpf имеет hwnd.

С сайта msdn:

«Все элементы WPF на экране в конечном итоге поддерживаются HWND. Когда вы создаете окно WPF, WPF создает HWND верхнего уровня и использует HwndSource для размещения окна и его содержимого WPF внутри HWND. Остальной контент вашего WPF в приложении использует этот единственный HWND. Исключение составляют меню, выпадающие списки со списком и другие всплывающие окна. Эти элементы создают свое собственное окно верхнего уровня, поэтому меню WPF потенциально может выходить за край окна HWND, которое его содержит. Когда вы используете HwndHost для размещения HWND внутри WPF, WPF сообщает Win32, как расположить новый дочерний HWND относительно HWND окна WPF.»

Для обеспечения совместимости с Win32 смотрите следующую ссылку:

http://msdn.microsoft.com/en-us/library/ms742522.aspx

Редактировать: для улучшения ответа на комментарий ниже:

Чтобы получить дескриптор окна, которому принадлежит hwnd, вы можете использовать класс WindowInteropHelper.

Этот пример также взят из документации MSDN

в c#

 WindowInteropHelper wih = new WindowInteropHelper(myDialog);
wih.Owner = ownerHwnd;
myDialog.ShowDialog();
  

в vb

 Dim wih As New WindowInteropHelper(myDialog)
wih.Owner = ownerHwnd
myDialog.ShowDialog()
  

Я надеюсь, что это поможет.

Комментарии:

1. Это верно, но в какой-то момент мой элемент управления будет размещен внутри элемента на экране, который поддерживается HWND, это то, что я пытаюсь обнаружить.

2. Привет. Я надеюсь, что дополнительная информация в тексте выше отвечает на ваш вопрос. Удачи!

Ответ №3:

Я всегда использовал Window.Исходное инициализированное событие для определения того, когда HWND (т.е. HwndSource) готов к использованию. В вашем случае вам, вероятно, потребуется добавить переопределение для метода OnVisualParentChanged. В вашем переопределении выполните поиск в визуальном дереве соответствующего окна (или используйте Window.GetWindow).

Если окно имеет действительный HWND, то вы можете просто использовать его как есть. Если нет, то вам придется подписаться на событие SourceInitialized. Вы могли бы отцепиться от инициализированного в вашем обработчике источника, чтобы убедиться, что он вызывается только один раз.

Это не сработало бы, если ваш элемент управления размещен внутри всплывающего окна. В этом случае вам нужно было бы получить ссылку на соответствующее всплывающее окно и следить за событием Opened.