2013-04-08 1 views
6

У меня есть окно WPF, которое должно вести себя как оверлей окна в стороннем запущенном приложении. Окно WPF должно быть в основном прозрачным с некоторыми видимыми элементами управления, всегда располагаться прямо над другим окном в z-порядке, перемещаться вместе с ним и т. Д. Короче: я хочу, чтобы он вел себя как дочернее окно.Окно WPF Child, размещенное в стороннем приложении, невидимое для Windows 7 Темы Aero

Я рассмотрел предложенные методы here (техника WPF HwndSource) и here (техника WPF SetParent). Техника HwndSource не работает вообще. Техника SetParent работает на Windows 7, но только с основной темой. С темами Windows 7 Aero это не работает: мое дочернее окно невидимо.

Я ищу решение, которое будет работать на всех темы для Windows 7.

Мое тестовое приложение создает тестовое окно и вызывает SetParent, чтобы сделать его дочерним окном (жестко запрограммированным HWND) для окна Notepad.

Под основной темой, это выглядит так:

Basic Theme

В рамках темы Windows 7, я не вижу:

Aero Theme

ребенка окно XAML:

<Window x:Class="WpfApplication22.TestWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="TestWindow" Height="300" Width="300" Background="#63000000" ShowInTaskbar="False" WindowStyle="None" Initialized="Window_Initialized" Loaded="Window_Loaded" AllowsTransparency="True"> 
    <Grid> 
     <Ellipse Height="87" HorizontalAlignment="Left" Margin="12,12,0,0" Name="ellipse1" Stroke="Black" VerticalAlignment="Top" Width="167" Fill="#FFBE3A3A" /> 
    </Grid> 
</Window> 

Дочернее окно код обработчика формы нагрузки:

var parentHwnd = new IntPtr(0x01DE0DFC); // Running Notepad 
    var guestHandle = new WindowInteropHelper(this).Handle; 

    var style = WS_VISIBLE | WS_CLIPSIBLINGS | WS_CHILD | WS_POPUP; 
    SetWindowLong(guestHandle, GWL_STYLE, (int)(style)); 
    SetParent(guestHandle, parentHwnd); 

(Я пытался не-настройки стиля WS_POPUP. Это не влияет.)

+1

Просто мысли, вы пробовали тестирование с любого окна (скажем calc.exe), кроме блокнота? У меня нет доступа к ПК с Windows 7 прямо сейчас, но я могу воспроизвести проблему с помощью блокнота, но не с помощью calc.exe, используя именно ваш код в Windows 8. На Win8 с вашим кодом дочернее окно появляется в блокноте , но как только я активирую окно блокнота, дочернее окно становится невидимым, поэтому я думаю, что блокнот делает что-то, чтобы сохранить свой текстовый блок поверх всех других детей. –

+0

Хммм ... спасибо за эту мысль, @AndreiPana. Я буду тестировать другие окна и проверить, как это работает в Windows 8. –

ответ

3

Вместо использования SetParent установите WindowInteropHelper.Owner вашего «дочернего» окна WPF в окно, которое вы хотите отобразить выше.

Обратите внимание, что в .NET 3.5, если вы делаете это в любом из обработчиков событий окна «дочерний», даже уже в OnSourceInitialized, владелец окна действительно не устанавливается. По-видимому, слишком поздно устанавливать владельца на тот момент.

Вместо этого установите владельца в код, который создает окно, прежде чем вы вызовете Show(). Предполагается, что .NET 4 позволяет установить Владелец из SourceInitialized.

  • Джек
+0

Спасибо, Джек! Это сработало отлично. –

+0

У меня возникла аналогичная проблема, но, похоже, я не могу открыть окно «Блокнот», например, вызывая «this.Owner = HwndSource.FromHwnd (hwnd_notepad) .RootVisual as Window;». Как вы это достигли? – Benj