Uniy打包时去边框和实现窗体透明穿透

Posted by d77 on 2021-10-24

Unity打包时去边框和实现窗体透明穿透

最近想做一个桌宠。主要的动画和互动设置其实都挺好实现的。但是有一点与往常制作不同,它需要运行时没有边框,同时需要实现一个窗体透明的效果。


参考链接:https://blog.csdn.net/q493201681/article/details/65936592

1.如何去边框

我们可以调用系统自带的函数来实现去边框。

这里首先要引入user32.dll这个动态连接库

[DllImport("user32.dll")]

利用获取窗体句柄FindWindow(),设置窗体属性SetWindowLong(),获取窗体属性GetWindowLong(),设置窗体大小置顶SetWindowPos()函数就可以解决置顶去边框的问题

[DllImport("user32.dll")]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

[DllImport("user32.dll")]
static extern int GetWindowLong(IntPtr hWnd, int nIndex);

[DllImport("user32.dll")]
static extern int SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);

const uint SWP_SHOWWINDOW = 0x0040;  
const int GWL_STYLE = -16;  
const int WS_BORDER = 1;  
const int WS_POPUP = 0x800000;  

函数使用(后面会有总体代码

  SetWindowLong(hwnd, GWL_STYLE, WS_POPUP);
        SetWindowPos(hwnd, -1, currentX, currentY, ResWidth, ResHeight, SWP_SHOWWINDOW); 

————————————————

关于去边框的参考链接:https://blog.csdn.net/gotone2008/article/details/103616033

2.如何实现窗体透明和窗体穿透

这里同样可以利用系统自带函数DwmExtendFrameIntoClientArea();
但是要另外引入库Dwmapi.dll

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

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

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

函数使用

var margins = new MARGINS() { cxLeftWidth = -1 };
DwmExtendFrameIntoClientArea(hwnd, ref margins);

3.总体代码


把代码挂在一个物体上就可以了,参考窗口大小:1280*720


using UnityEngine;
using System.Collections;
using System;
using System.Runtime.InteropServices;
using System.IO;


// 一共可选择三种样式
public enum enumWinStyle
{

// 置顶
WinTop,
// 置顶并且透明
WinTopAlpha,
// 置顶透明并且可以穿透
WinTopAlphaPenetrate
}
public class WinSetting : MonoBehaviour
{

#region Win函数常量
private struct MARGINS
{
    public int cxLeftWidth;
    public int cxRightWidth;
    public int cyTopHeight;
    public int cyBottomHeight;
}

[DllImport("user32.dll")]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

[DllImport("user32.dll")]
static extern int GetWindowLong(IntPtr hWnd, int nIndex);

[DllImport("user32.dll")]
static extern int SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);

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

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

private const int GWL_STYLE = -16;
private const int WS_POPUP = 0x800000;
private const int GWL_EXSTYLE = -20;

private const int WS_EX_LAYERED = 0x00080000;
private const int WS_BORDER = 0x00800000;
private const int WS_CAPTION = 0x00C00000;
private const int SWP_SHOWWINDOW = 0x0040;
private const int LWA_COLORKEY = 0x00000001;
private const int LWA_ALPHA = 0x00000002;
private const int WS_EX_TRANSPARENT = 0x20;
//
private const int ULW_COLORKEY = 0x00000001;
private const int ULW_ALPHA = 0x00000002;
private const int ULW_OPAQUE = 0x00000004;
private const int ULW_EX_NORESIZE = 0x00000008;
#endregion
//
public string strProduct;//项目名称
public enumWinStyle WinStyle = enumWinStyle.WinTop;//窗体样式
//
public int ResWidth;//窗口宽度
public int ResHeight;//窗口高度
//
public int currentX;//窗口左上角坐标x
public int currentY;//窗口左上角坐标y
//
private bool isAlpha;//是否透明
private bool isAlphaPenetrate;//是否要穿透窗体
// Use this for initialization
void Awake()
{
    Screen.fullScreen = false;
#if UNITY_EDITOR
print("编辑模式不更改窗体");
#else
    switch (WinStyle)
    {
        case enumWinStyle.WinTop:
            isAlpha = false;
            isAlphaPenetrate = false;
            break;
        case enumWinStyle.WinTopAlpha:
            isAlpha = true;
            isAlphaPenetrate = false;
            break;
        case enumWinStyle.WinTopAlphaPenetrate:
            isAlpha = true;
            isAlphaPenetrate = true;
            break;
    }
    //
    IntPtr hwnd = FindWindow(null, strProduct);
    //
    if (isAlpha)
    {
        //去边框并且透明
        SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_LAYERED);
        int intExTemp = GetWindowLong(hwnd, GWL_EXSTYLE);
        if (isAlphaPenetrate)//是否透明穿透窗体
        {
            SetWindowLong(hwnd, GWL_EXSTYLE, intExTemp | WS_EX_TRANSPARENT | WS_EX_LAYERED);
        }
        //
        SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_BORDER & ~WS_CAPTION);
        SetWindowPos(hwnd, -1, currentX, currentY, ResWidth, ResHeight, SWP_SHOWWINDOW);
        var margins = new MARGINS() { cxLeftWidth = -1 };
        //
        DwmExtendFrameIntoClientArea(hwnd, ref margins);
    }
    else
    {
        //单纯去边框
        SetWindowLong(hwnd, GWL_STYLE, WS_POPUP);
        SetWindowPos(hwnd, -1, currentX, currentY, ResWidth, ResHeight, SWP_SHOWWINDOW);
    }
#endif
}
}