none
Click through windows and child image issue

    Question

  • Hi

    I'm trying to code a window that has an image (controls.image) and is completely click through )including the image itself as well.

    This means that if I click on either the window or the image in the window, both would ignore my click and would pass the click
    (either itself or ask the OS to) to anything behind the window I've created.

    I have tried using winProc HTTRANSPARENT code but this doesn't seem to work (and this has been confirmed as being incorrect on another msdn forum).

    Is there any way that this can be achieved?

    For reference I have achieve a similar effect in a normal windows.form using the code below, however this also doesn't seem to work on the WPF window:

    [DllImport("User32", CharSet = CharSet.Auto)]
    public static extern int GetWindowLong(IntPtr hWnd,
    int index);
    
           
    [DllImport("User32", CharSet = CharSet.Auto)]
            public static extern int SetWindowLong
    (IntPtr hWnd, int index, int value);
    
    public static void make_transparent(IntPtr wHnd)
    {
          const int GWL_EXSTYLE = -20;
          const int WS_EX_LAYERED = 524288;
          const int WS_EX_TRANSPARENT = 0x00000020;
    
          int style = Win32.GetWindowLong
          (wHnd, GWL_EXSTYLE);
          Win32.SetWindowLong(wHnd, 
          GWL_EXSTYLE, style | WS_EX_LAYERED |  
          WS_EX_TRANSPARENT);
    }   
    Thanks
    Tuesday, October 27, 2009 9:47 AM

Answers

  • Hi

    For those who need a solution to this I have found one...

    You need to add the following to you XAML window tag:

    AllowsTransparency="True"  WindowStyle="None"


    Then add the following code into the main window code:

    protected override void OnSourceInitialized(EventArgs e)
    {
         base.OnSourceInitialized(e);
    
         // Get this window's handle
         IntPtr hwnd = new WindowInteropHelper(this).Handle;
    
         Win32.makeTransparent(hwnd);
    }


    Then create a new class called 'Win32' and add the following code:


    using System.Runtime.InteropServices;
    
    //Rest of this code in located in the class itself
    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);
    
    public static void makeTransparent(IntPtr hwnd)
    {
        // Change the extended window style to include 
    WS_EX_TRANSPARENT
    
    int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
    Win32.SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | 
    WS_EX_TRANSPARENT);
    
    }


    Note you can change the class name to be what ever you want (doesn't have to be Win32) but I used this for demo purposes.


    For more info see this thread:

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

    • Marked as answer by CrazyMagic Tuesday, October 27, 2009 5:48 PM
    Tuesday, October 27, 2009 5:48 PM

All replies

  • Hi

    For those who need a solution to this I have found one...

    You need to add the following to you XAML window tag:

    AllowsTransparency="True"  WindowStyle="None"


    Then add the following code into the main window code:

    protected override void OnSourceInitialized(EventArgs e)
    {
         base.OnSourceInitialized(e);
    
         // Get this window's handle
         IntPtr hwnd = new WindowInteropHelper(this).Handle;
    
         Win32.makeTransparent(hwnd);
    }


    Then create a new class called 'Win32' and add the following code:


    using System.Runtime.InteropServices;
    
    //Rest of this code in located in the class itself
    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);
    
    public static void makeTransparent(IntPtr hwnd)
    {
        // Change the extended window style to include 
    WS_EX_TRANSPARENT
    
    int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
    Win32.SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | 
    WS_EX_TRANSPARENT);
    
    }


    Note you can change the class name to be what ever you want (doesn't have to be Win32) but I used this for demo purposes.


    For more info see this thread:

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

    • Marked as answer by CrazyMagic Tuesday, October 27, 2009 5:48 PM
    Tuesday, October 27, 2009 5:48 PM
  • Hi, this is very cool, I just needed this :)

    but lets say I need to go back and make the application normal again, how would I go about it ?

    best regards
    /sushibite
    Wednesday, December 09, 2009 2:40 PM
  • I need make the aplication normal again, how ?

     

    Monday, January 10, 2011 10:22 AM
  • My autoanswer! ,this is the way.
    public static void makeNormal(IntPtr hwnd) 
    { 
       
        int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE); 
       
    Win32.SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle & ~WS_EX_TRANSPARENT); 
    } 
    Monday, January 10, 2011 4:18 PM
  • My autoanswer! ,this is the way.
    public static void makeNormal(IntPtr hwnd) 
    { 
       
        int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE); 
       
    Win32.SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle & ~WS_EX_TRANSPARENT); 
    } 
    Monday, January 10, 2011 4:19 PM
  • Thanks for your code~ I once thought this approach not work in WPF...
    Tuesday, April 24, 2012 6:54 AM