简体   繁体   中英

Get Toolkit Style Window with WPF

I am using the WPF toolkit and the WPF toolkit extended and notice that when I display a message box via:

MessageBox.Show("...");

I get the following...

在此处输入图片说明

I would like to make my main application window use this styling as well. Is there a way to do it?

EDIT: I've tried WindowStyle="ToolWindow" and it doesn't work.

Edit: In response to the answer below, please see picture below:

在此处输入图片说明

Also, I would like it to have a maximize and minimize button but with the same style as the button for close.

Thank you!

Your question is pretty vague. You don't say anywhere what part of the MessageBox's style you want but I think I know what you're asking (same colours and window chrome).

Since you're using the Extended Toolkit version of MessageBox you have two options.

Firstly, you could switch out every instance of Window that you have in your Xaml and replace it with extToolkit:ChildWindow (extToolkit being the namespaced at xmlns:extToolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit/extended").

This is the quick option but leaves you in the lurch with a couple of things. Title for one is missing from ChildWindow and Caption is used instead. That might be enough for you if you don't do too much with your Windows themselves.

Your second option is to Template Window itself by using the same style info from the MessageBox or ChildWindow templates. The Template for the extended toolkit ChildWindow is at the bottom of this answer but it will take some reworking to fall into line with the properties of Window. You'd have to hide the Window chrome too and have a borderless form since the chrome is implemented in the Template.

It's not the best situation to be in and the extended toolkit ought to have it's own Window implementation to be honest.

If I were you I'd try to switch your Windows for ChildWindows to start off.

HTH.

Here's that Template -

<ControlTemplate x:Key="ChildWindowControlTemplate1" TargetType="{x:Type extToolkit:ChildWindow}">
        <Grid x:Name="Root">
            <Grid.Resources>
                <Style x:Key="FocusVisualStyle" TargetType="{x:Type Control}">
                    <Setter Property="BorderBrush" Value="Black"/>
                    <Setter Property="Background" Value="Transparent"/>
                    <Setter Property="Margin" Value="-1"/>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate>
                                <Rectangle Fill="{TemplateBinding Background}" Margin="{TemplateBinding Margin}" Stroke="{TemplateBinding BorderBrush}" StrokeThickness="0.5" StrokeDashArray="4 3">
                                    <Rectangle.RenderTransform>
                                        <TranslateTransform X="{Binding Left}" Y="{Binding Top}"/>
                                    </Rectangle.RenderTransform>
                                </Rectangle>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
                <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
            </Grid.Resources>
            <Grid x:Name="PART_WindowRoot" HorizontalAlignment="Left" Height="{TemplateBinding Height}" MinWidth="{TemplateBinding MinWidth}" MinHeight="{TemplateBinding MinHeight}" VerticalAlignment="Top" Width="{TemplateBinding Width}">
                <Grid.RenderTransform>
                    <TransformGroup>
                        <ScaleTransform/>
                        <SkewTransform/>
                        <RotateTransform/>
                        <TranslateTransform/>
                    </TransformGroup>
                </Grid.RenderTransform>
                <Grid x:Name="WindowGrid">
                    <Border BorderBrush="{TemplateBinding WindowBorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="5,5,0,0" Opacity="{TemplateBinding WindowOpacity}"/>
                    <Grid Background="{x:Null}" Margin="0">
                        <Border x:Name="WindowBorder" Background="{TemplateBinding WindowBackground}" CornerRadius="4,4,0,0" Margin="1" Opacity="{TemplateBinding WindowOpacity}"/>
                        <Border BorderBrush="White" BorderThickness="1" CornerRadius="4,4,0,0" Margin="1" Opacity="0.7"/>
                    </Grid>
                </Grid>
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" MinHeight="26"/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <Grid x:Name="ContentGrid" Margin="6,0,6,6" Grid.Row="1">
                        <Grid.RowDefinitions>
                            <RowDefinition/>
                            <RowDefinition Height="Auto"/>
                        </Grid.RowDefinitions>
                        <Border BorderBrush="White" BorderThickness="1" CornerRadius="1"/>
                        <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="0.1" Margin="1">
                            <ContentPresenter x:Name="Content" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}"/>
                        </Border>
                    </Grid>
                    <Border x:Name="PART_DragWidget" Background="Transparent" Grid.Column="1" CornerRadius="5,5,0,0" Margin="1,1,1,0">
                        <Grid>
                            <Grid x:Name="CaptionHeader" Margin="1,1,105,0" VerticalAlignment="Center">
                                <ContentControl x:Name="Caption" Content="{TemplateBinding Caption}" Foreground="{TemplateBinding CaptionForeground}" HorizontalAlignment="Stretch" IsTabStop="False" Margin="5,0,0,0"/>
                            </Grid>
                        </Grid>
                    </Border>
                </Grid>
                <Border BorderBrush="#A5FFFFFF" BorderThickness="1,0,1,1" CornerRadius="0,0,3,3" HorizontalAlignment="Right" Margin="0,1,7,0" VerticalAlignment="Top">
                    <Button x:Name="PART_CloseButton" Height="17" IsTabStop="False" Style="{TemplateBinding CloseButtonStyle}" Visibility="{TemplateBinding CloseButtonVisibility}" Width="43">
                        <Path Data="M0.5,0.5L4.5178828,0.5 6.0620003,3.125 7.4936447,0.5 11.5,0.5 11.5,1.5476431 8.7425003,6.1201854 11.5,10.359666 11.5,11.5 7.4941902,11.5 6.0620003,8.8740005 4.5172949,11.5 0.5,11.5 0.5,10.43379 3.3059995,6.1201582 0.5,1.4676378 0.5,0.5z" Fill="#E4FFFFFF" HorizontalAlignment="Center" Height="10" Stretch="Fill" Stroke="#FF535666" VerticalAlignment="Center" Width="12"/>
                    </Button>
                </Border>
            </Grid>
        </Grid>
        <ControlTemplate.Triggers>
            <Trigger Property="WindowState" Value="Closed">
                <Setter Property="Visibility" Value="Collapsed"/>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>

add this to your window tag in the xaml editor

WindowStyle="ToolWindow"

I want to add a disclaimer here that I threw this together pretty quickly out of curiosity, more than anything. I haven't tested this much, other than dropping a few controls on there and running it. It works, but is shouldn't be considered fully complete. I also think there are probably better ways to do this, but I figured this would at least give you a good starting place.

Add a new ResourceDictionary to your project, and add the following XAML:

<ResourceDictionary
  x:Class="CustomWindow.BaseResource"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Style x:Key="WindowStyle" TargetType="{x:Type Window}">
    <Setter Property="BorderThickness" Value="0" />
    <Setter Property="WindowStyle" Value="None" />
    <Setter Property="ResizeMode" Value="NoResize" />
    <Setter Property="Background" Value="White" />
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type Window}">
          <Border
            x:Name="WindowBorder"
            BorderBrush="Black"
            BorderThickness="1">
            <Border.Background>
              <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                <GradientStop Offset="0" Color="White" />
                <GradientStop Offset="1" Color="#FFDADADA" />
              </LinearGradientBrush>
            </Border.Background>
            <Grid
              Width="{TemplateBinding Width}"
              Height="{TemplateBinding Height}"
              MinWidth="{TemplateBinding MinWidth}"
              MinHeight="{TemplateBinding MinHeight}"
              HorizontalAlignment="Left"
              VerticalAlignment="Top"
              Cursor="Arrow">
              <Grid.RowDefinitions>
                <RowDefinition Height="25" />
                <RowDefinition Height="*" />
              </Grid.RowDefinitions>
              <TextBlock
                Width="500"
                Height="23"
                Margin="11,2,0,0"
                HorizontalAlignment="Left"
                VerticalAlignment="Top"
                Text="{TemplateBinding Title}" />
              <Rectangle
                x:Name="TitleBar"
                Fill="Transparent"
                MouseDown="TitleBar_MouseDown" />
              <Rectangle
                Grid.RowSpan="2"
                Width="10"
                HorizontalAlignment="Left"
                Cursor="SizeWE"
                Fill="Transparent"
                MouseDown="Border_MouseDown"
                Tag="Left" />
              <Rectangle
                Grid.RowSpan="2"
                Width="10"
                HorizontalAlignment="Right"
                Cursor="SizeWE"
                Fill="Transparent"
                MouseDown="Border_MouseDown"
                Tag="Right" />
              <Rectangle
                Height="5"
                VerticalAlignment="Top"
                Cursor="SizeNS"
                Fill="Transparent"
                MouseDown="Border_MouseDown"
                Tag="Top" />
              <Rectangle
                Grid.Row="1"
                Height="10"
                VerticalAlignment="Bottom"
                Cursor="SizeNS"
                Fill="Transparent"
                MouseDown="Border_MouseDown"
                Tag="Bottom" />
              <StackPanel
                Margin="10,0"
                HorizontalAlignment="Right"
                VerticalAlignment="Top"
                Orientation="Horizontal">
                <Button
                  x:Name="MinimizeButton"
                  Width="43"
                  Height="17"
                  Click="MinimizeButton_Click"
                  IsTabStop="False">
                  min
                </Button>
                <Button
                  x:Name="MaximizeButton"
                  Width="43"
                  Height="17"
                  Margin="5,0"
                  Click="MaximizeButton_Click"
                  IsTabStop="False">
                  max
                </Button>
                <Button
                  x:Name="CloseButton"
                  Width="43"
                  Height="17"
                  Click="CloseButton_Click"
                  IsTabStop="False">
                  <Path
                    Width="12"
                    Height="10"
                    HorizontalAlignment="Center"
                    VerticalAlignment="Center"
                    Data="M0.5,0.5L4.5178828,0.5 6.0620003,3.125 7.4936447,
                      0.5 11.5,0.5 11.5,1.5476431 8.7425003,6.1201854 11.5,
                      10.359666 11.5,11.5 7.4941902,11.5 6.0620003,8.8740005 
                      4.5172949,11.5 0.5,11.5 0.5,10.43379 3.3059995,
                      6.1201582 0.5,1.4676378 0.5,0.5z"
                    Fill="#E4FFFFFF"
                    Stretch="Fill"
                    Stroke="#FF535666" />
                </Button>
              </StackPanel>
              <Border
                Grid.Row="1"
                Margin="10,0,10,10"
                BorderBrush="Black"
                BorderThickness="1">
                <Grid>
                  <Rectangle Fill="White" />
                  <ContentPresenter Content="{TemplateBinding Content}" />
                </Grid>
              </Border>
            </Grid>
          </Border>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</ResourceDictionary>

For illustrative purposes, let's say we named the ResourceDictionary, BaseResource.xaml .

Next add a new Class to the same directory where you added the resource, and name the file BaseResource.xaml.cs , substituting the actual name of your XAML file.

Go back to BaseResource.xaml and change the x:Class="CustomWindow.BaseResource" property to the full type name of the ResourceDictionary. If changed correctly, Visual Studio should complain that there is a duplicate definition in BaseResource.xaml.cs. Fix that by adding the partial keyword modifier to the class in the .cs file.

Finally, add the following code to the code file:

using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;

namespace CustomWindow
{
    public partial class BaseResource
    {
        private const uint WM_SYSCOMMAND = 0x112;

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern IntPtr 
            SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);

        private void CloseButton_Click(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
            Window.GetWindow((DependencyObject) sender).Close();
        }

        private void MinimizeButton_Click(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
            Window.GetWindow((DependencyObject) sender).WindowState = WindowState.Minimized;
        }

        private void MaximizeButton_Click(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
            var window = Window.GetWindow((DependencyObject) sender);
            window.WindowState = 
              (window.WindowState == WindowState.Maximized) ? WindowState.Normal : WindowState.Maximized;
        }

        private void TitleBar_MouseDown(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;
            Window.GetWindow((DependencyObject) sender).DragMove();
        }

        private void Border_MouseDown(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;
            var direction = (Direction)Enum.Parse(typeof(Direction), ((FrameworkElement)sender).Tag.ToString());
            ResizeWindow(PresentationSource.FromVisual((Visual)sender) as HwndSource, direction);
        }

        private void ResizeWindow(HwndSource hwndSource, Direction direction)
        {
            SendMessage(hwndSource.Handle, WM_SYSCOMMAND, (int)(61440 + direction), 0);
        }

        private enum Direction
        {
            Left = 1,
            Right = 2,
            Top = 3,
            TopLeft = 4,
            TopRight = 5,
            Bottom = 6,
            BottomLeft = 7,
            BottomRight = 8,
        }
    }
}

Next add the ResourceDictionary to global Application resources. Again, substituting BaseResource.xaml with the name of your file, if it is different.

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/BaseResource.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

Add the style to the target Window.

<Window
  ...
  Style="{StaticResource WindowStyle}">

A few things...

The designer messes with the style when there is no content. It is probably because of where I placed the TemplateBinding for Height and Width, but it looks fine at runtime, so I didn't mess with it further. I also didn't implement the resize grip for the corners, but it is easy enough to add to the template.

Finally, I didn't draw icons for the Minimize and Maximize buttons. I suck at creating Paths in Blend.

Hope it helps.

You can use the WPF Shell Integration Library to take complete control over the chrome of your window. The download includes a sample.

PS. A common misconception is that you can provide a custom chrome by setting your WindowStyle to None . Whilst this does remove the default chrome, it has several drawbacks, including that any chrome you do render will need to handle resizing/moving, and that your window will maximize over the user's task bar, which is not acceptable behavior.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM