Завдяки чому програми WPF виглядають у стилі метро навіть у Windows 7? (Вікно Chrome / Тематика / Тема)


123

Мені подобається хром вікон у нових Office Suite та Visual Studio:

введіть тут опис зображення

Я все ще розробляю додатки для Windows 7, звичайно, але мені цікаво, чи є швидкий і простий спосіб (читати: WPF-стиль або Windows-бібліотека) наслідувати цей стиль. У минулому я робив декілька стилів хромування вікон, але примусити його виглядати та вести себе правильно, це справді складно.

Хтось знає, чи існують шаблони або бібліотеки, щоб додати зовнішній вигляд "Сучасного інтерфейсу" до моїх програм WPF?


8
Цей посібник / NuGet пакет може бути корисним: MahaApps Metro Він містить набір стилів та елементів управління для створення WPF-додатків за допомогою Metro Look and feel.
Олівер Фогель

Питання, в яких просять рекомендувати або знайти книгу, інструмент, бібліотеку програмного забезпечення, навчальний посібник чи інший ресурс поза сайтом, - це поза темою для переповнення стека, оскільки вони, як правило, залучають впевнені відповіді та спам. Натомість опишіть проблему та що було зроблено поки що для її вирішення.
Скотт Солмер

Відповіді:


149

Що я зробив, це створити власне вікно та стиль. Тому що мені подобається мати контроль над усім, і я не хотів, щоб деякі зовнішні бібліотеки просто використовували вікно з нього. Я подивився на вже згаданий MahApps.Metro на GitHub

MahApps

а також дуже приємний сучасний інтерфейс на GitHub . (Лише .NET4.5)

Сучасний інтерфейс користувача

Є ще один це Elysium, але я справді цього не пробував.

Elysium

Стиль, який я робив, був дуже легким, коли я дивився, як це робиться в цих. Тепер у мене є власне Вікно, і я можу робити все, що завгодно, за допомогою xaml ... для мене це головна причина, чому я зробив своє. І я зробив ще один для вас :) Я, мабуть, мушу сказати, що я не зміг би це зробити, не вивчивши Сучасний інтерфейс, це було чудовою допомогою. Я намагався зробити так, щоб він виглядав як VS2012 Window. Це виглядає приблизно так.

MyWindow

Ось код (зверніть увагу, що він орієнтований на .NET4.5)

public class MyWindow : Window
{

    public MyWindow()
    {
        this.CommandBindings.Add(new CommandBinding(SystemCommands.CloseWindowCommand, this.OnCloseWindow));
        this.CommandBindings.Add(new CommandBinding(SystemCommands.MaximizeWindowCommand, this.OnMaximizeWindow, this.OnCanResizeWindow));
        this.CommandBindings.Add(new CommandBinding(SystemCommands.MinimizeWindowCommand, this.OnMinimizeWindow, this.OnCanMinimizeWindow));
        this.CommandBindings.Add(new CommandBinding(SystemCommands.RestoreWindowCommand, this.OnRestoreWindow, this.OnCanResizeWindow));
    }

    private void OnCanResizeWindow(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = this.ResizeMode == ResizeMode.CanResize || this.ResizeMode == ResizeMode.CanResizeWithGrip;
    }

    private void OnCanMinimizeWindow(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = this.ResizeMode != ResizeMode.NoResize;
    }

    private void OnCloseWindow(object target, ExecutedRoutedEventArgs e)
    {
        SystemCommands.CloseWindow(this);
    }

    private void OnMaximizeWindow(object target, ExecutedRoutedEventArgs e)
    {
        SystemCommands.MaximizeWindow(this);
    }

    private void OnMinimizeWindow(object target, ExecutedRoutedEventArgs e)
    {
        SystemCommands.MinimizeWindow(this);
    }

    private void OnRestoreWindow(object target, ExecutedRoutedEventArgs e)
    {
        SystemCommands.RestoreWindow(this);
    }
}

І ось ресурси:

<BooleanToVisibilityConverter x:Key="bool2VisibilityConverter" />

<Color x:Key="WindowBackgroundColor">#FF2D2D30</Color>
<Color x:Key="HighlightColor">#FF3F3F41</Color>
<Color x:Key="BlueColor">#FF007ACC</Color>
<Color x:Key="ForegroundColor">#FFF4F4F5</Color>

<SolidColorBrush x:Key="WindowBackgroundColorBrush" Color="{StaticResource WindowBackgroundColor}"/>
<SolidColorBrush x:Key="HighlightColorBrush" Color="{StaticResource HighlightColor}"/>
<SolidColorBrush x:Key="BlueColorBrush" Color="{StaticResource BlueColor}"/>
<SolidColorBrush x:Key="ForegroundColorBrush" Color="{StaticResource ForegroundColor}"/>

<Style x:Key="WindowButtonStyle" TargetType="{x:Type Button}">
    <Setter Property="Foreground" Value="{DynamicResource ForegroundColorBrush}" />
    <Setter Property="Background" Value="Transparent" />
    <Setter Property="HorizontalContentAlignment" Value="Center" />
    <Setter Property="VerticalContentAlignment" Value="Center" />
    <Setter Property="Padding" Value="1" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Grid Background="{TemplateBinding Background}">
                    <ContentPresenter x:Name="contentPresenter"
                          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                          Margin="{TemplateBinding Padding}"
                          RecognizesAccessKey="True" />
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="{StaticResource HighlightColorBrush}" />
                    </Trigger>
                    <Trigger Property="IsPressed" Value="True">
                        <Setter Property="Background" Value="{DynamicResource BlueColorBrush}" />
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter TargetName="contentPresenter" Property="Opacity" Value=".5" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style x:Key="MyWindowStyle" TargetType="local:MyWindow">
    <Setter Property="Foreground" Value="{DynamicResource ForegroundColorBrush}" />
    <Setter Property="Background" Value="{DynamicResource WindowBackgroundBrush}"/>
    <Setter Property="ResizeMode" Value="CanResizeWithGrip" />
    <Setter Property="UseLayoutRounding" Value="True" />
    <Setter Property="TextOptions.TextFormattingMode" Value="Display" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:MyWindow">
                <Border x:Name="WindowBorder" Margin="{Binding Source={x:Static SystemParameters.WindowNonClientFrameThickness}}" Background="{StaticResource WindowBackgroundColorBrush}">
                    <Grid>
                        <Border BorderThickness="1">
                            <AdornerDecorator>
                                <Grid x:Name="LayoutRoot">
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="25" />
                                        <RowDefinition Height="*" />
                                        <RowDefinition Height="15" />
                                    </Grid.RowDefinitions>
                                    <ContentPresenter Grid.Row="1" Grid.RowSpan="2" Margin="7"/>
                                    <Rectangle x:Name="HeaderBackground" Height="25" Fill="{DynamicResource WindowBackgroundColorBrush}" VerticalAlignment="Top" Grid.Row="0"/>
                                    <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Top" WindowChrome.IsHitTestVisibleInChrome="True" Grid.Row="0">
                                        <Button Command="{Binding Source={x:Static SystemCommands.MinimizeWindowCommand}}" ToolTip="minimize" Style="{StaticResource WindowButtonStyle}">
                                            <Button.Content>
                                                <Grid Width="30" Height="25" RenderTransform="1,0,0,1,0,1">
                                                    <Path Data="M0,6 L8,6 Z" Width="8" Height="7" VerticalAlignment="Center" HorizontalAlignment="Center"
                                                        Stroke="{Binding Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}" StrokeThickness="2"  />
                                                </Grid>
                                            </Button.Content>
                                        </Button>
                                        <Grid Margin="1,0,1,0">
                                            <Button x:Name="Restore" Command="{Binding Source={x:Static SystemCommands.RestoreWindowCommand}}" ToolTip="restore" Visibility="Collapsed" Style="{StaticResource WindowButtonStyle}">
                                                <Button.Content>
                                                    <Grid Width="30" Height="25" UseLayoutRounding="True" RenderTransform="1,0,0,1,.5,.5">
                                                        <Path Data="M2,0 L8,0 L8,6 M0,3 L6,3 M0,2 L6,2 L6,8 L0,8 Z" Width="8" Height="8" VerticalAlignment="Center" HorizontalAlignment="Center"
                                                            Stroke="{Binding Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}" StrokeThickness="1"  />
                                                    </Grid>
                                                </Button.Content>
                                            </Button>
                                            <Button x:Name="Maximize" Command="{Binding Source={x:Static SystemCommands.MaximizeWindowCommand}}" ToolTip="maximize" Style="{StaticResource WindowButtonStyle}">
                                                <Button.Content>
                                                    <Grid Width="31" Height="25">
                                                        <Path Data="M0,1 L9,1 L9,8 L0,8 Z" Width="9" Height="8" VerticalAlignment="Center" HorizontalAlignment="Center"
                                                            Stroke="{Binding Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}" StrokeThickness="2"  />
                                                    </Grid>
                                                </Button.Content>
                                            </Button>
                                        </Grid>
                                        <Button Command="{Binding Source={x:Static SystemCommands.CloseWindowCommand}}" ToolTip="close"  Style="{StaticResource WindowButtonStyle}">
                                            <Button.Content>
                                                <Grid Width="30" Height="25" RenderTransform="1,0,0,1,0,1">
                                                    <Path Data="M0,0 L8,7 M8,0 L0,7 Z" Width="8" Height="7" VerticalAlignment="Center" HorizontalAlignment="Center"
                                                        Stroke="{Binding Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}" StrokeThickness="1.5"  />
                                                </Grid>
                                            </Button.Content>
                                        </Button>
                                    </StackPanel>
                                    <TextBlock x:Name="WindowTitleTextBlock" Grid.Row="0" Text="{TemplateBinding Title}" HorizontalAlignment="Left" TextTrimming="CharacterEllipsis" VerticalAlignment="Center"  Margin="8 -1 0 0"  FontSize="16"  Foreground="{TemplateBinding Foreground}"/>
                                    <Grid Grid.Row="2">
                                        <Path x:Name="ResizeGrip" Visibility="Collapsed" Width="12" Height="12" Margin="1" HorizontalAlignment="Right"
                                        Stroke="{StaticResource BlueColorBrush}" StrokeThickness="1" Stretch="None" Data="F1 M1,10 L3,10 M5,10 L7,10 M9,10 L11,10 M2,9 L2,11 M6,9 L6,11 M10,9 L10,11 M5,6 L7,6 M9,6 L11,6 M6,5 L6,7 M10,5 L10,7 M9,2 L11,2 M10,1 L10,3" />
                                    </Grid>
                                </Grid>
                            </AdornerDecorator>
                        </Border>
                        <Border BorderBrush="{StaticResource BlueColorBrush}" BorderThickness="1" Visibility="{Binding IsActive, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Converter={StaticResource bool2VisibilityConverter}}" />
                    </Grid>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="WindowState" Value="Maximized">
                        <Setter TargetName="Maximize" Property="Visibility" Value="Collapsed" />
                        <Setter TargetName="Restore" Property="Visibility" Value="Visible" />
                        <Setter TargetName="LayoutRoot" Property="Margin" Value="7" />
                    </Trigger>
                    <Trigger Property="WindowState" Value="Normal">
                        <Setter TargetName="Maximize" Property="Visibility" Value="Visible" />
                        <Setter TargetName="Restore" Property="Visibility" Value="Collapsed" />
                    </Trigger>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="ResizeMode" Value="CanResizeWithGrip" />
                            <Condition Property="WindowState" Value="Normal" />
                        </MultiTrigger.Conditions>
                        <Setter TargetName="ResizeGrip" Property="Visibility" Value="Visible" />
                    </MultiTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="WindowChrome.WindowChrome">
        <Setter.Value>
            <WindowChrome CornerRadius="0" GlassFrameThickness="1" UseAeroCaptionButtons="False" />
        </Setter.Value>
    </Setter>
</Style>

1
Привіт і дякую вам за цей чудовий код, який ви опублікували. Просто послуга запитати, чи можна мати тінь на вікні? Єдине , що я зрозумів, змінюється GlassFrameThicknessна 1. Але тінь занадто сильна і темна. Як я можу змінити вагу та непрозорість?
xperator


Чи дуже важко створити власну налаштування компонентів замість використання MahApps?
Матей Сараїва

Фантастико! Дякую вам дуже за цей чудовий внесок, я багато разів намагався зробити те саме, але ніколи не мав такого ідеального результату.
Леодев

Припустимо, я хочу збільшити товщину синьої облямівки зверху та видалити рамку з усіх інших сторін (як, наприклад, малюнок із елізію у вашій відповіді), що я мав би змінити? Я новачок в WPF, і , отже , питання
mrid

49

Я вирішив обрати рішення - MahApps.Metro ( github ), який (після використання його на двох програмних програмах зараз) вважаю відмінним набором інтерфейсу (заслуга Олівера Вогеля за пропозицію) .

Стиль вікна

Він обробляє програму з дуже невеликими зусиллями та має адаптації стандартних елементів керування Windows 8. Це дуже надійно.

Текстове поле водяний знак

На Nuget доступна версія:

Ви можете встановити MahApps.Metro через Nuget за допомогою графічного інтерфейсу (клацніть правою кнопкою миші на вашому проекті, керуйте Nuget References, знайдіть "MahApps.Metro") або через консоль:

PM> Встановити-пакет MahApps.Metro

Це також безкоштовно - навіть для комерційного використання.

Оновлення 10-29-2013:

Я виявив, що версія Github MahApps.Metro укомплектована елементами керування та стилями, які недоступні в поточній нот-версії, включаючи:

Сітки даних:

введіть тут опис зображення

Чисте вікно:

введіть тут опис зображення

Мухи:

введіть тут опис зображення

Плитка:

введіть тут опис зображення

Репозиторій github дуже активний з досить невеликим внеском користувачів. Я рекомендую перевірити це.


Я тестую це, приємно +1 :)
Акрем

3
дуже приємне оновлення! Я також спробую MahApps.Metro, Modern UI для WPF та Elysium. Я виявив, що Elysium настільки складний у використанні та переплутанні на їхньому веб-сайті / Док. Метро є більш конкурентоспроможним щодо контролю за формою WPF.
Ченг

Чи дуже важко створити власну налаштування компонентів замість використання MahApps?
Матей Сараїва

42

я рекомендував би сучасний інтерфейс для WPF .

У нього дуже активний супровід, це приголомшливо і безкоштовно!

Сучасний інтерфейс для WPF (Знімок екрана прикладної програми

Я зараз переношу деякі проекти на MUI, перше (а тим часом друге) враження просто ух!

Щоб побачити MUI в дії, ви можете завантажити XAML Spy, який базується на MUI.

EDIT: Використовуючи сучасний інтерфейс для WPF кілька місяців, і я люблю його!


16

На основі відповіді Віктора Ла Круа з джерелом вище, я би змінив його на наступне:

Приклад шрифту Marlett

Краще використовувати шрифт Marlett, а не точки даних Path для кнопок Мінімізація, Відновлення / Максимізація та Закриття.

<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Top" WindowChrome.IsHitTestVisibleInChrome="True" Grid.Row="0">
<Button Command="{Binding Source={x:Static SystemCommands.MinimizeWindowCommand}}" ToolTip="minimize" Style="{StaticResource WindowButtonStyle}">
    <Button.Content>
        <Grid Width="30" Height="25">
            <TextBlock Text="0" FontFamily="Marlett" FontSize="14" VerticalAlignment="Center" HorizontalAlignment="Center" Padding="3.5,0,0,3" />
        </Grid>
    </Button.Content>
</Button>
<Grid Margin="1,0,1,0">
    <Button x:Name="Restore" Command="{Binding Source={x:Static SystemCommands.RestoreWindowCommand}}" ToolTip="restore" Visibility="Collapsed" Style="{StaticResource WindowButtonStyle}">
        <Button.Content>
            <Grid Width="30" Height="25" UseLayoutRounding="True">
                <TextBlock Text="2" FontFamily="Marlett" FontSize="14" VerticalAlignment="Center" HorizontalAlignment="Center" Padding="2,0,0,1" />
            </Grid>
        </Button.Content>
    </Button>
    <Button x:Name="Maximize" Command="{Binding Source={x:Static SystemCommands.MaximizeWindowCommand}}" ToolTip="maximize" Style="{StaticResource WindowButtonStyle}">
        <Button.Content>
            <Grid Width="31" Height="25">
                <TextBlock Text="1" FontFamily="Marlett" FontSize="14" VerticalAlignment="Center" HorizontalAlignment="Center" Padding="2,0,0,1" />
            </Grid>
        </Button.Content>
    </Button>
</Grid>
<Button Command="{Binding Source={x:Static SystemCommands.CloseWindowCommand}}" ToolTip="close"  Style="{StaticResource WindowButtonStyle}">
    <Button.Content>
        <Grid Width="30" Height="25">
            <TextBlock Text="r" FontFamily="Marlett" FontSize="14" VerticalAlignment="Center" HorizontalAlignment="Center" Padding="0,0,0,1" />
        </Grid>
    </Button.Content>
</Button>


Привіт Летаючий маверик. Чи могли б ви пояснити, чому кращою практикою є використання шрифту marlett? У мене є три різні реалізації, і я не впевнений, яку саме використовувати. Перший використовує точки даних про шлях, другий - використовує марлет, а третій - відтворення кнопок у форматі SVG. Я намагаюся використовувати 100% найкращих практик у цьому проекті і не впевнений, який із них найкращий варіант. Не могли б ви пояснити, чому краще виглядає марлет?
користувач1632018

1
Привіт, користувач1632018 Якщо ви хочете створити спеціальне хромоване вікно в Winform або WPF, вам слід поглянути на шрифт 'Marlett', який доступний у вашій системі. Цей шрифт містить фактичні гліфи, які використовуються в Windows для кнопок Мінімізація, Максимізація, Відновлення та Закриття. Використання цього шрифту дозволяє дуже легко повторно використовувати ці гліфи у спеціальному хромованому вікні, а не у користувальницьких зображеннях, які зазвичай використовуються. Ви можете подивитися шрифт Marlett на карті символів Windows або за наступним посиланням для отримання додаткової інформації: microsoft.com/typography/fonts/font.aspx?FMID=1264 Сподіваюся, це допоможе.
FlyingMaverick

2

Якщо ви готові платити, настійно рекомендую Telerik Components для WPF . Вони пропонують чудові стилі / теми, і є конкретні теми як для Office 2013, так і для Windows 8 (EDIT: а також тематичний стиль Visual Studio 2013). Однак там, пропонуючи набагато більше, ніж просто стилі, ви отримаєте цілу купу елементів керування, які справді корисні.

Ось як це виглядає в дії (скріншоти, взяті з зразків telerik):

Зразок приладної панелі Telerik

Зразок приладної панелі Telerik CRM

Ось посилання на зразок інформаційної панелі виконавчої telerik (перший скріншот) та тут на панелі керування CRM (другий скріншот).

Вони пропонують 30-денний пробний термін, просто сфотографуйте!


0

Погляньте на це вікно метро WPF у стилі метро з додатковими світиться рамками .

Це автономне додаток, яке не створює інших бібліотек, окрім Microsoft.Windows.Shell (в комплекті) для створення вікон у стилі метро з необов'язковими світиться межами.

Підтримує Windows аж до XP (.NET4).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.