Yalnızca bir tutma yeri aracılığıyla yeniden boyutlandırılabilen kenarlıksız bir WPF Penceresi nasıl oluşturulur?


95

ResizeMode="CanResizeWithGrip"Bir WPF'yi ayarlarsanız , Windowsağ alt köşede aşağıdaki gibi bir yeniden boyutlandırma tutacağı gösterilir:

WindowStyle="None"Aynı şekilde ayarlarsanız , başlık çubuğu kaybolur ancak gri eğimli kenar siz ayarlayana kadar kalır ResizeMode="NoResize". Ne yazık ki, bu özellik kombinasyonu ile yeniden boyutlandırma tutuşu da ortadan kalkar.

Ben Window'leri ControlTemplatebir gelenek yoluyla geçersiz kıldım Style. Pencerenin kenarlığını kendim belirtmek istiyorum ve kullanıcıların pencereyi dört taraftan da yeniden boyutlandırmasına ihtiyacım yok, ancak yeniden boyutlandırma kavramasına ihtiyacım var.

Birisi tüm bu kriterleri karşılamanın basit bir yolunu ayrıntılandırabilir mi?

  1. Do bir sınıra sahip Windowayrı birinden Kendimi belirtin ControlTemplate.
  2. Do sağ alt köşesinde bir çalışma yeniden boyutlandırma kavrama sahip.
  3. Etmeyin bir başlık çubuğu.

3
Lütfen İzin Verme'nin bellek sızıntısı oluşturduğunu unutmayın. Bu yüzden kullanmaktan kaçının. Lütfen social.msdn.microsoft.com/Forums/en/wpf/thread/…
Dipesh Bhatt

1
@DipeshBhatt Sağladığınız bağlantıda bu iddia için herhangi bir açıklama bulamadım. belki sonrası bağlantı anlamına social.msdn.microsoft.com/Forums/vstudio/en-US/...
itsho

Pencere stilini Yok olarak ayarlamama rağmen üstteki gri kenara bakıyordum. ResizeMode = "NoResize" sorunumu çözdü.
Surendra Shrestha

Yanıtlar:


186

AllowsTransparencyÖzelliği üzerinde Window(herhangi bir şeffaflık değeri ayarlamadan bile) ayarlarsanız, kenarlık kaybolur ve yalnızca tutma yeri aracılığıyla yeniden boyutlandırabilirsiniz.

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

Sonuç şöyle görünür:


Saf şans bunu biliyordum - bu öğleden sonra kendimle aynı kontrol setiyle oynuyordum. :)
ZombieSheep

2
Vay canına, bunu beklemiyordum, ama 5 dakikada kendi notlarınızı-postalayarak-yapmak için tamamen kullanışlı, teşekkürler :)
Tomáš Kafka

4
AllowTransparency'nin birkaç dezavantajı vardır, Windows artık WebBrowser gibi alt pencere kontrollerini barındıramaz, Genellikle yazılım oluşturmaya zorlar, bellek sızıntıları bildirdi. Aşağıdaki çözümüme bakın.
Wobbles

Sınırlardan kurtulmak için yalnızca WindowStyle = "Hiçbiri" gerekir; AllowsTransparency yalnızca bunu gerektirir, ancak sınırları etkilemez ..
Grault

2
@Grault thats pencere başlığından kurtulur, ancak formun etrafında hala sağlam bir kenarlık vardır. AllowsTransparency, sınırları ortadan kaldırır.
Wobbles

81

İle kenarlıksız bir pencere oluşturmaya çalışıyordum, WindowStyle="None"ancak test ettiğimde, üstte beyaz bir çubuk görünüyor, bazı araştırmalardan sonra bir "Yeniden boyutlandırma sınırı" gibi görünüyor, işte bir resim (sarı ile belirtmiştim):

Meydan okuma

İnternet üzerinde biraz araştırma yaptıktan ve xaml dışı birçok zor çözümden sonra, bulduğum tüm çözümler C # kodunun arkasında ve çok sayıda kod satırıydı, burada dolaylı olarak çözümü buldum: Maksimum özel pencere gölge etkisini kaybeder

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

Not : .NET 4.5 çerçevesini kullanmanız veya daha eski bir sürüm kullanıyorsanız WPFShell kullanmanız yeterlidir, Shell:WindowChrome.WindowChromebunun yerine kabuğa bakın ve kullanın .

Ben WindowChromeWindow özelliğini kullandım , eğer bunu beyaz "yeniden boyutlandırma kenarlığı" kaybolursa kullanırsanız, ancak doğru çalışması için bazı özellikler tanımlamanız gerekir.

CaptionHeight: Bu, normal bir başlık çubuğunun yaptığı gibi Aero snap, çift tıklama davranışına izin veren başlık alanının (başlık çubuğu) yüksekliğidir. Düğmelerin çalışması için bunu 0 (sıfır) olarak ayarlayın.

ResizeBorderThickness: Bu, pencereyi yeniden boyutlandırabileceğiniz pencerenin kenarındaki kalınlıktır. 5 koyuyorum çünkü bu sayıyı seviyorum ve sıfır koyarsanız pencereyi yeniden boyutlandırmak zor.

Bu kısa kodu kullandıktan sonra sonuç şudur:

Çözüm

Ve şimdi, beyaz sınır kullanılmadan kayboldu ResizeMode="NoResize"veAllowsTransparency="True" ayrıca pencerede bir gölge gösteriyor.

Daha sonra basit ve kısa kodla düğmelerin nasıl çalıştırılacağını (düğmeler için resim kullanmadım) kolayca açıklayacağım, yeniyim ve kod projesine gönderebileceğimi düşünüyorum çünkü burada yeri bulamadım öğreticiyi göndermek için.

Belki başka bir çözüm daha vardır (benim gibi çaylaklar için zor ve zor çözümler olduğunu biliyorum) ama bu kişisel projelerim için işe yarıyor.

İşte tam kod

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

Teşekkür ederim!


3
Peki, bunun için Tebrikler! Bu, bu konudaki en basit / takas yok cevabıdır! Çok daha fazla 'yukarı' oy almalı. Bu konuda biraz septik olduğumu itiraf etmeliyim, özellikle de kaputun altında neler olduğu konusunda. WFP ağacını bile kontrol ettim ve şeffaflık geri eklenmemiş gibi görünüyor. "WebBrowser" ekranı gibi zorlu kontroller bile gayet iyi. Uygulama çok fazla stres altındayken şeffaflığı kullanırken bir donma sorunu yaşadım ... Bu, bu çözümde gerçekleşmiyor. Sanırım @Wobbles çözümünü emekli etme zamanı geldi!
VeV

1
Görünüşe göre, Rectangle_PreviewMouseDownolayın kullanımını doğru bir şekilde yorumluyorsam, pencere sürükleme için yine de birlikte çalışmaya ihtiyaç duyabilir .
Wobbles

Bu <= Win 8.1'de çalışmayabilir, sanal makinemde bazı garip sonuçlar gördü. Aptal Aero sınır işini yaptıkları için Windows 7 ve 8 birincil endişelerdir.
Wobbles

Cevabınız için teşekkür ederiz
Fernando Aguirre

Merhaba @FernandoAguirre, bu konuyla ilgili soruyu gönderdim ve bir cevabınız varsa minnettar olurum.
sampathsris

40

Kabul edilen cevap çok doğru olsa da, AllowTransparency'nin bazı olumsuzlukları olduğunu belirtmek isterim. Alt pencere denetimlerinin, yani Web Tarayıcısının görünmesine izin vermez ve genellikle olumsuz performans etkilerine sahip olabilecek yazılım oluşturmaya zorlar.

Yine de etrafta daha iyi bir çalışma var.

Yeniden boyutlandırılabilen ve bir WebBrowser denetimini veya basitçe yapamadığınız bir URL'ye işaret eden bir Çerçeve denetimini barındırabilen kenarlığı olmayan bir pencere oluşturmak istediğinizde, söz konusu denetimin içeriği boş görünecektir.

Yine de bir çözüm buldum; Pencerede, WindowStyle'ı None, ResizeMode'u NoResize olarak ayarlarsanız (benimle birlikte olun, yine de bittikten sonra yeniden boyutlandırabilirsiniz) ardından UNCHECKED AllowsTransparency'ye sahip olduğunuzdan emin olun, kenarlıksız statik boyutlu bir pencereye sahip olacaksınız ve tarayıcı kontrolü.

Şimdi, muhtemelen yine de yeniden boyutlandırabilmek istiyorsundur, değil mi? Bunu bir birlikte çalışmayla yapabiliriz:

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

Ve işte, kenarsız ve yine de hareketli ve WebBrowser gibi kontrollerle uyumluluğu kaybetmeden yeniden boyutlandırılabilen bir WPF penceresi


Her yönden yeniden boyutlandırmak istiyorsak, sadece sağ alttan değil, ama yine de hiçbir kenarlığın görünmemesini istiyorsak nasıl devam etmeliyiz?
Daniel

6
İşte diğer wParam değerleri, gerektiğinde bunları kullanarak yeni UI Nesnelerine yeni etkinlikler atayınprivate enum ResizeDirection { Left = 61441, Right = 61442, Top = 61443, TopLeft = 61444, TopRight = 61445, Bottom = 61446, BottomLeft = 61447, BottomRight = 61448, }
Wobbles

Bu benim için harika çalışıyor, bir istisna dışında, NoResize'ye sahip olduğunuzda artık pencereyi en üste sürükleyerek kenetleyemezsiniz.
CJK

2
@CJK Doğru, ancak şüphesiz bunun için Windows mesajlarını da bağlayabilir ve halledebilirsiniz.
Wobbles

Pencereyi sürükleyemiyorum. herhangi bir fikriniz neden? (yeniden boyutlandırma bir cazibe gibi çalışır)
Li3ro

5

Örnek burada:

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

24
Kodun nasıl çalıştığına dair kısa bir açıklama eklemelisiniz.
M456

0

@ Fernando-aguirre'ı WindowChromeçalışmak için kullanarak cevabı almakta güçlük çekiyordum . Ben baskın oldu çünkü benim durumumda çalışma değildi OnSourceInitializediçinde MainWindowve baz sınıf yöntemini çağırarak değil.

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

Bu beni çok uzun süre şaşırttı.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.