如今在搞PC端應用開發,咱們開發中須要調用系統的窗口以及須要最大化最小化,縮放窗口拖拽窗口,以及設置窗口位置,去邊框等功能json
使用user32.dll解決windows
調用Comdlg32.dll中方法app
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 }
具體使用:ide
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\0 *.*\0\0";//是什麼文件類型就修改此處 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\0*.*\0\0"; 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 }
效果:工具
打開:ui
保存:spa
導入user32.dll的相關方法:3d
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);
具體使用:code
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);blog
注:
1.windows下的窗口一旦去了上邊欄(邊框),就沒法拖拽縮放了,邊框和上邊欄是一體的,因此拖拽功能要想保留不能直接去掉邊框,固然能夠本身寫拖拽縮放,我試着寫過,實現能夠,可是無奈領導說最好使用原生的,我就放棄了。
2.還有一個坑,注意windows環境下,屏幕座標原點(0,0)在左上角,不和unity中同樣在左下角。
去邊框上邊框(自帶白色上邊框)效果:
導入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)。
導入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 }
導入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 當前設備寬
保留任務欄最大化效果:
導入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 }
歡迎交流指正。