IsHitTestVisible = false in Transparent window

2,640 views
Skip to first unread message

Laurent Bugnion [MVP]

unread,
Jun 22, 2009, 5:36:57 PM6/22/09
to wpf-di...@googlegroups.com

Hey guys,

 

I am confused. Why does this Rectangle intercept the mouse clicks instead of passing the click to the application underneath the window. The Window is transparent and so is LayoutRoot. Clicking next to the small Rectangle will activate the application underneath. I expected the Rectangle to not react to user clicks and also pass the click to the application underneath, but this doesn’t work. Why not?

 

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        x:Class="WpfApplication3.MainWindow"

        x:Name="Window"

        Title="MainWindow"

        Width="640"

        Height="480"

        WindowStyle="None"

        AllowsTransparency="True"

        Background="{x:Null}">

 

    <Grid x:Name="LayoutRoot">

        <Rectangle Fill="White"

                   Stroke="Black"

                   HorizontalAlignment="Left"

                   VerticalAlignment="Top"

                   Width="100"

                   Height="100"

                   IsHitTestVisible="False" />

    </Grid>

</Window>

 

Cheers,

Laurent

Marlon Grech

unread,
Jun 22, 2009, 5:42:25 PM6/22/09
to wpf-di...@googlegroups.com
I guess it's because a Background.... as far as I know you can allow mouse clicks through a visual only if you set x:Null as the background
Regards
Marlon
WPF Blog - http://marlongrech.wordpress.com/

Laurent Bugnion [MVP]

unread,
Jun 22, 2009, 5:51:48 PM6/22/09
to wpf-di...@googlegroups.com

Nope, consider this:

 

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        x:Class="WpfApplication3.MainWindow"

        x:Name="Window"

        Title="MainWindow"

        Width="640"

        Height="480"

        WindowStyle="None"

        AllowsTransparency="True"

        Background="{x:Null}">

 

    <Grid x:Name="LayoutRoot" Background="{x:Null}">

        <Button Margin="205,162,252,221" Content="Button"/>

        <Rectangle Fill="White"

                   Stroke="Black"

                   HorizontalAlignment="Left"

                   VerticalAlignment="Top"

                   Width="298"

                   Height="207"

                   IsHitTestVisible="False" />

    </Grid>

</Window>

 

The Button will get the clicks through the rectangle, but even the Grid and the Window has no background, clicks don’t get through the window to the app underneath

 

Puzzled,

Laurent

Marlon Grech

unread,
Jun 22, 2009, 6:08:45 PM6/22/09
to wpf-di...@googlegroups.com
probably IsHitTestVisible works only within the app.... x:Null works for seperate apps....
Regards
Marlon
WPF Blog - http://marlongrech.wordpress.com/



Jeremiah Morrill

unread,
Jun 22, 2009, 9:39:42 PM6/22/09
to wpf-di...@googlegroups.com
When dealing with a Window class in WPF,  we cannot forget about it's relation to an hWnd and Windows in general.  I do think setting IsHitTestVisible on the Window should behave the way we expect to, but it doesn't.  Can we call that a bug?

If I recall correctly, an AllowTransparency window sets the hWnd to be a layered Window.  Layered windows will still accept hit tests, but but tests per pixel.

If you want it to click through to the application below, you'd probably have call the SetWindowLong(...) with the WS_EX_TRANSPARENT argument.  That might not be exactly what you are looking for as this may happen with anything on your window, even if IsHitTestVisible is true.  Weaksauce for sure.

-Jer

Jeremiah Morrill

unread,
Jun 22, 2009, 9:49:20 PM6/22/09
to wpf-di...@googlegroups.com
Slightly related...but found this to be a perfect opportunity to complain ;)

Just because AllowTransparency=true is hardware accelerated, does not mean you will get the same performance if AllowTransparency=false.  Add a D3DImage to the mix and watch your layered window eat all your CPU.  To me this is a big bummer as you can really see how cool stuff like WPF is held back by it's antiquated cousin Win32.

-Jer

Eric Burke

unread,
Jun 22, 2009, 10:48:00 PM6/22/09
to wpf-di...@googlegroups.com
Jer's right.  Here's a good link.

http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/41ca3605-247c-4c5b-ac5d-74ce5abd7b92



From: Jeremiah Morrill <jeremiah...@gmail.com>
To: wpf-di...@googlegroups.com
Sent: Monday, June 22, 2009 9:39:42 PM

Subject: [WPF Disciples] Re: IsHitTestVisible = false in Transparent window

When dealing with a Window class in WPF,  we cannot forget about it's relation to an hWnd and Windows in general.  I do think setting IsHitTestVisible on the Window should behave the way we expect to, but it doesn't.  Can we call that a bug?

If I recall correctly, an AllowTransparency window sets the hWnd to be a layered Window.  Layered windows will still accept hit tests, but but tests per pixel.

If you want it to click through to the application below, you'd probably have call the SetWindowLong(...) with the WS_EX_TRANSPARENT argument.  That might not be exactly what you are looking for as this may happen with anything on your window, even if IsHitTestVisible is true.  Weaksauce for sure.

-Jer

On Mon, Jun 22, 2009 at 2:51 PM, Laurent Bugnion [MVP] <lau...@galasoft.ch> wrote:

Nope, consider this:

Jeremiah Morrill

unread,
Jun 22, 2009, 11:16:38 PM6/22/09
to wpf-di...@googlegroups.com
Sacha,

You were thinking of a project where you can use Win32 a little more?  What if you made a Window subclass to fix and add features, like this one?  Or when the window resizes, the aspect ratio stays the same.  I'm sure there's a lot more cool ish you could do.

Nice find Eric!  Code snippet and all!  You have a head start now Sacha =P!

-Jer

Laurent Bugnion [MVP]

unread,
Jun 22, 2009, 11:59:39 PM6/22/09
to wpf-di...@googlegroups.com

Thanks guys. This will work to let all clicks go through. In my case I want the button to get the clicks, but not the rectangle. I am at a client and we were trying to find the best way to do a shadowed window (with a blurred black rectangle) where the shadow lets the clicks go through (same behavior than shadowed windows in Win7). Other options we discussed are to use templated windows but the client doesn’t like this option. I think they will either just leave it the way it is and get the clicks (doesn’t seem to be a huge deal for them) or use some Win32 interop to pass the clicks to the window below.

 

I am thinking of grouping all the Win32 interop code sections in files with a header saying “Abandon all hope, ye who enter here”.

http://en.wikipedia.org/wiki/Inferno_(Dante)

 

Cheers

Laurent

Jeremiah Morrill

unread,
Jun 23, 2009, 12:31:35 AM6/23/09
to wpf-di...@googlegroups.com
Would this work for you?

Use a Popup subclass to hold your rectangle you don't want to click through.  A Popup uses an hWnd window internally.  

In you Popup subclass, possibly use (HwndSource)PresentationSource.FromVisual(myPopup).Handle (not tested) to get the hWnd.

Use that hWnd to SetWindowLong(...) to make sure it clicks through.

It could work...Unsure..but I'm optimistic!

-Jer

Sacha Barber

unread,
Jun 23, 2009, 3:39:48 AM6/23/09
to wpf-di...@googlegroups.com
Ha ha, I am quite busy these days, but thanks for the heads up Jer.
 

 

Date: Mon, 22 Jun 2009 20:16:38 -0700

Subject: [WPF Disciples] Re: IsHitTestVisible = false in Transparent window

Beyond Hotmail — see what else you can do with Windows Live. Find out more.

Eric Burke

unread,
Jun 23, 2009, 7:58:10 AM6/23/09
to wpf-di...@googlegroups.com

Jer, I don't think Popups behave the way you would want in this case -- they tend to stay topmost and not move with their parent.  Trying to get them to do that is kind of a PITA.  Past attempts we've made to make them do what we want usually resulted in more code that we wanted to maintain (along with more Tylenol to get rid of the headache!).

 

 

Laurent, you might try using an HwndHook on the window and looking for WM_NCHITTEST.  If the mouse is over a clickable area, you return HTBORDER or some other HT* constant (look in Reflector at the Window class because I'm pretty sure they do something like that in there); if it's over the shadow, you return HTNOWHERE.  I haven't tried this but it might work.



Sent: Tuesday, June 23, 2009 12:31:35 AM

Laurent Bugnion [MVP]

unread,
Jun 24, 2009, 4:04:26 AM6/24/09
to wpf-di...@googlegroups.com

Hi Erik,

 

Good call about the Popup, I had that bite me in the past.

 

I will check the other way you suggest. My answer to the client was that it is not possible without Win32 interop, so it was good enough.

 

Cheers and thanks all,

Laurent

Eric Burke

unread,
Jun 24, 2009, 11:24:27 AM6/24/09
to wpf-di...@googlegroups.com
I tried the HwndSource + AddHook and it sort of works.  See attached code (rename to .ZIP).  The mouse moves make it work correctly, but sometimes the behavior reverts, especially if you click a mouse button.  There's probably another message I'm missing, or a different HT* return value, or something.  Anyhow, it's a starting point.  Let me know how it goes.


From: Laurent Bugnion [MVP] <lau...@galasoft.ch>
To: wpf-di...@googlegroups.com
Sent: Wednesday, June 24, 2009 4:04:26 AM
WpfApplication2.zi_

Jeremiah Morrill

unread,
Jun 24, 2009, 3:11:47 PM6/24/09
to wpf-di...@googlegroups.com
Going to play with this tonight!  Awesome stuffs Eric.

-Jer
Reply all
Reply to author
Forward
0 new messages