WPF_18_Window

Window类继承自 ContentControl 类,只能包含单个子元素,通常是一个布局。Window类的基本属性如下表:

属性名称 说明
AllowsTransparency 如果值为true,并且背景设置为透明色,允许其他窗口透过该窗口显示
Icon 窗口图标的 ImageSource 对象
Top Left 窗口左上角到屏幕顶部和左部之间的距离
ResizeMode 用户是否可以改变窗口的尺寸
RestoreBounds 获取窗口的边界,可表示位置和大小
ShowInTaskbar 值为true时,会在任务栏和 Alt+Tab 列表中显示窗口
SizeToContent 使用该属性创建自动放大自身尺寸的窗口
Title 标题
Topmost 总是显示在最前面
WindowStartupLocation 窗体放置的位置
WindowState 表示窗口是否被最大化,最小化或正常状态
WindowStyle 决定窗口的边框

客户区是窗口边界内部的表面,可放置自定义内容。非客户区包括边框和窗口顶部的标题栏,由操作系统管理。

显示窗口

ShowDialog() 方法显示模态窗口,通过锁住所有鼠标和键盘输入来阻止用户访问父窗口,直到模态窗口被关闭。另外,直到窗口关闭,ShowDialog()方法才返回,中间一直阻塞。

Show() 方法显示非模态窗口,不会阻止用户访问其他任何窗口。Close() 方法关闭窗口,Hide()方法隐藏窗口。

定位窗口

System.Windows.SystemParameters 类可以用来检索有关屏幕实际大小的基本信息。

// 将窗口定位到屏幕*,和设置窗口状态为 CenterScreen 的效果相同
double screeHeight = SystemParameters.FullPrimaryScreenHeight;
double screeWidth = SystemParameters.FullPrimaryScreenWidth;
this.Top = (screenHeight - this.Height) / 2;
this.Left = (screenWidth - this.Width) / 2;

// 将窗口定位到可用屏幕区域的*,不包括停靠任务栏的区域
double workHeight = SystemParameters.WorkArea.Height;
double workWidth = SystemParameters.WorkArea.Width;
this.Top = (workHeight - this.Height) / 2;
this.Left = (workWidth - this.Width) / 2;

窗口交互

Application 类提供了用于访问其他窗口的两个工具: MainWindowWindows 属性。

.Net允许一个窗口”拥有“其他窗口,当所有者最小化时被拥有者也自动最小化;当两者相互重叠时,被拥有者总显示在上面。

ToolWindow winTool = new ToolWindow();
winTool.Owner = this;
winTool.Show();

对话框模式可以给用户提供一些选择,代码等待选择结果然后执行相应的操作:

DialogWindow dialog = new DialogWindow();
if(dialog.ShowDialog() == true)
{
    // 用户选择了确认
}
else
{
    // 用户选择了取消
}

Windows操作系统提供了许多内置对话框,可通过Windows API访问这些对话框,WPF为其中几个对话框提供了封装程序。

  • System.Windows.MessageBox
  • PrintDialog
  • OpenFileDialog
  • SaveFileDialog

非矩形窗口

创建简单形状窗口需要以下几个步骤:

  • 将 Window.AllowsTransparency 属性设置为 true
  • 将 Window.WindowStyle 属性设置为 None.从而隐藏非客户区
  • 将窗口背景设置为透明

这样就移除窗口的标准外观,然后就需要提供了一些不透明的具有所需形状的内容:

  • 可以使用支持透明格式的文件提供背景插图
  • 可以使用WPF中的形状绘制功能创建具有矢量内容的背景
  • 可以使用简单的具有所需形状的WPF元素,比如Border
<Window WindowStyle="None" AllowsTransparency="True" Background="Transparent">
    <Window.Background>
        <ImageBrush ImageSource="squares.png"/>
    </Window.Background>
</Window>

去掉标题栏后,窗体就没办法随鼠标进行拖动,需要手动调用 Window.DragMove() 方法。

将 Window.ResizeMode 属性设置为 CanResizeWithGrip时,会在窗口的右下角添加图形手柄(grip).如果想通过拖动窗口边缘来改变窗口的尺寸就需要其他的工作:

  • 一种方法可以使用.NET的平台调用特性发送改变窗口尺寸的Win32消息
  • 一种方法当用户拖动一条侧边时,简单跟踪鼠标位置并设置窗口的Width属性

此时就需要探测用户何时会将鼠标移动到窗口边缘,然后改变鼠标形状。

<Rectangle VerticalAlignment="Stretch" HorizontalAlignment="Right"
    Cursor="SizeWE" Fill="Transparent"
    MouseLeftButtonDown="window_initiateWiden"
    MouseLeftButtonUp="window_endwiden"
    MouseMove="window_Widen"/>
bool isWiden = false;
private void window_initiateWidth(object sender, MouseEventArgs e)
{
    isWiden = true;
}
private void window_Widen(object sender, MouseEventArgs e)
{
    Rectangle rect = (Rectangle)sender;
    if (isWiden)
    {
        rect.CaptureMouse();
        double newWidth = e.GetPosition(this).X + 5;
        if (newWidth > 0) this.Width = newWidth;
    }
}
private void window_endWiden(object sender, MouseEventArgs e)
{
    isWiden = false;
    Rectangle rect = (Rectangle)sender;
    rect.ReleaseMouseCapture();
}

如果想把其他窗口都使用自定义窗口的话,可以使用控件模板。Widnow类的默认模板中包含 AdornerDecorator 元素,用于在窗口的其他客户内容之上创建一个特定的绘图区域,称之为装饰层。

<ControlTemplate x:Key="CustomWindowTemplate" TargetType="{x:Type Window}">
    <Border Name="windowFrame" ...>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <!--窗体的 Title-->
            <TextBlock Text="{TemplateBinding Title}" FontWeight="Bold"/>
            <Button Style="{StaticResource CloseButton}" HorizontalAlignment="Right"/>
            <!--窗体内容-->
            <Border Grid.Row="1">
                <AdornerDecorator>
                    <ContentPresenter/>
                </AdornerDecorator>
            </Border>
            <!--底部-->
            <ContentPresenter Grid.Row="2" Margin="10" HorizontalAlignment="Center"
                Content="{TemplateBinding Tag}"/>
            <!--改变大小-->
            <ResizeGrip Name="WindowResizeGrip" Grid.Row="2" HorizontalAlignment="Right"
                VerticalAlignment="Bottom" Visibility="Collapsed" IsTabStop="False"/>
            <!--拖拽缩放的侧边-->
            <Rectangle Grid.Row="1" Grid.RowSpan="3" Cursor="SizeWE"
                VerticalAlignment="Stretch" HorizontalAlignment="Right"
                Fill="Transparent" Width="5"/>
            <Rectangle Grid.Row="2" Cursor="SizeNS"
                VerticalAlignment="Bottom" HorizontalAlignment="Stretch"
                Fill="Transparent" Height="5"/>
        </Gird>
    </Border>

    <ControlTemplate.Triggers>
        <Trigger Property="ResizeMode" Value="CanResizeWithGrip">
            <Setter TargetName="WindowResizeGrip" Property="Visibility" Value="Visible"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

<Style x:Key="CustomWindowChrome" TargetType="{x:Type Window}">
    <Setter Property="AllowsTransparency" Value="True"/>
    <Setter Property="WindowStyle" Value="None"/>
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="Template" Value="{StaticResource CustomWidnowTemplate}"/>
</Style>

创建窗口,设置样式并填充一些基本内容:

<Window ...
    Title="CustomWindowTest"
    Style="{StaticResource CustomWindowChrome}">
    
    <StackPanel Margin="10">
        <TextBlock Margin="3">This is a test.</TextBlock>
    </StackPanel>
</Window>

我的公众号

WPF_18_Window

上一篇:System.Linq.Dynamic动态查询的使用


下一篇:【安安教具】-【数学】-【有理数计算】模拟器 教你如何用python制作有理数计算模拟器 python项目小发明 eval函数