[ DarkMan @ 26.05.2011. 08:04 ] @
Kada kopiramo kontrole iz windows form designer-a one se serijalizuju u odredjenu strukturu i kao takve postavljaju na clipboard. Kod koji sledi cita tu strukturu sa clipboard-a i prikazuje sta se u njoj nalazi. Pre pokretanja koda, na formu nabacajte neke kontrole, selektujete ih i zatim kopirajte. Ovaj kod ce prikazati sta se nalazi na cliboardu. Code (csharp): using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.Design; using System.ComponentModel.Design.Serialization; using System.Drawing; using System.Drawing.Printing; using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Windows.Forms; using System.CodeDom; using System.CodeDom.Compiler; using Microsoft.CSharp; using System.Xml.Serialization; namespace WindowsFormsApplication1 { static class Program { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { DisplayString(ObjectToString(DeserializeFromClipboard()), false); } private const string CF_DESIGNERCOMPONENTS_V2 = "CF_DESIGNERCOMPONENTS_V2"; public static ICollection DeserializeFromClipboard() { if (Clipboard.ContainsData(CF_DESIGNERCOMPONENTS_V2)) { byte[] bytes = Clipboard.GetData(CF_DESIGNERCOMPONENTS_V2) as byte[]; if (bytes != null && bytes.Length > 0) { var bf = new BinaryFormatter(); SerializationStore store = null; using (var ms = new MemoryStream(bytes)) { store = bf.Deserialize(ms) as SerializationStore; } if (store != null) { var mgr = new DesignerSerializationManager(); var svc = new CodeDomComponentSerializationService(mgr); ICollection items = svc.Deserialize(store); store.Close(); return items; } } } return null; } /// <summary> /// Debug method, displays string in a dialog. /// </summary> public static void DisplayString(string str, bool wordWrap) { Form form = null; TextBox textBox = null; try { form = new Form(); textBox = new TextBox(); textBox.Multiline = true; textBox.Dock = DockStyle.Fill; textBox.ScrollBars = ScrollBars.Both; textBox.WordWrap = wordWrap; textBox.Font = new Font("Courier New", 12); form.Controls.Add(textBox); textBox.Text = str; textBox.ReadOnly = true; textBox.SelectionLength = 0; form.Size = new Size(800, 600); form.Name = "DebugHelper_DisplayString"; form.StartPosition = FormStartPosition.CenterScreen; form.ShowDialog(); } catch { } try { if (textBox != null) textBox.Dispose(); } catch { } try { if (form != null) form.Dispose(); } catch { } } public static string ObjectToString(object obj) { return ObjectToString(obj, 0, new List<object>()); } public static string ObjectToString(object obj, int indent, List<object> processed) { if (obj != null) { var s = new System.Text.StringBuilder(); Type type = obj.GetType(); string ind = new string(' ', indent); if (obj is ICollection) { var items = (ICollection)obj; s.AppendLine(string.Format("ICollection({0}): {1} {{", type.FullName, items.Count)); int index = 0; foreach (object item in items) { string no = string.Format(" {0}: ", index++); s.AppendLine(string.Format("{0}{1}{2}", ind, no, ObjectToString(item, indent + no.Length, processed))); } s.Append(string.Format("{0}}}", ind)); return s.ToString(); } else if (obj is System.String || type.IsValueType || type.IsEnum) { return string.Format("Value({0}): {1}", type.FullName, obj); } else if (type.IsClass) { if (!processed.Contains(obj)) { processed.Add(obj); s.AppendLine(string.Format("Class({0}) {{", type.FullName)); foreach (PropertyDescriptor p in TypeDescriptor.GetProperties(obj)) { string name = string.Format(" {0}: ", p.Name); s.AppendLine(string.Format("{0}{1}{2}", ind, name, ObjectToString(p.GetValue(obj), indent + name.Length, processed))); } s.Append(string.Format("{0}}}", ind)); return s.ToString(); } return "already processed"; } else { return string.Format("Unknown type: {0}", type.FullName); } } return "null"; } } } Naredni kod radi suprotnu stvar, pokusava da na cliboard postavi strukturu koja moze da se pastuje u windows form designer-u. Code (csharp): using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.Design; using System.ComponentModel.Design.Serialization; using System.Drawing; using System.Drawing.Printing; using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Windows.Forms; using System.CodeDom; using System.CodeDom.Compiler; using Microsoft.CSharp; using System.Xml.Serialization; namespace WindowsFormsApplication2 { static class Program { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { var items = new ArrayList(); items.Add(new Button() { Name = "button1", Text = "button1", Location = new Point(0, 0), Size = new Size(50, 20) }); items.Add(new Button() { Name = "button2", Text = "button2", Location = new Point(0, 20), Size = new Size(50, 20) }); items.Insert(0, new string[] { "button1", "button2" }); SerializeToClipboard(items); } private const string CF_DESIGNERCOMPONENTS_V2 = "CF_DESIGNERCOMPONENTS_V2"; public static void SerializeToClipboard(ICollection collection) { if (collection != null && collection.Count > 0) { var bf = new BinaryFormatter(); var mgr = new DesignerSerializationManager(); var svc = new CodeDomComponentSerializationService(mgr); var store = svc.CreateStore(); foreach (object obj in collection) { svc.Serialize(store, obj); } store.Close(); using (var ms = new MemoryStream()) { bf.Serialize(ms, store); byte[] bytes = ms.ToArray(); Clipboard.SetDataObject(new DataObject(CF_DESIGNERCOMPONENTS_V2, bytes), true); } } } } } Medjutim, ako izvrste kod i probate da pastujete rezultat na formu dobiju se dva button-a ali su oba na istoj lokaciji i imaju nazive tipa object_86d73733_af1f_425a_9bd2_17471d43333f. Moje je pitanje: da li neko zna u cemu je problem kod serijalizacije na clipboard i kako ga resiti? |