locked
Click through window with image (WPF) issues (HTTRANSPARENT isn't working)

    Question

  • Hi

    I've had a look on a number of forums about using HTTRANSPARENT on a WPF window to allow mouse clicks to be registered by anything
    under the window in question (a click through/ glass like window).

    The problem is that handling windows messages doesn't seem to work (the code get's called but has not effect).

    I've also tried setting the IsHitTestVisible to false (just in case) but this also doesn't work.

    I've added the relevant code below:


    (XML stuff, note the background color is only there so that I can see the window for testing)
    <Window x:Class="MyNewWPF.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="768" Width="1024" WindowStyle="None" Topmost="True"  AllowsTransparency="True" Background="Blue" Opacity="0.2"
        xmlns:effect="clr-namespace:MyNewWPF"> 
        
        <Grid x:Name="imageGrid" >
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="43*" />
                <ColumnDefinition Width="181*" />
                <ColumnDefinition Width="254*" />
            </Grid.ColumnDefinitions>       
           
        </Grid>
    </Window>

     (Form code that tries to make it click through/ glass like) 

    public const Int32 WM_NCHITTEST = 0x84;
    public const Int32 HTTRANSPARENT = -1;
    
    
    void Window1_Loaded(object sender, RoutedEventArgs e)
    {
       HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
    
       source.AddHook(new HwndSourceHook(WndProc));
    }
    
    IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
       if (msg == (int)WM_NCHITTEST)
       {
          handled = true;
          return (IntPtr)HTTRANSPARENT;  
       }
    
       return IntPtr.Zero;
    }

    Any ideas why this isn't working??? Is it because WPF windows don't allow for this type of access?
       

    Thanks

    Monday, October 26, 2009 3:02 PM

Answers

  • HTTRANSPARENT only works to pass on the message to a window that's owned by the *same thread*.  That precludes "anything under the window".

    A WPF Window is transparent to mouse clicks if you set its AllowTransparency to true and set the Background to Transparent.  Ask more questions about this in the WPF forum.

    Hans Passant.
    • Marked as answer by CrazyMagic Tuesday, October 27, 2009 9:30 AM
    Monday, October 26, 2009 11:29 PM
    Moderator

All replies

  • HTTRANSPARENT only works to pass on the message to a window that's owned by the *same thread*.  That precludes "anything under the window".

    A WPF Window is transparent to mouse clicks if you set its AllowTransparency to true and set the Background to Transparent.  Ask more questions about this in the WPF forum.

    Hans Passant.
    • Marked as answer by CrazyMagic Tuesday, October 27, 2009 9:30 AM
    Monday, October 26, 2009 11:29 PM
    Moderator
  • Cool ok will do.

    The issue is that I also have a image that's needs to be click through as well.

    I'll ask this over on the WPF forum then

    Thanks
    Tuesday, October 27, 2009 9:31 AM
  • HittestVisible works for controls inside that window, which are unaware of OS and are entirely drawn by WPF. But the Window is different. It is OS object so you have to deal with WM_ and WS_ and PInvokes

    I've done this in WinForms, I've tried what youv'e written here, but it doesn't work . But fortunantly it is simple ones you know where to tweak.

    heres a winForms examlple

    http://social.msdn.microsoft.com/forums/en-US/winforms/thread/50dc4a18-853e-447f-8477-776e857d8330/?prof=required

     

    I plan to write the same thing in WPF

     

    Here's how I solved problem:

    I used the  WS_EX_TRANSPARENT flag. It took me days to find it. Nobody provided me with a ready example to invesatigate. U can see it if u google for [tsadigov ghost window]. But I was lucky and one day when my comp was overloaded and I was dragging a file the icon of dragged file stayed on screen and I could click through it. That was what I wanted. I also used Spy++ to realize how it was done. I hadnt enough time to finish that project. But project that I uploaded is a working example.

     

    also I've found an answer for how doing this in WPF on the NET

    heres source code

     

    class MyWindow:Window{
    //...
    //...
     protected override void OnSourceInitialized(EventArgs e)
        {
          // Get this window's handle         
          IntPtr hwnd = new WindowInteropHelper(this).Handle;
          // Change the extended window style to include WS_EX_TRANSPARENT         
          int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
          SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_TRANSPARENT);  
          base.OnSourceInitialized(e);
        }
        public const int WS_EX_TRANSPARENT = 0x00000020;   public const int GWL_EXSTYLE = (-20);   
    
        [DllImport("user32.dll")]
        public static extern int GetWindowLong(IntPtr hwnd, int index);
    
        [DllImport("user32.dll")]
        public static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle); 
    }
    

     


    .NET guy
    • Proposed as answer by tsadigov Thursday, September 09, 2010 6:58 PM
    Thursday, September 09, 2010 6:57 PM