65.9K
CodeProject 正在变化。 阅读更多。
Home

移动 WindowStyle 为 None 的 WPF 窗口

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (7投票s)

2009 年 4 月 1 日

CC (Attr 3U)

2分钟阅读

viewsIcon

96035

如何移动 WindowStyle 为 None 的 WPF 窗口。

CustomWindow

在我之前的文章中:创建自定义窗口样式,我展示了如何使用 Style 在 WPF 中创建自定义样式,使用 WindowStyle.NoneResizeMode.NoResize。 这种方法让我烦恼的是,你无法移动自定义窗口,因为你没有窗口边框来拖动屏幕。

我读过一篇 文章,其中使用了非常“硬核”的方法,并使用互操作来使用 SendMessageReleaseCaptureMouseMove 方法,但这是一种非常面向 Win32 的方法,实际上,WPF 提供了更简单的方法。

要使用户能够从窗口上的任何区域移动窗口(不一定只是标题,如果你想做一些真正不同的事情),你只需处理窗口上 UIElementMouseLeftButtonDown 事件,并调用 DragMove 方法,如以下代码示例所示。

private void title_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    DragMove();
}

将其连接到样式

在可重用的 Style 中定义了外观和感觉后,我们需要一种方法将 MouseLeftButtonDown 事件连接起来,并在我们的 Window 类中处理它。 遗憾的是,这有点棘手。 如果 Style 定义在定义你的 Window 的 XAML 中,那么你可以简单地为相关 UIElement 添加事件处理程序,就像对任何其他元素一样。 但是,将你的 Style 放入你的实际 Window 中并不能给你一个非常有用的 Style。 相反,给你的 Style 中的元素一个固定的名称,例如 PART_Title,然后获取对该元素的引用,并在你的 Window 类中连接事件。 你还跟着我吗?

以下 XAML 代码示例显示了 Window Style 中的命名部分。

<style targettype=""{x:Type" type="text/css" window="" x:key=""MessageBox"">...
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Window}">
                <Border Background="{DynamicResource MessageBoxBackgroundBrush}"
                        BorderBrush="{DynamicResource MessageBoxBorderBrush}"
                        BorderThickness="1">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="30" />
                            <RowDefinition />
                        </Grid.RowDefinitions>
                        <Grid x:Name="PART_Title">
                            <Grid.Background>
                                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                    <GradientStop Color="#FF214F18" Offset="0"/>
                                    <GradientStop Color="#FF20361C" Offset="1"/>
                                </LinearGradientBrush>
                            </Grid.Background>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition />
                                <ColumnDefinition Width="30" />
                            </Grid.ColumnDefinitions>
                            <Label Style="{DynamicResource MessageBoxTitle}" 
				Content="{TemplateBinding Title}" />
                            <Button x:Name="PART_Close"
                                    Content="{DynamicResource CloseButtonPath}"
                                    Grid.Column="1"
                                    Style="{DynamicResource CloseButton}"
                                    Padding="4" />
                        </Grid>
                        <AdornerDecorator Grid.Row="1">
                            <ContentPresenter Content="{TemplateBinding Content}" 
				Margin="{TemplateBinding Margin}" />
                        </AdornerDecorator>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter></style>

我从前一版本的 Style 所做的就是添加一个 x:Name 属性,其值为 PART_Title 到包含 Window 标题的 Grid

以下代码示例显示了如何在 CustomMessageBox 类中获取对该元素的引用并连接鼠标事件。

namespace CustomWindow
{
    /// <summary>
    /// Interaction logic for CustomMessageBox.xaml
    /// </summary>
    public partial class CustomMessageBox : Window
    {
        private MessageBoxResult _result = MessageBoxResult.None;
        private Button _close;
        private FrameworkElement _title;

        ...

        private void this_Loaded(object sender, RoutedEventArgs e)
        {
            this._close = (Button)this.Template.FindName("PART_Close", this);
            if (null != this._close)
            {
                if (false == this._cancel.IsVisible)
                {
                    this._close.IsCancel = false;
                }
            }

            this._title = (FrameworkElement)this.Template.FindName("PART_Title", this);
            if (null != this._title)
            {
                this._title.MouseLeftButtonDown += 
		new MouseButtonEventHandler(title_MouseLeftButtonDown);
            }
        }

        private void title_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            DragMove();
        }

        ...
    }
}

摘要

因此,如果你想为自定义样式的窗口启用窗口移动,那么你需要从 MouseLeftButtonDown 事件的处理程序中调用 DragMove 方法。 在此示例中,CustomMessageBox 类提供了该事件处理。 如果你正在使用一个应用于多个窗口的 Style,那么你需要在每个类中连接鼠标事件,或者实现一个提供此功能的基类并从中继承。

和以前一样,我提供了(现在已更新的)自定义消息框类的源代码。

© . All rights reserved.