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 saves several informations about the current desktop and stores 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 will be used by the function 'Desktop Auto-Load'
//
// V2.01-V2.03: Changes only in Desktop Auto-Load
//
// V2.04:
// Copy desktop gadget settings (sidebar) only when they are active
// Store in the ProgramSettings, if sidebar is active
// Store also the path to the sidebar
//
// V2.05:
// When storing current window positions, do not delete the settings of windows which are currently not active.
public static class DisplayFusionFunction
{
public static void Run(IntPtr windowHandle)
{
// Get Resolution of all Monitors and create profile name
Rectangle[] Monitors = BFS.Monitor.GetMonitorBounds();
string ProfileName = buildProfileName(Monitors);
// Safe the desktop icon profile
BFS.DisplayFusion.SaveDesktopIconsProfile(ProfileName);
//Copy current sidebar settings to the DisplayFusion User folder using the ProfileName
//Location of the sidebar settings
string source = Environment.ExpandEnvironmentVariables("%userprofile%\\AppData\\Local\\Microsoft\\Windows Sidebar\\Settings.ini");
//Location of the DisplyFusion user folder
string destination = Environment.ExpandEnvironmentVariables("%userprofile%\\AppData\\Local\\DisplayFusion");
bool ready2copy = false; // Copy only if destination folder exists
// Are there desktop gadgets running?
bool SideBarExists = BFS.Application.IsAppRunningByFile("*sidebar.exe");
if (Directory.Exists(destination)) // DisplyFusion user folder found?
{
// Creat a subfolder if it doesn't exist, yet
destination = destination + "\\SidebarSettings";
ready2copy = Directory.Exists(destination);
if (!ready2copy)
{
ready2copy = Directory.CreateDirectory(destination).Exists;
}
}
if (SideBarExists) // then copy the sidebar settings under profilename
{
if (ready2copy && File.Exists(source)) //copy, if everything is OK
{
destination = destination + "\\" + ProfileName + ".ini";
File.Copy(source, destination, true);
}
}
// read settings of restored windows
DesktopPrograms AllPrgrms = ReadProgramSettings(SideBarExists);
// Begin V2.05
DesktopPrograms SavedPrgrms = LoadProgramSettings(ProfileName); // Get the stored window settings
if (SavedPrgrms.Prgrms.Count > 0) // are settings available?
{
foreach (string key in SavedPrgrms.Prgrms.Keys) // for each stored window setting
{
if (!AllPrgrms.Prgrms.ContainsKey(key)) { // if it's not in the newly generated list
AllPrgrms.AddProgram(SavedPrgrms.Prgrms[key]);
}
}
}
// End V2.05
SaveProgramSettings(AllPrgrms, ProfileName);
}
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();
}
}
}
}