让你的Winform应用在运行时可自由拖放控件位置

    技术2022-05-11  111

    有这样一个场景,有AB两个客户总对界面摆放有着不同的喜好,一个喜欢查询条件输入区(被放在一个groupbox中)在界面的上半部分,输入区在下半部分(被放在另一个groupbox中),另一个用户则正好相反,所以我们在界面设计确认时今天A在时,我们听他的要求,改一次,明天A去开会了,B来确认,又让我们改回来,几次下来,觉得很痛苦,如果界面有区多的区域,比如说一个查询条件输入区、一个业务数据录入区、一个输出区,这种情况下,客户的喜好更是会让你左改右改,所以我们最后决定提供以GroupBox为单位的,运行时可拖拽上下位置的功能,让不同的客户根据自己的喜好去拖拽,我们后台自动保存设定就是了。

    场景描述很复杂,但代码实现却很简练:

    一个全权负责拖放管理的类实现:

    using System;using System.Windows.Forms;namespace Subindex{ /// <summary> /// /// </summary> public  class DragDropAgent//4 groupBox control in runtime dragDrop support, Written By Linnet 2006-4-6  {  private DragDropAgent()  {   //    // TODO: 在此处添加构造函数逻辑   //  }

      /// <summary>  /// 得到一个包含首层父控件的控件的对象名,如form1下groupbox1中的textbox1,将返回form1.textbox1  /// </summary>  /// <param name="sender">要获得对象名的控件实例</param>  /// <returns></returns>  public static string getFullName(Control sender)  {   string name=sender.Name;   while (sender.Parent!=null)    sender=sender.Parent;   return sender.Name+"."+name;  }

      /// <summary>  /// 设置指定GroupBox控件的拖放操作,根据CanDrag和CanDrop决定拖出/放入的支持  /// </summary>  /// <param name="sender">要设置拖放特性的GroupBox对象</param>  /// <param name="CanDrag">是否可以拖出</param>  /// <param name="CanDrop">是否可以放入</param>  public static void DragDropHook(GroupBox sender,bool CanDrag,bool CanDrop)  {   if (CanDrag) DragHook(sender);   if (CanDrop) DropHook(sender);    gutPosition(sender);  }

      /// <summary>  /// 设置指定GroupBox控件的拖放操作,同时支持拖出和放入  /// </summary>  /// <param name="sender">要设置拖放特性的GroupBox对象</param>  public static void DragDropHook(GroupBox sender)  {   DragDropHook(sender,true,true);  }

      private static void DragHook(GroupBox sender)  {   sender.MouseDown+=new MouseEventHandler(Do_Drag);  }

      private static void DropHook(GroupBox sender)  {      sender.AllowDrop=true;   sender.DragDrop+=new DragEventHandler(Drag_Drop);   sender.DragEnter+=new DragEventHandler(Drag_Enter);  }

      private static void Drag_Enter(object sender, System.Windows.Forms.DragEventArgs e)  {   if (e.Data.GetDataPresent(new GroupBox().GetType()))    e.Effect = DragDropEffects.Move ;  }

      private  static void Do_Drag(object sender, MouseEventArgs e)  {   (sender as Control) .DoDragDrop(sender, DragDropEffects.Move);

      }

      private static void Drag_Drop(object sender, System.Windows.Forms.DragEventArgs e)  {   try   {

        GroupBox self=sender as GroupBox;

        GroupBox ct= e.Data.GetData(self.GetType()) as GroupBox;

        if (self==ct) return;

        Control parent=self.Parent;

        int ord=parent.Controls.GetChildIndex(self);

        int ordself=self.Top>ct.Top?ord+1:ord-1;

        DockStyle dss=self.Dock;    self.Dock=ct.Dock;;    ct.Dock=dss;    //    System.Drawing.Point dps=self.Location;    //    self.Location=ct.Location;    //    ct.Location=dps;

        if (ordself>ord)    {     setPosition(self,ordself);     setPosition(ct,ord);    }    else    {     setPosition(ct,ord);     setPosition(self,ordself);    }

       }   catch (Exception ee)   {    System.Windows.Forms.MessageBox.Show(ee.Message,"Error");

       }  }

      private static void gutPosition(GroupBox sender)  {

       string order=AppSettings.ReadSetting(getFullName(sender)+":Order");   string dock=AppSettings.ReadSetting(getFullName(sender)+":Dock");   try   {    int Position=int.Parse(order);    sender.Parent.Controls.SetChildIndex(sender,Position);    Position=int.Parse(dock);    sender.Dock=(DockStyle)Position;   }   catch   {

       }  }

      private static void setPosition(GroupBox sender,int Position)  {   sender.Parent.Controls.SetChildIndex(sender,Position);

       AppSettings.WriteSetting(getFullName(sender)+":Order",Position.ToString());   AppSettings.WriteSetting(getFullName(sender)+":Dock",((int)sender.Dock).ToString());

      }

     

     }}

     

     

    只要将所有groupBox的Dock属性设为同一方向后,只需要Form_Load时调用只需一句就可实现运行时拖放:

       DragDropAgent.DragDropHook(this.grpIndex);   DragDropAgent.DragDropHook(this.grpWrap);//可拖动可放入,如果要设计成只可拖动或只可放入的请修改DragDropAgent类的那个实现方法的为public

    另外,上述类中使用了负责配置文件写入的AppSettings类,代码也一并给出:

    using System;using System.Xml;  using System.Configuration;using System.Reflection;using System.IO;

    namespace Subindex{ /// <summary> ///  /// </summary> public class AppSettings {  private static readonly string configFile;  private AppSettings()  {   //    // TODO: 在此处添加构造函数逻辑   //  }  static AppSettings()  {   configFile=getConfigFilePath();  } //  public static string ReadSetting(string key)//  {//   string s=null;//   try//   {////    s= ConfigurationSettings.AppSettings[key];//   }//   catch (Exception e)//   {//    System.Windows.Forms.MessageBox.Show(e.Message);//   }//   return s;//  }

     

      public static string ReadSetting(string Key)  {   string Path="/configuration/appSettings/add";   XmlDocument doc = loadConfigDocument();   //if (doc.SelectSingleNode(Path) == null) return null;   XmlElement elem = (XmlElement)doc.SelectSingleNode(string.Format(Path+"[@key='{0}']", Key));   return elem==null?null:elem.GetAttribute("value");;  }

      public static void WriteSetting(string Key, string Value)  {   XmlDocument doc = loadConfigDocument();

       if (doc.SelectSingleNode("//configuration") == null)    doc.AppendChild(doc.CreateNode(XmlNodeType.Element,"configuration",""));

       XmlNode node =  doc.SelectSingleNode("//appSettings");

       if (node == null)   {    node=doc.CreateNode(XmlNodeType.Element,"appSettings","");    doc.SelectSingleNode("//configuration").AppendChild(node);       }

       try   {    XmlElement elem = (XmlElement)node.SelectSingleNode(string.Format("//add[@key='{0}']", Key));

        if (elem != null)    {     elem.SetAttribute("value", Value);    }    else    {     elem = doc.CreateElement("add");     elem.SetAttribute("key", Key);     elem.SetAttribute("value", Value);      node.AppendChild(elem);    }    doc.Save(configFile);   }   catch   {    throw;   }  }

      public static void RemoveSetting(string key)  {   XmlDocument doc = loadConfigDocument();

       XmlNode node =  doc.SelectSingleNode("//appSettings");

       try   {    if (node == null)     throw new InvalidOperationException("appSettings section not found in config file.");    else    {     node.RemoveChild(node.SelectSingleNode(string.Format("//add[@key='{0}']", key)));     doc.Save(configFile);    }   }   catch (NullReferenceException e)   {    throw new Exception(string.Format("The key {0} does not exist.", key), e);   }  }

      private static XmlDocument loadConfigDocument()  {   XmlDocument doc = null;   try   {    doc = new XmlDocument();    doc.Load(configFile);   }   catch (Exception e)   {    System.Windows.Forms.MessageBox.Show(e.Message);   }   return doc;

      }

      public static string getConfigFilePath()  {   string configFile=Assembly.GetExecutingAssembly().Location + ".config";   if (!File.Exists(configFile)) CreateFile(configFile);   return configFile;  }

      public static bool ConfigFileExist()  {   string configFile=Assembly.GetExecutingAssembly().Location + ".config";   return File.Exists(configFile);  }

      private static void CreateFile(string FileName)  {   XmlTextWriter writer = new XmlTextWriter(FileName,System.Text.Encoding.Default);   writer.WriteStartElement("configuration");   writer.WriteStartElement("appSettings");   writer.WriteEndElement() ;   writer.Flush();   writer.Close();  } }

    }


    最新回复(0)