Search Unity

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

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

  1. krougeau

    krougeau

    Joined:
    Jul 1, 2012
    Posts:
    449
    Moved from the Scripting forums as this seemed the better, proper place for such a question:

    In short: How would I alter the example code below to use LWA_COLORKEY to achieve a transparent window with opaque contents, assuming that my Camera is set to clear a Solid Color (in this case, Green). Please see my second post, below, for example screenshots.

    After viewing the information at http://forum.unity3d.com/threads/windows-api-calls.127719/ & http://answers.unity3d.com/questions/869378/viewing-desktop-in-scene.html, I have managed to produce a semi-transparent window with semi-transparent contents. While this is certainly a step in the right direction towards what I'm trying to achieve, I was curious if any of you might suggest how to make the window itself transparent while keeping it's contents opaque (preferably 100% visible)?

    My tests with LWA_ALPHA are working well for making the window semi-transparent, but the content's themselves are also semi-transparent as LWA_ALPHA affects the entire window. Trying LWA_COLORKEY, which _should_ act more like chromakeying in video, has so far failed utterly and the window remains fully opaque. I'm fairly new to coding, and know little at all about MSDN and the Windows API, but I really thought that LWA_COLORKEY would be the way to go, which has made the evening's repeated failures quite frustrating.

    However it might be achieved, I'd ultimately like to make the main window 100% transparent whilst keeping the contents of the window (gameobjects, GUI elements, etc.) 100% visible. Any advice would be greatly appreciated. I've included richyrich's altered code & his usage instructions below for your consideration. Thanks!!

    Code (CSharp):
    1.  
    2. //Note: Inspired by and uses some code found here: http://forum.unity3d.com/threads/windows-api-calls.127719/
    3.  
    4. using UnityEngine;
    5. using System.Collections;
    6. using System;
    7. using System.Runtime.InteropServices; // Pro and Free!!!
    8.  
    9. //WARNING!! Running this code inside Unity when not in a build will make the entire development environment transparent
    10. //Restarting Unity would however resolve
    11.  
    12. public class TransparentWindow : MonoBehaviour
    13. {
    14.    [DllImport("user32.dll", EntryPoint = "SetWindowLongA")]
    15.    static extern int SetWindowLong(int hwnd, int nIndex, long dwNewLong);
    16.    [DllImport("user32.dll")]
    17.    static extern bool ShowWindowAsync(int hWnd, int nCmdShow);
    18.    [DllImport("user32.dll", EntryPoint = "SetLayeredWindowAttributes")]
    19.    static extern int SetLayeredWindowAttributes(int hwnd, int crKey, byte bAlpha, int dwFlags);
    20.    [DllImport("user32.dll", EntryPoint = "GetActiveWindow")]
    21.    private static extern int GetActiveWindow();
    22.    [DllImport("user32.dll", EntryPoint = "GetWindowLong")]
    23.    private static extern long GetWindowLong(int hwnd, int nIndex);
    24.    [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
    25.    private static extern int SetWindowPos(int hwnd, int hwndInsertAfter, int x, int y, int cx, int cy, int uFlags);
    26.  
    27.    void Start()
    28.    {
    29.      int handle = GetActiveWindow();
    30.      int fWidth = Screen.width;
    31.      int fHeight = Screen.height;
    32.  
    33.      //Remove title bar
    34.      long lCurStyle = GetWindowLong(handle, -16);  // GWL_STYLE=-16
    35.      int a = 12582912;  //WS_CAPTION = 0x00C00000L
    36.      int b = 1048576;  //WS_HSCROLL = 0x00100000L
    37.      int c = 2097152;  //WS_VSCROLL = 0x00200000L
    38.      int d = 524288;  //WS_SYSMENU = 0x00080000L
    39.      int e = 16777216;  //WS_MAXIMIZE = 0x01000000L
    40.  
    41.      lCurStyle &= ~(a | b | c | d);
    42.      lCurStyle &= e;
    43.      SetWindowLong(handle, -16, lCurStyle);// GWL_STYLE=-16
    44.  
    45.      // Transparent windows with click through
    46.      SetWindowLong(handle, -20, 524288 | 32);//GWL_EXSTYLE=-20; WS_EX_LAYERED=524288=&h80000, WS_EX_TRANSPARENT=32=0x00000020L
    47.      SetLayeredWindowAttributes(handle, 0, 51, 2);// Transparency=51=20%, LWA_ALPHA=2
    48.  
    49.      SetWindowPos(handle, 0, 0, 0, fWidth, fHeight, 32 | 64); //SWP_FRAMECHANGED = 0x0020 (32); //SWP_SHOWWINDOW = 0x0040 (64)
    50.      ShowWindowAsync(handle, 3); //Forces window to show in case of unresponsive app  // SW_SHOWMAXIMIZED(3)
    51.    }
    52. } // end of file
    richyrich's instructions:
    1. Add the above code to your project
    2. Go to your camera and select it. In the Inspector, change the colors and the alpha to 0.
    3. Build the (Windows) app - change the settings to windowed, then run
    "You now have a full screen window (without title bar) that allows the user to select things behind it, while at the same time still displaying anything you've rendered on top :) Note: this is a windows only solution."

    Update: Digging around a bit, it looks like switching from LWA_ALPHA to LWA_COLORKEY would do the trick if I supply a color for the transparency (much like chromakeying video). For that reason, I've set my Main Camera's background to be lime green (RGB 0, 255, 0) and have swapped out
    Code (CSharp):
    1. SetLayeredWindowAttributes(handle, 0, 51, 2);
    on line 47 for
    Code (CSharp):
    1. SetLayeredWindowAttributes(handle, 0x0000FF00, 0, 1); // handle = current window, 0x0000FF00 = full Green (RGB 0, 255, 0), Opacity = 0 (transparent - used with LWA_ALPHA), LWA_COLORKEY = 1

    Unfortunately, however, the window remains completely opaque (and a hideous lime green, haha). I'll keep fiddling with the values, but if anyone has any suggestions (or any idea why LWA_COLORKEY isn't working for me), that would be fantastic.

    Update 2: Thought I'd try UpdateLayeredWindow, but got the same results. I know this CAN be done, so I'm left to assume that I'm simply implementing it incorrectly... I'm at a loss. From everything I've read, this should be working just fine. On the plus side, I've killed a lot of time helping other people on the forums tonight, haha. Guess I'll get some rest and attack it again later.
     
    Last edited: May 3, 2015
    P-O-W likes this.
  2. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    6,443
    Hi,

    could you mock up a picture of what you're trying to achieve? I'm not entirely sure, but it seems that you want your window to have different shape than a rectangle, so in order to achieve that, you want parts of the rectangle to be transparent?
     
  3. krougeau

    krougeau

    Joined:
    Jul 1, 2012
    Posts:
    449
    Hey there! Thanks for responding :) I'll go you one better and show screenshots of what I'm actually doing (desktop icons intentionally blurred 'cause who cares what I have on my desktop, right?). I'm not looking for any irregular window shapes, just a fullscreen, transparent rectangle... Here is the closest to "working" that the idea has come, using LWA_ALPHA in the SetLayeredWindowAttributes code:




    While the first image may look alright at first glance, the second illustrates how the window's contents (the kitty) are also transparent. It's not as noticeable, but the window itself is also semi-transparent (with a black background in these examples) and slightly darkens the desktop behind them.

    What I'm aiming for is to have a completely clear window by setting my camera's background color to a specific solid color and using LWA_COLORKEY to make _just_ that color transparent, which would, ideally, leave my kitty 100% visible with no transparent parts, much like chromakeying video. Unfortunately, using LWA_COLORKEY and Green as my color, gives me the following results (see next image). My camera's Solid Color is RGBA (0, 255, 0, 0) , or 0x0000FF00 as the Windows specific code would have it. I'm fairly certainly I have these values right & will kick myself viciously if it turns out to be a simple matter of incorrect color choice, haha :) That said, I have tried several other colors, all with the same results.



    From everything I've read, the green color _should_ be being used as a transparency color, so it shouldn't be rendered at all... Some threads I've read also suggested using UpdateLayeredWindow in place of SetLayeredWindowdAttributes, but my results were the same with either.

    I have a feeling I'm simply implementing it incorrectly, but I've been unable to find any working examples for Unity, and the Windows examples I've found are, of course, full of other information that may or may not be relevant. This is my first attempt to make use of an external DLL or the Windows API, and so I'm at a loss as to just what I might be doing wrong. I have also posed my question over at CodeGurus.com, though that post hasn't been approved yet and may not ever be. Since my case is Unity3D specific, I was really hoping that someone here might be able to point me in the right direction.

    Update: For additional reference, here is the documentation on the SetLayeredWindowAttributes function on MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/ms633540(v=vs.85).aspx
     
    Last edited: May 3, 2015
  4. krougeau

    krougeau

    Joined:
    Jul 1, 2012
    Posts:
    449
    I had what I'd hoped was a "Eurkea!" moment last night, but implementation is proving difficult. I've got a feeling that Windows itself really doesn't notice or care what colors my Unity background is set to, and that it's probably only interested in what Windows sees... If that is the case, I need to have Windows set the background color, not Unity. I found some example code on the MSDN forums, but I'm having trouble ferreting out just how to use it through Unity. I've floundered around a bit and have tried importing & making calls to CPaintDC, GetClientRect, and FillSolidRect, but I have no idea if I'm using any of the three correctly, and trying to make sense of the gobbledeygook that is the MSDN documentation makes my head spin. Most of what I'm doing now is guesswork, and I'm not at all confident that my guesses are anywhere near hitting the mark. I suppose I've little choice but to back-burner this project until I can learn Windows API programming inside and out, and then apply that knowledge to Unity. Since it's taken me several years to get to the point where I'm even semi-confident in my C# coding, I doubt that it will be anytime soon. In the meantime, if anyone happens to have any ideas about where I should begin, I'm all ears :) Thanks!
     
  5. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    6,443
    Indeed, layered window will not work - it works when you do the drawing through GDI - drawing through Direct3D ignores the setting.

    Probably the easiest solution would be to write a custom image effect that would make pixels of certain color transparent, and then use DwmExtendFrameIntoClientArea function to actually make your window transparent.

    Check this out:

    https://msdn.microsoft.com/en-us/li...512(v=vs.85).aspx?f=255&MSPPError=-2147217396

    Note though, this method will not work on Windows XP as they added this function in Windows Vista only. Even though I doubt you're targeting such an ancient OS, but since Unity still supports it, I had to warn you :).
     
  6. krougeau

    krougeau

    Joined:
    Jul 1, 2012
    Posts:
    449
    Fantastic! Thanks ever, ever so much :) I'll have a look shortly! I'm up to my elbows in fine tuning another project at the moment, but I'm excited to know that I may still be able to make this happen!

    ETA: Oddly enough, I do still have an old XP box... I keep it around to run my ancient You Don't Know Jack games (among others). Can't say I'd bother trying to make a game for anything older than Vista though haha :p
     
    Last edited: May 4, 2015
  7. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    6,443
    To be honest, I couldn't resist and managed to implement it myself - it's such a cool idea :). Here's my example project:

    http://1drv.ms/1GVupEB
     
    vestigial, StephanM and krougeau like this.
  8. krougeau

    krougeau

    Joined:
    Jul 1, 2012
    Posts:
    449
    You, my friend, are a dozen kinds of way ² cool! :) It looks terrific! I'll be looking forward to poking through the script and shader code to glean what information I can, not to mention making use of it ASAP!!! I'll be crediting you in the upcoming project as well, if you don't mind, and assuming it all comes together. Thank you, thank you, thank you! \m/(>.<)\m/ If I had the means at the moment, I'd send a 12 pack your way, haha!
     
  9. krougeau

    krougeau

    Joined:
    Jul 1, 2012
    Posts:
    449
    It works like a charm! Thank you again!! I've combined your implementation with a modification of the script above, using LWA_ALPHA with a transparency of 254 (just shy of solid) so that users can still interact with their desktop while the program runs. It's absolutely beautiful! :p I can't wait to start teach this crazy kitty (not the mention the rest of my menagerie) to chase the mouse cursor and other fun things. I'll probably also look into keeping the window "always on top" & maybe putting the icon in the systray, but those are nowhere near as important as the transparency was. You, sir, are a scholar and a gentleman. I salute you! :) Have a terrific day (you've certainly made mine).
     
    Last edited: May 5, 2015
  10. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    6,443
    Glad to help :).
     
    ns-arsen and krougeau like this.
  11. krougeau

    krougeau

    Joined:
    Jul 1, 2012
    Posts:
    449
    Final update :) Here's a quick "proof of concept" video showing the kitten in action. It's incredibly minimalistic, but now that I have the window behaving as it should, I can get to work on blending animations properly and making it do more than beg for attention, haha. I was also able to figure out setting the window to be "always on top" this afternoon, so now I'm down to just (maybe) moving the window from the taskbar to the systray. Good times! :p
     
  12. StephanM

    StephanM

    Joined:
    Aug 20, 2013
    Posts:
    25
    Awesome! I'm the OP for the threat that this one came from. Got it working with click-through and always on top.

    using System;
    using System.Runtime.InteropServices;
    using UnityEngine;

    public class TransparentWindow : MonoBehaviour
    {
    [SerializeField]
    private Material m_Material;

    private struct MARGINS
    {
    public int cxLeftWidth;
    public int cxRightWidth;
    public int cyTopHeight;
    public int cyBottomHeight;
    }

    [DllImport("user32.dll")]
    private static extern IntPtr GetActiveWindow();

    [DllImport("user32.dll")]
    private static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);

    [DllImport("user32.dll")]
    static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);

    [DllImport("user32.dll", EntryPoint = "SetLayeredWindowAttributes")]
    static extern int SetLayeredWindowAttributes(IntPtr hwnd, int crKey, byte bAlpha, int dwFlags);

    [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
    private static extern int SetWindowPos(IntPtr hwnd, int hwndInsertAfter, int x, int y, int cx, int cy, int uFlags);

    [DllImport("Dwmapi.dll")]
    private static extern uint DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS margins);

    const int GWL_STYLE = -16;
    const uint WS_POPUP = 0x80000000;
    const uint WS_VISIBLE = 0x10000000;
    const int HWND_TOPMOST = -1;

    void Start()
    {
    #if !UNITY_EDITOR // You really don't want to enable this in the editor..

    int fWidth = Screen.width;
    int fHeight = Screen.height;
    var margins = new MARGINS() { cxLeftWidth = -1 };
    var hwnd = GetActiveWindow();

    SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);

    // Transparent windows with click through
    SetWindowLong(hwnd, -20, 524288 | 32);//GWL_EXSTYLE=-20; WS_EX_LAYERED=524288=&h80000, WS_EX_TRANSPARENT=32=0x00000020L
    SetLayeredWindowAttributes(hwnd, 0, 255, 2);// Transparency=51=20%, LWA_ALPHA=2
    SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, fWidth, fHeight, 32 | 64); //SWP_FRAMECHANGED = 0x0020 (32); //SWP_SHOWWINDOW = 0x0040 (64)
    DwmExtendFrameIntoClientArea(hwnd, ref margins);

    #endif
    }

    void OnRenderImage(RenderTexture from, RenderTexture to)
    {
    Graphics.Blit(from, to, m_Material);
    }
    }
     
    vestigial and krougeau like this.
  13. krougeau

    krougeau

    Joined:
    Jul 1, 2012
    Posts:
    449
    Very cool! So glad you were able to get it working as well, and thanks for starting that original thread, it was a great starting point :)
     
  14. kyewong

    kyewong

    Joined:
    Sep 11, 2014
    Posts:
    22
    I've tried the code provided by @StephanM, set the color of camera to (0,0,0,0) and material in script to (255,255,255,255), and enable the windows frame at start. it works!!!
    However, I've found that the color of the 3d objects is not quite right, comparing to the case in which the script is not used. Is it due to the material I set? What is the proper material (type and color) should I set to the script please?
    Thank you and wait for your respond!
     
    Last edited: Jun 4, 2015
  15. kyewong

    kyewong

    Joined:
    Sep 11, 2014
    Posts:
    22
    This share is not available at the moment. Could you please share it again? Thank you!
     
  16. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    6,443
    Novack, vestigial and GarthSmith like this.
  17. krougeau

    krougeau

    Joined:
    Jul 1, 2012
    Posts:
    449
    kyewong: The code I've been using is from the sample project Tautvydas posted, so it's really your best bet.

    Tautvydas: You're listed in the credits of my latest application & I'd be happy to send you a link if you'd like to see it in action :) Thanks again!
     
    Last edited: Jun 4, 2015
  18. kyewong

    kyewong

    Joined:
    Sep 11, 2014
    Posts:
    22
  19. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    6,443
    Probably, I think I made the project with Unity 5, can't remember. The scene is almost empty anyway: there's a cube with scripts attached to move and spin it, camera with script attached to make window transparent (and a material in scripts public field) and a directional light.
     
  20. kyewong

    kyewong

    Joined:
    Sep 11, 2014
    Posts:
    22
    I've tested in Unity 4.6.5, it just works perfectly!
    The shader is important. At first I set the material in the script to default diffuse, and found that the color is not quite right comparing to the case in which the transparent background is not set. After applying the shader, the color becomes correct.
    Thank you very much guys!
    BTW. I need to try Unity5.0 asap^_^
     
    krougeau likes this.
  21. kyewong

    kyewong

    Joined:
    Sep 11, 2014
    Posts:
    22
    I found one more bug with the above method: when I'm trying to show a small movie with transparent background inside the above setting(transparent window with opaque contents), by using the FX/flare shader to the plane of the video, it shows a black movie background, while the movie shows normally(with transparent background) in a normal scene(without applying the transparent window method). I guess it is the shader in this method that affects the shader of the movie plane.
    Could anyone give me suggestions on how to solve this problem please? Should I make some changes to the shader of the transparent window, or change the shader of the movie plane? Thank you!
     
  22. jrjr

    jrjr

    Joined:
    Feb 7, 2014
    Posts:
    5
    Hey there, I was wondering what the camera and material settings you all used for making this work? I have the click through and transparency working but the cube is still transparent also. Appreciate the hand!
     
  23. ATLAS-INTERACTIVE

    ATLAS-INTERACTIVE

    Joined:
    Mar 3, 2014
    Posts:
    1,295
    @krougeau A am using the code at the top for a side project i have been working on for a while now, but have run into a little problem with it I a hoping you will be able to fix, as I am not accustomed to working with, or understand the Windows API.
    If I have a button, with partial transparency, it doesn't just show what is behind it in the UI, which is a solid background image, but shows the desktop as well. From what I can tell, it is using that button's transparency for the whole area in the window, and is making the solid background behind it partially transparent.

    The code I am using is below:

    Code (CSharp):
    1. [SerializeField]
    2.     private Material m_Material;
    3.  
    4. [DllImport("user32.dll")]
    5.     private static extern IntPtr GetActiveWindow();
    6.  
    7.     [DllImport("user32.dll")]
    8.     private static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);
    9.  
    10.     [DllImport("Dwmapi.dll")]
    11.     private static extern uint DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS margins);
    12.  
    13. const uint WS_POPUP = 0x80000000;
    14.     const uint WS_VISIBLE = 0x10000000;
    15.  
    16. void Start ()
    17.     {
    18. var margins = new MARGINS() { cxLeftWidth = -1 };
    19.         var hwnd = GetActiveWindow();
    20.  
    21.         SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
    22.  
    23.         DwmExtendFrameIntoClientArea(hwnd, ref margins);
    24. }
    25.  
    26. void OnRenderImage(RenderTexture from, RenderTexture to)
    27.     {
    28.         Graphics.Blit(from, to, m_Material);
    29.     }
     
  24. LordDarkon76

    LordDarkon76

    Joined:
    Apr 1, 2015
    Posts:
    21
    Thank you for sharing.

    A particle emitter following the mouse.
     
  25. catafest

    catafest

    Joined:
    May 3, 2014
    Posts:
    47
    Last edited: Feb 26, 2016
  26. ns-arsen

    ns-arsen

    Joined:
    Oct 7, 2015
    Posts:
    9
    is it posible to put options in clock tray, like:
    1 cahange of character (dog or duck instead of cat)
    2 soound control to lover down sounds or mute


    thanks in advance
     
  27. MS80

    MS80

    Joined:
    Mar 7, 2014
    Posts:
    335
    @Tautvydas Zilys Thanks for sharing! Unfortunately I cannot get it to work, the color is keyed out, but the background is black instead of transparent. I'm on Win7 64bit, using Unity5.3.2.

    Is there anything special to do with this project or should it work out of the box?
     
    Last edited: Mar 13, 2016
  28. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    6,443
    Is AERO disabled? It works out of the box on Windows 8+, but it breaks down on Windows 7 if AERO is disabled.
     
  29. MS80

    MS80

    Joined:
    Mar 7, 2014
    Posts:
    335
    Thank you, that was the problem, after enabling AERO on Win7 it worked perfectly! :)

    Also I tried @StephanM 's script (click through) which works great, too. Now I have a question, do you think it is possible to get both, the opportunity to click and select desktop icons / folders AND to click on buttons / 3D Objects inside the unity build? (something like a application focus switch)?

    I have made a quick test with some ui elements (unity run in background, visible in backround, click through script by StephanM), and while I can select my desktop icons and everything else the unity buttons still recognize mouse over?!

    How could we switch between desktop (or any windows background) and unity foreground objects (like buttons, sliders, object pick, etc.)?
    Something like: if on transparent background = windows focus; everything else = unity focus??
     
    Last edited: Mar 23, 2016
  30. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    6,443
    It's probably possible - WinAPI is so vast that it probably has a way to achieve it. However, I've no idea how to implement it.
     
  31. zalo10

    zalo10

    Joined:
    Dec 5, 2012
    Posts:
    14
    I implemented it with raycasts; just disable clickthrough when the mouse is hovering on top of something and enable it when the mouse is hovering over nothingess.

    As long as your program is set to run in the background (set via the player settings (Edit -> Project Settings -> Player -> Resolution and Presentation -> Run In Background*)), it should capture focus AND trigger your action in the same click.

    Code (CSharp):
    1. using System;
    2. using System.Runtime.InteropServices;
    3. using UnityEngine;
    4.  
    5. [RequireComponent (typeof (Camera))]
    6. public class TransparentWindow : MonoBehaviour
    7. {
    8.     [SerializeField]
    9.     private Material m_Material;
    10.  
    11.     [SerializeField]
    12.     private Camera mainCamera;
    13.  
    14.     private bool clickThrough = true;
    15.     private bool prevClickThrough = true;
    16.  
    17.     private struct MARGINS
    18.     {
    19.         public int cxLeftWidth;
    20.         public int cxRightWidth;
    21.         public int cyTopHeight;
    22.         public int cyBottomHeight;
    23.     }
    24.  
    25.     [DllImport("user32.dll")]
    26.     private static extern IntPtr GetActiveWindow();
    27.  
    28.     [DllImport("user32.dll")]
    29.     private static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);
    30.  
    31.     [DllImport("user32.dll")]
    32.     static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
    33.  
    34.     [DllImport("user32.dll", EntryPoint = "SetLayeredWindowAttributes")]
    35.     static extern int SetLayeredWindowAttributes(IntPtr hwnd, int crKey, byte bAlpha, int dwFlags);
    36.  
    37.     [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
    38.     private static extern int SetWindowPos(IntPtr hwnd, int hwndInsertAfter, int x, int y, int cx, int cy, int uFlags);
    39.  
    40.     [DllImport("Dwmapi.dll")]
    41.     private static extern uint DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS margins);
    42.  
    43.     const int GWL_STYLE = -16;
    44.     const uint WS_POPUP = 0x80000000;
    45.     const uint WS_VISIBLE = 0x10000000;
    46.     const int HWND_TOPMOST = -1;
    47.  
    48.     int fWidth;
    49.     int fHeight;
    50.     IntPtr hwnd;
    51.     MARGINS margins;
    52.  
    53.     void Start()
    54.     {
    55.         mainCamera = GetComponent<Camera> ();
    56.  
    57.         #if !UNITY_EDITOR // You really don't want to enable this in the editor..
    58.  
    59.         fWidth = Screen.width;
    60.         fHeight = Screen.height;
    61.         margins = new MARGINS() { cxLeftWidth = -1 };
    62.         hwnd = GetActiveWindow();
    63.  
    64.         SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
    65.         SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, fWidth, fHeight, 32 | 64); //SWP_FRAMECHANGED = 0x0020 (32); //SWP_SHOWWINDOW = 0x0040 (64)
    66.         DwmExtendFrameIntoClientArea(hwnd, ref margins);
    67.  
    68.         Application.runInBackground = true;
    69.         #endif
    70.     }
    71.  
    72.     void Update ()
    73.     {
    74.         // If our mouse is overlapping an object
    75.         RaycastHit hit = new RaycastHit();
    76.         clickThrough = !Physics.Raycast (mainCamera.ScreenPointToRay (Input.mousePosition).origin,
    77.                 mainCamera.ScreenPointToRay (Input.mousePosition).direction, out hit, 100,
    78.                 Physics.DefaultRaycastLayers);
    79.  
    80.         if (clickThrough != prevClickThrough) {
    81.             if (clickThrough) {
    82.                 #if !UNITY_EDITOR
    83.                 SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
    84.                 SetWindowLong (hwnd, -20, (uint)524288 | (uint)32);//GWL_EXSTYLE=-20; WS_EX_LAYERED=524288=&h80000, WS_EX_TRANSPARENT=32=0x00000020L
    85.                 SetLayeredWindowAttributes (hwnd, 0, 255, 2);// Transparency=51=20%, LWA_ALPHA=2
    86.                 SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, fWidth, fHeight, 32 | 64); //SWP_FRAMECHANGED = 0x0020 (32); //SWP_SHOWWINDOW = 0x0040 (64)
    87.                 #endif
    88.             } else {
    89.                 #if !UNITY_EDITOR
    90.                 SetWindowLong (hwnd, -20, ~(((uint)524288) | ((uint)32)));//GWL_EXSTYLE=-20; WS_EX_LAYERED=524288=&h80000, WS_EX_TRANSPARENT=32=0x00000020L
    91.                 SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, fWidth, fHeight, 32 | 64); //SWP_FRAMECHANGED = 0x0020 (32); //SWP_SHOWWINDOW = 0x0040 (64)
    92.                 #endif
    93.             }
    94.             prevClickThrough = clickThrough;
    95.         }
    96.     }
    97.  
    98.     void OnRenderImage(RenderTexture from, RenderTexture to)
    99.     {
    100.         Graphics.Blit(from, to, m_Material);
    101.     }
    102. }
    Thank you, Tautvydas Zilys, for the original code!
     
    Last edited: Apr 4, 2016
    LazyDog_Rich likes this.
  32. friuns3

    friuns3

    Joined:
    Oct 30, 2009
    Posts:
    273

    is it possible to keep close button and border on the window?
    like this but wihtout blur
     
  33. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    6,443
    Not sure about border, but the title bar should remain if you don't specify WS_POPUP.
     
  34. friuns3

    friuns3

    Joined:
    Oct 30, 2009
    Posts:
    273
    didn't help it dont have tittle bar, please help :p
    source: https://oc.unity3d.com/public.php?service=files&t=3d5386c7d69be60cbb6873853bf0d7b1

    Code (CSharp):
    1. using System;
    2. using System.Runtime.InteropServices;
    3. using UnityEngine;
    4.  
    5. public class TransparentWindow1 : 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("Dwmapi.dll")]
    25.     private static extern uint DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS margins);
    26.  
    27.     const int GWL_STYLE = -16;
    28.     const uint WS_POPUP = 0x80000000;
    29.     const uint WS_VISIBLE = 0x10000000;
    30.  
    31.     void Start()
    32.     {
    33. //#if !UNITY_EDITOR   // You really don't want to enable this in the editor..
    34.         var margins = new MARGINS() { cxLeftWidth = -1 };
    35.         var hwnd = GetActiveWindow();
    36.  
    37.         SetWindowLong(hwnd, GWL_STYLE, WS_VISIBLE);
    38.  
    39.         DwmExtendFrameIntoClientArea(hwnd, ref margins);
    40. //#endif
    41.     }
    42.  
    43.     void OnRenderImage(RenderTexture from, RenderTexture to)
    44.     {
    45.         Graphics.Blit(from, to, m_Material);
    46.     }
    47. }
     
    Last edited: Jun 14, 2016
  35. EvalDaemon

    EvalDaemon

    Joined:
    Aug 8, 2013
    Posts:
    100
    I have a question, what is OnRenderImage and m_Material's purpose? What is it doing because I have it working without them.

    Also, how would you go about Turning Off the transparency?
     
  36. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    6,443
    So in my original example, camera gets cleared to blue color. The blit turns blue into transparent using the shader that's set on the material.
     
  37. Aizat-Musa

    Aizat-Musa

    Joined:
    Feb 25, 2016
    Posts:
    8
    Hi,

    this work just fine when i use only one display but when i activate more than 1 display, only the last display will turn transparent. is there any workaround to set all display to turn transparent or at least i can choose only to set display 1 to turn to transparent.
     
  38. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,372
    sorry to necro this thread, i'm just curious. it is possible to make the windows layer right behind the desktop icons to overlay the wallpaper?
     
  39. getbiks

    getbiks

    Joined:
    May 13, 2012
    Posts:
    20
    Hi.. Cool post.. Was fiddling with it.. but the canvas is very opaque and options are not clickable.... (check screenshot) So is there any way to make the canvas prominent... ????
     

    Attached Files:

  40. getbiks

    getbiks

    Joined:
    May 13, 2012
    Posts:
    20
    Cool.. Got it working... :D
     
  41. MR_asilva

    MR_asilva

    Joined:
    Oct 23, 2015
    Posts:
    13
    Hello @Tautvydas-Zilys,

    Thank you for the sample project.

    I am trying to build a proof of concept demo where I switch back and forth between a fully transparent window and a fully opaque UI by simply enabling and disabling the TransparentWindow component (along with doing the opposite on the UI root GameObject).

    Currently, if I start with the TransparentWindow component in the disabled state and then turn it on while turning my opaque UI off, I get the desired transparent window (except for two buttons which I am purposely leaving visible to toggle the states), but then if I try to go back, my opaque UI comes back on, but it is semi-transparent instead of opaque - so the TransparentWindow script or material/shader seems to be putting something in a state that it can't recover from and get back to its original fully opaque state. Also, going back to fully opaque keeps the semi-transparent UI as well and if I start with the TransparentWindow component enabled, I get the same result (i.e. my opaque UI is semi-transparent). I would think, based on the description and reading the shader, that if there are no pixels with the key color visible (255,0,0 in my case), then no pixels would be altered, but that does not appear to be the case.

    Can you please take a look at my very small sample project and tell me what I'm doing wrong? Or maybe I am misunderstanding the intent of the project/shader you provided?

    Thanks in advance for any help you can provide!

    Update: One other hint - the non-opacity issues only happen when one of the sprite textures has alpha information in it.
     

    Attached Files:

    Last edited: Apr 28, 2017
  42. MR_asilva

    MR_asilva

    Joined:
    Oct 23, 2015
    Posts:
    13
    Figured it out. :) It was the call to DwmExtendFrameIntoClientArea. What I didn't realize is that the main purpose for this line of code was to allow the window to be see-through into the desktop (because the margins were set to -1). I couldn't find what the defaults are supposed to be, but I used 0, since it's a full screen app and there shouldn't be any margins anyway. So, when I go into transparent mode, I set them to -1 and when I come back, I set them to 0. Hope this helps someone else out there! Thanks again to @Tautvydas-Zilys for the demo project!
     
    Lamarn and Berno like this.
  43. MR_asilva

    MR_asilva

    Joined:
    Oct 23, 2015
    Posts:
    13
    @Tautvydas-Zilys, I've run into what seems to be a limitation of this method and I'm wondering if you might have any suggestions for how to solve it. The limitation is that the method is a key color algorithm and so if an object is at all semi-transparent, you can see the background key color through the transparent areas.

    My first thought to get around this was to just apply this full screen effect to a camera that renders nothing but its background color and use that as the key color for the material/shader then render any semi-transparent objects on top of that using a second camera that doesn't clear the frame buffer. However, it seems that (at least in my current version of Unity, which is 5.3.7) I am not able to do this:

    Render bottom level camera with only key color in it -> apply full screen effect so that the whole screen is transparent -> render next level camera with semi-transparent objects in it

    in that order. No matter what I try, the full screen effect only seems to get applied after ALL cameras have rendered instead of after the camera that it's attached to in the inspector. Is there a way to get the render order to be in the order shown above? Or is there maybe another way to add semi-transparent object support where you don't see the key color through the semi-transparent (and instead see the desktop in those areas)?
     
    NightmarexGR likes this.
  44. royvaneijndhoven

    royvaneijndhoven

    Joined:
    Jun 1, 2017
    Posts:
    59
    I hoped this would work in a Windows Store build but sadly it doesn't. The background is transparant in a regular Windows build but completly black in a Windows Store build. Probably because of the way Windows 10 handles Apps from the Store.

    If someone finds a solution for this, please let me know.
     
  45. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    6,443
    It's possible, but you'll need to make a native plugin and use a transparent swapchain for this to work. I don't think you'll be able to get rid of the window borders, though.
     
  46. royvaneijndhoven

    royvaneijndhoven

    Joined:
    Jun 1, 2017
    Posts:
    59
    Alright, that's something we'll have to look into. Thanks.
     
  47. minhinh

    minhinh

    Joined:
    Aug 8, 2017
    Posts:
    1
    [QUOTE = "Tautvydas-Zilys, post: 2099155, member: 359058"] Vui lòng giúp đỡ :). [/ QUOTE]
    Bạn có thể xin vui lòng cho tôi mã nguồn của nó. Cảm ơn bạn !
    Email: americanstudio94@gmail.com
     
  48. Reddevildragg

    Reddevildragg

    Joined:
    May 19, 2014
    Posts:
    28
    Is there a way to disable DwmExtendFrameIntoClientArea when a new scene loads? I have a launcher that currently have the transparacy/pass through working but i want to disable it and return to the default windows settings when i select a scene. I tried setting the margins from -1 to 0 with this code
    Code (CSharp):
    1.         var margins = new MARGINS() { cxLeftWidth = -1 };
    2.         var hwnd = GetActiveWindow();
    3.         SetWindowLong(hwnd, GWL_STYLE, WS_VISIBLE);
    4.         DwmExtendFrameIntoClientArea(hwnd, ref margins);
    still end up with a transparent window though, just wanting to restore it back to its default windows behaviour and make full screen. Thanks for any help
     
  49. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    6,443
  50. Reddevildragg

    Reddevildragg

    Joined:
    May 19, 2014
    Posts:
    28
    Reading that (unless im misreading something) says that to create the "sheet of glass" effect where it has no border, which is what i want for the first scene, i need to set it to -1, unless i can do that by extending all 4 sides by something and then resetting them back?

    EDIT: so i tried doing this with setting all the boarders to 10 but this then did not have the transparency around the scene, just where the new boarders would of been, and it was rendered as a black background (although it did reset fine)
     
    Last edited: Aug 11, 2017