4

I have run into a very strange issue today:

I have a popup menu that opens when I hover above an image. The popup menu is positioned right of the image.

this popup menu is templated to look like a rectangle with a little arrow pointing to the image

the menu contains clickable elements, so I need to be able to move the mouse from the image to the menu without it closing in between, and this is where I get confused: if I move the mouse right over the tip of the arrow and then the menu, everything works fine. If I move the mouse over the transparent space between the image and the menu (above or under the arrow), the menu disappears.

Here is the template for the menu:

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

you'll notice that I specifically put Background="Transparent" and not Null (I am aware of the effect this as on the hitTesting, see this question)

funny thing is, though: If I put Background="#01000000", it works as expected. (And I get almost what I want, since this is almost a transparent background)

but I would still like to know what is going on there...

I suspect it has something to do with the fact that this is a popupmenu. I assume WPF does something to remove the hitTesting on any surface that is transparent in a popup menu, either when the background is null (which is expected) or even if it is specifically set to transparent (not expected). Can anyone confirm this?

4

1 回答 1

5

将我的评论转换为答案。

这似乎更像是一个“Windows OS”问题,而不是 WPF,特别是AllowTransparency="True"在窗口级别使系统在元素上Background="Transparent"Opacity="0"元素上忽略鼠标悬停事件的元素。

可以在此处找到有关此行为的详细说明

添加 MSDN 答案以防万一以后链接丢失:

Windows 通过称为“分层窗口”的功能支持 HWND 级别的透明度。
分层窗口由位图表示。操作系统(OS)在需要时渲染位图。
由于操作系统需要快速响应鼠标移动,Windows 使用了专用的原始输入线程 (RIT)。RIT 在内核中运行并处理来自鼠标硬件的信号。RIT 可以扫描 HWND 层次结构以检测鼠标在哪个窗口上。对于普通窗口,RIT 根据窗口的矩形检查鼠标位置。对于分层窗口,RIT 查看指定窗口内容的位图并检查该位置的有效透明度。有效透明度会受到不透明度、颜色和 Alpha 通道的影响。如果像素是 100% 透明的,则 RIT 会跳过窗口并继续查看。这就是没有触发 MouseMove 事件的原因。如果窗口和控件的背景都是透明的,分层窗口中代表此控件(在您的示例中为画布)的所有像素都是完全透明的。如上所述,RIT 将跳过它们并且从不发送 WM_MOUSEMOVE 消息。因此,如果您只想在鼠标悬停时才显示控件,否则窗口是透明的,您必须使控件不是 100% 透明。

在这种情况下需要注意的一点是,即使PopupWindow没有的情况下AllowTransparency="True",Popup 也会自己生成一个 Chrome-less 窗口,并且AllowTransparency="True"Popup 上的 影响这个新的 chromeless-Window 的方式与上面 MSDN 链接中提到的方式相同。

如果此控件只是像Button/ Rectangle... 这样的标准控件,那么只需设置 即可Background="Transparent"使其正常工作并且不会出现此问题。

于 2013-07-03T10:11:09.550 回答