Processing Ajax...
Save 25% on our desktop apps during our Black Friday/Cyber Monday sale!Save 25% on our desktop apps during our Black Friday/Cyber Monday sale, including DisplayFusion, ClipboardFusion, FileSeek, LogFusion, TrayStatus, and VoiceBot!Save 25% on our desktop apps during our Black Friday/Cyber Monday sale!

Title
Close Dialog

Message

Confirm
Close Dialog

Confirm
Close Dialog

Desktop Auto-Load

Description
This function applies a desktop icon profile, restores a backup of desktop gadget settings and applies them, and restores size and positions of currently running windows (restored ones only).
I assigned the Hotkey 'Ctrl + Win + R' and the trigger "Change Monitor Profile' to this function and use that to restore the desktop info any time the monitor profile changes.
I have another function 'Desktop Auto-Save' which is called by a hotkey and saves all that.
Language
C#.net
Minimum Version
Created By
Christian Treffler
Contributors
-
Date Created
Dec 13, 2016
Date Last Modified
Jan 16, 2018

Scripted Function (Macro) Code

using System;
using System.IO;
using System.Drawing;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Serialization;
using System.Text;

// V2.05
// by: Christian Treffler
// 
// The function loads several informations about the current desktop and applies them 
// for the current monitor setup:
// - Current desktop icons in a desktop icon profile
// - desktop gadget settings in "%userprofile%\AppData\Local\DisplayFusion\SidebarSettings"
// - position of windows in restored state in "%userprofile%\AppData\Local\DisplayFusion\WindowSettings"
// The profile name is built using the resolution and Y-position info of each monitor
// except the primary monitor where the Y-Position is 0.
// The information was generated by the function 'Desktop Auto-Save' 
//
// Recommended to start with trigger "Monitor Profile changed"
//
// History: 
// V2.01:
// Bugfix:
// - If Desktop Gadgets are running, but no respective settings have been saved for the ProfileName,
//   they are not stopped. Nevertheless an attempt to restart them was made, leading to the opening 
//   of the System32 folder.
//
// V2.02:
// Improvement:
// Some windows seem not to be on the right place when this function is triggered by a change in monitor profiles.
// Only when calling it a second time it works.
// Introduced a wait time. RearrangeWait variable contains this time. 
// 1s works most of the time, but not always
// 2s seems also not OK. Moved to desktop windows only, wait 2s after desktop gadgets
// 2s not enough, tried 5s
// 
// V2.03:
// Removed wait time because it doesn't work
// Remove check, if Desktop Gadgets are running. Instead check, if a settings file for the profile exists
// Check program windos before Desktop Gadgets
//
// V2.04:
// Desktop gadget settings (sidebar): do not check, if setting exist. Info about start/stop is now stored with Program Settings
// The path to the sidebar appliaciton will also be stored
// Assure that LoadProgramSettings returns an object != null
//
// V2.05: Changes only in Desktop Auto-Save


public static class DisplayFusionFunction
{
	public static void Run(IntPtr windowHandle)
	{
		string app = "";
		
		// Are there desktop gadgets running?
        bool SideBarExists = BFS.Application.IsAppRunningByFile("*sidebar.exe");
 
		
		// Get Resolution of all Monitors and generate profile name
		Rectangle[] Monitors = BFS.Monitor.GetMonitorBounds(); 
		string ProfileName = buildProfileName(Monitors);
		
		BFS.DisplayFusion.LoadDesktopIconsProfile(ProfileName);
   
        DesktopPrograms AllPrgrms = ReadProgramSettings(SideBarExists /*V2.04*/); // Check current windows
        DesktopPrograms SavedPrgrms = LoadProgramSettings(ProfileName); // Get stored window settings
        
        if (SavedPrgrms.Prgrms.Count > 0)                       // were settings stored?
        {
            foreach (string key in SavedPrgrms.Prgrms.Keys)     // for each stored window setting
            {
                if (AllPrgrms.Prgrms.ContainsKey(key))          // is the respective window running?
                {
                    // restore size and location
                    Rectangle rct = SavedPrgrms.Prgrms[key].Rct;
                    IntPtr window = AllPrgrms.Prgrms[key].Ptr;
                    BFS.Window.SetSizeAndLocation(window, rct.X, rct.Y, rct.Size.Width, rct.Size.Height);
                }
            }
        }

        // Stop desktop gadgets
        bool ok = true;
        uint appID = BFS.Application.GetAppIDByFile("*sidebar.exe");
        app = BFS.Application.GetMainFileByAppID(appID);

        if (SideBarExists){ // V2.03
            ok = BFS.Application.Kill(appID);
        }
                
        SideBarExists = SavedPrgrms.SideBarExists;  //V2.04
        if(SideBarExists)
        {
            //Replace current sidebar settings from the DisplayFusion User folder using the ProfileName
            //Location of the DisplyFusion user folder&File
            string source = Environment.ExpandEnvironmentVariables("%userprofile%\\AppData\\Local\\DisplayFusion\\SidebarSettings\\" + ProfileName + ".ini");
            //Location of the sidebar settings
            string destination = Environment.ExpandEnvironmentVariables("%userprofile%\\AppData\\Local\\Microsoft\\Windows Sidebar\\Settings.ini");

            if (File.Exists(source) && Directory.Exists(Path.GetDirectoryName(destination)))  // Check that operation is possible
            {
                if (ok) // if sidebar is inactive
                {
                    File.Copy(source, destination, true);
                    // SideBarExists = true;   //V2.03, moved with V2.04
                } // else SideBarExists = false; removed with V2.04
                // desktop gadgets will be restart after changing window settings
            }   // else SideBarExists = false; Removed with V2.04
            
            
            // restart desktop gadgets
            BFS.Application.Start(SavedPrgrms.SideBarPath,"");  // V2.04
        } 
    }
	
	public static string buildProfileName(Rectangle[] screens)
	{
		// needs System.Text to have StringBuilder class
		
		StringBuilder pname = new StringBuilder();
		
		for (int i = 0; i < screens.Length; i++) // For each monitor
		{
			// Add monitors resolution in the format "[<Width>x<Height>, <Y>]"
			pname.Append("[");
			pname.Append(screens[i].Width);
			pname.Append("x");
			pname.Append(screens[i].Height);
			if(screens[i].X!=0 || screens[i].Y!=0) // Primary screen has coordinates [0,0]
			{
				// Add the y-coordinate, if not primary screen
				pname.Append(",");
				pname.Append(screens[i].Y);
			}
			pname.Append("]");
		}
		
		return pname.ToString();
	}
	
    public static DesktopPrograms ReadProgramSettings(bool SideBarExists /*V2.04*/)  // Get window settings
    {
        DesktopPrograms AllPrograms = new DesktopPrograms();
        AllPrograms.SideBarExists = SideBarExists;          // V2.04
        if (SideBarExists)                                  // V2.04
        {
            uint appID = BFS.Application.GetAppIDByFile("*sidebar.exe");
            AllPrograms.SideBarPath = BFS.Application.GetMainFileByAppID(appID);
        }

        foreach(IntPtr window in BFS.Window.GetVisibleWindowHandles())
		{
            if (BFS.Window.IsRestored(window) && BFS.Window.GetText(window)!="") // only for windows which are not maximized or minimized
            {
                DProgram prgrm = new DProgram();    // DProgram is the class to store a setting
                
                prgrm.ProgramClass = BFS.Window.GetClass(window);
                prgrm.Text = BFS.Window.GetText(window);
                prgrm.Rct = BFS.Window.GetBounds(window);
                prgrm.Ptr = window;

                AllPrograms.AddProgram(prgrm);      // add to list
            }
		}
 
        return AllPrograms;
     }

    public static void SaveProgramSettings(DesktopPrograms Data, string profile) // store all window settings in an xml file with the provided filename
    {
        XmlSerializer XmlSer = new XmlSerializer(typeof(DesktopPrograms));       // Provides the methods for XML-Serialization
        // will be stored in the users local DisplayFusion AppData folder:
        string path = Environment.ExpandEnvironmentVariables("%userprofile%\\AppData\\Local\\DisplayFusion\\WindowSettings\\" + profile + ".xml");
      
        bool ready2copy = false; // Copy only if destination folder exists

        try
        {
            //Location of the DisplyFusion user folder
            string destination = Environment.ExpandEnvironmentVariables("%userprofile%\\AppData\\Local\\DisplayFusion");
            if (Directory.Exists(destination))  // DisplyFusion user folder found?
            {
                // Creat a subfolder if it doesn't exist, yet
                destination = destination + "\\WindowSettings";
                ready2copy = Directory.Exists(destination);
                if (!ready2copy)
                {
                    ready2copy = Directory.CreateDirectory(destination).Exists;
                }
            }
        }
    
        catch (Exception) { }

        if (ready2copy) // if destination folder exists
        {
            FileStream DStream = new FileStream(path, FileMode.Create);     // Create the Filestream, overwrite mode

            try
            {
                XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); // Use this object
                ns.Add("", "");                                             // to prevent that attributes are added in the files

                XmlWriterSettings xws = new XmlWriterSettings();            // Use this object to
                xws.Indent = true;                                          // - add line feeds and indents
                xws.CloseOutput = true;                                     // - close stream after writing
                xws.Encoding = Encoding.Default;                            // - set encoding
                xws.IndentChars = "      ";                                 // - set indent depth
                xws.NewLineHandling = NewLineHandling.None;                 // - handle line feeds properly

                using (XmlWriter writer = XmlWriter.Create(DStream, xws))   // Now serialize
                {
                    XmlSer.Serialize(writer, Data, ns);
                    writer.Close();
                }
            }

            catch (Exception) { }

            finally
            {
                if (!(DStream == null)) DStream.Close();                    // Close the stream
            }       
        }
    }

    public static DesktopPrograms LoadProgramSettings(string profile)   // read window settings from an xml file with the provided filename
    {
        DesktopPrograms r = new DesktopPrograms();
        string p = Environment.ExpandEnvironmentVariables("%userprofile%\\AppData\\Local\\DisplayFusion\\WindowSettings\\" + profile + ".xml"); // Full Filename with path
        XmlSerializer XmlSer = new XmlSerializer(typeof(DesktopPrograms)); // Provides the methods for XML-Serialization

        FileStream DStream = null;
        try
        {
            if (File.Exists(p))
            {
                DStream = new FileStream(p, FileMode.Open);         // Create the Filestream
                r = (DesktopPrograms)XmlSer.Deserialize(DStream);   // and load the Data 
            }
        }

        catch (Exception) { }

        finally
        {
            if (!(DStream == null)) DStream.Close();                // Done
            if (r == null) r = new DesktopPrograms();               // V2.04
        }
        return r;
    }

    [Serializable]
    public class DProgram   // stores window settings
    {
        public string Text = "";
        public string ProgramClass = "";
        public Rectangle Rct = new Rectangle();
        
        [XmlIgnoreAttribute]    // the handle will not be stored to file
        public IntPtr Ptr = new IntPtr();
        
        public Point Loc
        {
            get
            {
                return Rct.Location;
            }
        }

        public DProgram() { } // empty constructor is needed to make the class serializable
    }

    [Serializable]
    public class DesktopPrograms     // list of window settings
    {
        public DesktopPrograms() { } // empty constructor is needed to make the class serializable

        public XMLDictionary<string, DProgram> Prgrms = new XMLDictionary<string, DProgram>();  // list of windows
        public bool SideBarExists = false;  // V2.04  
        public string SideBarPath = "";     // V2.04
 
        public void AddProgram(DProgram prgrm)  // build a key and add the window settings to the list
        {
            // the key will be built out of the windows class and name and a counter
            int i = 0;
            string keyo = prgrm.ProgramClass + prgrm.Text;
            string key = keyo + i.ToString("00");
            while (Prgrms.ContainsKey(key))
            {
                if (++i > 99) break;
                key = keyo + i.ToString("00");
            }
            if (i < 100)
            {
                Prgrms.Add(key, prgrm);
            }
        }
    }

    // ***** XMLDictionary *****
    // A Module to provide a dictionary which is serializable.
    // Purpose: e.g. ini-files
    // Paul Welter 3/5/2006
    //
    // http://weblogs.asp.net/pwelter34/archive/2006/05/03/444961.aspx
    public class XMLDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
    {
        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(System.Xml.XmlReader reader)
        {
            XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
            XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

            bool wasEmpty = reader.IsEmptyElement;
            reader.Read();

            if (wasEmpty)
                return;

            while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
            {
                reader.ReadStartElement("item");

                reader.ReadStartElement("key");
                TKey key = (TKey)keySerializer.Deserialize(reader);
                reader.ReadEndElement();

                reader.ReadStartElement("value");
                TValue value = (TValue)valueSerializer.Deserialize(reader);
                reader.ReadEndElement();

                this.Add(key, value);

                reader.ReadEndElement();
                reader.MoveToContent();
            }
            reader.ReadEndElement();
        }

        public void WriteXml(System.Xml.XmlWriter writer)
        {
            XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
            XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

            // Addition by Christian Treffler, 6/9/2010:
            XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); // Use this object
            ns.Add("", "");                                             // to prevent that attributes are added in the files
            // End of addition

            foreach (TKey key in this.Keys)
            {
                writer.WriteStartElement("item");

                writer.WriteStartElement("key");
                keySerializer.Serialize(writer, key, ns);       // Added ns in this call
                writer.WriteEndElement();

                writer.WriteStartElement("value");
                TValue value = this[key];
                valueSerializer.Serialize(writer, value, ns);   // Added ns in this call
                writer.WriteEndElement();

                writer.WriteEndElement();
            }
        }
    }
}