Як створити вікно WPF без межі, розмір якої можна змінити лише за допомогою ручки?


94

Якщо ви встановите ResizeMode="CanResizeWithGrip"WPF, Windowтоді в нижньому правому куті відображається ручка зміни розміру, як показано нижче:

Якщо встановити WindowStyle="None"також рядок заголовка, зникає, але сірий скошений край залишається, доки ви не встановите ResizeMode="NoResize". На жаль, за допомогою такої комбінації властивостей ручка зміни розміру також зникає.

Я заміняю Window«S з ControlTemplateдопомогою звичаю Style. Я хочу вказати межу вікна сам, і мені не потрібні користувачі, щоб мати змогу змінювати розмір вікна з усіх чотирьох сторін, але мені потрібна ручка зміни розміру.

Чи може хтось докладно описати простий спосіб задоволення всіх цих критеріїв?

  1. Не майте межі, Windowкрім тієї, яку я вказав у а ControlTemplate.
  2. Є чи у робочої зміни розміру захоплення в нижньому правому куті.
  3. Не мають рядка заголовка.

3
Зверніть увагу, що Allowtransperency створює витік пам'яті. Тому уникайте його використання. Будь ласка, зверніться до social.msdn.microsoft.com/Forums/en/wpf/thread/…
Діпеш Бхатт

1
@DipeshBhatt Я не міг знайти пояснення цього твердження у наданому вами посиланні. можливо, ви мали намір розмістити посилання social.msdn.microsoft.com/Forums/vstudio/en-US/…
іто

Я звернувся до сірого краю вгорі, хоча для стилю вікна встановив значення Нічого. ResizeMode = "NoResize" вирішив мою проблему.
Сурендра Шрестха,

Відповіді:


180

Якщо ви встановите AllowsTransparencyвластивість на Window(навіть без встановлення будь-яких значень прозорості), межа зникає, і ви можете змінити розмір лише за допомогою ручки.

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

Результат виглядає так:


Чистий випад, я це знав - сьогодні вдень я грав із тим самим контролем. :)
ZombieSheep 04.03.09

2
Ого, я б цього не очікував, але це цілком зручно для того, щоб зробити свої власні публікації за 5 хвилин, дякую :)
Томаш Кафка,

4
AllowTransparency має кілька падінь, однак, Windows більше не може розміщувати елементи керування підвікном, такими як WebBrowser, Зазвичай примушує візуалізацію програмного забезпечення, повідомляє про витоки пам'яті. Дивіться моє обхідне рішення нижче.
Хитається

Вам потрібно лише WindowStyle = "None", щоб позбутися меж; Служба AllowsTransparency вимагає лише цього, але не впливає на кордони ..
Граулт

2
@Grault позбавляється заголовка вікна, але навколо форми все ще залишається суцільна межа. AllowsTransparency позбавляється кордонів.
Хитається

79

Я намагався створити вікно без полів, WindowStyle="None"але коли я його протестував, здається, що у верхній частині з'являється біла смужка, після деяких досліджень це, здається, "Змінити розмір межі", ось зображення (я зазначив жовтим):

Змагання

Після деяких досліджень в Інтернеті та безлічі складних рішень, не пов’язаних з xaml, всі знайдені рішення були кодом позаду в C # та безліч рядків коду, і я знайшов непряме рішення тут: Максимальне власне вікно втрачає ефект тіні

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

Примітка : Вам потрібно використовувати .NET 4.5 framework, або якщо ви використовуєте стару версію, використовуйте WPFShell, просто посилайтеся на оболонку та використовуйте Shell:WindowChrome.WindowChromeзамість неї.

Я використовував WindowChromeвластивість Window, якщо ви використовуєте це, білий колір "зміна розміру" зникає, але вам потрібно визначити деякі властивості, щоб працювати коректно.

CaptionHeight: Це висота області підписів (заголовка), яка дозволяє здійснювати прив'язку Aero, подвійне клацання, як це робить звичайний рядок заголовка. Встановіть значення 0 (нуль), щоб кнопки працювали.

ResizeBorderThickness: Це товщина по краю вікна, де можна змінити розмір вікна. Я поставив 5, тому що мені подобається це число, і тому, що якщо ви ставите нуль, важко змінити розмір вікна.

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

Рішення

І ось, біла рамка зникла без використання, ResizeMode="NoResize"а AllowsTransparency="True"також вона показує тінь у вікні.

Пізніше я поясню, як змусити роботу кнопок (я не використовував зображення для кнопок) легко за допомогою простого та короткого коду. опублікувати підручник.

Можливо, є інше рішення (я знаю, що існують важкі та складні рішення для таких нобів, як я), але це працює для моїх особистих проектів.

Ось повний код

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

Дякую!


3
Ну, слава цьому! Це, безумовно, найпростіша відповідь цієї теми! Має набирати значно більше голосів. Я повинен визнати, що я був якось септичний щодо цього, особливо щодо того, що відбувалося під капотом. Я навіть перевірив дерево WFP, і, схоже, прозорість не додається назад. Навіть складні елементи управління, такі як "WebBrowser", чудово відображаються. У мене виникла проблема із заморожуванням візуалізації з використанням прозорості, коли додаток зазнавав сильного стресу ... Ну, цього не відбувається з цим рішенням. Я думаю, що настав час вийти з рішення @Wobbles!
VeV

1
Схоже, це все одно може потребувати взаємодії для перетягування вікон, якщо я Rectangle_PreviewMouseDownправильно інтерпретую використання події.
Хитається

Це може не спрацювати в <= Win 8.1, у моїй віртуальній машині спостерігалися деякі дивні результати. Основною проблемою є Windows 7 і 8, оскільки вони роблять дурну справу Aero border.
Хитається

Дякуємо за відповідь
Фернандо Агірре

Привіт, @FernandoAguirre, я розмістив відповідне запитання і був би вдячний, якщо у вас є відповідь.
sampathsris

40

Хоча прийнята відповідь є дуже правдивою, просто хочу зазначити, що AllowTransparency має деякі падіння. Він не дозволяє відображати дочірні елементи керування вікном, тобто WebBrowser, і, як правило, змушує візуалізацію програмного забезпечення, що може мати негативні ефекти продуктивності.

Однак є краща робота.

Коли ви хочете створити вікно без кордону, розмір якого можна змінити, і він може розмістити елемент керування WebBrowser або елемент керування Frame, який вказує на URL-адресу, яку ви просто не змогли, вміст згаданого елемента керування відображатиметься порожнім.

Хоча я знайшов обхідний шлях; у вікні, якщо ви встановите для WindowStyle значення None, ResizeMode - NoResize (потерпіть зі мною, ви все одно зможете змінити розмір після завершення), тоді переконайтеся, що у вас є UNCHECKED AllowsTransparency, у вас буде вікно статичного розміру без меж і буде відображатися управління браузером.

Тепер ви, мабуть, все ще хочете мати можливість змінити розмір, чи не так? Ну, ми можемо до цього за допомогою виклику взаємодії:

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

І вуаля, вікно WPF без меж, все ще рухоме та змінне розмір, не втрачаючи сумісності з такими елементами керування, як WebBrowser


Як нам діяти, якщо ми хочемо змінити розмір з усіх боків, а не лише знизу праворуч, але все ж хочемо, щоб не було видимо кордону?
Даніель

6
Ось інші значення wParam, просто призначте нові події новим об'єктам інтерфейсу, використовуючи їх за потребоюprivate enum ResizeDirection { Left = 61441, Right = 61442, Top = 61443, TopLeft = 61444, TopRight = 61445, Bottom = 61446, BottomLeft = 61447, BottomRight = 61448, }
Wobbles 24.03.15

Це чудово працює для мене, за одним винятком, хоча після того, як у вас є NoResize, ви більше не можете застібати вікно, перетягуючи його вгору.
CJK

2
@CJK Правда, але без сумніву, ви також можете підключити повідомлення Windows для цього і впоратися з цим.
Хитається

Я не можу перетягнути вікно. будь-яка ідея чому? (зміна розміру працює як шарм)
Li3ro

5

Зразок тут:

<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
Ви повинні включити коротке пояснення того, як працює код.
M456

0

Мені було важко отримати відповідь @ fernando-aguirre, використовуючи WindowChromeдля роботи. Це не працює в моєму випадку , тому що я був перевизначення OnSourceInitializedв MainWindowі не викликати метод базового класу.

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

Це мене дуже довго тупило.

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