unity_使用windows框体实现自由缩放拖拽功能_笔记

实现常见windows程序 自由拖拽缩放框体大小功能。

主要体现常见且习惯性操作体验。

build setting :

另 附上一段代码 有关win32的

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;


public class WIN32API
{

    [DllImport("User32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
    public static extern int MessageBox(IntPtr handle, String message, String title, int type);

    #region WIN32API
    delegate bool EnumWindowsCallBack(IntPtr hwnd, IntPtr lParam);
    [DllImport("user32", CharSet = CharSet.Unicode)]
    static extern bool SetWindowTextW(IntPtr hwnd, string title);
    [DllImport("user32")]
    static extern int EnumWindows(EnumWindowsCallBack lpEnumFunc, IntPtr lParam);
    [DllImport("user32")]
    static extern uint GetWindowThreadProcessId(IntPtr hWnd, ref IntPtr lpdwProcessId);
    #endregion
    public IntPtr myWindowHandle { get; private set; }

    public void Start()
    {
        UnityEngine.Screen.SetResolution(UnityEngine.Screen.width, UnityEngine.Screen.height, false);
        IntPtr handle = (IntPtr)System.Diagnostics.Process.GetCurrentProcess().Id;  //获取进程ID
        EnumWindows(new EnumWindowsCallBack(EnumWindCallback), handle);     //枚举查找本窗口
    }

    /// <summary>
    /// $"程序名 {Application.version} {Application.unityVersion} {GameApp.Ins.appConfig.buildtime}"
    /// </summary>
    /// <param name="title"></param>
    public void SetAppTitle(string title)
    {
        if (null != myWindowHandle)
        {
            SetWindowTextW(myWindowHandle, title); //设置窗口标题
        }
    }

    bool EnumWindCallback(IntPtr hwnd, IntPtr lParam)
    {
        IntPtr pid = IntPtr.Zero;
        GetWindowThreadProcessId(hwnd, ref pid);
        if (pid == lParam)  //判断当前窗口是否属于本进程
        {
            myWindowHandle = hwnd;
            return false;
        }
        return true;
    }

    public IntPtr FindU3DHandle()
    {
        var found = IntPtr.Zero;
        var tid = GetCurrentThreadId();
        EnumThreadWindows(tid, delegate (IntPtr hwnd, IntPtr param)
        {
            var sb = new StringBuilder(256);
            GetClassNameW(hwnd, sb, 256);

            if (sb.ToString() != "UnityWndClass")
            {
                return true;
            }

            found = hwnd;

            return true;
        }, IntPtr.Zero);

        return found;
    }


    public const int SWP_NOSIZE = 0x0001;
    public const int SWP_NOMOVE = 0x0002;
    public const int SW_SHOWNORMAL = 1;
    public const int SW_SHOWMINIMIZED = 2;
    public const int SW_SHOWMAXIMIZED = 3;
    public const int CLIP_TEXT_DATA = 13;
    public const int GWL_STYLE = -16;

    public const uint WS_POPUP = 0x80000000;
    public const uint WS_CAPTION = 0xC00000;     /* WS_BORDER | WS_DLGFRAME  */
    public const uint WS_MINIMIZEBOX = 0x20000;
    public const uint WS_MAXIMIZEBOX = 0x10000;
    public const uint WS_SYSMENU = 0x80000;
    public const uint WS_THICKFRAME = 0x40000;

    public const uint MB_OK = 0x00000000;
    public const uint MB_OKCANCEL = 0x00000001;
    public const uint MB_ABORTRETRYIGNORE = 0x00000002;
    public const uint MB_YESNOCANCEL = 0x00000003;
    public const uint MB_YESNO = 0x00000004;
    public const uint MB_RETRYCANCEL = 0x00000005;


    public const uint KLF_ACTIVATE = 0x00000001;
    public const uint KLF_SUBSTITUTE_OK = 0x00000002;
    public const uint KLF_REORDER = 0x00000008;
    public const uint KLF_NOTELLSHELL = 0x00000080;
    public const uint KLF_SETFORPROCESS = 0x00000100;
    public const uint KLF_SHIFTLOCK = 0x00010000;
    public const uint KLF_RESET = 0x40000000;

    public struct RECT
    {
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;

        public RECT(int left, int top, int right, int bottom)
        {
            Left = left;
            Top = top;
            Right = right;
            Bottom = bottom;
        }
    }

    public struct POINT
    {
        public int X;
        public int Y;
    }

    #region User32.dll 函数

    /// <summary>

    /// 该函数检索一指定窗口的客户区域或整个屏幕的显示设备上下文环境的句柄,以后可以在GDI函数中使用该句柄来在设备上下文环境中绘图。hWnd:设备上下文环境被检索的窗口的句柄

    /// </summary>

    [DllImport("user32.dll", CharSet = CharSet.Auto)]

    public static extern IntPtr GetDC(IntPtr hWnd);

    /// <summary>

    /// 函数释放设备上下文环境(DC)供其他应用程序使用。

    /// </summary>
    [DllImport("user32.dll")]

    public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);

    /// <summary>

    /// 该函数返回桌面窗口的句柄。桌面窗口覆盖整个屏幕。

    /// </summary>
    [DllImport("user32.dll")]

    static public extern IntPtr GetDesktopWindow();

    /// <summary>

    /// 该函数设置指定窗口的显示状态。

    /// </summary>
    [DllImport("user32.dll")]

    static public extern bool ShowWindow(IntPtr hWnd, short State);

    /// <summary>

    /// 通过发送重绘消息 WM_PAINT 给目标窗体来更新目标窗体客户区的无效区域。

    /// </summary>
    [DllImport("user32.dll")]

    static public extern bool UpdateWindow(IntPtr hWnd);

    /// <summary>

    /// 该函数将创建指定窗口的线程设置到前台,并且激活该窗口。键盘输入转向该窗口,并为用户改各种可视的记号。系统给创建前台窗口的线程分配的权限稍高于其他线程。

    /// </summary>
    [DllImport("user32.dll")]

    static public extern bool SetForegroundWindow(IntPtr hWnd);

    /// <summary>

    /// 该函数改变一个子窗口,弹出式窗口式顶层窗口的尺寸,位置和Z序。

    /// </summary>
    [DllImport("user32.dll")]

    static public extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int Width, int Height, uint flags);

    /// <summary>

    /// 打开剪切板

    /// </summary>
    [DllImport("user32.dll")]

    static public extern bool OpenClipboard(IntPtr hWndNewOwner);

    /// <summary>

    /// 关闭剪切板

    /// </summary>
    [DllImport("user32.dll")]

    static public extern bool CloseClipboard();

    /// <summary>

    /// 清空剪切板</summary>
    [DllImport("user32.dll")]

    static public extern bool EmptyClipboard();

    /// <summary>

    /// 将存放有数据的内存块放入剪切板的资源管理中

    /// </summary>
    [DllImport("user32.dll")]

    static public extern IntPtr SetClipboardData(uint Format, IntPtr hData);

    /// <summary>

    /// 在一个矩形中装载指定菜单条目的屏幕坐标信息 

    /// </summary>
    [DllImport("user32.dll")]

    public static extern bool GetMenuItemRect(IntPtr hWnd, IntPtr hMenu, uint Item, ref RECT rc);



    [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]

    /// <summary>

    /// 该函数获得一个指定子窗口的父窗口句柄。

    /// </summary>

    public static extern IntPtr GetParent(IntPtr hWnd);

    /// <summary>

    /// 该函数将指定的消息发送到一个或多个窗口。此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回。 

    /// </summary>

    /// <param name="hWnd">其窗口程序将接收消息的窗口的句柄</param>

    /// <param name="msg">指定被发送的消息</param>

    /// <param name="wParam">指定附加的消息指定信息</param>

    /// <param name="lParam">指定附加的消息指定信息</param>

    /// <returns></returns>
    [DllImport("user32.dll")]
    public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);
    [DllImport("user32.dll")]
    public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, IntPtr lParam);
    [DllImport("user32.dll")]
    public static extern void SendMessage(IntPtr hWnd, int msg, int wParam, ref RECT lParam);

    /// <summary>

    /// 该函数将一个消息放入(寄送)到与指定窗口创建的线程相联系消息队列里

    /// </summary>
    [DllImport("user32.dll")]
    public static extern IntPtr PostMessage(IntPtr hWnd, int msg, int wParam, int lParam);




    [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]

    public static extern bool UnhookWindowsHookEx(IntPtr hhook);



    [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]

    public static extern IntPtr CallNextHookEx(IntPtr hhook, int code, IntPtr wparam, IntPtr lparam);

    /// <summary>

    /// 该函数对指定的窗口设置键盘焦点。

    /// </summary>
    [DllImport("user32.dll")]
    public static extern IntPtr SetFocus(IntPtr hWnd);

    /// <summary>

    /// 该函数在指定的矩形里写入格式化文本,根据指定的方法对文本格式化(扩展的制表符,字符对齐、折行等)。

    /// </summary>
    [DllImport("user32.dll")]
    public extern static int DrawText(IntPtr hdc, string lpString, int nCount, ref RECT lpRect, int uFormat);

    /// <summary>

    /// 该函数改变指定子窗口的父窗口。

    /// </summary>
    [DllImport("user32.dll")]
    public extern static IntPtr SetParent(IntPtr hChild, IntPtr hParent);

    /// <summary>

    /// 获取对话框中子窗口控件的句柄

    /// </summary>
    [DllImport("user32.dll")]
    public extern static IntPtr GetDlgItem(IntPtr hDlg, int nControlID);

    /// <summary>

    /// 该函数获取窗口客户区的坐标。

    /// </summary>
    [DllImport("user32.dll")]
    public extern static int GetClientRect(IntPtr hWnd, ref RECT rc);

    /// <summary>

    /// 该函数向指定的窗体添加一个矩形,然后窗口客户区域的这一部分将被重新绘制。

    /// </summary>
    [DllImport("user32.dll")]
    public extern static int InvalidateRect(IntPtr hWnd, IntPtr rect, int bErase);

    /// <summary>

    /// 该函数产生对其他线程的控制,如果一个线程没有其他消息在其消息队列里。

    /// </summary>
    [DllImport("user32.dll")]
    public static extern bool WaitMessage();

    /// <summary>

    /// 该函数从一个与应用事例相关的可执行文件(EXE文件)中载入指定的光标资源.

    /// </summary>
    [DllImport("user32.dll")]
    public static extern IntPtr LoadCursor(IntPtr hInstance, uint cursor);

    /// <summary>

    /// 该函数确定光标的形状。

    /// </summary>
    [DllImport("user32.dll")]
    public static extern IntPtr SetCursor(IntPtr hCursor);

    /// <summary>

    /// 确定当前焦点位于哪个控件上。

    /// </summary>
    [DllImport("user32.dll")]
    public static extern IntPtr GetFocus();

    /// <summary>

    /// 该函数从当前线程中的窗口释放鼠标捕获,并恢复通常的鼠标输入处理。捕获鼠标的窗口接收所有的鼠标输入(无论光标的位置在哪里),除非点击鼠标键时,光标热点在另一个线程的窗口中。

    /// </summary>
    [DllImport("user32.dll")]
    public static extern bool ReleaseCapture();

    /// <summary>

    /// 该函数返回指定窗口的边框矩形的尺寸。该尺寸以相对于屏幕坐标左上角的屏幕坐标给出。

    /// </summary>
    [DllImport("user32.dll")]
    public static extern bool GetWindowRect(IntPtr hWnd, ref RECT rect);

    /// <summary>

    /// 

    /// </summary>
    [DllImport("user32.dll")]
    public static extern bool SetWindowRgn(IntPtr hWnd, IntPtr hRgn, bool redraw);

    /// <summary>

    /// 该函数检取指定虚拟键的状态。

    /// </summary>
    [DllImport("user32.dll")]
    public static extern ushort GetKeyState(int virtKey);

    /// <summary>

    /// 该函数改变指定窗口的位置和尺寸。对于顶层窗口,位置和尺寸是相对于屏幕的左上角的:对于子窗口,位置和尺寸是相对于父窗口客户区的左上角坐标的。

    /// </summary>
    [DllImport("user32.dll")]
    public static extern bool MoveWindow(IntPtr hWnd, int x, int y, int width, int height, bool repaint);

    /// <summary>

    /// 该函数改变指定窗口的属性

    /// </summary>
    [DllImport("user32.dll")]
    public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

    /// <summary>

    /// 该函数检索指定窗口客户区域或整个屏幕的显示设备上下文环境的句柄,在随后的GDI函数中可以使用该句柄在设备上下文环境中绘图。

    /// </summary>
    [DllImport("user32.dll")]
    public static extern IntPtr GetDCEx(IntPtr hWnd, IntPtr hRegion, uint flags);

    /// <summary>

    /// 获取整个窗口(包括边框、滚动条、标题栏、菜单等)的设备场景 返回值 Long。

    /// </summary>
    [DllImport("user32.dll")]
    public static extern IntPtr GetWindowDC(IntPtr hWnd);

    /// <summary>

    /// 该函数用指定的画刷填充矩形,此函数包括矩形的左上边界,但不包括矩形的右下边界。

    /// </summary>
    [DllImport("user32.dll")]
    public static extern int FillRect(IntPtr hDC, ref RECT rect, IntPtr hBrush);

    /// <summary>

    /// 该函数改变指定窗口的标题栏的文本内容

    /// </summary>
    [DllImport("user32.dll")]
    public static extern int SetWindowText(IntPtr hWnd, string text);

    /// <summary>

    /// 用于得到被定义的系统数据或者系统配置信息.

    /// </summary>
    [DllImport("user32.dll")]
    static public extern int GetSystemMetrics(int nIndex);
    /// <summary>

    /// 该函数显示或隐藏所指定的滚动条。

    /// </summary>
    [DllImport("user32.dll")]
    public static extern int ShowScrollBar(IntPtr hWnd, int bar, int show);

    /// <summary>

    /// 该函数可以激活一个或两个滚动条箭头或是使其失效。

    /// </summary>
    [DllImport("user32.dll")]
    public static extern int EnableScrollBar(IntPtr hWnd, uint flags, uint arrows);

    /// <summary>

    /// 该函数将指定的窗口设置到Z序的顶部。

    /// </summary>
    [DllImport("user32.dll")]
    public static extern int BringWindowToTop(IntPtr hWnd);

    /// <summary>

    /// 该函数滚动指定窗体客户区域的目录。

    /// </summary>
    [DllImport("user32.dll")]
    static public extern int ScrollWindowEx(IntPtr hWnd, int dx, int dy, ref RECT rcScroll, ref RECT rcClip, IntPtr UpdateRegion, ref RECT rcInvalidated, uint flags);

    /// <summary>

    /// 该函数确定给定的窗口句柄是否识别一个已存在的窗口。

    /// </summary>
    [DllImport("user32.dll")]
    public static extern int IsWindow(IntPtr hWnd);

    /// <summary>

    /// 该函数将256个虚拟键的状态拷贝到指定的缓冲区中。

    /// </summary>
    [DllImport("user32.dll")]
    public static extern int GetKeyboardState(byte[] pbKeyState);

    /// <summary>

    /// 该函数将指定的虚拟键码和键盘状态翻译为相应的字符或字符串。该函数使用由给定的键盘布局句柄标识的物理键盘布局和输入语言来翻译代码。

    /// </summary>
    [DllImport("user32.dll")]
    public static extern int ToAscii(int uVirtKey, int uScanCode, byte[] lpbKeyState, byte[] lpwTransKey, int fuState);

    public delegate bool EnumWindowsProc(IntPtr hwnd, IntPtr lparam);

    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    public static extern bool EnumThreadWindows(int thread, EnumWindowsProc proc, IntPtr param);

    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    public static extern int GetClassNameW(IntPtr hwnd, StringBuilder str, int len);

    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    public static extern int GetWindowTextW(IntPtr hwnd, StringBuilder str, int len);


    [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
    public static extern int GetCurrentThreadId();

    #endregion

}
原文地址:https://www.cnblogs.com/Roz-001/p/14892900.html