使用unity做桌面程序,只需要把wallpaper.cs文件放入到unity项目中然后挂载到一个游戏物体上即可。
运行对话框选全屏/窗口模式都行。
在unity编辑器模式下运行不会成为桌面程序,必须发布后才行。
Build setting需要设置的是需要勾选running background。
可以做一个关闭按钮来关闭程序,也可以在任务管理器中结束进程来关闭。
Unity 脚本中Void Main()函数可以被系统首先调用。
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.UI;
public class WallPaper : MonoBehaviour
{
[DllImport("user32.dll")]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string className, string winName);
[DllImport("user32.dll")]
public static extern IntPtr SetParent(IntPtr hwnd, IntPtr parentHwnd);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int ShowWindow(IntPtr hwnd, int nCmdShow);
[DllImport("user32.dll")]
public static extern bool EnumWindows(EnumWindowsProc proc, IntPtr lParam);
public delegate bool EnumWindowsProc(IntPtr hwnd, IntPtr lParam);
[DllImport("user32.dll")]
public static extern IntPtr SendMessageTimeout(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam, uint fuFlage, uint timeout, IntPtr result);
public delegate bool WNDENUMPROC(IntPtr hwnd, uint lParam);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool EnumWindows(WNDENUMPROC lpEnumFunc, uint lParam);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr GetParent(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, ref uint lpdwProcessId);
[DllImport("kernel32.dll")]
public static extern void SetLastError(uint dwErrCode);
public int ResWidth;//窗口宽度
public int ResHeight;//窗口高度
IntPtr wallPaper;
IntPtr progman;
IntPtr result;
void Main()
{
ResWidth = Screen.width;
ResHeight = Screen.height;
Screen.SetResolution(ResWidth, ResHeight, true, 30);
if (Application.platform == RuntimePlatform.WindowsPlayer)
{
wallPaper = GetProcessWnd();
progman = FindWindow("Progman", null);
result = IntPtr.Zero;
// 向 Program Manager 窗口发送 0x52c 的一个消息,超时设置为0x3e8(1秒)。
SendMessageTimeout(progman, 0x52c, IntPtr.Zero, IntPtr.Zero, 0, 0x3e8, result);
EnumWindows((hwnd, lParam) =>
{
// 找到包含 SHELLDLL_DefView 这个窗口句柄的 WorkerW
if (FindWindowEx(hwnd, IntPtr.Zero, "SHELLDLL_DefView", null) != IntPtr.Zero)
{
// 找到当前 WorkerW 窗口的,后一个 WorkerW 窗口。
IntPtr tempHwnd = FindWindowEx(IntPtr.Zero, hwnd, "WorkerW", null);
// 隐藏这个窗口
ShowWindow(tempHwnd, 0);
}
return true;
}, IntPtr.Zero);
SetParent(wallPaper, progman);
}
}
private void Awake()
{
//Log.Init(true, Application.persistentDataPath);
}
// Update is called once per frame
void Update()
{
}
private void OnApplicationFocus(bool focus)
{
if (Application.platform == RuntimePlatform.WindowsPlayer)
{
if (focus)
{
}
else
{
}
}
}
private void OnApplicationQuit()
{
SetParent(wallPaper, IntPtr.Zero);
}
public static IntPtr GetProcessWnd()
{
IntPtr ptrWnd = IntPtr.Zero;
uint pid = (uint)Process.GetCurrentProcess().Id;
// 当前进程 ID
bool bResult = EnumWindows(new WNDENUMPROC(delegate (IntPtr hwnd, uint lParam)
{
uint id = 0;
if (GetParent(hwnd) == IntPtr.Zero)
{
GetWindowThreadProcessId(hwnd, ref id);
if (id == lParam)
// 找到进程对应的主窗口句柄
{
ptrWnd = hwnd;
// 把句柄缓存起来
SetLastError(0);
// 设置无错误
return false;
// 返回 false 以终止枚举窗口
}
}
return true;
}), pid);
return (!bResult && Marshal.GetLastWin32Error() == 0) ? ptrWnd : IntPtr.Zero;
}
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow(); //获得本窗体的句柄
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd); //设置此窗体为活动窗体
}