2016-09-17 63 views
1

我有一個簡單的例子來顯示這個問題。有兩個Window其中之一是主窗口和另一個是SecondWindow。我在SecondWindow裏面放了一個大按鈕,按鈕上有一個IsMouseOver觸發器。但是當光標移動時它不能正常工作。我使用下面的代碼來創建這個完整的例子。試試看看問題。我該如何解決它?儘管光標不在按鈕上,爲什麼IsMouseOver觸發器不起作用?

MainWindow.xaml

<Window x:Class="WpfApplication3.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" Height="350" Width="525" AllowsTransparency="True" WindowStyle="None"> 
<Grid> 
    <Button Content="Show Dialog" HorizontalAlignment="Left" Margin="10,71,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click" RenderTransformOrigin="-1.211,0.918"/> 

</Grid> 

SecondWindow.xaml

<Window x:Class="WpfApplication3.SecondWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="300" Width="300" 
    Background="Green" AllowsTransparency="True" WindowStyle="None"> 
<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition /> 
    </Grid.RowDefinitions> 

    <Button Content="SAVE" Height="50" VerticalAlignment="Bottom"> 
     <Button.Style> 
      <Style TargetType="Button"> 
       <Setter Property="Background" Value="Blue"/> 
       <Setter Property="Template"> 
        <Setter.Value> 
         <ControlTemplate TargetType="Button"> 
          <Border Background="{TemplateBinding Background}"> 
           <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/> 
          </Border> 
          <ControlTemplate.Triggers> 
           <Trigger Property="IsMouseOver" Value="True"> 
            <Setter Property="Background" Value="Red"/> 
            <Setter Property="Foreground" Value="White"/> 
           </Trigger> 
          </ControlTemplate.Triggers> 
         </ControlTemplate> 
        </Setter.Value> 
       </Setter> 
      </Style> 
     </Button.Style> 
    </Button> 
</Grid> 

MainWindow.cs

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
    } 

    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     SecondWindow w = new SecondWindow(); 
     w.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterOwner; 
     w.Owner = this; 
     w.ShowDialog(); 
    } 
} 

問題圖片:在主窗口,而不是SecondWindow,但按鈕的背景顏色,光標不會變爲藍色,它仍然是紅色的。

enter image description here

+0

這是因爲當鼠標水平地離開按鈕時,它不會擊中按鈕的直接父母,因爲窗口是無框的,並且按鈕沒有空白。在SecondWindow的上下文中,然後沒有離開按鈕並且觸發器不被執行。如果你在按鈕上設置了一定的邊距,它會起作用 - 但是對你而言可能不是最佳的? –

+0

但它應該沒有設置保證金。我之前也試過,但除非邊距很大,否則不敏感。你認爲這可能是一個錯誤或遺忘的東西來修復語言設計師? –

+0

@AliTor你的代碼應該和我的工作很好 – dkozl

回答

1

這是相當大的挑戰,因爲它似乎AllowsTransparency =「真」禁用鼠標與底層的Windows等

作爲變通一切正常behavoir我試圖讓按鈕的子類這樣的伎倆如下所示:

按鈕類:

using System; 
using System.Runtime.InteropServices; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Media; 

namespace SO39547486 
{ 
    public class MagicButton : Button, IDisposable 
    { 
    System.Timers.Timer m_colorTimer; 
    DateTime m_lastMouseMove; 
    Brush m_tmpBackground; 
    Brush m_tmpForeground; 

    public MagicButton() 
    { 
     MouseMove += MagicButton_MouseMove; 
    } 

    ~MagicButton() 
    { 
     Dispose(); 
    } 

    public Brush FocusBackground 
    { 
     get { return (Brush)GetValue(FocusBackgroundProperty); } 
     set { SetValue(FocusBackgroundProperty, value); } 
    } 

    // Using a DependencyProperty as the backing store for FocusBackground. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty FocusBackgroundProperty = 
     DependencyProperty.Register("FocusBackground", typeof(Brush), typeof(MagicButton), new PropertyMetadata(Brushes.Magenta)); 

    public Brush FocusForeground 
    { 
     get { return (Brush)GetValue(FocusForegroundProperty); } 
     set { SetValue(FocusForegroundProperty, value); } 
    } 

    // Using a DependencyProperty as the backing store for FocusForeground. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty FocusForegroundProperty = 
     DependencyProperty.Register("FocusForeground", typeof(Brush), typeof(MagicButton), new PropertyMetadata(Brushes.White)); 


    private void CleanupTimer() 
    { 
     if (m_colorTimer != null) 
     { 
     m_colorTimer.Stop(); 
     m_colorTimer.Dispose(); 
     m_colorTimer = null; 
     } 
    } 

    public void Dispose() 
    { 
     CleanupTimer(); 
    } 

    private void MagicButton_MouseMove(object sender, System.Windows.Input.MouseEventArgs e) 
    { 
     if (m_colorTimer == null) 
     { 
     m_colorTimer = new System.Timers.Timer(50); 
     m_colorTimer.Elapsed += ColorTimer_Elapsed; 
     m_colorTimer.Start(); 
     m_tmpBackground = Background; 
     Background = FocusBackground; 
     m_tmpForeground = Foreground; 
     Foreground = FocusForeground; 
     } 

     var point = e.GetPosition(this); 
     m_lastMouseMove = DateTime.Now; 
    } 

    [DllImport("user32.dll")] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    private static extern bool GetCursorPos(ref Win32Point pt); 

    [StructLayout(LayoutKind.Sequential)] 
    private struct Win32Point 
    { 
     public Int32 X; 
     public Int32 Y; 
    }; 
    private static Point GetMousePosition() 
    { 
     Win32Point w32Mouse = new Win32Point(); 
     GetCursorPos(ref w32Mouse); 
     return new Point(w32Mouse.X, w32Mouse.Y); 
    } 

    private bool IsCursorOverMe() 
    { 
     var cursorPos = GetMousePosition(); 
     var topLeft = PointToScreen(new Point(0, 0)); 
     Rect bounds = new Rect(topLeft.X, topLeft.Y, ActualWidth, ActualHeight); 
     return bounds.Contains(cursorPos); 
    } 

    private void ColorTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
    { 
     if (m_colorTimer != null) 
     { 
     var duration = DateTime.Now - m_lastMouseMove; 
     if (duration.TotalMilliseconds < 100) 
     { 
      Dispatcher.Invoke(() => 
      { 
      if (!IsCursorOverMe()) 
      { 
       Background = m_tmpBackground; 
       Foreground = m_tmpForeground; 
       CleanupTimer(); 
      } 
      });   
     } 
     } 
    } 
    } 
} 

和相應的XAML看起來像這樣:

<Window 
    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" mc:Ignorable="d" x:Class="SO39547486.SecondWindow" 
    xmlns:local="clr-namespace:SO39547486" 
    Title="Window1" Height="300" Width="300"  
    Background="Green" AllowsTransparency="True" WindowStyle="None"> 
    <Grid> 
    <local:MagicButton 
     Content="SAVE" 
     x:Name="SaveCmd" 
     Height="50" 
     VerticalAlignment="Bottom" 
     FocusBackground="Red" 
     FocusForeground="White" 
     > 
     <Button.Style> 
     <Style TargetType="{x:Type Button}"> 
      <Setter Property="Background" Value="Blue"/> 
     </Style> 
     </Button.Style> 
     <Button.Template> 
     <ControlTemplate TargetType="{x:Type Button}"> 
      <Border Background="{TemplateBinding Background}" UseLayoutRounding="True" d:DesignUseLayoutRounding="True"> 
      <ContentPresenter 
       ContentTemplate="{TemplateBinding ContentTemplate}" 
       Content="{TemplateBinding Content}" 
       ContentStringFormat="{TemplateBinding ContentStringFormat}" 
       HorizontalAlignment="Center" 
       UseLayoutRounding="True" 
       VerticalAlignment="Center" 
       d:DesignUseLayoutRounding="True"/> 
      </Border> 
     </ControlTemplate> 
     </Button.Template> 
    </local:MagicButton> 
    </Grid> 
</Window> 

這是這麼小的結果相當沉重的解決方法。至少它適用於我的電腦,所以我希望它也適用於你。

+0

您的解決方案正在運行。但是,我期待沒有創建自定義控件的更短的方式。無論如何,除非有更好的結果,否則這是最好的想法。感謝您的努力@亨利克。 –

相關問題