Làm thế nào để tạo một Cửa sổ WPF không có đường viền mà chỉ có thể thay đổi kích thước thông qua một tay cầm?


94

Nếu bạn đặt ResizeMode="CanResizeWithGrip"trên WPF Windowthì phần kẹp thay đổi kích thước được hiển thị ở góc dưới bên phải, như bên dưới:

Nếu bạn đặt WindowStyle="None"cũng như vậy, thanh tiêu đề sẽ biến mất nhưng cạnh vát màu xám vẫn còn cho đến khi bạn đặt ResizeMode="NoResize". Thật không may, với sự kết hợp của các thuộc tính được thiết lập, tay cầm thay đổi kích thước cũng biến mất.

Tôi đã ghi đè của Window's ControlTemplatethông qua một tùy chỉnh Style. Tôi muốn tự chỉ định đường viền của cửa sổ và tôi không cần người dùng có thể thay đổi kích thước cửa sổ từ cả bốn phía, nhưng tôi cần một tay nắm thay đổi kích thước.

Ai đó có thể nêu chi tiết một cách đơn giản để đáp ứng tất cả các tiêu chí này?

  1. Không có đường viền Windowngoài đường viền mà tôi tự chỉ định trong a ControlTemplate.
  2. Đừng có một va li thay đổi kích thước làm việc ở góc dưới bên phải.
  3. Không có thanh tiêu đề.

3
Xin lưu ý rằng Allowtransperency tạo rò rỉ bộ nhớ. Vì vậy, hãy tránh sử dụng nó. Vui lòng tham khảo social.msdn.microsoft.com/Forums/en/wpf/thread/…
Dipesh Bhatt

1
@DipeshBhatt Tôi không thể tìm thấy bất kỳ lời giải thích nào cho khiếu nại đó trong liên kết bạn cung cấp. có thể bạn muốn đăng liên kết social.msdn.microsoft.com/Forums/vstudio/en-US/…
itho

Tôi đang đối mặt với cạnh màu xám ở trên cùng mặc dù tôi đã đặt kiểu cửa sổ thành Không có. ResizeMode = "NoResize" đã giải quyết được vấn đề của tôi.
Surendra Shrestha

Câu trả lời:


180

Nếu bạn đặt thuộc AllowsTransparencytính trên Window(ngay cả khi không đặt bất kỳ giá trị độ trong suốt nào) thì đường viền sẽ biến mất và bạn chỉ có thể thay đổi kích thước thông qua báng cầm.

<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>

Kết quả giống như sau:


Tôi biết điều này - tôi đã chơi với điều khiển tương tự do tôi tự thiết lập vào chiều nay. :)
ZombieSheep

2
Wow, tôi sẽ không mong đợi điều này, nhưng nó là hoàn toàn có ích cho make-bạn-của-post-it-nốt-trong-5-phút, nhờ :)
Tomáš Kafka

4
Tuy nhiên, AllowTransparency có một số lỗi, Windows không thể lưu trữ các điều khiển cửa sổ phụ như WebBrowser, Thường buộc kết xuất phần mềm, đã báo cáo rò rỉ bộ nhớ. Xem cách giải quyết của tôi bên dưới.
Wobbles

Bạn chỉ cần WindowStyle = "None" để loại bỏ các đường viền; AllowsTransparency chỉ xảy ra khi yêu cầu nó, nhưng không ảnh hưởng đến biên giới ..
Grault

2
@Grault đã loại bỏ tiêu đề cửa sổ, nhưng vẫn có một đường viền chắc chắn xung quanh biểu mẫu. AllowsTransparency loại bỏ các đường viền.
Wobbles

78

Tôi đã cố gắng tạo một cửa sổ không có đường viền WindowStyle="None"nhưng khi tôi kiểm tra nó, có vẻ như xuất hiện một thanh màu trắng ở trên cùng, sau một số nghiên cứu, nó có vẻ là "Đường viền thay đổi kích thước", đây là một hình ảnh (tôi nhận xét là màu vàng):

Các thách thức

Sau một số nghiên cứu trên internet và rất nhiều giải pháp không phải xaml khó khăn, tất cả các giải pháp mà tôi tìm thấy đều nằm sau mã trong C # và rất nhiều dòng mã, tôi đã gián tiếp tìm thấy giải pháp ở đây: Cửa sổ tùy chỉnh tối đa làm mất hiệu ứng bóng đổ

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

Lưu ý : Bạn cần sử dụng .NET 4.5 framework hoặc nếu bạn đang sử dụng phiên bản cũ hơn, hãy sử dụng WPFShell, chỉ cần tham chiếu shell và sử dụng Shell:WindowChrome.WindowChromethay thế.

Tôi đã sử dụng thuộc WindowChrometính của Window, nếu bạn sử dụng điều này, "đường viền thay đổi kích thước" màu trắng sẽ biến mất, nhưng bạn cần xác định một số thuộc tính để hoạt động chính xác.

CaptionHeight: Đây là chiều cao của vùng phụ đề (thanh tiêu đề) cho phép thực hiện hành vi nhấp đúp vào Aero snap như thanh tiêu đề bình thường. Đặt giá trị này thành 0 (không) để các nút hoạt động.

ResizeBorderThickness: Đây là độ dày ở cạnh cửa sổ, nơi bạn có thể thay đổi kích thước cửa sổ. Tôi đặt thành 5 vì tôi thích con số đó, và bởi vì nếu bạn đặt số 0 thì rất khó để thay đổi kích thước cửa sổ.

Sau khi sử dụng đoạn mã ngắn này, kết quả là:

Giải pháp

Và bây giờ, đường viền màu trắng đã biến mất mà không cần sử dụng ResizeMode="NoResize"AllowsTransparency="True"nó cũng hiển thị một cái bóng trong cửa sổ.

Sau đó, tôi sẽ giải thích cách làm cho các nút hoạt động (tôi không sử dụng hình ảnh cho các nút) một cách dễ dàng với mã đơn giản và ngắn, Tôi là người mới và tôi nghĩ rằng tôi có thể đăng lên codeproject, vì ở đây tôi không tìm thấy nơi để đăng hướng dẫn.

Có thể có một giải pháp khác (tôi biết rằng có những giải pháp khó và khó cho những người như tôi) nhưng điều này phù hợp với các dự án cá nhân của tôi.

Đây là mã hoàn chỉnh

<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>

Cảm ơn bạn!


3
Chà, Kudos cho cái này! Đây là câu trả lời đơn giản nhất / không có giao dịch nào của chủ đề này! Sẽ nhận được nhiều phiếu 'lên' hơn. Tôi phải thừa nhận rằng tôi đã rất tự mãn về nó, đặc biệt là về những gì đang xảy ra dưới mui xe. Tôi thậm chí đã kiểm tra cây WFP và có vẻ như độ trong suốt không được thêm lại. Ngay cả các điều khiển phức tạp như màn hình 'WebBrowser' cũng tốt. Tôi đã gặp sự cố đóng băng hiển thị bằng cách sử dụng tính trong suốt khi ứng dụng đang gặp nhiều căng thẳng ... Chà, điều này không xảy ra với giải pháp này. Tôi nghĩ có lẽ đã đến lúc giải pháp @Wobbles ngừng hoạt động!
VeV

1
Có vẻ như điều này có thể vẫn cần tương tác để kéo cửa sổ nếu tôi diễn giải việc sử dụng Rectangle_PreviewMouseDownsự kiện đúng cách.
Wobbles

Điều này có thể không hoạt động trong <= Win 8.1, đã thấy một số kết quả kỳ lạ trong máy ảo của tôi. Windows 7 và 8 là những mối quan tâm hàng đầu khi chúng thực hiện điều ngu ngốc viền Aero.
Wobbles

Cảm ơn bạn đã trả lời của bạn
Fernando Aguirre

Xin chào @FernandoAguirre, tôi đã đăng câu hỏi liên quan này và rất biết ơn nếu bạn có câu trả lời.
sampathsris

39

Mặc dù câu trả lời được chấp nhận là rất đúng, nhưng tôi chỉ muốn chỉ ra rằng AllowTransparency có một số điểm yếu. Nó không cho phép các điều khiển cửa sổ con hiển thị, tức là WebBrowser, và nó thường buộc hiển thị phần mềm có thể có tác động tiêu cực đến hiệu suất.

Có một công việc tốt hơn xung quanh mặc dù.

Khi bạn muốn tạo một cửa sổ không có đường viền có thể thay đổi kích thước và có thể lưu trữ điều khiển WebBrowser hoặc điều khiển Khung chỉ đến một URL mà bạn chỉ đơn giản là không thể, nội dung của điều khiển nói trên sẽ hiển thị trống.

Tôi đã tìm thấy một giải pháp thay thế mặc dù; trong Window, nếu bạn đặt WindowStyle thành None, ResizeMode thành NoResize (xin lưu ý với tôi, bạn vẫn có thể thay đổi kích thước sau khi hoàn thành) thì hãy đảm bảo rằng bạn đã UNCHECKED AllowsTransparency, bạn sẽ có một cửa sổ có kích thước tĩnh không có đường viền và sẽ hiển thị kiểm soát trình duyệt.

Bây giờ, bạn có thể vẫn muốn có thể thay đổi kích thước phải không? Chúng ta có thể làm điều đó với một cuộc gọi tương tác:

    [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);
    }

Và thì đấy, một cửa sổ WPF không có đường viền và vẫn có thể di chuyển và thay đổi kích thước mà không mất khả năng tương thích với các điều khiển như WebBrowser


Chúng ta nên làm như thế nào nếu chúng ta muốn thay đổi kích thước từ tất cả các bên, không chỉ dưới cùng bên phải, nhưng vẫn muốn không có đường viền hiển thị?
Daniel

6
Dưới đây là các giá trị wParam khác, chỉ cần assign sự kiện mới để các đối tượng giao diện người dùng mới sử dụng những khi cần thiếtprivate enum ResizeDirection { Left = 61441, Right = 61442, Top = 61443, TopLeft = 61444, TopRight = 61445, Bottom = 61446, BottomLeft = 61447, BottomRight = 61448, }
rung động

Điều này hoạt động tuyệt vời đối với tôi, với một ngoại lệ, mặc dù khi bạn có NoResize, bạn không thể chụp cửa sổ bằng cách kéo nó lên trên cùng nữa.
CJK

2
@CJK Đúng, nhưng chắc chắn bạn cũng có thể kết nối các thông báo windows cho điều đó và xử lý nó.
Wobbles

Tôi không thể kéo cửa sổ. bất kỳ ý tưởng tại sao? (thay đổi kích thước hoạt động giống như một nét duyên dáng)
Li3ro

5

Mẫu ở đây:

<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>

23
Bạn nên bao gồm một giải thích ngắn gọn về cách mã hoạt động.
M456

0

Tôi gặp khó khăn trong việc tìm câu trả lời bằng cách sử dụng @ fernando-aguirre WindowChromeđể làm việc. Nó không được làm việc trong trường hợp của tôi bởi vì tôi đã trọng OnSourceInitializedtrong MainWindowvà không gọi phương thức lớp cơ sở.

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

Điều này đã làm tôi bối rối trong một thời gian rất dài.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.