zoukankan      html  css  js  c++  java
  • Unity中调用Windows窗口句柄以及根据需求设置并且解决扩展屏窗体显示错乱/位置错误的Bug/指定Windows窗口文件类型筛选

    问题背景:

    现在在搞PC端应用开发,我们开发中需要调用系统的窗口以及需要最大化最小化,缩放窗口拖拽窗口,以及设置窗口位置,去边框等功能

    解决根据:

    使用user32.dll解决

    具体功能:

    Unity中对Windows窗口设置

    <1>.unity中调用打开文件窗口和保存窗口:

    调用Comdlg32.dll中方法

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Runtime.InteropServices;
     5 using System.Text;
     6 using System.Threading.Tasks;
     7 
     8 namespace Tx3d.Ventilation
     9 {
    10     /// <summary>
    11     /// 场景窗口类型基类
    12     /// </summary>
    13     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    14     public class SceneWindows
    15     {
    16         public int structSize = 0;
    17         public IntPtr dlgOwner = IntPtr.Zero;
    18         public IntPtr instance = IntPtr.Zero;
    19         public String filter = null;
    20         public String customFilter = null;
    21         public int maxCustFilter = 0;
    22         public int filterIndex = 0;
    23         public String file = null;
    24         public int maxFile = 0;
    25         public String fileTitle = null;
    26         public int maxFileTitle = 0;
    27         public String initialDir = null;
    28         public String title = null;
    29         public int flags = 0;
    30         public short fileOffset = 0;
    31         public short fileExtension = 0;
    32         public String defExt = null;
    33         public IntPtr custData = IntPtr.Zero;
    34         public IntPtr hook = IntPtr.Zero;
    35         public String templateName = null;
    36         public IntPtr reservedPtr = IntPtr.Zero;
    37         public int reservedInt = 0;
    38         public int flagsEx = 0;
    39     }
    40 
    41     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    42     public class OpenFile : SceneWindows
    43     {
    44 
    45     }
    46 
    47     public class OpenFileWindow
    48     {
    49         [DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
    50 
    51         public static extern bool GetOpenFileName([In, Out] OpenFile ofd);
    52     }
    53 
    54     public class SaveFileWindow
    55     {
    56         [DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
    57         public static extern bool GetSaveFileName([In, Out] SaveFile ofd);
    58     }
    59 
    60     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    61     public class SaveFile : SceneWindows
    62     {
    63 
    64     }
    65 
    66 }

    具体使用:

      1  /// <summary>
      2         /// 创建保存场景/另存场景面板
      3         /// </summary>
      4         /// <param name="titleName">面板主题名</param>
      5         /// <param name="filePath">保存路径</param>
      6         private void SaveOrSaveAsWindows(string titleName,Action<string> action)
      7         {
      8             SaveFile pth = new SaveFile();
      9             pth.structSize = System.Runtime.InteropServices.Marshal.SizeOf(pth);
     10             pth.filter = "All Files *.*";//是什么文件类型就修改此处
     11             pth.file = new string(new char[256]);
     12             pth.maxFile = pth.file.Length;
     13             pth.fileTitle = new string(new char[64]);
     14             pth.maxFileTitle = pth.fileTitle.Length;
     15             pth.initialDir = Application.dataPath;  // default path  
     16             pth.title = titleName;
     17             pth.defExt = "json";
     18             pth.flags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000200 | 0x00000008;
     19             if (SaveFileWindow.GetSaveFileName(pth))
     20             {
     21                 string filepath = pth.file;//选择的文件路径;  
     22                 action(filepath);
     23             }
     24         }
     25 
     26         /// <summary>
     27         /// 打开项目弹框
     28         /// </summary>
     29         /// <returns></returns>
     30         private void OpenWindow(Action<string> action)
     31         {
     32             string filepath = "";
     33             OpenFile pth = new OpenFile();
     34             pth.structSize = System.Runtime.InteropServices.Marshal.SizeOf(pth);
     35             // pth.filter = "JSON file(*.json)";//是什么文件类型就修改此处
     36             pth.filter = "All Files*.*";
     37             pth.file = new string(new char[256]);
     38             pth.maxFile = pth.file.Length;
     39             pth.fileTitle = new string(new char[64]);
     40             pth.maxFileTitle = pth.fileTitle.Length;
     41             pth.initialDir = Application.dataPath;  // default path  
     42             pth.title = "打开项目";
     43             pth.defExt = "json";
     44 
     45             //注意 一下项目不一定要全选 但是0x00000008项不要缺少
     46             //0x00080000   是否使用新版文件选择窗口,0x00000200   是否可以多选文件
     47             pth.flags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000200 | 0x00000008;
     48 
     49             if (OpenFileWindow.GetOpenFileName(pth))
     50             {
     51                 filepath = pth.file;//选择的文件路径;  
     52                 action(filepath);
     53             }
     54         }
     55 
     56         /// <summary>
     57         /// 根据路径生成本地json文件
     58         /// </summary>
     59         /// <param name="filePath">写入的路径</param>
     60         /// <param name="jsonData">写入的json数据</param>
     61         private void WriteJsonFile(string filePath,JsonData jsonData)
     62         {
     63             //构建文件流,创建文件,若存在则覆盖
     64             FileStream fileStream = new FileStream(filePath, FileMode.Create);
     65 
     66             //构建写流,设置文件格式
     67             StreamWriter sw = new StreamWriter(fileStream, Encoding.UTF8);
     68 
     69             //ToJson接口将你的json数据传进去,并自动转换为string类型
     70             string json = JsonMapper.ToJson(jsonData);
     71 
     72             //将转好的json字符串写入文件
     73             sw.WriteLine(json);
     74 
     75             sw.Flush();
     76             
     77             //关流,释放资源
     78             sw.Close();
     79             fileStream.Close();
     80             sw.Dispose();
     81         }
     82 
     83         /// <summary>
     84         /// 读取json文件
     85         /// </summary>
     86         /// <param name="path"></param>
     87         /// <returns></returns>
     88         private JsonData ReadJson(string path)
     89         {
     90             //构建读流,设置文件格式
     91             StreamReader sr = new StreamReader(path);
     92 
     93             //再转换成json数据
     94             JsonReader json = new JsonReader(sr);
     95             //读取json数据
     96             JsonData data = JsonMapper.ToObject(json);
     97 
     98             sr.Close();
     99 
    100             return data;
    101         }
    102 
    103         /// <summary>
    104         /// 获取SceneName
    105         /// </summary>
    106         /// <param name="name">路径名字</param>
    107         /// <returns></returns>
    108         private string GetSceneName(string name)
    109         {
    110            string [] names= name.Split('\');
    111            string myname=names[names.Length - 1].Split('.')[0];
    112            return myname;
    113         }
    View Code

     效果:

    打开:

     保存:

    <2>.去边框/设置窗口尺寸和位置

    导入user32.dll的相关方法:

     1         //设置窗口边框
     2         [DllImport("user32.dll")]
     3         public static extern IntPtr SetWindowLong(IntPtr hwnd, int _nIndex, int dwNewLong);
     4 
     5         //设置窗口位置,尺寸
     6         [DllImport("user32.dll")]
     7         public static extern bool SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
     8 
     9         [DllImport("user32.dll", SetLastError = true)]
    10         private static extern int GetWindowLong(IntPtr hWnd, int nIndex);

    具体使用:

     1 //边框参数
     2         private const uint SWP_SHOWWINDOW = 0x0040;
     3         private const int GWL_STYLE = -16;
     4         private const int WS_BORDER = 1;
     5 
     6         //隐藏标题栏图标
     7         private const int WS_POPUP = 0x800000;
     8         private const int WS_SYSMENU = 0x80000;
     9 
    10         //最大最小化
    11         private const int SW_SHOWMINIMIZED = 2;//(最小化窗口)
    12         private const int SW_SHOWMAXIMIZED = 3;//最大化窗口
    13         
    14         //去除标题栏保留边框
    15         private const int WS_CAPTION = 0x00C00000;
    16         private const int WS_THICKFRAME = 0x00040000;
    17 
    18 //去除上边栏(不可拖拽缩放)
    19                 SetWindowLong(GetForegroundWindow(), GWL_STYLE, WS_POPUP);
    20 
    21 
    22 
    23 //设置拖拽缩放模式(未完全去掉(参数控制,即GetWindowLong(GetForegroundWindow(), GWL_STYLE)& ~WS_CAPTION | WS_THICKFRAME))
    24                     SetWindowLong(GetForegroundWindow(), GWL_STYLE, GetWindowLong(GetForegroundWindow(), GWL_STYLE)
    25              & ~WS_CAPTION | WS_THICKFRAME);

    //设置窗口位置及分辨率
    bool result = SetWindowPos(GetForegroundWindow(), 0, (int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height, SWP_SHOWWINDOW);

    
    

    注:

    1.windows下的窗口一旦去了上边栏(边框),就无法拖拽缩放了,边框和上边栏是一体的,所以拖拽功能要想保留不能直接去掉边框,当然可以自己写拖拽缩放,我试着写过,实现可以,但是无奈领导说最好使用原生的,我就放弃了。

    2.还有一个坑,注意windows环境下,屏幕坐标原点(0,0)在左上角,不和unity中一样在左下角。

    去边框上边框(自带白色上边框)效果:

    <3>.最大化最小化窗口(没有上边框下,有的话就不用考虑这功能了)

    导入user32.dll的相关方法以及参数:

    1  //最大最小化
    2         private const int SW_SHOWMINIMIZED = 2;//(最小化窗口)
    3         private const int SW_SHOWMAXIMIZED = 3;//最大化窗口

               //设置当前窗口的显示状态
               [DllImport("user32.dll")]
               public static extern bool ShowWindow(System.IntPtr hwnd, int nCmdShow);

    使用:

     1  /// <summary>
     2         /// 最小化窗口
     3         /// </summary>
     4         public void SetMinWindows()
     5         {
     6             ShowWindow(GetForegroundWindow(), SW_SHOWMINIMIZED);
     7         }
     8 
     9         /// <summary>
    10         /// 最大化窗口
    11         /// </summary>
    12         public void SetMaxWindows()
    13         {
    14            ShowWindow(GetForegroundWindow(), SW_SHOWMAXIMIZED);
    15         }

    注:这里的最大化窗口是指全屏铺满,如果想要那种普通exe的最大化(保留任务栏),需要自己去掉任务栏高再设置分辨率以及定位置

    <4>.拖动窗口

    导入user32.dll的相关方法:

    1 //窗口拖动
    2         [DllImport("user32.dll")]
    3         public static extern bool ReleaseCapture();
    4         [DllImport("user32.dll")]
    5         public static extern bool SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
    6         
    7  //获取当前激活窗口
    8         [DllImport("user32.dll", EntryPoint = "GetForegroundWindow")]
    9         public static extern System.IntPtr GetForegroundWindow();

    使用:

            /// <summary>
            /// 拖动窗口
            /// </summary>
            /// <param name="window">当前句柄</param>
            public void DragWindow(IntPtr window)
            {
                ReleaseCapture();
                SendMessage(window, 0xA1, 0x02, 0);
                SendMessage(window, 0x0202, 0, 0);
            }

    注:里面参数都是默认的,无需改(重点是很多参数,想搞明白去查下user32 的API)。

    <5>.更改标题栏

    导入user32.dll的相关方法:

    1         //更改标题栏
    2         [DllImport("user32.dll")]
    3         public static extern int SetWindowText(IntPtr hWnd, string text);
    1         /// <summary>
    2         /// 改变标题栏标题
    3         /// </summary>
    4         public void ChangeTitleText()
    5         {
    6             SetWindowText(GetForegroundWindow(), string.Empty);
    7         }

    <6>.查找任务栏,并获取任务栏高度(这个需求是因为该库中最大化是指全屏铺满,但是我们需要的最大化时保留下方任务栏)

    导入user32.dll的相关方法:

    1         //使用查找任务栏
    2         [DllImport("user32.dll")]
    3         public static extern IntPtr FindWindow(string strClassName, int nptWindowName);
     1         /// <summary>
     2         /// 获取任务栏高度
     3         /// </summary>
     4         /// <returns>任务栏高度</returns>
     5         private int GetTaskBarHeight()
     6         {
     7             int taskbarHeight = 10;
     8             IntPtr hWnd = FindWindow("Shell_TrayWnd", 0);
     9             RECT rect = new RECT();
    10             GetWindowRect(hWnd, ref rect);
    11             taskbarHeight = rect.Bottom - rect.Top;
    12             return taskbarHeight;
    13         }

    此时设置想要保留任务栏的最大化:

    1         /// <summary>
    2         /// 最大化窗口
    3         /// </summary>
    4         public void SetMaxWindows()
    5         {
    6             int currMaxScreenHeight = Screen.currentResolution.height - GetTaskBarHeight();
    7             SetWindowPos(GetForegroundWindow(), 0, 0, 0, Screen.currentResolution.width, currMaxScreenHeight, SWP_SHOWWINDOW);
    8             // ShowWindow(GetForegroundWindow(), SW_SHOWMAXIMIZED);
    9         }

    注:Screen.currentResolution.height 当前设备高,Screen.currentResolution.width 当前设备宽

    保留任务栏最大化效果:

     

    <7>.获取当前窗口句柄的分辨率

    导入user32.dll的相关方法:

     1         //获取窗口位置以及大小
     2         [DllImport("user32.dll")]
     3         [return: MarshalAs(UnmanagedType.Bool)]
     4         public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
     5         [StructLayout(LayoutKind.Sequential)]
     6         public struct RECT
     7         {
     8             public int Left; //最左坐标
     9             public int Top; //最上坐标
    10             public int Right; //最右坐标
    11             public int Bottom; //最下坐标
    12         }

    使用:

     1         /// <summary>
     2         /// 获取当前窗口尺寸
     3         /// </summary>
     4         /// <returns></returns>
     5         public Rect GetWindowInfo()
     6         {
     7             RECT rect = new RECT();
     8             Rect targetRect = new Rect();
     9             GetWindowRect(GetForegroundWindow(), ref rect);
    10             targetRect.width = Mathf.Abs(rect.Right - rect.Left);
    11             targetRect.height = Mathf.Abs(rect.Top - rect.Bottom);

    //锚点在左上角
    12 targetRect.x = rect.Left; 13 targetRect.y = rect.Top; 14 return targetRect; 15 }
    注:锚点在左上角 targetRect.x = rect.Left; targetRect.y = rect.Top;所以拿的是左上。

    完整代码:

      1   /// <summary>
      2     /// 窗口工具系统类(窗口状态)
      3     /// </summary>
      4     public class WindowsTool
      5     {
      6 
      7         #region 系统字段 & 系统方法
      8 
      9         //设置当前窗口的显示状态
     10         [DllImport("user32.dll")]
     11         public static extern bool ShowWindow(System.IntPtr hwnd, int nCmdShow);
     12 
     13         //获取当前激活窗口
     14         [DllImport("user32.dll", EntryPoint = "GetForegroundWindow")]
     15         public static extern System.IntPtr GetForegroundWindow();
     16 
     17         //设置窗口边框
     18         [DllImport("user32.dll")]
     19         public static extern IntPtr SetWindowLong(IntPtr hwnd, int _nIndex, int dwNewLong);
     20 
     21         //设置窗口位置,尺寸
     22         [DllImport("user32.dll")]
     23         public static extern bool SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
     24 
     25         [DllImport("user32.dll", SetLastError = true)]
     26         private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
     27 
     28         //窗口拖动
     29         [DllImport("user32.dll")]
     30         public static extern bool ReleaseCapture();
     31         [DllImport("user32.dll")]
     32         public static extern bool SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
     33         
     34         //更改标题栏
     35         [DllImport("user32.dll")]
     36         public static extern int SetWindowText(IntPtr hWnd, string text);
     37 
     38         //使用查找任务栏
     39         [DllImport("user32.dll")]
     40         public static extern IntPtr FindWindow(string strClassName, int nptWindowName);
     41 
     42         //获取窗口位置以及大小
     43         [DllImport("user32.dll")]
     44         [return: MarshalAs(UnmanagedType.Bool)]
     45         public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
     46         [StructLayout(LayoutKind.Sequential)]
     47         public struct RECT
     48         {
     49             public int Left; //最左坐标
     50             public int Top; //最上坐标
     51             public int Right; //最右坐标
     52             public int Bottom; //最下坐标
     53         }
     54 
     55         //边框参数
     56         private const uint SWP_SHOWWINDOW = 0x0040;
     57         private const int GWL_STYLE = -16;
     58         private const int WS_BORDER = 1;
     59 
     60         //隐藏标题栏图标
     61         private const int WS_POPUP = 0x800000;
     62         private const int WS_SYSMENU = 0x80000;
     63 
     64         //最大最小化
     65         private const int SW_SHOWMINIMIZED = 2;//(最小化窗口)
     66         private const int SW_SHOWMAXIMIZED = 3;//最大化窗口
     67         
     68         //去除标题栏保留边框
     69         private const int WS_CAPTION = 0x00C00000;
     70         private const int WS_THICKFRAME = 0x00040000;
     71 
     72         #endregion
     73 
     74         #region 方法
     75 
     76         /// <summary>
     77         /// 最小化窗口
     78         /// </summary>
     79         public void SetMinWindows()
     80         {
     81             ShowWindow(GetForegroundWindow(), SW_SHOWMINIMIZED);
     82         }
     83 
     84         /// <summary>
     85         /// 最大化窗口
     86         /// </summary>
     87         public void SetMaxWindows()
     88         {
     89             int currMaxScreenHeight = Screen.currentResolution.height - GetTaskBarHeight();
     90             SetWindowPos(GetForegroundWindow(), 0, 0, 0, Screen.currentResolution.width, currMaxScreenHeight, SWP_SHOWWINDOW);
     91             // ShowWindow(GetForegroundWindow(), SW_SHOWMAXIMIZED);
     92         }
     93 
     94         /// <summary>
     95         /// 设置无边框,窗口位置及分辨率
     96         /// </summary>
     97         /// <param name="rect">尺寸数据</param>
     98         public void SetNoFrameWindow(Rect rect, bool isMax, bool isDrag = false)
     99         {
    100             if (!isDrag)
    101             {
    102                 //去除上边栏(不可拖拽缩放)
    103                 SetWindowLong(GetForegroundWindow(), GWL_STYLE, WS_POPUP);
    104             }
    105             else
    106             {
    107                 if (!isMax)
    108                 {
    109                     //设置拖拽缩放模式
    110                     SetWindowLong(GetForegroundWindow(), GWL_STYLE, GetWindowLong(GetForegroundWindow(), GWL_STYLE)
    111              & ~WS_CAPTION | WS_THICKFRAME);
    112                 }
    113                 else {
    114                     //去除上边栏(不可拖拽缩放)
    115                     SetWindowLong(GetForegroundWindow(), GWL_STYLE, WS_POPUP);
    116                 }
    117             }
    118 
    119             //隐藏上边栏(部分)
    120             // SetWindowLong(GetForegroundWindow(), GWL_STYLE, GetWindowLong(GetForegroundWindow(), GWL_STYLE) & ~WS_POPUP);
    121 
    122             if (isMax)
    123             {
    124                 SetMaxWindows();
    125             }
    126             else
    127             {
    128                 //设置窗口位置及分辨率
    129                 bool result = SetWindowPos(GetForegroundWindow(), 0, (int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height, SWP_SHOWWINDOW);
    130             }
    131         }
    132 
    133         /// <summary>
    134         /// 拖动窗口
    135         /// </summary>
    136         /// <param name="window">当前句柄</param>
    137         public void DragWindow(IntPtr window)
    138         {
    139             ReleaseCapture();
    140             SendMessage(window, 0xA1, 0x02, 0);
    141             SendMessage(window, 0x0202, 0, 0);
    142         }
    143 
    144         /// <summary>
    145         /// 改变标题栏标题
    146         /// </summary>
    147         public void ChangeTitleText()
    148         {
    149             SetWindowText(GetForegroundWindow(), string.Empty);
    150         }
    151 
    152         /// <summary>
    153         /// 获取当前窗口尺寸
    154         /// </summary>
    155         /// <returns></returns>
    156         public Rect GetWindowInfo()
    157         {
    158             RECT rect = new RECT();
    159             Rect targetRect = new Rect();
    160             GetWindowRect(GetForegroundWindow(), ref rect);
    161             targetRect.width = Mathf.Abs(rect.Right - rect.Left);
    162             targetRect.height = Mathf.Abs(rect.Top - rect.Bottom);
    163             targetRect.x = rect.Left;
    164             targetRect.y = rect.Top;
    165             return targetRect;
    166         }
    167 
    168         #endregion
    169 
    170         #region Private Methods
    171 
    172         /// <summary>
    173         /// 获取任务栏高度
    174         /// </summary>
    175         /// <returns>任务栏高度</returns>
    176         private int GetTaskBarHeight()
    177         {
    178             int taskbarHeight = 10;
    179             IntPtr hWnd = FindWindow("Shell_TrayWnd", 0);
    180             RECT rect = new RECT();
    181             GetWindowRect(hWnd, ref rect);
    182             taskbarHeight = rect.Bottom - rect.Top;
    183             return taskbarHeight;
    184         }
    185 
    186         #endregion
    187     }
    View Code

    最新:发布后windows扩展模式下窗体显示错乱不对的情况?

    几种扩展特殊扩展屏幕方式,比如:

    这四种方式,大家都知道,扩展屏就是在原有基本尺寸屏幕上,扩了一定尺寸的屏幕显示,实质上还是一个屏(计算机内部认为)

    初步分析下:

    1.左右扩展:往左扩展就在X方向减去初始屏幕的分辨率宽,往右扩展就在X方向加上初始屏幕的分辨率宽。

    2.上下扩展:往上扩展就在Y方向加上初始屏幕的分辨率高,往下扩展就在Y方向减去初始屏幕的分辨率高。

    姑且这样认为。测试一下,这个地方的坐标是不是我们认为的这种(左-,右+,上+,下-),这个地方我测了下,如图:

    1区(X>0 & Y<0),2区(X<0 & Y<0),3区(X<0 & Y>0),5区(X>0 & Y>0),4区是窗口区域,左上角是窗口锚点o(0,0)点。

    原则搞清楚了不是我们想的那样。按我们上面分析的,到这里你可以解决上述四种扩展方式屏幕的问题,但是,恶心的事发生了(一直没注意),扩展屏幕的排列方式很自由,比如:

    图1.

    图2.

    图3.

    图4.

    瞬间让我感觉windows太JB没底线了,给老子加难度。

    下面再仔细分析一下还有什么问题?

    我想知道这俩排列的高度差,也就是分屏的信息,主机连接了几个显示器?各自分辨率是多少?屏幕锚点坐标是什么?我们需要这些信息!不然根本没法确定窗口位置。

    Unity中获取主机连接了几个显示器,显示器的分辨率以及位置这些是没提供给我们相应的API的。

    有人说有Resolution[] resolutions = Screen.resolutions;    

    这不是所有显示器分辨率列表

     这是说明,自己看看,也可以试试,绝不是你想象中的那样亦或者你仅仅可以获取当前屏幕的分辨率。

    还有人说Display这是unity中的分屏处理,具体自己去查查吧,比较官方。

    所以这里我使用了WinForm中的API,即主要是System.Windows.Forms.dll这个库中的Screen.AllScreens函数获取显示器信息,显示器数量,位置,分辨率等信息。

    间接引用到System.Drawing.dll但是在引用这个库时遇到诸多问题:

    1.System.Windows.Forms.dll正常引用方式引用不进来(在vs“引用”中直接应用,原因不详,可能是与问题2所说的有关系),只能将System.Windows.Forms.dll放到工程中来,在Plugins下,当作其他那种dll用

    2.由于.NET类库System.Drawing.dll提供了一系列的图形函数,但由于其使用的是GDI接口,与DirectX和OpenGL之间不兼容,在Unity中默认是不被支持的。引用方式如1.

    3.引用进来后打包出错,或者导进去直接报错(具体忘记是什么了),找到playerSetting中的Other Settings中的改成如图。(还有错误就重启Unity,可能需要重新配置)

    我记忆中会有以上的三个问题,最后我的解决方案是:

    1.无需将这两个DLL放入工程

    2.写一名为csc.rsp的文件,内容是-r:System.Windows.Forms.dll -r:System.Drawing.dll。-r开头,想引用多个dll就空格后继续-r,然后将这文件放到Assets文件夹下(根目录)然后就搞定了,引用成功。

    具体代码:

    获取第一显示器的锚点和分辨率

    //Y坐标       
    int Y = System.Windows.Forms.Screen.AllScreens[0].Bounds.Y; //X坐标
    int X = System.Windows.Forms.Screen.AllScreens[0].Bounds.X; //高度
    int height = System.Windows.Forms.Screen.AllScreens[0].Bounds.Height; //宽度
    int width = System.Windows.Forms.Screen.AllScreens[0].Bounds.Width;

    最大化窗口(不同显示器定位搞定):

    App.initDeviceWidth 初始显示器宽,
    App.initDeviceHeight 初始显示器高

    (里面没说明的函数,上面去找)
     1         /// <summary>
     2         /// 最大化窗口
     3         /// </summary>
     4         public void SetMaxWindows()
     5         {
     8             int currMaxScreenHeight = Screen.currentResolution.height - GetTaskBarHeight();
     9             Rect rect = GetWindowInfo();
    10             Y = System.Windows.Forms.Screen.AllScreens[0].Bounds.Y;
    11             X = System.Windows.Forms.Screen.AllScreens[0].Bounds.X;
    12             height = System.Windows.Forms.Screen.AllScreens[0].Bounds.Height;
    13             width = System.Windows.Forms.Screen.AllScreens[0].Bounds.Width;
    14 
    15             //
    16             if (rect.x >= App.initDeviceWidth)
    17             {
    18                 if (Y < 0)//
    19                 {
    20                     SetWindowPos(GetForegroundWindow(), 0, (int)(width - App.initDeviceWidth), Y, Screen.currentResolution.width, currMaxScreenHeight, SWP_SHOWWINDOW);
    21                 }
    22                 else
    23                 {
    24                     SetWindowPos(GetForegroundWindow(), 0, (int)App.initDeviceWidth, (int)(height - App.initDeviceHeight), Screen.currentResolution.width, currMaxScreenHeight, SWP_SHOWWINDOW);
    25                 }
    26                 return;
    27             }
    28             else if (rect.x < 0)//
    29             {
    30                 //
    31                 if (Y < 0)
    32                 {
    33                     SetWindowPos(GetForegroundWindow(), 0, X, Y, Screen.currentResolution.width, currMaxScreenHeight, SWP_SHOWWINDOW);
    34                 }
    35                 else
    36                 {
    37                     SetWindowPos(GetForegroundWindow(), 0, -(int)App.initDeviceWidth, (int)(height - App.initDeviceHeight), Screen.currentResolution.width, currMaxScreenHeight, SWP_SHOWWINDOW);
    38                 }
    39                 return;
    40             }
    41             else if (rect.y >= App.initDeviceHeight || rect.y < 0)
    42             {
    43                 //正下
    44                 if (Y == 0)
    45                 {
    46                     SetWindowPos(GetForegroundWindow(), 0, 0, (int)App.initDeviceHeight, Screen.currentResolution.width, currMaxScreenHeight, SWP_SHOWWINDOW);
    47                 }
    48                 else
    49                 {
    50                     SetWindowPos(GetForegroundWindow(), 0, 0, -(int)App.initDeviceHeight, Screen.currentResolution.width, currMaxScreenHeight, SWP_SHOWWINDOW);
    51                 }
    52                 return;
    53             }
    54             else
    55             {
    56                 SetWindowPos(GetForegroundWindow(), 0, 0, 0, Screen.currentResolution.width, currMaxScreenHeight, SWP_SHOWWINDOW);
    57             }
    58         }

    显示器信息拿到了,设置位置就全是算数问题了,

    但是有如下几坑:

    1.如上图1234,扩展屏这个地方拿到的是Hright和width其实是下图的黑框大小(默认为组合屏的(两个屏幕的最外围矩形)尺寸),位置xy指的红圈处的坐标

    2.图1这种情况左上角锚点(x=0 &y<0),图2这种情况左上角锚点(x=0 &y=0),图3这种情况左上角锚点(x<0 &y<0),图4这种情况左上角锚点(x<0 &y=0)

    图二和图四是坑,容易想错,注意!!!

    完美解决!

    最新问题:上面一系列操作最近遇到了一点问题,就是使用获取窗口的方式用的有错误,我使用的是获取当前激活窗口GetForegroundWindow();在你切换exe时,可能操作的窗口就不是你原本想操作的那个窗口了,我们应该使用一个方法,获取指定窗口,无论你切换到哪个窗口都不能影响,这个方法是FindWindow();

    具体方法:

            //获取指定unity.exe窗口
            [DllImport("user32.dll", EntryPoint = "FindWindow")]
            public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
            public static IntPtr ParenthWnd = FindWindow(null, "ProjectName");    //build时候的项目名,playerSetting中设置的

    用这个方法替换掉GetForegroundWindow()就可以解决了,这样就可以避免由于切换窗口失去指定窗口句柄的问题。

    最新问题:Unity中调用windows窗口对文件进行筛选功能,文件类型自定义。如:

     主要是:设置filter,并且结合pth.filterIndex去选择使用生成的类型列表中的第几个(注意是从1开始的)。

    1 //字符串分隔符(多个根据分割的字符串形成下拉列表);
    2 //pth.filter = "JSON file(*.json)*.jsonFBX file(*.fbx)*.fbx"; //* *.fbx";
    3 //;是&的作用 1:.json;.fbx;.gltf 2:.json 3:.fbx 4:.gltf 5:PNG 6:All Files
    4 pth.filter = "模型文件(*.json|*.fbx|*.gltf)*.json;*.fbx;*.gltfJSON file(*.json)*.jsonFBX file(*.fbx)*.fbxGLTF file(*.gltf)*.gltfPNG file(*.png)*.pngAll Files*.*";

     完整代码:

     1  /// <summary>
     2     /// 文件过滤器类型
     3     /// </summary>
     4     public enum FileFilterType
     5     {
     6 
     7         /// <summary>
     8         /// 模型文件(.json/.gltf/.fbx)   1
     9         /// </summary>
    10         Model_File,
    11 
    12         /// <summary>
    13         /// json文件(.json) 2
    14         /// </summary>
    15         JSON_File,
    16 
    17         /// <summary>
    18         /// FBX文件(.fbx) 3
    19         /// </summary>
    20         FBX_File,
    21 
    22         /// <summary>
    23         /// GLTF文件(.gltf)  4
    24         /// </summary>
    25         GLTF_File,
    26 
    27         /// <summary>
    28         /// PNG文件(.png)   5    
    29         /// </summary>
    30         PNG_File,
    31 
    32         /// <summary>
    33         /// ALLFile    6
    34         /// </summary>
    35         AllFile,
    36     } 
    37 
    38 /// <summary>
    39         /// 打开项目弹框
    40         /// </summary>
    41         /// <returns></returns>
    42         private void OpenWindow(string foldName, FileFilterType fileFilterType, string defExtString, Action<string> action)
    43         {
    44             string filepath = "";
    45             OpenFile pth = new OpenFile();
    46             pth.structSize = System.Runtime.InteropServices.Marshal.SizeOf(pth);
    47 
    48             //字符串分隔符(多个根据分割的字符串形成下拉列表);
    49             //pth.filter = "JSON file(*.json)*.jsonFBX file(*.fbx)*.fbx"; //* *.fbx";
    50             //;是&的作用   1:.json;.fbx;.gltf 2:.json 3:.fbx 4:.gltf 5:PNG  6:All Files
    51             pth.filter = "模型文件(*.json|*.fbx|*.gltf)*.json;*.fbx;*.gltfJSON file(*.json)*.jsonFBX file(*.fbx)*.fbxGLTF file(*.gltf)*.gltfPNG file(*.png)*.pngAll Files*.*";
    52             pth.filterIndex = ((int)fileFilterType + 1);
    53             pth.file = new string(new char[256]);
    54             pth.maxFile = pth.file.Length;
    55             pth.fileTitle = new string(new char[64]);
    56             pth.maxFileTitle = pth.fileTitle.Length;
    57             pth.initialDir = Application.dataPath;  // default path  
    58             pth.title = foldName;
    59             pth.defExt = defExtString;
    60 
    61             //注意 一下项目不一定要全选 但是0x00000008项不要缺少
    62             //0x00080000   是否使用新版文件选择窗口,0x00000200   是否可以多选文件
    63             pth.flags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000200 | 0x00000008;
    64 
    65             if (OpenFileWindow.GetOpenFileName(pth))
    66             {
    67                 filepath = pth.file;//选择的文件路径;  
    68                 action(filepath);
    69             }
    70         }

    欢迎交流指正。

  • 相关阅读:
    DIV+CSS—菜鸟分享学习心得!入门篇
    有关 JavaScript 的 10 件让人费解的事情
    [论离职]走的人不少,来的人更多
    面朝电脑,春暖花开
    职场小说:《米亚快跑》PDF版下载
    flex和html的对比
    10个可以简化开发过程的MySQL工具
    转:大型网站架构不得不考虑的10个问题
    怎样善用色彩层次?40个精彩站点给你灵感
    50个令人耳目一新的网页纹理设计
  • 原文地址:https://www.cnblogs.com/answer-yj/p/11654190.html
Copyright © 2011-2022 走看看