/// <summary> /// Sets desktop wallpaper to user selected image in filebrowser. /// </summary> /// <param name="filePath">wallpaper path.</param> public void SetCustomWallpaper(string filePath) { if (filePath != null) { StaticPinvoke.SystemParametersInfo(SPI_SETDESKWALLPAPER, (UInt32)filePath.Length, filePath, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE); } }
/// <summary> /// Move rePaper to corresponding display. /// </summary> public void MoveToDisplay(int i) { StaticPinvoke.RECT appBounds_; Rectangle screenBounds_; Screen[] screens = Screen.AllScreens; if (i > (screens.Length - 1)) { i = 0; //primary monitor } StaticPinvoke.GetWindowRect(workerw, out appBounds_); screenBounds_ = System.Windows.Forms.Screen.FromHandle(workerw).Bounds; //force refresh desktop StaticPinvoke.SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, null, SPIF_UPDATEINIFILE); if (i == -1) { //crash, skipping for now. //StaticPinvoke.SetWindowPos(old_unity_handle, 1, appBounds_.Left, appBounds_.Top, screens[i].Bounds.Width, screens[i].Bounds.Height, 0); } else { // adding the workerw offsets to x & y. (basically the bounds change since rePaper is a child of workerw handle) StaticPinvoke.SetWindowPos(old_unity_handle, 1, screens[i].Bounds.X - appBounds_.Left, screens[i].Bounds.Y - appBounds_.Top, screens[i].Bounds.Width, screens[i].Bounds.Height, 0); } }
/// <summary> /// Shows Error alert box with OK button. /// </summary> /// <param name="text">Main alert text / content.</param> /// <param name="caption">Message box title.</param> public void Error(string text, string caption) { try { int msgboxID = StaticPinvoke.MessageBox(GetWindowHandle(), text, caption, (uint)(0x00000006L | 0x00000010L)); //Debug.Log(msgboxID); switch (msgboxID) { case 2: //cancel Application.Quit(); break; case 10: //tryagain CheckMonitors(); break; case 11: //continue break; } } catch (Exception ex) { Debug.Log(ex.Message); } }
public SystemTray() { trayMenu = new System.Windows.Forms.ContextMenu(); trayIcon = new NotifyIcon(); //trayIcon.Text = UnityEngine.Application.productName; if (UnityEngine.Application.isEditor) { trayIcon.Icon = new Icon(SystemIcons.Application, 40, 40); } else { ushort uicon, uicon2; StringBuilder strB = new StringBuilder(AppDomain.CurrentDomain.BaseDirectory + "\\icons\\icon_run.ico"); IntPtr handle = StaticPinvoke.ExtractAssociatedIcon(IntPtr.Zero, strB, out uicon); ico_run = Icon.FromHandle(handle); trayIcon.Icon = ico_run; strB.Clear(); strB = new StringBuilder(AppDomain.CurrentDomain.BaseDirectory + "\\icons\\icon_pause.ico"); handle = StaticPinvoke.ExtractAssociatedIcon(IntPtr.Zero, strB, out uicon2); ico_pause = Icon.FromHandle(handle); strB.Clear(); } trayIcon.ContextMenu = trayMenu; }
/// <summary> /// Delay before monitoring paunse/unpause. /// </summary> IEnumerator Startup() { //why I did this instead of just sleeping the thread before entering loop, I will never know... x_x yield return(new WaitForSeconds(5f)); hWnd = StaticPinvoke.GetForegroundWindow(); t_watcher.Start(); }
/// <summary> /// Disclaimer Messagebox /// </summary> public int WarningMsg(string text, string caption) { try { int msgboxID = StaticPinvoke.MessageBox(GetWindowHandle(), text, caption, (uint)(0x00000001L | 0x00000030L)); return(msgboxID); } catch (Exception ex) { Debug.Log(ex.Message); return(2); } }
/// <summary> /// Retrieves windows desktop wallpaper & loads it. /// </summary> public void GetWallpaperImage() { RegistryKey currentMachine = Registry.CurrentUser; RegistryKey controlPanel = currentMachine.OpenSubKey("Control Panel"); RegistryKey desktop = controlPanel.OpenSubKey("Desktop"); string filePath = Convert.ToString(desktop.GetValue("WallPaper")); controlPanel.Close(); if (!System.IO.File.Exists(filePath)) { //Try to retrieve wallpaper image with cached file.. filePath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Microsoft\\Windows\\Themes\\CachedFiles"; if (Directory.Exists(filePath)) { string[] filePaths = Directory.GetFiles(filePath); if (filePaths.Length > 0) { filePath = filePaths[0]; } } else { //Try to retrieve wallpaper image by original source.. RegistryKey regKey = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Internet Explorer\\Desktop\\General\\", false); filePath = regKey.GetValue("WallpaperSource").ToString() + "h"; if (!System.IO.File.Exists(filePath)) { //Failed to retrieve wallpaper image by original source.. filePath = new String('\0', MAX_PATH); StaticPinvoke.SystemParametersInfo(SPI_GETDESKWALLPAPER, (UInt32)filePath.Length, filePath, 0); filePath = filePath.Substring(0, filePath.IndexOf('\0')); } } } if (System.IO.File.Exists(filePath)) { MenuController.menuController.wallpaperPath = filePath; tex = new Texture2D(2, 2); StartCoroutine(WaitForImageDownload(filePath)); //async image loading. } else { UnityEngine.Debug.Log("Failed to retrieve wallpaper image using all methods!"); } desktop.Close(); currentMachine.Close(); }
/// <summary> /// Retrieves current wallpaper path, including name. /// </summary> /// <returns> /// Wallpaper path string. /// </returns> public static string GetWallpaperImagePath() { RegistryKey currentMachine = Registry.CurrentUser; RegistryKey controlPanel = currentMachine.OpenSubKey("Control Panel"); RegistryKey desktop = controlPanel.OpenSubKey("Desktop"); string filePath = Convert.ToString(desktop.GetValue("WallPaper")); controlPanel.Close(); if (!System.IO.File.Exists(filePath)) { filePath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Microsoft\\Windows\\Themes\\CachedFiles"; if (Directory.Exists(filePath)) { string[] filePaths = Directory.GetFiles(filePath); if (filePaths.Length > 0) { filePath = filePaths[0]; } } else { RegistryKey regKey = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Internet Explorer\\Desktop\\General\\", false); filePath = regKey.GetValue("WallpaperSource").ToString() + "h"; if (!System.IO.File.Exists(filePath)) { filePath = new String('\0', MAX_PATH); StaticPinvoke.SystemParametersInfo(SPI_GETDESKWALLPAPER, (UInt32)filePath.Length, filePath, 0); filePath = filePath.Substring(0, filePath.IndexOf('\0')); } } } desktop.Close(); currentMachine.Close(); if (System.IO.File.Exists(filePath)) { //UnityEngine.Debug.Log(filePath); return(filePath); } else { UnityEngine.Debug.LogError("Failed to retrieve wallpaper image using all methods!"); return(null); } }
/// <summary> /// Background thread that monitors running audio session & update labeltext. /// </summary> void Monitor() { int sessionCnt = 0; while (true) { Thread.Sleep(1000); foreach (AudioSession item in AudioUtilities.GetAllSessions()) { if (item.Process == null || IntPtr.Equals(item.Process.MainWindowHandle, IntPtr.Zero)) { item.Dispose(); continue; } item.Process.Refresh(); //if audio playback active. if (item.State == AudioSessionState.Active) { sessionCnt += 1; try { if (item.Process.ProcessName.Equals("spotify", StringComparison.InvariantCultureIgnoreCase)) { UpdateLabel_T(item.Process.MainWindowTitle); } else if (item.Process.ProcessName.Equals("foobar2000", StringComparison.InvariantCultureIgnoreCase)) { //UpdateLabel_T(item.Process.MainWindowTitle.Replace("[foobar2000]", "")); UpdateLabel_T(item.Process.MainWindowTitle.Substring(0, item.Process.MainWindowTitle.Length - 12)); //cheaper. } else if (item.Process.ProcessName.Equals("vlc", StringComparison.InvariantCultureIgnoreCase)) { UpdateLabel_T(item.Process.MainWindowTitle.Substring(0, item.Process.MainWindowTitle.Length - 19)); } else if (item.Process.ProcessName.Equals("chrome", StringComparison.InvariantCultureIgnoreCase)) { // won't update if video changes & different tab open on browser. if (item.Process.MainWindowTitle.Contains(" - YouTube - Google Chrome")) { UpdateLabel_T(item.Process.MainWindowTitle.Substring(0, item.Process.MainWindowTitle.Length - 26)); } } else if (item.Process.ProcessName.Equals("firefox", StringComparison.InvariantCultureIgnoreCase)) { //failed to find correct process for firefox, finding windowhandle instead. hWnd = StaticPinvoke.FindWindow("MozillaWindowClass", null); StaticPinvoke.GetWindowThreadProcessId(hWnd, out processID); currProcess = Process.GetProcessById(processID); // won't update if video changes & different tab open on browser. if (currProcess.MainWindowTitle.Contains(" - YouTube - Mozilla Firefox")) { UpdateLabel_T(currProcess.MainWindowTitle.Substring(0, currProcess.MainWindowTitle.Length - 28)); } } else if (item.Process.ProcessName.Equals("nvcontainer", StringComparison.InvariantCultureIgnoreCase)) // nvidia gfe screen recording. { sessionCnt -= 1; } else { UpdateLabel_T(item.Process.MainWindowTitle); } } catch (ArgumentOutOfRangeException) //when window title < subtracting value. { UpdateLabel_T(item.Process.MainWindowTitle); } } item.Dispose(); } if (sessionCnt <= 0) { UpdateLabel_T("No Playback"); } sessionCnt = 0; } }
// Use this for initialization void Start() { if (MenuController.menuController.userSettings.isDXVA == true && MenuController.menuController.userSettings.vidPath != null) { Application.targetFrameRate = 60; } else { Application.targetFrameRate = MenuController.menuController.userSettings.fps; } if (Application.isEditor == true) //disable on Unity Editor. { return; } //{UNUSED} Hide application icon from taskbar(background process). #region borderless /* * // Find the application's Window * var handle = FindWindowByCaption(IntPtr.Zero, Application.productName); * if (handle == IntPtr.Zero) return; * * // Move the Window Off Screen * SetWindowPos(handle, 1, 0, 0, 640, 360, 0); * //SetWindowPos(handle, 0, -720, 0, 720, 480, 0); //ORIGINAL * * // Remove the Window from the Taskbar * ShowWindow(handle, (uint)0); * SetWindowLong(handle, GWL_EXSTYLE, GetWindowLong(handle, GWL_EXSTYLE) | WS_EX_TOOLWINDOW); * ShowWindow(handle, (uint)5); */ #endregion // Renders behind desktop icons & windows. #region behind_icon // Find Progman windowhandle progman = StaticPinvoke.FindWindow("Progman", null); // Desktop folderView = StaticPinvoke.FindWindowEx(progman, IntPtr.Zero, "SHELLDLL_DefView", null); if (folderView == IntPtr.Zero) { do { workerWOrig = StaticPinvoke.FindWindowEx(StaticPinvoke.GetDesktopWindow(), workerWOrig, "WorkerW", null); folderView = StaticPinvoke.FindWindowEx(workerWOrig, IntPtr.Zero, "SHELLDLL_DefView", null); } while (folderView == IntPtr.Zero && workerWOrig != IntPtr.Zero); } folderView = StaticPinvoke.FindWindowEx(folderView, IntPtr.Zero, "SysListView32", "FolderView"); result = IntPtr.Zero; //todo: Set Animate controls & elements inside windows settings using Systemparametersinfo() // Send 0x052C to Progman. Spawns WorkerW behind desktop icons. // "Animate controls and elements inside windows" needs to be enabled in: This PC -> Properties -> Advanced System Settings -> Performance -> Settings. // This is used to show Fade effect on windows wallpaper change. // In windows 7 this setting is probably(?) under multiple settings. StaticPinvoke.SendMessageTimeout(progman, 0x052C, new IntPtr(0), IntPtr.Zero, StaticPinvoke.SendMessageTimeoutFlags.SMTO_NORMAL, 1000, out result); workerw = IntPtr.Zero; // Find newly created worker StaticPinvoke.EnumWindows(new StaticPinvoke.EnumWindowsProc((tophandle, topparamhandle) => { p = StaticPinvoke.FindWindowEx(tophandle, IntPtr.Zero, "SHELLDLL_DefView", IntPtr.Zero); if (p != IntPtr.Zero) { // Gets the WorkerW Window after the current one. workerw = StaticPinvoke.FindWindowEx(IntPtr.Zero, tophandle, "WorkerW", IntPtr.Zero); } return(true); }), IntPtr.Zero); if (IntPtr.Equals(workerw, IntPtr.Zero) || workerw == null) { //todo: set the settings through code using SystemParametersInfo() - complication: microsoft uses registry to update the radio button UI in the Performance dialog, //which DOES not reflect actual applied settings! o_O..will have to edit registry too. if (MenuController.menuController.WarningMsg("It looks like some settings need to be set to make rePaper work:- \n" + "1. Open This PC(My Computer)\n" + "2. Right-click empty area\n" + "3. Select Properties\n" + "4. Select Advanced System Settings\n" + "5. Under Performance tab select Settings\n" + "6. Enable Animate controls and elements inside windows & Apply.\n" + "If Windows 7 just set - Adjust for best appearance & Apply\n" + "If still not working, close & start rePaper again or restart windows." + "Press OK to Exit, Cancel to proceed anyway.", "Hold on..") == 1) { main.instance.Close_Action(null, null); } } IntPtr handle = IntPtr.Zero; // Find the application's Window, should work in 90% case handle = StaticPinvoke.FindWindowByCaption(IntPtr.Zero, Application.productName); while (handle != null && !IntPtr.Equals(handle, IntPtr.Zero)) { #region processid //Process.GetCurrentProcess().MainWindowHandle returns 0, searching with found handle instead. StaticPinvoke.GetWindowThreadProcessId(handle, out processID); unity_process = Process.GetProcessById(processID); // Verify weather the window handle is rePaper-Unity.exe before proceeding further!. if (unity_process.ProcessName.Equals(Application.productName, StringComparison.InvariantCultureIgnoreCase)) { old_unity_handle = handle; break; } else // something else!!...probably explorer window with window title caption. { Debug.Log("Different window handle found instead of rePaper-Unity, searching again!"); old_unity_handle = handle; //searching the next window handle... handle = StaticPinvoke.FindWindowEx(IntPtr.Zero, old_unity_handle, null, Application.productName); } #endregion processid } if (handle == null || IntPtr.Equals(handle, IntPtr.Zero)) { Debug.Log("Could't find unity window! Handle:- "); return; } if (MenuController.menuController.isMultiMonitor == false) { StaticPinvoke.SetWindowPos(handle, 1, 0, 0, UnityEngine.Screen.currentResolution.width, UnityEngine.Screen.currentResolution.height, 0); } else //multiple monitors detected. { /* * //Attempted to make window appear on primary monitor, failure!. * var monitor = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea; * StaticPinvoke.SetWindowPos(handle, 1, monitor.Left, monitor.Top, monitor.Width,monitor.Height, 0); */ //Success, basically offset value of desktop handle needs to be added to x,y //todo:- update pause/sleep algorithm for multiple displays. ( currently based on primary display) MoveToDisplay(MenuController.menuController.userSettings.ivar2); } //os = SystemInfo.operatingSystem.ToLowerInvariant(); //unity operating system info. if (System.Environment.OSVersion.Version.Major == 6 && System.Environment.OSVersion.Version.Minor == 1) //windows 7(min: support) { if (debuggin == false) { workerWOrig = progman; StaticPinvoke.ShowWindow(workerw, (uint)0); StaticPinvoke.SetParent(handle, progman); } } else //assuming above win7, will fail in vista etc { if (debuggin == false) { StaticPinvoke.SetParent(handle, workerw); } } #endregion behind_icon #region pause_unpause_monitor t_watcher = new Thread(new ThreadStart(Update_T)); t_watcher.IsBackground = true; //exit with application StartCoroutine(Startup()); desktopHandle = StaticPinvoke.GetDesktopWindow(); shellHandle = StaticPinvoke.GetShellWindow(); hWnd = workerWOrig; // bug fix: early launch, might detect application as hWndID. #endregion pause_unpause_monitor }
public static volatile bool isDesktop = true; //volatile - cache flush/refresh, thread synchronisation not essential in this application..? //string currProcessName = null; //foreground process-name /// <summary> /// Background thread that monitor foreground windows type, size etc to decide pause/unpause unity main-thread. /// </summary> private void Update_T() { while (true) { // delay, can be higher but longer time to unpause/pause...50milliseconds seems fine on my i5 4core system. Thread.Sleep(50); // current foreground window. Only used to get foreground process-name, nothing is being stored. If you don't like rePaper monitoring then replace hWnd = StaticPinvoke.GetForegroundWindow() with hWnd = workerWOrig; hWnd = StaticPinvoke.GetForegroundWindow(); try { // retrieve foreground window process-name. Since repaper is started as non-admin process, name retrieval might fail for admin/certain processes. StaticPinvoke.GetWindowThreadProcessId(hWnd, out processID); currProcess = Process.GetProcessById(processID); } catch (Exception) { // todo: unity functions are thread unsafe, cant use unity debug. } if (true) //old-code/future use. { #region Exceptions_&_Fixes // failed to find in some cases. if (IntPtr.Equals(workerWOrig, IntPtr.Zero) == true) { folderView = StaticPinvoke.FindWindowEx(progman, IntPtr.Zero, "SHELLDLL_DefView", null); if (folderView == IntPtr.Zero) { do { workerWOrig = StaticPinvoke.FindWindowEx(StaticPinvoke.GetDesktopWindow(), workerWOrig, "WorkerW", null); folderView = StaticPinvoke.FindWindowEx(workerWOrig, IntPtr.Zero, "SHELLDLL_DefView", null); } while (folderView == IntPtr.Zero && workerWOrig != IntPtr.Zero); } } try { //currProcessName = currProcess.ProcessName.toLowerInvarient(); if (pause_disable == true || MenuController.menuController.userSettings.bvar2 == true || String.IsNullOrEmpty(currProcess.ProcessName)) //debugging, skip rePaper pause/sleep. { continue; } skipAhead = false; if (MenuController.menuController.userSettings.appFocusPause == false) { //user defined application-pause/sleep-rules foreach (var item in MenuController.menuController.appList) { //if (item.processName.ToLowerInvariant() == currProcessName) if (currProcess.ProcessName.Equals(item.processName, StringComparison.InvariantCultureIgnoreCase)) { if (item.sleep == false) //always run when this process is foreground window, even when maximized { hWnd = workerWOrig; //assume desktop, to force unpause/wakeup of rePaper. } else //sleep { isDesktop = false; runningFullScreen = true; main.instance.ChangeTrayIcon(runningFullScreen); manualResetEvent.Reset(); skipAhead = true; } break; } } if (skipAhead == true) { continue; } } if (currProcess.ProcessName.Equals("repaper-unity", StringComparison.InvariantCultureIgnoreCase) || // bug fix: early launch, might detect application as hWnd ID currProcess.ProcessName.Equals("config-repaper", StringComparison.InvariantCultureIgnoreCase) || //config utility for rePaper currProcess.ProcessName.Equals("shellexperiencehost", StringComparison.InvariantCultureIgnoreCase) || //notification tray etc currProcess.ProcessName.Equals("searchui", StringComparison.InvariantCultureIgnoreCase) //startmenu search etc //|| currProcessName.Equals("applicationframehost", StringComparison.InvariantCultureIgnoreCase) //windows10 dialogues like adjust time, all uwp processes(store apps) comes under this. //|| currProcessName.Equals("discord", StringComparison.InvariantCultureIgnoreCase) //fix, when trying to minimize maximised discord window, it does not minimize properly to systemtray, foreground windowhandle still at discord. ) { hWnd = workerWOrig; //assume desktop, to force unpause/wakeup of rePaper. For win7 workerWOrig is set as progman in Start() } } catch (Exception) { //ignore } if (IntPtr.Equals(old_unity_handle, hWnd))// bug fix: early launch, might detect application as hWnd ID. what a pain.. { hWnd = workerWOrig; } if (IntPtr.Equals(shell_tray, IntPtr.Zero) == true) //startmenu, sometimes become zero? { shell_tray = StaticPinvoke.FindWindow("Shell_TrayWnd", null); } #endregion Exceptions_&_Fixes if (hWnd != null && !hWnd.Equals(IntPtr.Zero)) { if (!(hWnd.Equals(desktopHandle) || hWnd.Equals(shellHandle))) { StaticPinvoke.GetWindowRect(hWnd, out appBounds); //open applications window size, could use IsZoomed() if such fine control is not required. screenBounds = System.Windows.Forms.Screen.FromHandle(hWnd).Bounds; if ((appBounds.Bottom - appBounds.Top) >= screenBounds.Height * .9f && (appBounds.Right - appBounds.Left) >= screenBounds.Width * .9f) //foreground window > 90% work_area, ie: work_area = display_resolution - taskbar { //todo: could avoid this check everytime by making two versions of this fn, win7 & other. if (System.Environment.OSVersion.Version.Major == 6 && System.Environment.OSVersion.Version.Minor == 1) //windows 7 { if (IntPtr.Equals(hWnd, progman) != true) //not equal to desktop & fullscreen apprunning { isDesktop = false; runningFullScreen = true; main.instance.ChangeTrayIcon(runningFullScreen); manualResetEvent.Reset(); } else // currently at desktop(if user clicks or minimize all apps) { isDesktop = true; manualResetEvent.Set(); runningFullScreen = false; main.instance.ChangeTrayIcon(runningFullScreen); } } else // windows 8, 10 etc.. { if (IntPtr.Equals(hWnd, workerWOrig) != true) //not equal to desktop & fullscreen apprunning { isDesktop = false; runningFullScreen = true; main.instance.ChangeTrayIcon(runningFullScreen); manualResetEvent.Reset(); } else // currently at desktop(if user clicks) { isDesktop = true; manualResetEvent.Set(); runningFullScreen = false; main.instance.ChangeTrayIcon(runningFullScreen); } } } else if (IntPtr.Equals(shell_tray, IntPtr.Zero) != true && IntPtr.Equals(hWnd, shell_tray) == true) //systrayhandle { isDesktop = true; main.instance.ChangeTrayIcon(runningFullScreen); runningFullScreen = false; manualResetEvent.Set(); } else //application window is not greater >90% { isDesktop = false; if (MenuController.menuController.userSettings.appFocusPause == false) { runningFullScreen = false; main.instance.ChangeTrayIcon(runningFullScreen); manualResetEvent.Set(); } else { runningFullScreen = true; main.instance.ChangeTrayIcon(runningFullScreen); manualResetEvent.Reset(); } } } } } } //while loop }
/// <summary> /// Force refresh desktop. /// </summary> void SetWallpaper() { StaticPinvoke.SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, null, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE); }
//https://gist.github.com/roydejong/130a91e1835154a3acaeda78c9dfbbd7 public static System.IntPtr GetWindowHandle() { return(StaticPinvoke.GetActiveWindow()); }