如何在失去焦点时启用自定义模态对话框闪烁? [英] How to enable custom modal dialog to blink when losing focus?

查看:18
本文介绍了如何在失去焦点时启用自定义模态对话框闪烁?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have designed a custom window in a resource dictionary.

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 上定义的

ResourceDictionary.xaml.cs, any window that uses this ResourceDictionary has these two events seamlessly, because they are defined on the 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>

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

Any window that uses this custom shell can be opened with customWindow.Show() and customWindow.ShowDialog(). With dialog, I lose the event that flashes or blinks the dialog window when user attempts to click somewhere else in the application.

有没有像我在 ResourceDictionary.xaml 中定义的拖动/关闭那样通过知道打开的窗口实例是否是模态对话框来无缝执行的?

Is there anyway of doing so seamlessly as I did with Drag/Close defined in the ResourceDictionary.xaml by knowing if the opened window instance is a modal dialog or not?

推荐答案

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

It is possible, but you have to create a CustomWindow class (inherit Window) and extend that class.

这是我版本的一小部分.

Here is a very small part of my version.

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

It is a little bit lagging in the Gif.

这篇关于如何在失去焦点时启用自定义模态对话框闪烁?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆