Search Unity

[SOLVED!] Windows: Transparent window with opaque contents (LWA_COLORKEY)?

Discussion in 'Windows' started by krougeau, May 2, 2015.

  1. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    6,545
    Using four zeroes should reset it to initial state, I think (that's the impression I've got from reading the link I posted - I did not try it).
     
  2. LazyDog_Rich

    LazyDog_Rich

    Joined:
    Apr 27, 2014
    Posts:
    58
    Hi! Sorry for necro this old post, but this is the only thing I found about this...
    I have problems making the window click-through unless there's some collider or UI in front.

    I can have a fully click-through window, or a non-click-throughable window

    What I got so far is that if I use:
    SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
    In the Start (). I have a click-able and transparent scene

    And if I use:
    SetWindowLong(hwnd, -20, 524288 | 32);
    In the Start(), I will have a transparent and click-through scene

    But I tried change between them using a Input key, and I can change from, click-able to click-through, but I cannot change from click-through to clickable...

    I was debbuging the whole time, so I know the input Im using is being detected, but still dont work :(

    This is the whole code:
    Code (CSharp):
    1. using System;
    2. using System.Runtime.InteropServices;
    3. using UnityEngine;
    4.  
    5. public class TransparentWindow : MonoBehaviour
    6. {
    7.     [SerializeField]
    8.     private Material m_Material;
    9.  
    10.     private struct MARGINS
    11.         {
    12.         public int cxLeftWidth;
    13.         public int cxRightWidth;
    14.         public int cyTopHeight;
    15.         public int cyBottomHeight;
    16.         }
    17.  
    18.     [DllImport("user32.dll")]
    19.     private static extern IntPtr GetActiveWindow();
    20.  
    21.     [DllImport("user32.dll")]
    22.     private static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);
    23.  
    24.     [DllImport("user32.dll")]
    25.     static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
    26.  
    27.     [DllImport("user32.dll", EntryPoint = "SetLayeredWindowAttributes")]
    28.     static extern int SetLayeredWindowAttributes(IntPtr hwnd, int crKey, byte bAlpha, int dwFlags);
    29.  
    30.     [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
    31.     private static extern int SetWindowPos(IntPtr hwnd, int hwndInsertAfter, int x, int y, int cx, int cy, int uFlags);
    32.  
    33.     [DllImport("Dwmapi.dll")]
    34.     private static extern uint DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS margins);
    35.  
    36.     const int GWL_STYLE = -16;
    37.     const uint WS_POPUP = 0x80000000;
    38.     const uint WS_VISIBLE = 0x10000000;
    39.     const int HWND_TOPMOST = -1;
    40.  
    41.     void Start()
    42.         {
    43. #if !UNITY_EDITOR // You really don't want to enable this in the editor..
    44.  
    45.         var margins = new MARGINS() { cxLeftWidth = -1 };
    46.         var hwnd = GetActiveWindow();
    47.  
    48.         SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
    49.  
    50.         DwmExtendFrameIntoClientArea(hwnd, ref margins);
    51.  
    52. #endif
    53.         }
    54.  
    55.     private bool clickThrough;
    56.  
    57.     void ChangeTransparency ()
    58.         {
    59.         var margins = new MARGINS() { cxLeftWidth = -1 };
    60.         var hwnd = GetActiveWindow();
    61.         if(!clickThrough)
    62.             {
    63.             Debug.Log("Window is click-able now");
    64.             margins = new MARGINS() { cxLeftWidth = 0, cxRightWidth = 0, cyTopHeight = 0, cyBottomHeight = 0 };
    65.             SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
    66.             }
    67.         else
    68.             {
    69.             Debug.Log("Window is click-through now");
    70.             int fWidth = Screen.width;// is not
    71.             int fHeight = Screen.height;// is not
    72.             SetWindowLong(hwnd, -20, 524288 | 32);//is not //GWL_EXSTYLE=-20; WS_EX_LAYERED=524288=&h80000, WS_EX_TRANSPARENT=32=0x00000020L
    73.             SetLayeredWindowAttributes(hwnd, 0, 255, 2);//is not // Transparency=51=20%, LWA_ALPHA=2
    74.             SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, fWidth, fHeight, 32 | 64); //is not //SWP_FRAMECHANGED = 0x0020 (32); //SWP_SHOWWINDOW = 0x0040 (64)
    75.             }
    76.         DwmExtendFrameIntoClientArea(hwnd, ref margins);
    77.         }
    78.  
    79.     void Update ()
    80.         {
    81.         if(Input.GetKeyDown(KeyCode.Q))
    82.             {
    83.             clickThrough = !clickThrough;
    84.             ChangeTransparency ();
    85.             }
    86.         }
    87.  
    88.     void OnRenderImage(RenderTexture from, RenderTexture to)
    89.         {
    90.         Graphics.Blit(from, to, m_Material);
    91.         }
    92. }
     
  3. LazyDog_Rich

    LazyDog_Rich

    Joined:
    Apr 27, 2014
    Posts:
    58
  4. AlanMattano

    AlanMattano

    Joined:
    Aug 22, 2013
    Posts:
    1,082
    Thanks, Tautvydas-Zilys for the script! is working.

    My default resolution is 800x600. But when I apply this "TransparentWindow" the resolution change to 816x639 losing the 4:3 proportion. Any idea to how to resolve this?
     
  5. baksarbed

    baksarbed

    Joined:
    Sep 29, 2016
    Posts:
    2
    Can you tell me, please, how can I do it for Mac OS?
     
  6. weixiaowang

    weixiaowang

    Joined:
    Mar 9, 2017
    Posts:
    6
    I enable aero on windows7,but it is tranparent on starting,then become black background quickly. How can I fix this? On windows10,it's fine.
     
  7. Jed_500

    Jed_500

    Joined:
    Oct 30, 2013
    Posts:
    1
    necro.... I know but for completeness zalo10 solution works fine just to add for ui detection add:-

    Code (CSharp):
    1. public bool OverUI() { //Use sparingly
    2.         //Set up the new Pointer Event
    3.         PointerEventData m_PointerEventData = new PointerEventData(EventSystem.current);
    4.         m_PointerEventData.position = Input.mousePosition;
    5.         List<RaycastResult> results = new List<RaycastResult>();
    6.         EventSystem.current.RaycastAll(m_PointerEventData, results);
    7.         if (results.Count > 0) return true;
    8.         return false;
    9.     }
    and change:

    Code (CSharp):
    1. clickThrough = !Physics.Raycast (mainCamera.ScreenPointToRay (Input.mousePosition).origin,
    2.                 mainCamera.ScreenPointToRay (Input.mousePosition).direction, out hit, 100,
    3.                 Physics.DefaultRaycastLayers);
    to:

    Code (CSharp):
    1. clickThrough = !Physics.Raycast (mainCamera.ScreenPointToRay (Input.mousePosition).origin,
    2.                 mainCamera.ScreenPointToRay (Input.mousePosition).direction, out hit, 100,
    3.                 Physics.DefaultRaycastLayers)&&!OverUI();
     
  8. kilik128

    kilik128

    Joined:
    Jul 15, 2013
    Posts:
    870
    it's working with multi windows ?
     
  9. vestigial

    vestigial

    Joined:
    May 9, 2015
    Posts:
    37
    Just to note, this works in 2018.3.b12, but not in 2019.1.0a11 (yet)
     
  10. EvalDaemon

    EvalDaemon

    Joined:
    Aug 8, 2013
    Posts:
    100
    You mean multi-monitor? If so YES I have it working with up to 8 monitors.
     
  11. EvalDaemon

    EvalDaemon

    Joined:
    Aug 8, 2013
    Posts:
    100
    Any idea why? I'm still running 2018 and that could be a deal breaker for me on a 2019 upgrade.
     
  12. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    6,545
  13. EvalDaemon

    EvalDaemon

    Joined:
    Aug 8, 2013
    Posts:
    100
    Is anyone else having problems running this using Player Settings -> Scripting Runtime Version .NET 4.x Equivalent?
     
  14. EvalDaemon

    EvalDaemon

    Joined:
    Aug 8, 2013
    Posts:
    100
    I'll answer my own question. If you change to Scripting Runtime = >net 4.x you need to also set the Api Compatibility Level to .NET 4.x
     
  15. vestigial

    vestigial

    Joined:
    May 9, 2015
    Posts:
    37
    It's working again in 2019.1.7! (and 2019.2.0b6 and 2019.3.0a2). Big thanks to Unity for keeping this awesome functionality alive.

    Per Tautvydas-Zilys, you have to make sure to UNCHECK "Use DXGI Flip Model Swapchain for D3D11" under Player Settings -> Resolution and Presentation. (I also had to tweak the shader to use alpha instead of color key, and havent tried clickthrough yet but the transparency is there, or NOT there I guess!)
     

    Attached Files:

  16. EvalDaemon

    EvalDaemon

    Joined:
    Aug 8, 2013
    Posts:
    100
    Ya you beat me to it, I was just looking at 2019.1.7 release notes.

    Windows: Added a Player Setting for reverting to BltBlt swapchain model which was used before 2019.1. This enables several scenarios like transparent window to be used once again (1107463, 1152570)
     
  17. baoenzo

    baoenzo

    Joined:
    Jul 6, 2019
    Posts:
    1
    I have a question, how to open the application it's always at the right corner of the desktop.
    I tried many ways on online but it didn't work
     
  18. Foxofthelight

    Foxofthelight

    Joined:
    Nov 20, 2018
    Posts:
    1
    hi i got this to work for my overlay i was making for a game i play (osu!) but if i have the game in fullscreen (which i would like to have because otherwise the game has a little input delay) then the unity window does not overlay it anymore is there a way to fix this?