.net 如何创建只能通过手柄调整大小的没有边框的 WPF 窗口?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/611298/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 12:16:05  来源:igfitidea点击:

How to create a WPF Window without a border that can be resized via a grip only?

.netwpfwindowcontroltemplateresizegrip

提问by Drew Noakes

If you set ResizeMode="CanResizeWithGrip"on a WPF Windowthen a resize grip is shown in the lower right corner, as below:

如果您ResizeMode="CanResizeWithGrip"在 WPF 上设置,Window则右下角会显示调整大小的手柄,如下所示:

If you set WindowStyle="None"as well the title bar disappears but the grey bevelled edge remains until you set ResizeMode="NoResize". Unfortunately, with this combination of properties set, the resize grip also disappears.

如果您也设置WindowStyle="None",标题栏会消失,但灰色斜边会一直保留,直到您设置ResizeMode="NoResize"。不幸的是,设置了这种属性组合后,调整大小的手柄也会消失。

I have overridden the Window's ControlTemplatevia a custom Style. I want to specify the border of the window myself, and I don't need users to be able to resize the window from all four sides, but I do need a resize grip.

我已经覆盖了WindowControlTemplate通过自定义Style。我想自己指定窗口的边框,我不需要用户能够从所有四个边调整窗口大小,但我确实需要一个调整大小的手柄。

Can someone detail a simple way to meet all of these criteria?

有人可以详细说明满足所有这些标准的简单方法吗?

  1. Do nothave a border on the Windowapart from the one I specify myself in a ControlTemplate.
  2. Dohave a working resize grip in the lower right corner.
  3. Do nothave a title bar.
  1. 不要对边框Window除了一个我指定我自己的ControlTemplate
  2. 在右下角工作调整大小的抓地力。
  3. 没有标题栏。

回答by ZombieSheep

If you set the AllowsTransparencyproperty on the Window(even without setting any transparency values) the border disappears and you can only resize via the grip.

如果您AllowsTransparencyWindow(即使没有设置任何透明度值)上设置属性,边框就会消失,您只能通过手柄调整大小。

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="640" Height="480" 
    WindowStyle="None"
    AllowsTransparency="True"
    ResizeMode="CanResizeWithGrip">

    <!-- Content -->

</Window>

Result looks like:

结果看起来像:

回答by Fernando Aguirre

I was trying to create a borderless window with WindowStyle="None"but when I tested it, seems that appears a white bar in the top, after some research it appears to be a "Resize border", here is an image (I remarked in yellow):

我试图创建一个无边框窗口, WindowStyle="None"但是当我测试它时,顶部似乎出现一个白色条,经过一些研究,它似乎是一个“调整边框大小”,这是一个图像(我用黄色标记):

The Challenge

挑战

After some research over the internet, and lots of difficult non xaml solutions, all the solutions that I found were code behind in C# and lots of code lines, I found indirectly the solution here: Maximum custom window loses drop shadow effect

经过在互联网上的一些研究,以及许多困难的非 xaml 解决方案,我发现的所有解决方案都是 C# 中的代码和大量代码行,我在这里间接找到了解决方案:Maximum custom window lost drop shadow effect

<WindowChrome.WindowChrome>
    <WindowChrome 
        CaptionHeight="0"
        ResizeBorderThickness="5" />
</WindowChrome.WindowChrome>

Note: You need to use .NET 4.5 framework, or if you are using an older version use WPFShell, just reference the shell and use Shell:WindowChrome.WindowChromeinstead.

注意:您需要使用 .NET 4.5 框架,或者如果您使用的是旧版本,请使用 WPFShell,只需引用 shell 并Shell:WindowChrome.WindowChrome改用即可。

I used the WindowChromeproperty of Window, if you use this that white "resize border" disappears, but you need to define some properties to work correctly.

我使用了WindowChromeWindow的属性,如果你使用它,白色的“调整边框”就会消失,但你需要定义一些属性才能正常工作。

CaptionHeight:This is the height of the caption area (headerbar) that allows for the Aero snap, double clicking behaviour as a normal title bar does. Set this to 0 (zero) to make the buttons work.

CaptionHeight:这是标题区域(标题栏)的高度,它允许 Aero 捕捉、双击行为,就像普通标题栏一样。将此设置为 0(零)以使按钮工作。

ResizeBorderThickness:This is thickness at the edge of the window which is where you can resize the window. I put to 5 because i like that number, and because if you put zero its difficult to resize the window.

ResizeBorderThickness:这是窗口边缘的厚度,您可以在此处调整窗口大小。我设置为 5 是因为我喜欢这个数字,并且因为如果设置为零,则很难调整窗口大小。

After using this short code the result is this:

使用这个短代码后,结果是这样的:

The Solution

解决方案

And now, the white border disappeared without using ResizeMode="NoResize"and AllowsTransparency="True", also it shows a shadow in the window.

现在,白色边框没有使用ResizeMode="NoResize"和 就消失了AllowsTransparency="True",并且在窗口中显示了一个阴影。

Later I will explain how to make to work the buttons (I didn't used images for the buttons) easily with simple and short code, Im new and i think that I can post to codeproject, because here I didn't find the place to post the tutorial.

稍后我将解释如何使用简单而简短的代码轻松地使用按钮(我没有使用按钮的图像),我是新手,我认为我可以发布到 codeproject,因为在这里我没有找到位置发布教程。

Maybe there is another solution (I know that there are hard and difficult solutions for noobs like me) but this works for my personal projects.

也许还有另一种解决方案(我知道像我这样的菜鸟有困难和困难的解决方案)但这适用于我的个人项目。

Here is the complete code

这是完整的代码

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:Concursos"
    mc:Ignorable="d"
    Title="Concuros" Height="350" Width="525"
    WindowStyle="None"
    WindowState="Normal" 
    ResizeMode="CanResize"
    >
<WindowChrome.WindowChrome>
    <WindowChrome 
        CaptionHeight="0"
        ResizeBorderThickness="5" />
</WindowChrome.WindowChrome>

    <Grid>

    <Rectangle Fill="#D53736" HorizontalAlignment="Stretch" Height="35" VerticalAlignment="Top" PreviewMouseDown="Rectangle_PreviewMouseDown" />
    <Button x:Name="Btnclose" Content="r" HorizontalAlignment="Right" VerticalAlignment="Top" Width="35" Height="35" Style="{StaticResource TempBTNclose}"/>
    <Button x:Name="Btnmax" Content="2" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,0,35,0" Width="35" Height="35" Style="{StaticResource TempBTNclose}"/>
    <Button x:Name="Btnmin" Content="0" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,0,70,0" Width="35" Height="35" Style="{StaticResource TempBTNclose}"/>

</Grid>

Thank you!

谢谢!

回答by Wobbles

While the accepted answer is very true, just want to point out that AllowTransparency has some downfalls. It does not allow child window controls to show up, ie WebBrowser, and it usually forces software rendering which can have negative performance effects.

虽然公认的答案是正确的,但我只想指出 AllowTransparency 有一些缺点。它不允许显示子窗口控件,即 WebBrowser,并且它通常会强制软件渲染,这会对性能产生负面影响。

There is a better work around though.

不过有一个更好的解决方法。

When you want to create a window with no border that is resizeable and is able to host a WebBrowser control or a Frame control pointed to a URL you simply couldn't, the contents of said control would show empty.

如果您想创建一个无边框、可调整大小并且能够承载 WebBrowser 控件或指向您根本无法创建的 URL 的 Frame 控件的窗口,则该控件的内容将显示为空。

I found a workaround though; in the Window, if you set the WindowStyle to None, ResizeMode to NoResize (bear with me, you will still be able to resize once done) then make sure you have UNCHECKED AllowsTransparency you will have a static sized window with no border and will show the browser control.

不过,我找到了一种解决方法;在窗口中,如果您将 WindowStyle 设置为 None,将 ResizeMode 设置为 NoResize(请耐心等待,完成后您仍然可以调整大小)然后确保您已取消选中 AllowsTransparency 您将拥有一个没有边框的静态大小窗口,并将显示浏览器控件。

Now, you probably still want to be able to resize right? Well we can to that with a interop call:

现在,您可能仍然希望能够调整大小,对吗?好吧,我们可以通过互操作调用来实现:

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

    [DllImportAttribute("user32.dll")]
    public static extern bool ReleaseCapture();

    //Attach this to the MouseDown event of your drag control to move the window in place of the title bar
    private void WindowDrag(object sender, MouseButtonEventArgs e) // MouseDown
    {
        ReleaseCapture();
        SendMessage(new WindowInteropHelper(this).Handle,
            0xA1, (IntPtr)0x2, (IntPtr)0);
    }

    //Attach this to the PreviewMousLeftButtonDown event of the grip control in the lower right corner of the form to resize the window
    private void WindowResize(object sender, MouseButtonEventArgs e) //PreviewMousLeftButtonDown
    {
        HwndSource hwndSource = PresentationSource.FromVisual((Visual)sender) as HwndSource;
        SendMessage(hwndSource.Handle, 0x112, (IntPtr)61448, IntPtr.Zero);
    }

And voila, A WPF window with no border and still movable and resizable without losing compatibility with with controls like WebBrowser

瞧,一个没有边框的 WPF 窗口,仍然可以移动和调整大小,而不会失去与 WebBrowser 等控件的兼容性

回答by Kebes

Sample here:

样品在这里:

<Style TargetType="Window" x:Key="DialogWindow">
        <Setter Property="AllowsTransparency" Value="True"/>
        <Setter Property="WindowStyle" Value="None"/>
        <Setter Property="ResizeMode" Value="CanResizeWithGrip"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Window}">
                    <Border BorderBrush="Black" BorderThickness="3" CornerRadius="10" Height="{TemplateBinding Height}"
                            Width="{TemplateBinding Width}" Background="Gray">
                        <DockPanel>
                            <Grid DockPanel.Dock="Top">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition></ColumnDefinition>
                                    <ColumnDefinition Width="50"/>
                                </Grid.ColumnDefinitions>
                                <Label Height="35" Grid.ColumnSpan="2"
                                       x:Name="PART_WindowHeader"                                            
                                       HorizontalAlignment="Stretch" 
                                       VerticalAlignment="Stretch"/>
                                <Button Width="15" Height="15" Content="x" Grid.Column="1" x:Name="PART_CloseButton"/>
                            </Grid>
                            <Border HorizontalAlignment="Stretch" VerticalAlignment="Stretch" 
                                        Background="LightBlue" CornerRadius="0,0,10,10" 
                                        Grid.ColumnSpan="2"
                                        Grid.RowSpan="2">
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition/>
                                        <ColumnDefinition Width="20"/>
                                    </Grid.ColumnDefinitions>
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="*"/>
                                        <RowDefinition Height="20"></RowDefinition>
                                    </Grid.RowDefinitions>
                                    <ResizeGrip Width="10" Height="10" Grid.Column="1" VerticalAlignment="Bottom" Grid.Row="1"/>
                                </Grid>
                            </Border>
                        </DockPanel>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

回答by Mike Ward

I was having difficulty getting the answer by @fernando-aguirre using WindowChrometo work. It was not working in my case because I was overriding OnSourceInitializedin the MainWindowand not calling the base class method.

我在工作时遇到了@fernando-aguirre 的WindowChrome问题。它在我的情况下不起作用,因为我覆盖OnSourceInitializedMainWindow而不是调用基类方法。

protected override void OnSourceInitialized(EventArgs e)
{
    ViewModel.Initialize(this);
    base.OnSourceInitialized(e); // <== Need to call this!
}

This stumped me for a very long time.

这让我难住了很长时间。