如何在失去焦点时启用自定义模式对话框以闪烁?

时间:2017-05-29 07:44:57

标签: c# wpf xaml

我在资源字典中设计了一个自定义窗口。

ResourceDictionary.xaml

<ResourceDictionary>
    <ControlTemplate x:Key="CustomWindowTemplate" TargetType="Window">
        <Border Style="{StaticResource MainWindowBorderStyle}" Margin="20" x:Name="MainWindowBorder">
            <Border.Effect>
                <DropShadowEffect Color="Gray"
                          Direction="270"
                          BlurRadius="20"
                          ShadowDepth="3" />
            </Border.Effect>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="35"/>
                    <RowDefinition Height="590*"/>
                </Grid.RowDefinitions>

                <Border Grid.Row="0" Style="{StaticResource TitleBarBorderStyle}">
                    <Grid>
                        <TextBlock Style="{StaticResource TitleStyle}"/>
                        <Button x:Name="BtnClose" Style="{StaticResource CloseButtonStyle}"/>
                    </Grid>
                </Border>

                <Grid Grid.Row="1">
                    <ContentPresenter/>
                </Grid>
            </Grid>
        </Border>
    </ControlTemplate>

    <Style TargetType="Window" x:Key="CustomChromeWindowStyle">
        <Setter Property="Template" Value="{StaticResource CustomWindowTemplate}"/>
        <Setter Property="Height" Value="600" />
        <Setter Property="Width" Value="870" />
        <Setter Property="ResizeMode" Value="NoResize" />
        <Setter Property="AllowsTransparency" Value="True" />
        <Setter Property="WindowStyle" Value="None" />
        <Setter Property="Background" Value="Transparent" />
        <Setter Property="Title" Value="Your Custom Window Title" />
    </Style>
</ResourceDictionary>

ResourceDictionary.xaml.cs ,任何使用此ResourceDictionary的窗口都无缝地拥有这两个事件,因为它们是在ResourceDictionary.xaml上定义的

// EventSetter in CloseButtonStyle
private void BtnClose_Click(object sender, RoutedEventArgs e)
{
    var closeButton = sender as Button;
    var senderWindow = Window.GetWindow(closeButton);
    senderWindow.Close();
}

// EventSetter in TitleBarBorderStyle
private void Border_MouseDown(object sender, MouseButtonEventArgs e)
{
    var border = sender as Border;
    var senderWindow = Window.GetWindow(border);
    senderWindow.DragMove();
}

WindowA.xaml 示例用法

<Window x:Class="CustomWindowBase.WindowA"
        Style="{DynamicResource CustomChromeWindowStyle}"
        Title="Window A" Height="200" Width="300"
        WindowStartupLocation="CenterScreen">
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                 <ResourceDictionary Source="pack://application:,,,/CustomWindowBase.Resources;component/Dictionary/ResourceDictionary.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
    <Grid>
         <!-- Window A Stuff here-->
    </Grid>
</Window>

可以使用customWindow.Show()customWindow.ShowDialog()打开使用此自定义shell的任何窗口。使用对话框,当用户尝试单击应用程序中的其他位置时,我将丢失闪烁或闪烁对话框窗口的事件。

无论如何通过知道打开的窗口实例是否是模态对话框而无法在ResourceDictionary.xaml中定义的Drag / Close进行无缝操作?

1 个答案:

答案 0 :(得分:1)

这是可能的,但你必须创建一个CustomWindow类(继承Window)并扩展该类。

这是我的版本的一小部分。

/// <summary>
/// The custom Window in Windows10 Style.
/// </summary>
public class CustomWindow : Window
{
    // ##############################################################################################################################
    // Constructor
    // ##############################################################################################################################

    /// <summary>
    /// Constructor of the <see cref="CustomWindow"/>.
    /// </summary>
    public CustomWindow()
    {
        Activated += HTWindow10_Activated;
        Deactivated += HTWindow10_Deactivated;
    }

    static CustomWindow()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomWindow), new FrameworkPropertyMetadata(typeof(CustomWindow)));
    }

    // ##############################################################################################################################
    // Animation and Style Events
    // ##############################################################################################################################

    private void HTWindow10_Deactivated(object sender, EventArgs e)
    {
        _WindowDropShadowEffect.Color = new System.Windows.Media.Color { A = 100, B = 26, G = 26, R = 26 }; //Dark Grey
        _WindowBorder.BorderBrush = new System.Windows.Media.SolidColorBrush(new System.Windows.Media.Color { A = 255, B = 26, G = 26, R = 26 });
        _WindowBorder.Background = System.Windows.Media.Brushes.White;
    }

    private void HTWindow10_Activated(object sender, EventArgs e)
    {
        _WindowDropShadowEffect.Color = new System.Windows.Media.Color { A = 100, B = 33, G = 124, R = 243 }; //Orange
        _WindowBorder.BorderBrush = new System.Windows.Media.SolidColorBrush(new System.Windows.Media.Color { A = 255, B = 33, G = 124, R = 243 });
        _WindowBorder.Background = System.Windows.Media.Brushes.White;
    }

    // ##############################################################################################################################
    // EventHandler
    // ##############################################################################################################################

    private ComboBox _AvailableTranslation;
    private Label _WindowTitle;
    private Button _CloseButton;
    private Rectangle _MoveRect;
    private Button _MinimizeButton;
    private Button _RestoreButton;
    private Grid _ResizeGrid;
    private MenuItem _MenuItemRestore;
    private MenuItem _MenuItemMinimize;
    private MenuItem _MenuItemMaximize;
    private MenuItem _MenuItemClose;
    private Border _WindowBorder;
    private Rectangle _CloseRectangle;
    private StackPanel _AvailableTranslationStackPanel;
    private Image _Logo;
    private DropShadowEffect _WindowDropShadowEffect;
    public override void OnApplyTemplate()
    {
        _WindowTitle = GetTemplateChild("WindowTitle") as Label;
        _CloseButton = GetTemplateChild("closeButton") as Button;
        _MoveRect = GetTemplateChild("moveRectangle") as Rectangle;
        _MinimizeButton = GetTemplateChild("minimizeButton") as Button;
        _RestoreButton = GetTemplateChild("restoreButton") as Button;
        _ResizeGrid = GetTemplateChild("resizeGrid") as Grid;
        _AvailableTranslation = GetTemplateChild("availableTranslationComboBox") as ComboBox;
        _AvailableTranslationStackPanel = GetTemplateChild("availableTranslationStackPanel") as StackPanel;

        _MenuItemRestore = GetTemplateChild("menuItemRestore") as MenuItem;
        _MenuItemMinimize = GetTemplateChild("menuItemMinimize") as MenuItem;
        _MenuItemMaximize = GetTemplateChild("menuItemMaximize") as MenuItem;
        _MenuItemClose = GetTemplateChild("menuItemClose") as MenuItem;

        _WindowBorder = GetTemplateChild("windowBorder") as Border;

        _CloseRectangle = GetTemplateChild("closeRectangle") as Rectangle;
        _Logo = GetTemplateChild("logo") as Image;
        _WindowDropShadowEffect = GetTemplateChild("windowDropShadowEffect") as DropShadowEffect;

        base.OnApplyTemplate();
    }

    private HwndSource _hwndSource;

    protected override void OnInitialized(EventArgs e)
    {
        SourceInitialized += OnSourceInitialized;
        base.OnInitialized(e);
    }

    private void OnSourceInitialized(object sender, EventArgs e)
    {
        _hwndSource = (HwndSource)PresentationSource.FromVisual(this);

        System.IntPtr handle = (new WinInterop.WindowInteropHelper(this)).Handle;
        WinInterop.HwndSource.FromHwnd(handle).AddHook(new WinInterop.HwndSourceHook(WindowProc));
    }

    private void FlashTitleBar(bool active)
    {
        if (active)
        {
            _WindowDropShadowEffect.Color = new System.Windows.Media.Color { A = 100, B = 33, G = 124, R = 243 }; //Orange
            _WindowBorder.BorderBrush = new System.Windows.Media.SolidColorBrush(new System.Windows.Media.Color { A = 255, B = 33, G = 124, R = 243 });
            _WindowBorder.Background = System.Windows.Media.Brushes.White;
        }
        else
        {
            _WindowDropShadowEffect.Color = new System.Windows.Media.Color { A = 255, B = 0, G = 0, R = 255 }; //Red
            _WindowBorder.BorderBrush = new System.Windows.Media.SolidColorBrush(new System.Windows.Media.Color { A = 255, B = 0, G = 0, R = 255 });
            _WindowBorder.Background = System.Windows.Media.Brushes.Red;
        }
    }


    private System.IntPtr WindowProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled)
    {
        var retVal = IntPtr.Zero;

        switch (msg) //http://www.mycsharp.de/wbb2/thread.php?postid=111901 Auflistung der WndProc-Message-Kommandos 
        {
            case 0x0086: //https://msdn.microsoft.com/de-de/library/windows/desktop/ms632633%28v=vs.85%29.aspx //WM_NCACTIVATE message
                retVal = DefWindowProc(hwnd, 0x0086, new IntPtr(1), new IntPtr(-1));
                FlashTitleBar((int)wParam == 1 ? true : false);
                handled = true;
                break;
        }


        return retVal;
    }

    [DllImport("user32")]
    internal static extern IntPtr DefWindowProc([In] IntPtr hwnd, [In] int msg, [In] IntPtr wParam, [In] IntPtr lParam);
}

预览

在Gif中有点滞后。

preview