programing

wpf에서 사용자 지정 윈도우 크롬을 만드는 방법은 무엇입니까?

lovejava 2023. 5. 14. 09:56

wpf에서 사용자 지정 윈도우 크롬을 만드는 방법은 무엇입니까?

닫기 단추를 포함하지 않고 이동 및 크기 조정이 가능한 WPF 창의 기본 사용자 지정 창 크롬을 어떻게 만들 수 있습니까?

창을 설정합니다.WindowStyle="None"그런 다음 자신만의 창 인터페이스를 클릭합니다.자체 최소/최대/닫기/끌기 이벤트 핸들러를 내장해야 하지만 크기 조정은 계속 유지됩니다.

예:

<Window 
    WindowState="Maximized"
    WindowStyle="None"
    WindowStartupLocation="CenterScreen"
    MaxWidth="{Binding Source={x:Static SystemParameters.WorkArea}, Path=Width}"
    MaxHeight="{Binding Source={x:Static SystemParameters.WorkArea}, Path=Height}"
>

    <DockPanel x:Name="RootWindow">
        <DockPanel x:Name="TitleBar" DockPanel.Dock="Top">
            <Button x:Name="CloseButton" Content="X"
                    Click="CloseButton_Click"
                    DockPanel.Dock="Right" />
            <Button x:Name="MaxButton" Content="Restore"
                    Click="MaximizeButton_Click"
                    DockPanel.Dock="Right" />
            <Button x:Name="MinButton" Content="Min"
                    Click="MinimizeButton_Click"
                    DockPanel.Dock="Right" />

            <TextBlock HorizontalAlignment="Center">Application Name</TextBlock>
        </DockPanel>

        <ContentControl Content="{Binding CurrentPage}" />
    </DockPanel>

</Window>

다음은 일반 창 기능에 대한 코드백 예제입니다.

/// <summary>
/// TitleBar_MouseDown - Drag if single-click, resize if double-click
/// </summary>
private void TitleBar_MouseDown(object sender, MouseButtonEventArgs e)
{
    if(e.ChangedButton == MouseButton.Left)
        if (e.ClickCount == 2)
        {
            AdjustWindowSize();
        }
        else
        {
            Application.Current.MainWindow.DragMove();
        }
 }

/// <summary>
/// CloseButton_Clicked
/// </summary>
private void CloseButton_Click(object sender, RoutedEventArgs e)
{
   Application.Current.Shutdown();
}

/// <summary>
/// MaximizedButton_Clicked
/// </summary>
private void MaximizeButton_Click(object sender, RoutedEventArgs e)
{
    AdjustWindowSize();
}

/// <summary>
/// Minimized Button_Clicked
/// </summary>
private void MinimizeButton_Click(object sender, RoutedEventArgs e)
{
    this.WindowState = WindowState.Minimized;
}

/// <summary>
/// Adjusts the WindowSize to correct parameters when Maximize button is clicked
/// </summary>
private void AdjustWindowSize()
{
    if (this.WindowState == WindowState.Maximized)
    {
        this.WindowState = WindowState.Normal;
        MaxButton.Content = "1";
    }
    else
    {
        this.WindowState = WindowState.Maximized;
        MaxButton.Content = "2";
    }

}

.NET 4.5는 이를 매우 단순화하는 새로운 클래스를 추가했습니다.

WPF(Windows Presentation Foundation) 콘텐츠를 일반적으로 운영 체제의 창 관리자용으로 예약된 창의 비클라이언트 영역으로 확장할 수 있습니다.

여기에서 튜토리얼을 찾을 수 있습니다.

여기 짧은 사용 가 있습니다.

아래 예제를 .net 4.5에 사용했는데 매우 잘 작동합니다.흥미롭게도, 클릭 이벤트를 위한 리소스 사전에 대한 코드를 사용합니다.리소스 사전을 참조하기만 하면 됩니다.app.xaml파일을 작성한 다음 창에 스타일 지정CustomWindowStyle이것은 뻔뻔스럽게도 http://www.eidias.com/blog/2014/1/27/restyle-your-window 에서 도난당했습니다.

<ResourceDictionary x:Class="WpfApp7.WindowStyle"
                    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">


    <Style x:Key="CustomWindowStyle" TargetType="{x:Type Window}">
        <Setter Property="WindowChrome.WindowChrome">
            <Setter.Value>
                <WindowChrome CaptionHeight="30"
                              CornerRadius="4"
                              GlassFrameThickness="0"
                              NonClientFrameEdges="None"
                              ResizeBorderThickness="5"
                              UseAeroCaptionButtons="False" />
            </Setter.Value>
        </Setter>

        <Setter Property="BorderBrush" Value="Black" />
        <Setter Property="Background" Value="Gray" />

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Window}">
                    <Grid>
                        <Border Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="5,30,5,5">
                            <AdornerDecorator>
                                <ContentPresenter />
                            </AdornerDecorator>
                        </Border>

                        <Grid Height="30"
                            VerticalAlignment="Top">

                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition Width="Auto"/>
                            </Grid.ColumnDefinitions>

                            <StackPanel Orientation="Horizontal" Margin="5,0">
                                <Button Content="A" Margin="0,0,5,0" VerticalAlignment="Center" Click="Button_Click" WindowChrome.IsHitTestVisibleInChrome="True"/>
                                <Button Content="B" Margin="0,0,5,0" VerticalAlignment="Center" Click="Button_Click" WindowChrome.IsHitTestVisibleInChrome="True"/>
                                <Button Content="C" Margin="0,0,5,0" VerticalAlignment="Center" Click="Button_Click" WindowChrome.IsHitTestVisibleInChrome="True"/>
                                <Button Content="D" Margin="0,0,5,0" VerticalAlignment="Center" Click="Button_Click" WindowChrome.IsHitTestVisibleInChrome="True"/>
                            </StackPanel>


                            <TextBlock Margin="5,0,0,0"
                                       VerticalAlignment="Center"
                                       HorizontalAlignment="Center"
                                       FontSize="16"
                                       Foreground="White"
                                       Text="{TemplateBinding Title}" 
                                       Grid.Column="1"/>


                            <StackPanel Orientation="Horizontal"
                                        Grid.Column="2">
                                <Button x:Name="btnClose"
                                    Width="15"
                                    Margin="5"
                                    Click="CloseClick"
                                    Content="X"
                                    WindowChrome.IsHitTestVisibleInChrome="True" />


                                <Button x:Name="btnRestore"
                                    Width="15"
                                    Margin="5"
                                    Click="MaximizeRestoreClick"
                                    Content="#"
                                    WindowChrome.IsHitTestVisibleInChrome="True" />

                                <Button x:Name="btnMinimize"
                                    Width="15"
                                    Margin="5"
                                    VerticalContentAlignment="Bottom"
                                    Click="MinimizeClick"
                                    Content="_"
                                    WindowChrome.IsHitTestVisibleInChrome="True" />
                            </StackPanel>
                        </Grid>

                    </Grid>

                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

뒤에 있는 코드의 경우:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace WpfApp7
{
    public partial class WindowStyle : ResourceDictionary
    {
        public WindowStyle()
        {
            InitializeComponent();
        }

        private void CloseClick(object sender, RoutedEventArgs e)
        {
            var window = (Window)((FrameworkElement)sender).TemplatedParent;
            window.Close();
        }

        private void MaximizeRestoreClick(object sender, RoutedEventArgs e)
        {
            var window = (Window)((FrameworkElement)sender).TemplatedParent;
            if (window.WindowState == System.Windows.WindowState.Normal)
            {
                window.WindowState = System.Windows.WindowState.Maximized;
            }
            else
            {
                window.WindowState = System.Windows.WindowState.Normal;
            }
        }

        private void MinimizeClick(object sender, RoutedEventArgs e)
        {
            var window = (Window)((FrameworkElement)sender).TemplatedParent;
            window.WindowState = System.Windows.WindowState.Minimized;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Hello!");
        }
    }
}

다음은 기본 Windows 10 단추와 매우 유사하게 보이는 쉬운 솔루션으로 기호에 동일한 글꼴을 사용합니다.

<StackPanel Orientation="Horizontal" VerticalAlignment="Top" WindowChrome.IsHitTestVisibleInChrome="True">
<Button Click="Minimize_Click" Content="&#xE949;" FontFamily="Segoe MDL2 Assets" FontSize="10" Padding="15,15,15,5" Background="Transparent" BorderBrush="Transparent" />
<Button Click="Maximize_Click" FontFamily="Segoe MDL2 Assets" FontSize="10" Padding="15,10" Background="Transparent" BorderBrush="Transparent">
    <Button.Style>
        <Style TargetType="{x:Type Button}">
            <Setter Property="Button.Content" Value="&#xE739;" />
            <Style.Triggers>
                <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=WindowState}" Value="Maximized">
                    <Setter Property="Button.Content" Value="&#xE923;" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Button.Style>
</Button>
<Button Click="Close_Click" Content="&#xE106;" FontFamily="Segoe MDL2 Assets" FontSize="10" Padding="15,10" Background="Transparent" BorderBrush="Transparent" />
</StackPanel>

이전 Windows 버전(7 및 8)에 대한 지원을 원하는 경우 다음을 참조하십시오. https://stackoverflow.com/a/27911618/9758687

다음은 필요한 접근 방식의 개요입니다.

  • 세트WindowStyle="None"UI를 사용할 수 있습니다.
  • 사용하다WindowChrome.CaptionHeight표준 제목 표시줄 끌기/더블 클릭/흔들기 동작을 가져오고 설정하려면WindowChrome.IsHitTestVisibleInChrome="True"버튼을 클릭할 수 있습니다.
  • 단추에 대한 클릭 핸들러를 구현합니다.
  • 창에 연결합니다.StateChanged 이벤트를 통해 최대화/복원 변경 사항을 처리하고 UI를 업데이트합니다.모든 사용자가 제목 표시줄 단추를 사용하여 최대화 및 복원한다고 가정할 수는 없습니다.키보드 단축키(Win+Up/Win+Down) 또는 제목 표시줄을 두 번 클릭하면 이러한 문제가 발생할 수 있습니다.
  • 당신이 최대화할 때 당신의 창문의 7개가 사방에서 잘려나갑니다.수정하려면 WM_GETMINMAXINFO에 연결하여 정확한 최대 위치를 제공해야 합니다.
  • 다른 배경에 대비하려면 창 테두리를 다시 구현해야 합니다.
  • 제목 표시줄 아이콘을 다른 DPI에서 잘 보이도록 렌더링하려면 <Path>를 사용합니다.
  • 창이 활성화되어 있는지 여부에 따라 제목 표시줄의 모양을 변경하여 사용자에게 포커스가 있는 창을 표시합니다.

전체 기록은 약간 깁니다. 는 이 블로그 게시물의 코드 예제와 함께 그것들을 자세히 살펴봅니다.

언급URL : https://stackoverflow.com/questions/6792275/how-to-create-custom-window-chrome-in-wpf