Окошко в стиле Yahoo Messenger
16 декабря 2007 - 17:23
Увидел недавно Yahoo Messenger for Vista и решил сделать аналогичное окно.
Это оказалось несложно. Итак,
Скачать пример:
Написано на Visual Studio 2008 под .NET Framework 3.5
P.S. Данный пример не претендует на какую-либо завершённость, поэтому используйте его на свой страх и риск...
Это оказалось несложно. Итак,
Создаём главное окно
- Ставим стиль окна (WindowStyle) None, по желанию ставим ResizeWithGrip.
- Добавляем кнопки закрытия/минимизации/максимизации.
<StackPanel HorizontalAlignment="Right" VerticalAlignment="Top" Width="Auto" Height="20" Orientation="Horizontal"> <Button Content="0" Width="30" Template="{DynamicResource CaptionButtonControlTemplate}" Focusable="False" IsTabStop="False" Margin="0,0,-1,0" FontFamily="Webdings" Foreground="#FFD8D8D8" Click="OnMinimizeClick"/> <Button Content="2" Width="30" Template="{DynamicResource CaptionButtonControlTemplate}" Focusable="False" IsTabStop="False" Margin="0,0,-1,0" FontFamily="Webdings" Foreground="#FFD8D8D8" Click="OnMaximizeClick" x:Name="maximizeButton"/> <Button Content="r" Width="30" Template="{DynamicResource CaptionButtonControlTemplate}" Focusable="False" IsTabStop="False" FontFamily="Webdings" Foreground="#FFD8D8D8" Click="OnCloseClick"/> </StackPanel>
- Добавляем возможность перетаскивать окно при хватании за какой-нибудь контрол. Событие вызывается нажатием мыши - DragMove().
// При нажатии мыши на заголовке private void OnMouseDown(object sender, MouseButtonEventArgs e) { DragMove(); }
- Используя DWM расширяем границы стеклянности на пару пикселей. В Yahoo Messenger все окно сделано стеклянным, но никакого смыла в этом я не вижу, и Microsoft в своих гайдах не рекомендует так делать, поэтому и я не буду.
// Настраиваем DWM bool nonDwn = false; try { // Obtain the window handle for WPF application IntPtr hwnd = new WindowInteropHelper(this).Handle; HwndSource mainWindowSrc = HwndSource.FromHwnd(hwnd); mainWindowSrc.CompositionTarget.BackgroundColor = Color.FromArgb(0, 0, 0, 0); // Set Margins MARGINS margins = new MARGINS(); // Extend glass frame into client area // Note that the default desktop Dpi is 96dpi. The margins are // adjusted for the system Dpi. margins.cxLeftWidth = 5; margins.cxRightWidth = 5; margins.cyTopHeight = 5; margins.cyBottomHeight = 5; int hr = DwmExtendFrameIntoClientArea(mainWindowSrc.Handle, ref margins); // if (hr < 0) { //DwmExtendFrameIntoClientArea Failed nonDwn = true; } } // If not Vista, paint background white. catch (DllNotFoundException) { nonDwn = true; }
- Добавляем контролы по вкусу и стили для них. Я вот добавил панель RadioButton-ов с различными цветами, по нажатию на которые меняется цвет фона.
Создаем окно с аватаром
- Ставим AllowTransparency = true.
- Убиваем Background.
- Настраиваем события так, чтобы при нажатии на картинку любой клавишей мыши активировалось основное окно и вызывалось событие DragMove() .
// При нажатии кнопки мыши на картинке private void OnMouseDown(object sender, MouseButtonEventArgs e) { Owner.Activate(); // Если кнопка левая, то начинаем таскать главное окно if(e.ChangedButton==MouseButton.Left) Owner.DragMove(); }
- Добавляем контролы по вкусу.
Совмещаем окна
- При создании главного окна создаём окно с аватаром устанавливаем у него Owner - главное окно
// Показываем окно с аватаром avatarWindow.Owner = this; avatarWindow.Left = Left; avatarWindow.Top = Top-100; avatarWindow.Show();
- В главном окне перехватываем передвижение и перемещаем окно с аватаром в нужную позицию
// При изменении позиции protected override void OnLocationChanged(EventArgs e) { // Устанавливаем новую позицию окна с аватаром if (WindowState != WindowState.Maximized) { avatarWindow.Left = Left; avatarWindow.Top = Top-100; } else { avatarWindow.Left = Left+10; avatarWindow.Top = Top+6; } base.OnLocationChanged(e); }
- Дорабатываем всякие незначительные мелочи...
Скачать пример:
Написано на Visual Studio 2008 под .NET Framework 3.5
P.S. Данный пример не претендует на какую-либо завершённость, поэтому используйте его на свой страх и риск...