我今天遇到了一个非常奇怪的问题:
当我将鼠标悬停在图像上方时,我会打开一个弹出菜单.弹出菜单位于图像的右侧.
此弹出菜单模板看起来像一个带有指向图像的小箭头的矩形
菜单包含可点击的元素,所以我需要能够将鼠标从图像移动到菜单而不在它之间关闭,这就是我感到困惑的地方:如果我将鼠标移到箭头尖端然后菜单,一切正常.如果我将鼠标移动到图像和菜单之间的透明空间(箭头上方或下方),菜单将消失.
这是菜单的模板:
<Popup AllowsTransparency="True" Name="c_popup" Width="300" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}" Placement="Right">
<Grid Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Path Data="M 0 10 L 10 0 10 20 Z" Stroke="#252C37" Fill="#252C37" Margin="0,18,0,0" Grid.Column="0" />
<Grid Grid.Column="1" Background="#252C37">
<TextBlock Text="{Binding Name}" Margin="20,10,0,0" FontSize="18" Foreground="White" HorizontalAlignment="Stretch" VerticalAlignment="Top" TextWrapping="WrapWithOverflow" />
</Grid>
</Grid>
</Popup>
Run Code Online (Sandbox Code Playgroud)
你会注意到我特意把Background =" Transparent "而不是Null(我知道这对hitTesting有什么影响,请看这个问题)
但有趣的是:如果我把Background ="#01000000",它按预期工作.(我几乎得到了我想要的东西,因为这几乎是一个透明的背景)
但我还是想知道那里发生了什么......
我怀疑这与popupmenu这个事实有关.我假设WPF做了一些事情来删除弹出菜单中透明的任何表面上的hitTesting,无论是背景为空(预期)还是特别设置为透明(不是预期的).谁能证实这一点?
将我的评论转换为答案.
这似乎更像是一个"Windows操作系统"问题而不是WPF特别是AllowTransparency="True"
在Window级别的方式使得系统在元素上Background="Transparent"
或Opacity="0"
元素上忽略鼠标悬停事件的元素.
可以在此处找到此行为的详细说明
添加MSDN答案以防以后链接丢失:
Windows通过名为"分层窗口"的功能支持HWND级别的透明度.
分层窗口由位图表示.操作系统(OS)在需要时呈现位图.
由于操作系统需要对鼠标移动做出快速响应,因此Windows使用专用的原始输入线程(RIT).RIT在内核中运行并处理来自鼠标硬件的信号.RIT可以扫描HWND层次结构以检测鼠标所在的窗口.对于普通窗口,RIT会根据窗口的矩形检查鼠标位置.对于分层窗口,RIT在位图中查找指定窗口内容的位图,并检查该位置的有效透明度.有效透明度可能受不透明度,颜色和Alpha通道的影响.如果像素是100%透明的,则RIT会跳过窗口并继续查看.这一点是没有触发MouseMove事件的原因.如果窗口和控件的背景都是透明的,在分层窗口中表示此控件(示例中为Canvas)的所有像素都是完全透明的.如上所述,RIT将跳过它们并且永远不会发送WM_MOUSEMOVE消息.因此,如果您只想在鼠标结束时显示控件,否则窗口是透明的,您必须使控件不是100%透明.
在这种情况下需要注意的是,即使Popup
在Window
没有的情况下AllowTransparency="True"
,Popup 也会生成一个无Chrome的窗口,弹出窗口AllowTransparency="True"
会影响这个新的chromeless-Window,就像上面的MSDN链接中提到的那样.
如果这个控件只是一个标准的控件,比如Button
/ Rectangle
...那么只需设置Background="Transparent"
它就可以使它正常工作而不会出现这个问题.