Search Unity

  1. We are migrating the Unity Forums to Unity Discussions by the end of July. Read our announcement for more information and let us know if you have any questions.
    Dismiss Notice
  2. Dismiss Notice

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

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

  1. howlthewizard24

    howlthewizard24

    Joined:
    Apr 17, 2023
    Posts:
    1
    Hi, I am also trying to make a transparent windowed game and it works well but I have a problem. I want to set game window above the windows task bar. I tried out to change int y value in SetWindowPos but it didn't work. So if anyone can help me or just give an advice that would be amazing.
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System;
    4. using System.Runtime.InteropServices; // Pro and Free!!!
    5.  
    6.  
    7. public class TransparentWindow : MonoBehaviour
    8. {
    9.     [DllImport("user32.dll", EntryPoint = "SetWindowLongA")]
    10.     static extern int SetWindowLong(int hwnd, int nIndex, long dwNewLong);
    11.     [DllImport("user32.dll")]
    12.     static extern bool ShowWindowAsync(int hWnd, int nCmdShow);
    13.     [DllImport("user32.dll", EntryPoint = "SetLayeredWindowAttributes")]
    14.     static extern int SetLayeredWindowAttributes(int hwnd, int crKey, byte bAlpha, uint dwFlags);
    15.     [DllImport("user32.dll", EntryPoint = "GetActiveWindow")]
    16.     private static extern int GetActiveWindow();
    17.     [DllImport("user32.dll", EntryPoint = "GetWindowLong")]
    18.     private static extern long GetWindowLong(int hwnd, int nIndex);
    19.     [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
    20.     private static extern int SetWindowPos(int hwnd, int hwndInsertAfter, int x, int y, int cx, int cy, int uFlags);
    21.  
    22.     const uint LWA_COLORKEY = 0x00000001;
    23.     const int HWND_TOPMOST = -1;
    24.  
    25.     void Start()
    26.     {
    27.         int handle = GetActiveWindow();
    28.         int fWidth = Screen.width;
    29.         int fHeight = Screen.height;
    30.  
    31.         //Remove title bar
    32.         long lCurStyle = GetWindowLong(handle, -16);  // GWL_STYLE=-16
    33.         int a = 12582912;  //WS_CAPTION = 0x00C00000L
    34.         int b = 1048576;  //WS_HSCROLL = 0x00100000L
    35.         int c = 2097152;  //WS_VSCROLL = 0x00200000L
    36.         int d = 524288;  //WS_SYSMENU = 0x00080000L
    37.         int e = 16777216;  //WS_MAXIMIZE = 0x01000000L
    38.  
    39.         lCurStyle &= ~(a | b | c | d);
    40.         lCurStyle &= e;
    41.         SetWindowLong(handle, -16, lCurStyle);// GWL_STYLE=-16
    42.  
    43.         // Transparent windows with click through
    44.         SetWindowLong(handle, -20, 524288);//GWL_EXSTYLE=-20; WS_EX_LAYERED=524288=&h80000, WS_EX_TRANSPARENT=32=0x00000020L
    45.         SetLayeredWindowAttributes(handle, 0, 0, LWA_COLORKEY);// Transparency=51=20%, LWA_ALPHA=2
    46.  
    47.         SetWindowPos(handle, HWND_TOPMOST, 0,0, fWidth, fHeight * 2 /5, 32); //SWP_FRAMECHANGED = 0x0020 (32); //SWP_SHOWWINDOW = 0x0040 (64)
    48.         ShowWindowAsync(handle, 3); //Forces window to show in case of unresponsive app  // SW_SHOWMAXIMIZED(3)
    49.     }
    50. } /
     
  2. devfromest

    devfromest

    Joined:
    Oct 18, 2023
    Posts:
    2
    I am trying to achieve the same thing, have you found the solution?
     
  3. Threeyes

    Threeyes

    Joined:
    Jun 19, 2014
    Posts:
    81
    It seems that the developer can only control the state of the mouse inside the window, and when the window area is exceeded, the cursor is controlled by the system. Therefore, you can only get and update the status of the cursor in the window in real time through the system API.
     
  4. devfromest

    devfromest

    Joined:
    Oct 18, 2023
    Posts:
    2
    Thank you. Do you mean like this?:
    Code (CSharp):
    1. using System;
    2. using System.Runtime.InteropServices;
    3. using UnityEngine;
    4.  
    5. public class CustomCursorRenderer : MonoBehaviour
    6. {
    7.     [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
    8.     public static extern IntPtr LoadCursorFromFile(string filename);
    9.  
    10.     [DllImport("user32.dll")]
    11.     static extern bool SetSystemCursor(IntPtr hcur, uint id);
    12.  
    13.  
    14.  
    15.     void Start()
    16.     {
    17.         // Load the custom cursor from file
    18.         string cursorFilePath = Application.dataPath + "/CustomCursor.cur"; // Adjust the file path as necessary
    19.         IntPtr cursorHandle = LoadCursorFromFile(cursorFilePath);
    20.  
    21.         // Set the system cursor to the custom cursor
    22.         SetSystemCursor(cursorHandle, 32512); // 32512 is the ID for the normal arrow cursor, adjust if necessary
    23.     }
    24.  
    25.     void Update()
    26.     {
    27.         // Handle cursor movement and input events here
    28.     }
    29. }
    As my main goal is overlay the mouse and not change it everywhere, it is not working for me. I need it to work in my window. But when I apply transparency (WS_EX_TRANSPARENT = 0x00000020) I assume system is taking it like there is no window. My theory is, that I need to turn it of , and may be there is some way to send clicks from my window to the system behind it. But I have not find the solution yet.