Окошко в стиле Yahoo Messenger


Увидел недавно Yahoo Messenger for Vista и решил сделать аналогичное окно.
Окошко в стиле Yahoo Messenger

Это оказалось несложно. Итак,

Создаём главное окно

  • Ставим стиль окна (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. Данный пример не претендует на какую-либо завершённость, поэтому используйте его на свой страх и риск...

КОММЕНТАРИИ


НОВЫЙ КОММЕНТАРИЙ


*жирный*
_курсив_
+подчеркнутый+
! заголовок 1
!! заголовок 2
* список
** список 2
# нумерованый список
## нумерованый список 2
[url:http://www.example.com]
{"без форматирования"}
Полное описание синтаксиса