จะสร้างหน้าต่าง WPF โดยไม่มีขอบที่สามารถปรับขนาดได้ผ่านกริปเท่านั้นได้อย่างไร?


95

หากคุณตั้งค่าResizeMode="CanResizeWithGrip"บน WPF Windowกริปปรับขนาดจะแสดงที่มุมขวาล่างดังต่อไปนี้:

ถ้าคุณตั้งค่าWindowStyle="None"เช่นเดียวกับแถบชื่อเรื่องจะหายไป แต่ยังคงสีเทาขอบ bevelled ResizeMode="NoResize"จนกว่าคุณชุด น่าเสียดายที่ชุดคุณสมบัตินี้รวมกันกริปปรับขนาดก็หายไปเช่นกัน

ฉันได้แทนที่Window's ผ่านทางที่กำหนดเองControlTemplate Styleฉันต้องการระบุเส้นขอบของหน้าต่างด้วยตัวเองและฉันไม่ต้องการให้ผู้ใช้สามารถปรับขนาดหน้าต่างได้จากทั้งสี่ด้าน แต่ฉันต้องการกริปปรับขนาด

มีใครสามารถให้รายละเอียดวิธีง่ายๆในการปฏิบัติตามเกณฑ์เหล่านี้ได้หรือไม่

  1. ห้ามมีเส้นขอบที่Windowนอกเหนือจากที่ฉันระบุในไฟล์ControlTemplate.
  2. อย่ามีด้ามจับปรับขนาดการทำงานในที่มุมขวาล่าง
  3. ห้ามมีแถบชื่อเรื่อง

3
โปรดทราบว่า Allowtransperency ทำให้หน่วยความจำรั่วไหล ดังนั้นหลีกเลี่ยงการใช้มัน โปรดดูที่social.msdn.microsoft.com/Forums/en/wpf/thread/…
Dipesh Bhatt

1
@DipeshBhatt ฉันไม่พบคำอธิบายใด ๆ เกี่ยวกับการอ้างสิทธิ์นั้นในลิงก์ที่คุณให้มา บางทีคุณอาจจะหมายถึงการเชื่อมโยงการโพสต์social.msdn.microsoft.com/Forums/vstudio/en-US/...
itsho

ฉันหันหน้าไปทางขอบสีเทาที่ด้านบนแม้ว่าฉันจะตั้งค่ารูปแบบหน้าต่างเป็นไม่มี ResizeMode = "NoResize" แก้ปัญหาของฉันได้
Surendra Shrestha

คำตอบ:


186

หากคุณตั้งค่า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

2
ว้าวฉันไม่คาดหวังสิ่งนี้ แต่มันมีประโยชน์มากสำหรับการทำโพสต์อิทโน้ตใน 5 นาทีของคุณเองขอบคุณ :)
Tomáš Kafka

4
AllowTransparency มีข้อผิดพลาดหลายประการ แต่ Windows ไม่สามารถโฮสต์การควบคุมหน้าต่างย่อยได้อีกต่อไปเช่นเว็บเบราว์เซอร์ซึ่งโดยปกติจะบังคับให้แสดงซอฟต์แวร์ได้รายงานการรั่วไหลของหน่วยความจำ ดูวิธีแก้ปัญหาของฉันด้านล่าง
Wobbles

คุณต้องการเพียง WindowStyle = "None" เพื่อกำจัดเส้นขอบ AllowsTransparency จะเกิดขึ้นจะต้อง แต่ไม่ได้ส่งผลกระทบต่อพรมแดน ..
Grault

2
@Grault ที่กำจัดส่วนหัวของหน้าต่าง แต่ยังมีเส้นขอบทึบรอบแบบฟอร์ม AllowsTransparency กำจัดเส้นขอบ
Wobbles

81

ฉันพยายามสร้างหน้าต่างไร้ขอบด้วย 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 snap พฤติกรรมการคลิกสองครั้งเหมือนแถบชื่อเรื่องปกติ ตั้งค่านี้เป็น 0 (ศูนย์) เพื่อให้ปุ่มทำงาน

ResizeBorderThickness:นี่คือความหนาที่ขอบหน้าต่างซึ่งเป็นที่ที่คุณสามารถปรับขนาดหน้าต่างได้ ฉันใส่เป็น 5 เพราะฉันชอบตัวเลขนั้นและเพราะถ้าคุณใส่ศูนย์มันจะยากที่จะปรับขนาดหน้าต่าง

หลังจากใช้รหัสย่อนี้ผลลัพธ์จะเป็นดังนี้:

การแก้ไขปัญหา

และตอนนี้ขอบสีขาวหายไปโดยไม่ต้องใช้งานResizeMode="NoResize"และAllowsTransparency="True"ยังแสดงเงาในหน้าต่าง

ต่อมาฉันจะอธิบายวิธีทำให้ปุ่มทำงาน (ฉันไม่ได้ใช้รูปภาพสำหรับปุ่ม) อย่างง่ายดายด้วยรหัสง่ายๆและสั้นฉันใหม่และฉันคิดว่าฉันสามารถโพสต์ลงใน codeproject ได้เพราะที่นี่ฉันไม่พบสถานที่ เพื่อโพสต์บทแนะนำ

อาจมีวิธีแก้ปัญหาอื่น (ฉันรู้ว่ามีวิธีแก้ปัญหาที่ยากและยากสำหรับ noobs เช่นฉัน) แต่วิธีนี้ใช้ได้กับโครงการส่วนตัว

นี่คือรหัสที่สมบูรณ์

<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 ด้วยซ้ำและดูเหมือนว่าจะไม่มีการเพิ่มความโปร่งใสกลับเข้าไป แม้แต่การควบคุมที่ยุ่งยากเช่นการแสดงผล "เว็บเบราว์เซอร์" ก็ทำได้ดี ฉันมีปัญหาในการแสดงผลการแช่แข็งโดยใช้ความโปร่งใสเมื่อแอปอยู่ภายใต้ความเครียดมาก ... สิ่งนี้ไม่ได้เกิดขึ้นกับโซลูชันนี้ ฉันคิดว่าอาจถึงเวลาที่ต้องเลิกใช้โซลูชัน @Wobbles!
VeV

1
ดูเหมือนว่าสิ่งนี้อาจต้องใช้การทำงานร่วมกันสำหรับการลากหน้าต่างถ้าฉันตีความการใช้Rectangle_PreviewMouseDownเหตุการณ์อย่างถูกต้อง
Wobbles

สิ่งนี้อาจใช้ไม่ได้ใน <= Win 8.1 เห็นผลลัพธ์แปลก ๆ ใน VM ของฉัน Windows 7 และ 8 เป็นปัญหาหลักในการทำสิ่งที่ไร้พรมแดน Aero
Wobbles

ขอบคุณสำหรับการตอบกลับของคุณ
Fernando Aguirre

สวัสดี @FernandoAguirre ฉันโพสต์คำถามที่เกี่ยวข้องนี้และจะขอบคุณหากคุณมีคำตอบ
sampathsris

40

แม้ว่าคำตอบที่ได้รับการยอมรับจะเป็นความจริง แต่เพียงต้องการชี้ให้เห็นว่า AllowTransparency มีข้อผิดพลาดบางประการ ไม่อนุญาตให้แสดงตัวควบคุมหน้าต่างลูกเช่นเว็บเบราว์เซอร์และโดยปกติจะบังคับให้แสดงซอฟต์แวร์ซึ่งอาจมีผลกระทบด้านประสิทธิภาพเชิงลบ

มีวิธีแก้ไขที่ดีกว่าแม้ว่า

เมื่อคุณต้องการสร้างหน้าต่างที่ไม่มีเส้นขอบที่สามารถปรับขนาดได้และสามารถโฮสต์การควบคุมเว็บเบราว์เซอร์หรือการควบคุมเฟรมที่ชี้ไปยัง 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);
    }

และ voila หน้าต่าง WPF ที่ไม่มีขอบและยังเคลื่อนย้ายได้และปรับขนาดได้โดยไม่สูญเสียความเข้ากันได้กับการควบคุมเช่น WebBrowser


เราจะทำอย่างไรถ้าเราต้องการปรับขนาดจากทุกด้านไม่ใช่แค่ด้านล่างขวา แต่ยังไม่ต้องการให้เห็นเส้นขอบ?
Daniel

6
นี่คือค่า wParam อื่น ๆ เพียงกำหนดเหตุการณ์ใหม่ให้กับ UI Objects ใหม่โดยใช้สิ่งเหล่านี้ตามต้องการprivate enum ResizeDirection { Left = 61441, Right = 61442, Top = 61443, TopLeft = 61444, TopRight = 61445, Bottom = 61446, BottomLeft = 61447, BottomRight = 61448, }
Wobbles

วิธีนี้ใช้งานได้ดีสำหรับฉันโดยมีข้อยกเว้นอย่างหนึ่งแม้ว่าเมื่อคุณมี NoResize แล้วคุณจะไม่สามารถสแน็ปหน้าต่างโดยลากไปที่ด้านบนได้อีกต่อไป
CJK

2
@CJK True แต่ไม่ต้องสงสัยเลยว่าคุณสามารถเชื่อมต่อข้อความ windows สำหรับสิ่งนั้นได้เช่นกันและจัดการได้
Wobbles

ฉันไม่สามารถลากหน้าต่างได้ ทำไม? (ปรับขนาดได้เหมือนมีเสน่ห์)
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>

24
คุณควรใส่คำอธิบายสั้น ๆ เกี่ยวกับวิธีการทำงานของโค้ด
M456

0

ฉันประสบปัญหาในการรับคำตอบโดย @ fernando-aguirre ใช้WindowChromeในการทำงาน มันก็ไม่ได้ทำงานในกรณีของฉันเพราะฉันเอาชนะOnSourceInitializedในMainWindowและไม่โทรหาวิธีการเรียนฐาน

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

สิ่งนี้ทำให้ฉันนิ่งงันเป็นเวลานานมาก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.