926 lines
32 KiB
C#
926 lines
32 KiB
C#
/*
|
|
* UniWinCore.cs
|
|
*
|
|
* Author: Kirurobo http://twitter.com/kirurobo
|
|
* License: MIT 许可证
|
|
*/
|
|
|
|
using System;
|
|
using System.Runtime.InteropServices;
|
|
using AOT;
|
|
using UnityEngine;
|
|
using System.Text;
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
#endif
|
|
|
|
namespace Kirurobo
|
|
{
|
|
/// <summary>
|
|
/// LibUniWinC 的原生插件包装
|
|
/// </summary>
|
|
internal class UniWinCore : IDisposable
|
|
{
|
|
/// <summary>
|
|
/// 仅 Windows 下的透明方法类型
|
|
/// </summary>
|
|
public enum TransparentType : int
|
|
{
|
|
None = 0,
|
|
Alpha = 1,
|
|
ColorKey = 2,
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 状态变更事件类型(实验性)
|
|
/// </summary>
|
|
[Flags]
|
|
public enum WindowStateEventType : int
|
|
{
|
|
None = 0,
|
|
StyleChanged = 1,
|
|
Resized = 2,
|
|
|
|
// 后续规格可能会有变更
|
|
TopMostEnabled = 16 + 1 + 8,
|
|
TopMostDisabled = 16 + 1,
|
|
BottomMostEnabled = 32 + 1 + 8,
|
|
BottomMostDisabled = 32 + 1,
|
|
WallpaperModeEnabled = 64 + 1 + 8,
|
|
WallpaperModeDisabled = 64 + 1,
|
|
};
|
|
|
|
#region Native functions
|
|
protected class LibUniWinC
|
|
{
|
|
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
|
public delegate void StringCallback([MarshalAs(UnmanagedType.LPWStr)] string returnString);
|
|
|
|
[UnmanagedFunctionPointer((CallingConvention.Winapi))]
|
|
public delegate void IntCallback([MarshalAs(UnmanagedType.I4)] int value);
|
|
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool IsActive();
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool IsTransparent();
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool IsBorderless();
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool IsTopmost();
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool IsBottommost();
|
|
|
|
[DllImport("LibUniWinC", CallingConvention=CallingConvention.Winapi)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool IsMaximized();
|
|
|
|
[DllImport("LibUniWinC", CallingConvention=CallingConvention.Winapi)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool IsFreePositioningEnabled();
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool AttachMyWindow();
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool AttachMyOwnerWindow();
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool AttachMyActiveWindow();
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool DetachWindow();
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
public static extern void Update();
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
public static extern void SetTransparent([MarshalAs(UnmanagedType.U1)] bool bEnabled);
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
public static extern void SetBorderless([MarshalAs(UnmanagedType.U1)] bool bEnabled);
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
public static extern void SetAlphaValue(float alpha);
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
public static extern void SetClickThrough([MarshalAs(UnmanagedType.U1)] bool bEnabled);
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
public static extern void SetTopmost([MarshalAs(UnmanagedType.U1)] bool bEnabled);
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
public static extern void SetBottommost([MarshalAs(UnmanagedType.U1)] bool bEnabled);
|
|
|
|
[DllImport("LibUniWinC", CallingConvention = CallingConvention.Winapi)]
|
|
public static extern void SetMaximized([MarshalAs(UnmanagedType.U1)] bool bZoomed);
|
|
|
|
[DllImport("LibUniWinC", CallingConvention = CallingConvention.Winapi)]
|
|
public static extern void EnableFreePositioning([MarshalAs(UnmanagedType.U1)] bool bEnabled);
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
public static extern void SetPosition(float x, float y);
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool GetPosition(out float x, out float y);
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
public static extern void SetSize(float x, float y);
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool GetSize(out float x, out float y);
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool GetClientSize(out float width, out float height);
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool GetClientRectangle(out float x, out float y, out float width, out float height);
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool RegisterDropFilesCallback([MarshalAs(UnmanagedType.FunctionPtr)] StringCallback callback);
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool UnregisterDropFilesCallback();
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool RegisterMonitorChangedCallback([MarshalAs(UnmanagedType.FunctionPtr)] IntCallback callback);
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool UnregisterMonitorChangedCallback();
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool RegisterWindowStyleChangedCallback([MarshalAs(UnmanagedType.FunctionPtr)] IntCallback callback);
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool UnregisterWindowStyleChangedCallback();
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool SetAllowDrop([MarshalAs(UnmanagedType.U1)] bool enabled);
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
public static extern int GetCurrentMonitor();
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
public static extern int GetMonitorCount();
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool GetMonitorRectangle(int index, out float x, out float y, out float width, out float height);
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
public static extern void SetCursorPosition(float x, float y);
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool GetCursorPosition(out float x, out float y);
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
public static extern int GetMouseButtons();
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
public static extern int GetModifierKeys();
|
|
|
|
|
|
#region 仅适用于 Windows
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
public static extern void SetTransparentType(int type);
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
public static extern void SetKeyColor(uint colorref);
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
public static extern int GetDebugInfo();
|
|
|
|
[DllImport("LibUniWinC",CallingConvention=CallingConvention.Winapi)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
public static extern bool AttachWindowHandle(IntPtr hWnd);
|
|
#endregion
|
|
}
|
|
#endregion
|
|
|
|
static string[] lastDroppedFiles;
|
|
static bool wasDropped = false;
|
|
static bool wasMonitorChanged = false;
|
|
static bool wasWindowStyleChanged = false;
|
|
static WindowStateEventType windowStateEventType = WindowStateEventType.None;
|
|
|
|
#if UNITY_EDITOR
|
|
/// <summary>
|
|
/// 获取 Unity 编辑器窗口
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
/// <seealso href="http://baba-s.hatenablog.com/entry/2017/09/17/135018"/>
|
|
public static EditorWindow GetGameView()
|
|
{
|
|
var assembly = typeof(EditorWindow).Assembly;
|
|
var type = assembly.GetType("UnityEditor.GameView");
|
|
var gameView = EditorWindow.GetWindow(type);
|
|
return gameView;
|
|
}
|
|
#endif
|
|
|
|
/// <summary>
|
|
/// 判断窗口是否已附加且可用
|
|
/// </summary>
|
|
/// <value><c>true</c> 如果此实例处于活动状态;否则为 <c>false</c>。</value>
|
|
public bool IsActive { get; private set; } = false;
|
|
|
|
/// <summary>
|
|
/// 判断附加窗口是否始终置顶
|
|
/// </summary>
|
|
public bool IsTopmost { get { return (IsActive && _isTopmost); } }
|
|
private bool _isTopmost = false;
|
|
|
|
/// <summary>
|
|
/// 判断附加窗口是否始终置底
|
|
/// </summary>
|
|
public bool IsBottommost { get { return (IsActive && _isBottommost); } }
|
|
private bool _isBottommost = false;
|
|
|
|
/// <summary>
|
|
/// 判断附加窗口是否透明
|
|
/// </summary>
|
|
public bool IsTransparent { get { return (IsActive && _isTransparent); } }
|
|
private bool _isTransparent = false;
|
|
|
|
/// <summary>
|
|
/// 判断附加窗口是否点击穿透(即不接收任何鼠标操作)
|
|
/// </summary>
|
|
public bool IsClickThrough { get { return (IsActive && _isClickThrough); } }
|
|
private bool _isClickThrough = false;
|
|
|
|
/// <summary>
|
|
/// 判断附加窗口是否无边框(无标题栏和边框)
|
|
/// </summary>
|
|
public bool IsBorderless { get { return (IsActive && _isBorderless); } }
|
|
private bool _isBorderless = false;
|
|
|
|
/// <summary>
|
|
/// 判断附加窗口是否可以自由定位(仅 macOS)
|
|
/// </summary>
|
|
public bool IsFreePositioningEnabled { get { return (IsActive && _isFreePositioningEnabled); } }
|
|
private bool _isFreePositioningEnabled = false;
|
|
|
|
/// <summary>
|
|
/// Windows 下的透明方法类型
|
|
/// </summary>
|
|
private TransparentType transparentType = TransparentType.Alpha;
|
|
|
|
/// <summary>
|
|
/// 当 transparentType 为 ColorKey 时用于透明的颜色
|
|
/// </summary>
|
|
private Color32 keyColor = new Color32(1, 0, 1, 0);
|
|
|
|
|
|
#region Constructor or destructor
|
|
/// <summary>
|
|
/// 窗口控制构造函数
|
|
/// </summary>
|
|
public UniWinCore()
|
|
{
|
|
IsActive = false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 析构函数
|
|
/// </summary>
|
|
~UniWinCore()
|
|
{
|
|
Dispose();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 结束时的处理
|
|
/// </summary>
|
|
public void Dispose()
|
|
{
|
|
// 由于最后恢复窗口状态会引起注意,所以特意不恢复,因此注释掉
|
|
//DetachWindow();
|
|
|
|
// 替代 DetachWindow()
|
|
LibUniWinC.UnregisterDropFilesCallback();
|
|
LibUniWinC.UnregisterMonitorChangedCallback();
|
|
LibUniWinC.UnregisterWindowStyleChangedCallback();
|
|
}
|
|
#endregion
|
|
|
|
|
|
#region Callbacks
|
|
|
|
/// <summary>
|
|
/// 显示器或分辨率变化时的回调
|
|
/// 此处的处理保持最低限度,仅设置标志
|
|
/// </summary>
|
|
/// <param name="monitorCount"></param>
|
|
[MonoPInvokeCallback(typeof(LibUniWinC.IntCallback))]
|
|
private static void _monitorChangedCallback([MarshalAs(UnmanagedType.I4)] int monitorCount)
|
|
{
|
|
wasMonitorChanged = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 窗口样式、最大化、最小化等调用的回调
|
|
/// 此处的处理保持最低限度,仅设置标志
|
|
/// </summary>
|
|
/// <param name="e"></param>
|
|
[MonoPInvokeCallback(typeof(LibUniWinC.IntCallback))]
|
|
private static void _windowStyleChangedCallback([MarshalAs(UnmanagedType.I4)] int e)
|
|
{
|
|
wasWindowStyleChanged = true;
|
|
windowStateEventType = (WindowStateEventType)e;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 文件或文件夹被拖放时调用的回调
|
|
/// 将字符串转换为数组,并设置标志位
|
|
/// </summary>
|
|
/// <param name="paths"></param>
|
|
[MonoPInvokeCallback(typeof(LibUniWinC.StringCallback))]
|
|
private static void _dropFilesCallback([MarshalAs(UnmanagedType.LPWStr)] string paths)
|
|
{
|
|
// 将以 LF 分隔的字符串分割为路径数组
|
|
//char[] delimiters = { '\n', '\0' };
|
|
//string[] files = paths.Split(delimiters).Where(s => s != "").ToArray();
|
|
string[] files = parsePaths(paths);
|
|
|
|
if (files.Length > 0)
|
|
{
|
|
lastDroppedFiles = new string[files.Length];
|
|
files.CopyTo(lastDroppedFiles, 0);
|
|
|
|
wasDropped = true;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 将双引号包围、LF(或null)分隔的字符串转换为数组并返回
|
|
/// </summary>
|
|
/// <param name="text"></param>
|
|
/// <returns></returns>
|
|
internal static string[] parsePaths(string text)
|
|
{
|
|
System.Collections.Generic.List<string> list = new System.Collections.Generic.List<string>();
|
|
bool inEscaped = false;
|
|
int len = text.Length;
|
|
StringBuilder sb = new StringBuilder();
|
|
for (int i = 0; i < len; i++)
|
|
{
|
|
char c = text[i];
|
|
if (c == '"')
|
|
{
|
|
if (inEscaped)
|
|
{
|
|
if (((i + 1) < len) && text[i + 1] == '"')
|
|
{
|
|
i++;
|
|
sb.Append(c); // 连续双引号视为一个双引号
|
|
continue;
|
|
}
|
|
}
|
|
inEscaped = !inEscaped; // 非连续则切换是否在引号内
|
|
}
|
|
else if (c == '\n')
|
|
{
|
|
if (inEscaped)
|
|
{
|
|
// 如果在引号内,则作为路径的一部分
|
|
sb.Append(c);
|
|
}
|
|
else
|
|
{
|
|
// 如果不在引号内,则作为分隔符,移到下一个路径
|
|
if (sb.Length > 0)
|
|
{
|
|
list.Add(sb.ToString());
|
|
//sb.Clear(); // for .NET 4 or later
|
|
sb.Length = 0; // for .NET 2
|
|
}
|
|
}
|
|
}
|
|
else if (c == '\0')
|
|
{
|
|
// 空字符始终作为分隔符,移到下一个路径
|
|
if (sb.Length > 0)
|
|
{
|
|
list.Add(sb.ToString());
|
|
//sb.Clear(); // for .NET 4 or later
|
|
sb.Length = 0; // for .NET 2
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sb.Append(c);
|
|
}
|
|
}
|
|
if (sb.Length > 0)
|
|
{
|
|
list.Add(sb.ToString());
|
|
}
|
|
|
|
// 移除空字符串元素
|
|
list.RemoveAll(v => v.Length == 0);
|
|
return list.ToArray();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Find, attach or detach
|
|
|
|
/// <summary>
|
|
/// 将窗口状态恢复至最初并从操作对象中解除
|
|
/// </summary>
|
|
public void DetachWindow()
|
|
{
|
|
#if UNITY_EDITOR
|
|
// 在编辑器中,窗口样式可能无法正确获取置顶状态,
|
|
// 因此默认视为非置顶,在分离时强制取消置顶
|
|
EnableTopmost(false);
|
|
#endif
|
|
LibUniWinC.DetachWindow();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 查找自己的窗口(如果游戏视图是独立窗口则查找它)并作为操作对象
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public bool AttachMyWindow()
|
|
{
|
|
#if UNITY_EDITOR_WIN
|
|
// 似乎没有可靠的方法获取游戏视图,因此给予焦点后立即获取活动窗口
|
|
var gameView = GetGameView();
|
|
if (gameView)
|
|
{
|
|
gameView.Focus();
|
|
LibUniWinC.AttachMyActiveWindow();
|
|
}
|
|
#else
|
|
LibUniWinC.AttachMyWindow();
|
|
#endif
|
|
// 添加事件处理程序
|
|
LibUniWinC.RegisterDropFilesCallback(_dropFilesCallback);
|
|
LibUniWinC.RegisterMonitorChangedCallback(_monitorChangedCallback);
|
|
LibUniWinC.RegisterWindowStyleChangedCallback(_windowStyleChangedCallback);
|
|
|
|
IsActive = LibUniWinC.IsActive();
|
|
return IsActive;
|
|
}
|
|
|
|
public bool AttachWindowHandle(IntPtr hWnd)
|
|
{
|
|
LibUniWinC.AttachWindowHandle(hWnd);
|
|
IsActive = LibUniWinC.IsActive();
|
|
return IsActive;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 选择自己进程中当前活动的窗口
|
|
/// 编辑器情况下,窗口会关闭或停靠,因此在聚焦时调用
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public bool AttachMyActiveWindow()
|
|
{
|
|
LibUniWinC.AttachMyActiveWindow();
|
|
IsActive = LibUniWinC.IsActive();
|
|
return IsActive;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region About window status
|
|
/// <summary>
|
|
/// 定期调用以维持窗口样式
|
|
/// </summary>
|
|
public void Update()
|
|
{
|
|
LibUniWinC.Update();
|
|
}
|
|
|
|
string GetDebubgWindowSizeInfo()
|
|
{
|
|
float x, y, cx, cy;
|
|
LibUniWinC.GetSize(out x, out y);
|
|
LibUniWinC.GetClientSize(out cx, out cy);
|
|
return $"W:{x},H:{y} CW:{cx},CH:{cy}";
|
|
}
|
|
|
|
/// <summary>
|
|
/// 设置/取消透明
|
|
/// </summary>
|
|
/// <param name="isTransparent"></param>
|
|
public void EnableTransparent(bool isTransparent)
|
|
{
|
|
// 编辑器无法透明或边框与正常不同,因此跳过
|
|
#if !UNITY_EDITOR
|
|
LibUniWinC.SetTransparent(isTransparent);
|
|
LibUniWinC.SetBorderless(isTransparent);
|
|
#endif
|
|
this._isTransparent = isTransparent;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 设置窗口透明度
|
|
/// </summary>
|
|
/// <param name="alpha">0.0 - 1.0</param>
|
|
public void SetAlphaValue(float alpha)
|
|
{
|
|
// Windows 编辑器下,一旦半透明化后显示不会更新,因此禁用。Mac 则没问题
|
|
#if !UNITY_EDITOR_WIN
|
|
LibUniWinC.SetAlphaValue(alpha);
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// 设置窗口 Z 顺序(是否置顶)。
|
|
/// </summary>
|
|
/// <param name="isTopmost">如果设为 <c>true</c> 则置顶。</param>
|
|
public void EnableTopmost(bool isTopmost)
|
|
{
|
|
LibUniWinC.SetTopmost(isTopmost);
|
|
this._isTopmost = isTopmost;
|
|
this._isBottommost = false; // 互斥
|
|
}
|
|
|
|
/// <summary>
|
|
/// 设置窗口 Z 顺序(是否置底)。
|
|
/// </summary>
|
|
/// <param name="isBottommost">如果设为 <c>true</c> 则置底。</param>
|
|
public void EnableBottommost(bool isBottommost)
|
|
{
|
|
LibUniWinC.SetBottommost(isBottommost);
|
|
this._isBottommost = isBottommost;
|
|
this._isTopmost = false; // 互斥
|
|
}
|
|
|
|
/// <summary>
|
|
/// 设置/取消点击穿透
|
|
/// </summary>
|
|
/// <param name="isThrough"></param>
|
|
public void EnableClickThrough(bool isThrough)
|
|
{
|
|
// 编辑器下点击穿透可能导致无法操作,因此跳过
|
|
#if !UNITY_EDITOR
|
|
LibUniWinC.SetClickThrough(isThrough);
|
|
#endif
|
|
this._isClickThrough = isThrough;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 最大化窗口(Mac 上为缩放)
|
|
/// 最大化后可能还会调整大小,目前可能无法可靠工作
|
|
/// </summary>
|
|
public void SetZoomed(bool isZoomed)
|
|
{
|
|
LibUniWinC.SetMaximized(isZoomed);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取窗口是否已最大化(Mac 上为缩放)
|
|
/// 最大化后可能还会调整大小,目前可能无法可靠工作
|
|
/// </summary>
|
|
public bool GetZoomed()
|
|
{
|
|
return LibUniWinC.IsMaximized();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 设置窗口位置。
|
|
/// </summary>
|
|
/// <param name="position">位置。</param>
|
|
public void SetWindowPosition(Vector2 position)
|
|
{
|
|
LibUniWinC.SetPosition(position.x, position.y);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取窗口位置。
|
|
/// </summary>
|
|
/// <returns>位置。</returns>
|
|
public Vector2 GetWindowPosition()
|
|
{
|
|
Vector2 pos = Vector2.zero;
|
|
LibUniWinC.GetPosition(out pos.x, out pos.y);
|
|
return pos;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 设置窗口大小。
|
|
/// </summary>
|
|
/// <param name="size">x 为宽度,y 为高度</param>
|
|
public void SetWindowSize(Vector2 size)
|
|
{
|
|
LibUniWinC.SetSize(size.x, size.y);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取窗口大小。
|
|
/// </summary>
|
|
/// <returns>x 为宽度,y 为高度</returns>
|
|
public Vector2 GetWindowSize()
|
|
{
|
|
Vector2 size = Vector2.zero;
|
|
LibUniWinC.GetSize(out size.x, out size.y);
|
|
return size;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取客户区大小。
|
|
/// </summary>
|
|
/// <returns>x 为宽度,y 为高度</returns>
|
|
public Vector2 GetClientSize()
|
|
{
|
|
Vector2 size = Vector2.zero;
|
|
LibUniWinC.GetClientSize(out size.x, out size.y);
|
|
return size;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取客户区矩形。
|
|
/// </summary>
|
|
/// <returns>x 为宽度,y 为高度</returns>
|
|
public Rect GetClientRectangle()
|
|
{
|
|
Vector2 pos = Vector2.zero;
|
|
Vector2 size = Vector2.zero;
|
|
LibUniWinC.GetClientRectangle(out pos.x, out pos.y, out size.x, out size.y);
|
|
return new Rect(pos.x, pos.y, size.x, size.y);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region File opening
|
|
public void SetAllowDrop(bool enabled)
|
|
{
|
|
LibUniWinC.SetAllowDrop(enabled);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Event observers
|
|
|
|
/// <summary>
|
|
/// 检查文件拖放并取消拖放标志
|
|
/// </summary>
|
|
/// <param name="files"></param>
|
|
/// <returns>如果文件被拖放则返回 true</returns>
|
|
public bool ObserveDroppedFiles(out string[] files)
|
|
{
|
|
files = lastDroppedFiles;
|
|
|
|
if (!wasDropped || files == null) return false;
|
|
|
|
wasDropped = false;
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 检查显示器数量或分辨率变化,并取消标志
|
|
/// </summary>
|
|
/// <returns>如果已变化则返回 true</returns>
|
|
public bool ObserveMonitorChanged()
|
|
{
|
|
if (!wasMonitorChanged) return false;
|
|
|
|
wasMonitorChanged = false;
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 检查窗口样式是否已变更,并取消标志
|
|
/// </summary>
|
|
/// <returns>如果窗口样式已变更则返回 true</returns>
|
|
public bool ObserveWindowStyleChanged()
|
|
{
|
|
if (!wasWindowStyleChanged) return false;
|
|
|
|
windowStateEventType = WindowStateEventType.None;
|
|
wasWindowStyleChanged = false;
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 检查窗口样式是否已变更,并取消标志
|
|
/// </summary>
|
|
/// <returns>如果窗口样式已变更则返回 true</returns>
|
|
public bool ObserveWindowStyleChanged(out WindowStateEventType type)
|
|
{
|
|
if (!wasWindowStyleChanged)
|
|
{
|
|
type = WindowStateEventType.None;
|
|
return false;
|
|
}
|
|
|
|
type = windowStateEventType;
|
|
windowStateEventType = WindowStateEventType.None;
|
|
wasWindowStyleChanged = false;
|
|
return true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region About mouse cursor
|
|
/// <summary>
|
|
/// 设置鼠标指针位置。
|
|
/// </summary>
|
|
/// <param name="position">位置。</param>
|
|
public static void SetCursorPosition(Vector2 position)
|
|
{
|
|
LibUniWinC.SetCursorPosition(position.x, position.y);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取鼠标指针位置。
|
|
/// </summary>
|
|
/// <returns>位置。</returns>
|
|
public static Vector2 GetCursorPosition()
|
|
{
|
|
Vector2 pos = Vector2.zero;
|
|
LibUniWinC.GetCursorPosition(out pos.x, out pos.y);
|
|
return pos;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get pressed mouse buttons.
|
|
/// </summary>
|
|
/// <returns>Bit flags of pressed buttons</returns>
|
|
public static int GetMouseButtons()
|
|
{
|
|
return LibUniWinC.GetMouseButtons();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取按下的修饰键。
|
|
/// </summary>
|
|
/// <returns>按下键的位标志</returns>
|
|
public static int GetModifierKeys()
|
|
{
|
|
return LibUniWinC.GetModifierKeys();
|
|
}
|
|
|
|
// 未实现
|
|
public static bool GetCursorVisible()
|
|
{
|
|
return true;
|
|
}
|
|
#endregion
|
|
|
|
#region for Windows only
|
|
/// <summary>
|
|
/// 指定透明方法(仅 Windows 支持)
|
|
/// </summary>
|
|
/// <param name="type"></param>
|
|
public void SetTransparentType(TransparentType type)
|
|
{
|
|
LibUniWinC.SetTransparentType((Int32)type);
|
|
transparentType = type;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 单色透明时指定透明色(仅 Windows 支持)
|
|
/// </summary>
|
|
/// <param name="color"></param>
|
|
public void SetKeyColor(Color32 color)
|
|
{
|
|
LibUniWinC.SetKeyColor((UInt32)(color.b * 0x10000 + color.g * 0x100 + color.r));
|
|
keyColor = color;
|
|
}
|
|
#endregion
|
|
|
|
#region for macOS only
|
|
/// <summary>
|
|
/// 设置/取消窗口的自由配置(仅 macOS 支持)
|
|
/// </summary>
|
|
/// <param name="enabled"></param>
|
|
public void EnableFreePositioning(bool enabled)
|
|
{
|
|
LibUniWinC.EnableFreePositioning(enabled);
|
|
_isFreePositioningEnabled = LibUniWinC.IsFreePositioningEnabled();
|
|
}
|
|
#endregion
|
|
|
|
#region About monitors
|
|
/// <summary>
|
|
/// 获取窗口所在显示器的索引
|
|
/// </summary>
|
|
/// <returns>显示器索引</returns>
|
|
public int GetCurrentMonitor()
|
|
{
|
|
return LibUniWinC.GetCurrentMonitor();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取已连接显示器的数量
|
|
/// </summary>
|
|
/// <returns>数量</returns>
|
|
public static int GetMonitorCount()
|
|
{
|
|
return LibUniWinC.GetMonitorCount();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取显示器的位置和大小
|
|
/// </summary>
|
|
/// <param name="index"></param>
|
|
/// <param name="position"></param>
|
|
/// <param name="size"></param>
|
|
/// <returns></returns>
|
|
public static bool GetMonitorRectangle(int index, out Vector2 position, out Vector2 size)
|
|
{
|
|
return LibUniWinC.GetMonitorRectangle(index, out position.x, out position.y, out size.x, out size.y);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 将窗口适配到指定显示器
|
|
/// </summary>
|
|
/// <param name="monitorIndex"></param>
|
|
/// <returns></returns>
|
|
public bool FitToMonitor(int monitorIndex)
|
|
{
|
|
float dx, dy, dw, dh;
|
|
if (LibUniWinC.GetMonitorRectangle(monitorIndex, out dx, out dy, out dw, out dh))
|
|
{
|
|
// 如果处于最大化状态则先恢复
|
|
if (LibUniWinC.IsMaximized()) LibUniWinC.SetMaximized(false);
|
|
|
|
// 指定显示器的中心坐标
|
|
float cx = dx + (dw / 2);
|
|
float cy = dy + (dh / 2);
|
|
|
|
// 将窗口中心移动到指定显示器中心
|
|
float ww, wh;
|
|
LibUniWinC.GetSize(out ww, out wh);
|
|
float wx = cx - (ww / 2);
|
|
float wy = cy - (wh / 2);
|
|
LibUniWinC.SetPosition(wx, wy);
|
|
|
|
// 最大化
|
|
LibUniWinC.SetMaximized(true);
|
|
|
|
//Debug.Log(String.Format("显示器 {4} : {0},{1} - {2},{3}", dx, dy, dw, dh, monitorIndex));
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 打印显示器列表
|
|
/// </summary>
|
|
[Obsolete]
|
|
public static void DebugMonitorInfo()
|
|
{
|
|
int monitors = LibUniWinC.GetMonitorCount();
|
|
|
|
int currentMonitorIndex = LibUniWinC.GetCurrentMonitor();
|
|
|
|
string message = "当前显示器: " + currentMonitorIndex + "\r\n";
|
|
|
|
for (int i = 0; i < monitors; i++)
|
|
{
|
|
float x, y, w, h;
|
|
bool result = LibUniWinC.GetMonitorRectangle(i, out x, out y, out w, out h);
|
|
message += String.Format(
|
|
"显示器 {0}: X:{1}, Y:{2} - W:{3}, H:{4}\r\n",
|
|
i, x, y, w, h
|
|
);
|
|
}
|
|
Debug.Log(message);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 获取用于调试的信息
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
[Obsolete]
|
|
public static int GetDebugInfo()
|
|
{
|
|
return LibUniWinC.GetDebugInfo();
|
|
}
|
|
#endregion
|
|
|
|
}
|
|
} |