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/ & Viewing desktop in-scene - Questions & Answers - Unity Discussions, 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!!
//Note: Inspired by and uses some code found here: http://forum.unity3d.com/threads/windows-api-calls.127719/
using UnityEngine;
using System.Collections;
using System;
using System.Runtime.InteropServices; // Pro and Free!!!
//WARNING!! Running this code inside Unity when not in a build will make the entire development environment transparent
//Restarting Unity would however resolve
public class TransparentWindow : MonoBehaviour
{
[DllImport("user32.dll", EntryPoint = "SetWindowLongA")]
static extern int SetWindowLong(int hwnd, int nIndex, long dwNewLong);
[DllImport("user32.dll")]
static extern bool ShowWindowAsync(int hWnd, int nCmdShow);
[DllImport("user32.dll", EntryPoint = "SetLayeredWindowAttributes")]
static extern int SetLayeredWindowAttributes(int hwnd, int crKey, byte bAlpha, int dwFlags);
[DllImport("user32.dll", EntryPoint = "GetActiveWindow")]
private static extern int GetActiveWindow();
[DllImport("user32.dll", EntryPoint = "GetWindowLong")]
private static extern long GetWindowLong(int hwnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
private static extern int SetWindowPos(int hwnd, int hwndInsertAfter, int x, int y, int cx, int cy, int uFlags);
void Start()
{
int handle = GetActiveWindow();
int fWidth = Screen.width;
int fHeight = Screen.height;
//Remove title bar
long lCurStyle = GetWindowLong(handle, -16); // GWL_STYLE=-16
int a = 12582912; //WS_CAPTION = 0x00C00000L
int b = 1048576; //WS_HSCROLL = 0x00100000L
int c = 2097152; //WS_VSCROLL = 0x00200000L
int d = 524288; //WS_SYSMENU = 0x00080000L
int e = 16777216; //WS_MAXIMIZE = 0x01000000L
lCurStyle &= ~(a | b | c | d);
lCurStyle &= e;
SetWindowLong(handle, -16, lCurStyle);// GWL_STYLE=-16
// Transparent windows with click through
SetWindowLong(handle, -20, 524288 | 32);//GWL_EXSTYLE=-20; WS_EX_LAYERED=524288=&h80000, WS_EX_TRANSPARENT=32=0x00000020L
SetLayeredWindowAttributes(handle, 0, 51, 2);// Transparency=51=20%, LWA_ALPHA=2
SetWindowPos(handle, 0, 0, 0, fWidth, fHeight, 32 | 64); //SWP_FRAMECHANGED = 0x0020 (32); //SWP_SHOWWINDOW = 0x0040 (64)
ShowWindowAsync(handle, 3); //Forces window to show in case of unresponsive app // SW_SHOWMAXIMIZED(3)
}
} // end of file
richyrich’s instructions:
- Add the above code to your project
- Go to your camera and select it. In the Inspector, change the colors and the alpha to 0.
- 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
csharp* *SetLayeredWindowAttributes(handle, 0, 51, 2);* *
on line 47 for
csharp* *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.