当前位置: 首页 > news >正文

C#创建磁性窗体的方法:创建特殊窗体

目录

一、磁性窗体

二、磁性窗体的实现方法

(1)无标题窗体的移动

(2)Left属性

(3)Top属性

二、设计一个磁性窗体的实例

(1)资源管理器Resources.Designer.cs设计

(2)公共类Frm_Play.cs

(3)主窗体

1.Frm_Play.cs

2.Frm_Play.Designer.cs

(4)子窗体1

1.Frm_ListBox.cs

2.Frm_ListBox.Designer.cs

(5)子窗体2

1.Frm_Libretto.cs

2.Frm_Libretto.Designer.cs

(6)生成效果


一、磁性窗体

        经常会遇到一种情况,即当拖动一个窗体(主窗体)时,其他窗体(子窗体)随着该窗体移动,当拖动子窗体时,其他窗体将不跟随移动,这就是磁性窗体。

二、磁性窗体的实现方法

        在主窗体移动时,通过改变跟随窗体的Left和Top属性值实现“磁性”。

(1)无标题窗体的移动

        无标题窗体的移动主要是通过控件来移动窗体,比如,用Panel控件来进行。首先,在Panel控件的MouseDown事件中将鼠标按下时的位置值(负值)存入到全局变量CPoint中,代码如下:

private void panel_Title_MouseDown(object sender,MouseEventArgs e)
CPoint=new Point(-e.X,-e.Y);    //获取鼠标按下时的位置

        然后,在Panel控件的MouseMove事件中按照CPoint变量的值,以屏幕坐标平移指定的量,并用平移后的结果设置窗体的DesktopLocation属性,代码如下:

private void panel_Title_MouseMove(object sender,MouseEventArgs e)
if(e.Button==MouseButtons.Left)
{Point myPosittion=Control.MousePosition; //获取当前鼠标的屏幕坐标myPosittion.Offset(CPoint.X,CPoint.Y);   //以屏幕坐标平移指定的量DesktopLocation=myPosittion;             //设置当前窗体在屏幕上的位置}

(2)Left属性

        该属性用于获取或设置控件左边缘与其容器的工作区左边缘之间的距离(以像素为单位)。语法格式如下:

public int Left {get;set;}
参数说明
属性值:窗体左边缘与其容器的工作区左边缘之间的距离(以像素为单位)。

(3)Top属性

        该属性用于获取或设置控件上边缘与其容器的工作区上边缘之间的距离(以像素为单位)。语法格式如下:

public int Top{get;set;}
参数说明属性值:窗体上边缘与其容器的工作区上边缘之间的距离(以像素为单位)。

二、设计一个磁性窗体的实例

        本实例将制作一个磁性窗体,当拖动主窗体移动时,两个子窗体如果相连,则跟随移动。

  • 三个窗体:主窗体Frm_Play.cs,2个子窗体:Frm_ListBox.cs、Frm_Libretto.cs;
  • 鼠标按下任一窗体顶部的控件,可以拖动窗体;
  • 拖动子窗体时,会使得粘在一起的窗体分开,拖动主窗体时会使粘在一起的子窗体随动;
  • 拖动主窗体靠近子窗体小于相互吸引的缝隙10时,松开鼠标,靠近的窗体会像磁铁一样吸引在一起;主窗体吸引子窗体后,该子窗体还可以吸引其它子窗体;
  • 双击主窗体的控件,激活所有窗体;

(1)资源管理器Resources.Designer.cs设计

        项目使用的图片资源应设计到资源管理器,详见本文作者写的其它文章:C#手动改变自制窗体的大小-CSDN博客 https://wenchm.blog.csdn.net/article/details/137027140

(2)公共类Frm_Play.cs

// 类设计
namespace _185
{internal class FrmClass{#region  磁性窗体-公共变量//记录窗体的隐藏与显示public static bool Frm_ListShow = false;public static bool Frm_LibrettoShow = false;public static bool Frm_ScreenShow = false;//记录鼠标的当前位置public static Point CPoint;public static Point FrmPoint;public static int Gap = 10;//设置窗体间相互吸引的缝隙尺寸//Frm_Play窗体的位置及大小public static int Frm_Play_Top = 0;public static int Frm_Play_Left = 0;public static int Frm_Play_Width = 0;public static int Frm_Play_Height = 0;public static bool Is_TwoAssitForm_AdhereTo = false;//辅助窗体是否磁性在一起//Frm_ListBos窗体的位置及大小public static int Frm_List_Top = 0;public static int Frm_List_Left = 0;public static int Frm_List_Width = 0;public static int Frm_List_Height = 0;public static bool Is_Frm_List_AdhereTo = false;//辅助窗体是否与主窗体磁性在一起//Frm_Libretto窗体的位置及大小public static int Frm_Libretto_Top = 0;public static int Frm_Libretto_Left = 0;public static int Frm_Libretto_Width = 0;public static int Frm_Libretto_Height = 0;public static bool Is_Frm_Libretto_AdhereTo = false;//辅助窗体是否与主窗体磁性在一起//窗体之间的距离差public static int Frm_List_Gap_Top = 0;public static int Frm_List_Gap_Left = 0;public static int Frm_Libretto_Gap_Top = 0;public static int Frm_Libretto_Gap_Left = 0;#endregion#region  检测各窗体是否连接在一起/// <summary>/// 检测各窗体是否连接在一起/// </summary>public static void Is_Addhered_Check(){//Frm_ListBos与主窗体bool Temp_Magnetism = false;if ((Frm_Play_Top - Frm_List_Top) == 0)Temp_Magnetism = true;if ((Frm_Play_Left - Frm_List_Left) == 0)Temp_Magnetism = true;if ((Frm_Play_Left - Frm_List_Left - Frm_List_Width) == 0)Temp_Magnetism = true;if ((Frm_Play_Left - Frm_List_Left + Frm_List_Width) == 0)Temp_Magnetism = true;if ((Frm_Play_Top - Frm_List_Top - Frm_List_Height) == 0)Temp_Magnetism = true;if ((Frm_Play_Top - Frm_List_Top + Frm_List_Height) == 0)Temp_Magnetism = true;if (Temp_Magnetism)Is_Frm_List_AdhereTo = true;//Frm_Libretto与主窗体Temp_Magnetism = false;if ((Frm_Play_Top - Frm_Libretto_Top) == 0)Temp_Magnetism = true;if ((Frm_Play_Left - Frm_Libretto_Left) == 0)Temp_Magnetism = true;if ((Frm_Play_Left - Frm_Libretto_Left - Frm_Libretto_Width) == 0)Temp_Magnetism = true;if ((Frm_Play_Left - Frm_Libretto_Left + Frm_Libretto_Width) == 0)Temp_Magnetism = true;if ((Frm_Play_Top - Frm_Libretto_Top - Frm_Libretto_Height) == 0)Temp_Magnetism = true;if ((Frm_Play_Top - Frm_Libretto_Top + Frm_Libretto_Height) == 0)Temp_Magnetism = true;if (Temp_Magnetism)Is_Frm_Libretto_AdhereTo = true;//两个辅窗体Temp_Magnetism = false;if ((Frm_List_Top - Frm_Libretto_Top) == 0)Temp_Magnetism = true;if ((Frm_List_Left - Frm_Libretto_Left) == 0)Temp_Magnetism = true;if ((Frm_List_Left - Frm_Libretto_Left - Frm_Libretto_Width) == 0)Temp_Magnetism = true;if ((Frm_List_Left - Frm_Libretto_Left + Frm_Libretto_Width) == 0)Temp_Magnetism = true;if ((Frm_List_Top - Frm_Libretto_Top - Frm_Libretto_Height) == 0)Temp_Magnetism = true;if ((Frm_List_Top - Frm_Libretto_Top + Frm_Libretto_Height) == 0)Temp_Magnetism = true;if (Temp_Magnetism)Is_TwoAssitForm_AdhereTo = true;}#endregion#region  利用窗体上的控件移动窗体/// <summary>/// 利用控件移动窗体/// </summary>/// <param Frm="Form">窗体</param>/// <param e="MouseEventArgs">控件的移动事件</param>public static void MoveForm(Form Frm, MouseEventArgs e) {if (e.Button == MouseButtons.Left){Point myPosittion = Control.MousePosition;    //获取当前鼠标的屏幕坐标myPosittion.Offset(CPoint.X, CPoint.Y);       //重载当前鼠标的位置Frm.DesktopLocation = myPosittion;            //设置当前窗体在屏幕上的位置}}#endregion#region  计算窗体之间的缝隙/// <summary>/// 计算窗体之间的距离差/// </summary>/// <param Frm="Form">窗体</param>/// <param Follow="Form">跟随窗体</param>public static void Calculate_Gap(Form Frm, Form Follow){switch (Follow.Name){case "Frm_ListBox":{Frm_List_Gap_Top = Follow.Top - Frm.Top;Frm_List_Gap_Left = Follow.Left - Frm.Left;break;}case "Frm_Libretto":{Frm_Libretto_Gap_Top = Follow.Top - Frm.Top;Frm_Libretto_Gap_Left = Follow.Left - Frm.Left;break;}}}#endregion#region  磁性窗体的移动/// <summary>/// 磁性窗体的移动/// </summary>/// <param Frm="Form">窗体</param>/// <param e="MouseEventArgs">控件的移动事件</param>/// <param Follow="Form">跟随窗体</param>public static void MoveManyForm(Form Frm, MouseEventArgs e, Form Follow){ArgumentNullException.ThrowIfNull(Frm);if (e.Button == MouseButtons.Left){int Tem_Left = 0;int Tem_Top = 0;Point myPosittion = Control.MousePosition;//获取当前鼠标的屏幕坐标switch (Follow.Name){case "Frm_ListBox":{Tem_Top = Frm_List_Gap_Top - FrmPoint.Y;Tem_Left = Frm_List_Gap_Left - FrmPoint.X;break;}case "Frm_Libretto":{Tem_Top = Frm_Libretto_Gap_Top - FrmPoint.Y;Tem_Left = Frm_Libretto_Gap_Left - FrmPoint.X;break;}}myPosittion.Offset(Tem_Left, Tem_Top);Follow.DesktopLocation = myPosittion;}}#endregion#region  对窗体的位置进行初始化/// <summary>/// 对窗体的位置进行初始化/// </summary>/// <param Frm="Form">窗体</param>public static void FrmInitialize(Form Frm){switch (Frm.Name){case "Frm_Play":{Frm_Play_Top = Frm.Top;Frm_Play_Left = Frm.Left;Frm_Play_Width = Frm.Width;Frm_Play_Height = Frm.Height;break;}case "Frm_ListBox":{Frm_List_Top = Frm.Top;Frm_List_Left = Frm.Left;Frm_List_Width = Frm.Width;Frm_List_Height = Frm.Height;break;}case "Frm_Libretto":{Frm_Libretto_Top = Frm.Top;Frm_Libretto_Left = Frm.Left;Frm_Libretto_Width = Frm.Width;Frm_Libretto_Height = Frm.Height;break;}}}#endregion#region  存储各窗体的当前信息/// <summary>/// 存储各窗体的当前信息/// </summary>/// <param Frm="Form">窗体</param>/// <param e="MouseEventArgs">控件的移动事件</param>public static void FrmPlace(Form Frm){FrmInitialize(Frm);FrmMagnetism(Frm);}#endregion#region  窗体的磁性设置/// <summary>/// 窗体的磁性设置/// </summary>/// <param Frm="Form">窗体</param>public static void FrmMagnetism(Form Frm){if (Frm.Name != "Frm_Play"){FrmMagnetismCount(Frm, Frm_Play_Top, Frm_Play_Left, Frm_Play_Width, Frm_Play_Height, "Frm_Play");}if (Frm.Name != "Frm_ListBos"){FrmMagnetismCount(Frm, Frm_List_Top, Frm_List_Left, Frm_List_Width, Frm_List_Height, "Frm_ListBos");}if (Frm.Name != "Frm_Libratto"){FrmMagnetismCount(Frm, Frm_Libretto_Top, Frm_Libretto_Left, Frm_Libretto_Width, Frm_Libretto_Height, "Frm_Libratto");}FrmInitialize(Frm);}#endregion#region  磁性窗体的计算/// <summary>/// 磁性窗体的计算/// </summary>/// <param Frm="Form">窗体</param>/// <param e="MouseEventArgs">控件的移动事件</param>public static void FrmMagnetismCount(Form Frm, int top, int left, int width, int height, string Mforms){bool Tem_Magnetism = false;    //判断是否有磁性发生string Tem_MainForm = "";      //临时记录主窗体string Tem_AssistForm = "";    //临时记录辅窗体//上面进行磁性窗体if ((Frm.Top + Frm.Height - top) <= Gap && (Frm.Top + Frm.Height - top) >= -Gap){//当一个主窗体不包含辅窗体时if ((Frm.Left >= left && Frm.Left <= (left + width)) || ((Frm.Left + Frm.Width) >= left && (Frm.Left + Frm.Width) <= (left + width))){Frm.Top = top - Frm.Height;if ((Frm.Left - left) <= Gap && (Frm.Left - left) >= -Gap)Frm.Left = left;Tem_Magnetism = true;}//当一个主窗体包含辅窗体时if (Frm.Left <= left && (Frm.Left + Frm.Width) >= (left + width)){Frm.Top = top - Frm.Height;if ((Frm.Left - left) <= Gap && (Frm.Left - left) >= -Gap)Frm.Left = left;Tem_Magnetism = true;}}//下面进行磁性窗体if ((Frm.Top - (top + height)) <= Gap && (Frm.Top - (top + height)) >= -Gap){//当一个主窗体不包含辅窗体时if ((Frm.Left >= left && Frm.Left <= (left + width)) || ((Frm.Left + Frm.Width) >= left && (Frm.Left + Frm.Width) <= (left + width))){Frm.Top = top + height;if ((Frm.Left - left) <= Gap && (Frm.Left - left) >= -Gap)Frm.Left = left;Tem_Magnetism = true;}//当一个主窗体包含辅窗体时if (Frm.Left <= left && (Frm.Left + Frm.Width) >= (left + width)){Frm.Top = top + height;if ((Frm.Left - left) <= Gap && (Frm.Left - left) >= -Gap)Frm.Left = left;Tem_Magnetism = true;}}//左面进行磁性窗体if ((Frm.Left + Frm.Width - left) <= Gap && (Frm.Left + Frm.Width - left) >= -Gap){//当一个主窗体不包含辅窗体时if ((Frm.Top > top && Frm.Top <= (top + height)) || ((Frm.Top + Frm.Height) >= top && (Frm.Top + Frm.Height) <= (top + height))){Frm.Left = left - Frm.Width;if ((Frm.Top - top) <= Gap && (Frm.Top - top) >= -Gap)Frm.Top = top;Tem_Magnetism = true;}//当一个主窗体包含辅窗体时if (Frm.Top <= top && (Frm.Top + Frm.Height) >= (top + height)){Frm.Left = left - Frm.Width;if ((Frm.Top - top) <= Gap && (Frm.Top - top) >= -Gap)Frm.Top = top;Tem_Magnetism = true;}}//右面进行磁性窗体if ((Frm.Left - (left + width)) <= Gap && (Frm.Left - (left + width)) >= -Gap){//当一个主窗体不包含辅窗体时if ((Frm.Top > top && Frm.Top <= (top + height)) || ((Frm.Top + Frm.Height) >= top && (Frm.Top + Frm.Height) <= (top + height))){Frm.Left = left + width;if ((Frm.Top - top) <= Gap && (Frm.Top - top) >= -Gap)Frm.Top = top;Tem_Magnetism = true;}//当一个主窗体包含辅窗体时if (Frm.Top <= top && (Frm.Top + Frm.Height) >= (top + height)){Frm.Left = left + width;if ((Frm.Top - top) <= Gap && (Frm.Top - top) >= -Gap)Frm.Top = top;Tem_Magnetism = true;}}if (Frm.Name == "Frm_Play")Tem_MainForm = "Frm_Play";elseTem_AssistForm = Frm.Name;if (Mforms == "Frm_Play")Tem_MainForm = "Frm_Play";elseTem_AssistForm = Mforms;if (Tem_MainForm == ""){Is_TwoAssitForm_AdhereTo = Tem_Magnetism;}else{switch (Tem_AssistForm){case "Frm_ListBos":Is_Frm_List_AdhereTo = Tem_Magnetism;break;case "Frm_Libratto":Is_Frm_Libretto_AdhereTo = Tem_Magnetism;break;}}}#endregion#region  恢复窗体的初始大小/// <summary>/// 恢复窗体的初始大小(当松开鼠标时,如果窗体的大小小于300*200,恢复初始状态)/// </summary>/// <param Frm="Form">窗体</param>public static void FrmScreen_FormerlySize(Form Frm, int PWidth, int PHeight){if (Frm.Width < PWidth || Frm.Height < PHeight){Frm.Width = PWidth;Frm.Height = PHeight;//Example_Size = false;}}#endregion}
}

(3)主窗体

1.Frm_Play.cs

namespace _185
{public partial class Frm_Play : Form{public Frm_Play(){InitializeComponent();}#region  公共变量FrmClass Cla_FrmClass = new();public static Form F_List = new();public static Form F_Libretto = new();public static Form F_Screen = new();#endregionprivate void Frm_Play_Load(object sender, EventArgs e){FrmClass.FrmInitialize(this);                //窗体位置的初始化}private void Panel1_MouseDown(object sender, MouseEventArgs e){if (e.Button == MouseButtons.Left)            //按下的是否为鼠标左键{FrmClass.Is_Addhered_Check();             //检测各窗体是否连在一起int Tem_Y = e.Y;FrmClass.FrmPoint = new Point(e.X, Tem_Y);//获取鼠标在窗体上的位置,用于磁性窗体FrmClass.CPoint = new Point(-e.X, -Tem_Y);//获取鼠标在屏幕上的位置,用于窗体的移动if (FrmClass.Is_Frm_List_AdhereTo)              //如果与frm_ListBox窗体相连接{FrmClass.Calculate_Gap(this, F_List);        //计算窗体的距离差if (FrmClass.Is_TwoAssitForm_AdhereTo)       //两个辅窗体是否连接在一起{FrmClass.Calculate_Gap(this, F_Libretto);//计算窗体的距离差}}if (FrmClass.Is_Frm_Libretto_AdhereTo)        //如果与frm_Libretto窗体相连接{FrmClass.Calculate_Gap(this, F_Libretto); //计算窗体的距离差if (FrmClass.Is_TwoAssitForm_AdhereTo)    //两个辅窗体是否连接在一起{FrmClass.Calculate_Gap(this, F_List); //计算窗体的距离差}}}}private void Panel1_MouseMove(object sender, MouseEventArgs e){if (e.Button == MouseButtons.Left)            //按下的是否为鼠标左键{FrmClass.MoveForm(this, e);               //利用控件移动窗体if (FrmClass.Is_Frm_List_AdhereTo)        //如果frm_ListBox窗体与主窗体连接{FrmClass.MoveManyForm(this, e, F_List);//磁性窗体的移动FrmClass.FrmInitialize(F_List);        //对frm_ListBox窗体的位置进行初始化if (FrmClass.Is_TwoAssitForm_AdhereTo) //如果两个子窗体连接在一起{FrmClass.MoveManyForm(this, e, F_Libretto);FrmClass.FrmInitialize(F_Libretto);}}if (FrmClass.Is_Frm_Libretto_AdhereTo)    //如果frm_Libretto窗体与主窗体连接{FrmClass.MoveManyForm(this, e, F_Libretto);FrmClass.FrmInitialize(F_Libretto);if (FrmClass.Is_TwoAssitForm_AdhereTo){FrmClass.MoveManyForm(this, e, F_List);FrmClass.FrmInitialize(F_List);}}FrmClass.FrmInitialize(this);}}private void Panel1_MouseUp(object sender, MouseEventArgs e){FrmClass.FrmPlace(this);}private void Frm_Play_Shown(object sender, EventArgs e){//显示列表窗体F_List = new Frm_ListBox{ShowInTaskbar = false};FrmClass.Frm_ListShow = true;F_List.Show();//显示歌词窗体F_Libretto = new Frm_Libretto{ShowInTaskbar = false,Left = Left + Width,Top = Top};FrmClass.Frm_LibrettoShow = true;F_Libretto.Show();//各窗体位置的初始化FrmClass.FrmInitialize(F_List);FrmClass.FrmInitialize(F_Libretto);}private void Panel2_Click(object sender, EventArgs e){F_List.Close();F_List.Dispose();F_Libretto.Close();F_Libretto.Dispose();F_Screen.Close();F_Screen.Dispose();Close();}private void Panel1_Click(object sender, EventArgs e){F_List.Focus();F_Libretto.Focus();Focus();}}
}

2.Frm_Play.Designer.cs

namespace _185
{partial class Frm_Play{/// <summary>///  Required designer variable./// </summary>private System.ComponentModel.IContainer components = null;/// <summary>///  Clean up any resources being used./// </summary>/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>protected override void Dispose(bool disposing){if (disposing && (components != null)){components.Dispose();}base.Dispose(disposing);}#region Windows Form Designer generated code/// <summary>///  Required method for Designer support - do not modify///  the contents of this method with the code editor./// </summary>private void InitializeComponent(){panel1 = new Panel();pictureBox1 = new PictureBox();panel2 = new Panel();((System.ComponentModel.ISupportInitialize)pictureBox1).BeginInit();SuspendLayout();// // panel1// panel1.BackgroundImage = Properties.Resources._5;panel1.BackgroundImageLayout = ImageLayout.Stretch;panel1.Dock = DockStyle.Top;panel1.Location = new Point(0, 0);panel1.Name = "panel1";panel1.Size = new Size(290, 31);panel1.TabIndex = 0;panel1.Click += Panel1_Click;panel1.MouseDown += Panel1_MouseDown;panel1.MouseMove += Panel1_MouseMove;panel1.MouseUp += Panel1_MouseUp;// // pictureBox1// pictureBox1.BackgroundImage = Properties.Resources._01;pictureBox1.BackgroundImageLayout = ImageLayout.Stretch;pictureBox1.Dock = DockStyle.Fill;pictureBox1.Location = new Point(0, 31);pictureBox1.Name = "pictureBox1";pictureBox1.Size = new Size(290, 89);pictureBox1.TabIndex = 1;pictureBox1.TabStop = false;// // panel2// panel2.BackgroundImage = Properties.Resources.Close;panel2.BackgroundImageLayout = ImageLayout.Stretch;panel2.Location = new Point(265, 5);panel2.Name = "panel2";panel2.Size = new Size(18, 18);panel2.TabIndex = 0;panel2.Click += Panel2_Click;// // Frm_Play// AutoScaleDimensions = new SizeF(7F, 17F);AutoScaleMode = AutoScaleMode.Font;ClientSize = new Size(290, 120);Controls.Add(panel2);Controls.Add(pictureBox1);Controls.Add(panel1);FormBorderStyle = FormBorderStyle.None;Name = "Frm_Play";Text = "Form1";Load += Frm_Play_Load;Shown += Frm_Play_Shown;((System.ComponentModel.ISupportInitialize)pictureBox1).EndInit();ResumeLayout(false);}#endregionprivate Panel panel1;private PictureBox pictureBox1;private Panel panel2;}
}

(4)子窗体1

1.Frm_ListBox.cs

namespace _185
{public partial class Frm_ListBox : Form{public Frm_ListBox(){InitializeComponent();}#region  公共变量FrmClass Cla_FrmClass = new();#endregionprivate void Frm_ListBox_Load(object sender, EventArgs e){Left = FrmClass.Frm_Play_Left;Top = FrmClass.Frm_Play_Top + FrmClass.Frm_Play_Height;FrmClass.FrmInitialize(this);}private void Panel1_MouseDown(object sender, MouseEventArgs e){FrmClass.CPoint = new Point(-e.X, -e.Y);}private void Panel1_MouseMove(object sender, MouseEventArgs e){FrmClass.Is_TwoAssitForm_AdhereTo = false;FrmClass.Is_Frm_List_AdhereTo = false;FrmClass.MoveForm(this, e);}private void Panel1_MouseUp(object sender, MouseEventArgs e){FrmClass.FrmPlace(this);}}
}

2.Frm_ListBox.Designer.cs


namespace _185
{partial class Frm_ListBox{/// <summary>/// Required designer variable./// </summary>private System.ComponentModel.IContainer components = null;/// <summary>/// Clean up any resources being used./// </summary>/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>protected override void Dispose(bool disposing){if (disposing && (components != null)){components.Dispose();}base.Dispose(disposing);}#region Windows Form Designer generated code/// <summary>/// Required method for Designer support - do not modify/// the contents of this method with the code editor./// </summary>private void InitializeComponent(){panel1 = new Panel();pictureBox1 = new PictureBox();((System.ComponentModel.ISupportInitialize)pictureBox1).BeginInit();SuspendLayout();// // panel1// panel1.BackgroundImage = Properties.Resources._5;panel1.Dock = DockStyle.Top;panel1.Location = new Point(0, 0);panel1.Name = "panel1";panel1.Size = new Size(290, 31);panel1.TabIndex = 0;panel1.MouseDown += Panel1_MouseDown;panel1.MouseMove += Panel1_MouseMove;panel1.MouseUp += Panel1_MouseUp;// // pictureBox1// pictureBox1.BackgroundImage = Properties.Resources._02;pictureBox1.BackgroundImageLayout = ImageLayout.Stretch;pictureBox1.Dock = DockStyle.Fill;pictureBox1.Location = new Point(0, 31);pictureBox1.Name = "pictureBox1";pictureBox1.Size = new Size(290, 89);pictureBox1.TabIndex = 1;pictureBox1.TabStop = false;// // Frm_ListBox// AutoScaleDimensions = new SizeF(7F, 17F);AutoScaleMode = AutoScaleMode.Font;ClientSize = new Size(290, 120);Controls.Add(pictureBox1);Controls.Add(panel1);FormBorderStyle = FormBorderStyle.None;Name = "Frm_ListBox";Text = "Form1";Load += Frm_ListBox_Load;((System.ComponentModel.ISupportInitialize)pictureBox1).EndInit();ResumeLayout(false);}#endregionprivate Panel panel1;private PictureBox pictureBox1;}
}

(5)子窗体2

1.Frm_Libretto.cs

namespace _185
{public partial class Frm_Libretto : Form{public Frm_Libretto(){InitializeComponent();}#region  公共变量FrmClass Cla_FrmClass = new();#endregionprivate void Frm_Libretto_Load(object sender, EventArgs e){Left = FrmClass.Frm_Play_Left;Top = FrmClass.Frm_Play_Top + FrmClass.Frm_Play_Height;FrmClass.FrmInitialize(this);}private void Panel1_MouseDown(object sender, MouseEventArgs e){FrmClass.CPoint = new Point(-e.X, -e.Y);}private void Panel1_MouseMove(object sender, MouseEventArgs e){FrmClass.Is_TwoAssitForm_AdhereTo = false;FrmClass.Is_Frm_List_AdhereTo = false;FrmClass.MoveForm(this, e);}private void Panel1_MouseUp(object sender, MouseEventArgs e){FrmClass.FrmPlace(this);}}
}

2.Frm_Libretto.Designer.cs

namespace _185
{partial class Frm_Libretto{/// <summary>/// Required designer variable./// </summary>private System.ComponentModel.IContainer components = null;/// <summary>/// Clean up any resources being used./// </summary>/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>protected override void Dispose(bool disposing){if (disposing && (components != null)){components.Dispose();}base.Dispose(disposing);}#region Windows Form Designer generated code/// <summary>/// Required method for Designer support - do not modify/// the contents of this method with the code editor./// </summary>private void InitializeComponent(){panel1 = new Panel();pictureBox1 = new PictureBox();((System.ComponentModel.ISupportInitialize)pictureBox1).BeginInit();SuspendLayout();// // panel1// panel1.BackgroundImage = Properties.Resources._5;panel1.BackgroundImageLayout = ImageLayout.Stretch;panel1.Dock = DockStyle.Top;panel1.Location = new Point(0, 0);panel1.Name = "panel1";panel1.Size = new Size(290, 31);panel1.TabIndex = 0;panel1.MouseDown += Panel1_MouseDown;panel1.MouseMove += Panel1_MouseMove;panel1.MouseUp += Panel1_MouseUp;// // pictureBox1// pictureBox1.BackgroundImage = Properties.Resources._03;pictureBox1.BackgroundImageLayout = ImageLayout.Stretch;pictureBox1.Dock = DockStyle.Fill;pictureBox1.Location = new Point(0, 31);pictureBox1.Name = "pictureBox1";pictureBox1.Size = new Size(290, 209);pictureBox1.TabIndex = 1;pictureBox1.TabStop = false;// // Frm_Libretto// AutoScaleDimensions = new SizeF(7F, 17F);AutoScaleMode = AutoScaleMode.Font;ClientSize = new Size(290, 240);Controls.Add(pictureBox1);Controls.Add(panel1);FormBorderStyle = FormBorderStyle.None;Name = "Frm_Libretto";Text = "Form2";Load += Frm_Libretto_Load;((System.ComponentModel.ISupportInitialize)pictureBox1).EndInit();ResumeLayout(false);}#endregionprivate Panel panel1;private PictureBox pictureBox1;}
}

(6)生成效果

         三个窗体吸引在一起

         三个窗体被拖动分开

 

        主窗体吸引子窗体再吸引子窗体 

相关文章:

C#创建磁性窗体的方法:创建特殊窗体

目录 一、磁性窗体 二、磁性窗体的实现方法 (1)无标题窗体的移动 (2)Left属性 (3)Top属性 二、设计一个磁性窗体的实例 &#xff08;1&#xff09;资源管理器Resources.Designer.cs设计 &#xff08;2&#xff09;公共类Frm_Play.cs &#xff08;3&#xff09;主窗体 …...

Gateway 基本配置指南:构建高效的网络接入网关

简介&#xff1a; Gateway 是一个常用的网络接入网关&#xff0c;它可以帮助组织实现安全、可靠和高性能的网络连接。本文将介绍 Gateway 的基本配置&#xff0c;帮助读者了解如何正确配置和部署一个高效的 Gateway 网关。 1.网络拓扑规划&#xff1a; 在配置 Gateway 前&#…...

自定义类型: 结构体 (详解)

本文索引 一. 结构体类型的声明1. 结构体的声明和初始化2. 结构体的特殊声明3. 结构体的自引用 二. 结构体内存对齐1. 对齐规则2. 为啥存在对齐?3. 修改默认对齐值 三. 结构体传参四. 结构体实现位段1. 什么是位段?2. 位段的内存分配3. 位段的应用4. 位段的注意事项 ​ 前言:…...

设计模式(23):访问者模式

定义 表示一个作用于某对象结构中的各元素的操作&#xff0c;它使我们可以在不改变元素的类的前提下定义作用与这些元素的新操作。 模式动机 对于存储在一个集合中的对象&#xff0c;他们可能具有不同的类型(即使有一个公共的接口)&#xff0c;对于该集合中的对象&#xff0…...

【C++】类和对象③(类的默认成员函数:拷贝构造函数 | 赋值运算符重载)

&#x1f525;个人主页&#xff1a;Forcible Bug Maker &#x1f525;专栏&#xff1a;C 目录 前言 拷贝构造函数 概念 拷贝构造函数的特性及用法 赋值运算符重载 运算符重载 赋值运算符重载 结语 前言 本篇主要内容&#xff1a;类的6个默认成员函数中的拷贝构造函数…...

掀起区块链开发狂潮!Scaffold-eth带你一键打造震撼DApp

文章目录 前言一、Scaffold-eth是什么&#xff1f;二、安装和配置1.准备工作2.安装3.配置开发环境 三、进阶使用1.放入自己的合约2.部署运行 总结 前言 前面的文章传送&#x1f6aa;&#xff1a;hardhat入门 与 hardhat进阶 在之前的文章中&#xff0c;我们已经探讨了使用Har…...

【Qt 学习笔记】Qt常用控件 | 按钮类控件Check Box的使用及说明

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt常用控件 | 按钮类控件Check Box的使用及说明 文章编号&#xff1a;…...

android gradle 配置远程仓库

build.gradle buildscript { ext.kotlin_version "1.6.0" // 使用适合你项目的Kotlin版本 repositories { maven { url http://maven.aliyun.com/nexus/content/groups/public/ } maven { url http://maven.aliyun.com/nexus/content/repos…...

第十二章 OpenGL ES 基础-色温、色调、亮度、对比度、饱和度、高光

第十二章 OpenGL ES 基础-色温、色调、亮度、对比度、饱和度、高光 第一章 OpenGL ES 基础-屏幕、纹理、顶点坐标 第二章 OpenGL ES 基础-GLSL语法简单总结 第三章 OpenGL ES 基础-GLSL渲染纹理 第四章 OpenGL ES 基础-位移、缩放、旋转原理 第五章 OpenGL ES 基础-透视投影…...

力扣经典150题解析之二十八:盛最多水的容器

目录 力扣经典150题解析之二十八&#xff1a;盛最多水的容器1. 介绍2. 问题描述3. 示例4. 解题思路5. 算法实现6. 复杂度分析7. 测试与验证测试用例设计测试结果分析 8. 总结9. 参考文献感谢阅读 力扣经典150题解析之二十八&#xff1a;盛最多水的容器 1. 介绍 在这篇文章中&…...

Rockchip Android13 Vold(二):Framework层

目录 前言 1、接收VolumeInfo状态 2、通知VolumeInfo状态变化 3、创建StorageVolume...

Oracle数据库故障类别及日常运维规划策略

一、故障类别 1、语句故障 单个数据库操作失败&#xff08;select、insert、update或delete&#xff09;&#xff0c;如&#xff1a; 在表中输入无效的数据&#xff0c;解决方法&#xff1a;可与用户合作来验证并更正数据&#xff1b;执行操作&#xff0c;但权限不足&#x…...

电商技术揭秘九:搜索引擎中的SEO数据分析与效果评估

相关系列文章 电商技术揭秘一&#xff1a;电商架构设计与核心技术 电商技术揭秘二&#xff1a;电商平台推荐系统的实现与优化 电商技术揭秘三&#xff1a;电商平台的支付与结算系统 电商技术揭秘四&#xff1a;电商平台的物流管理系统 电商技术揭秘五&#xff1a;电商平台的个性…...

多线程传参以及线程的优缺点

进程是资源分配的基本单位 线程是调度的基本单位 笼统来说&#xff0c;线程有以下优点&#xff1a; 创建一个新线程的代价要比创建一个新进程小得多 与进程之间的切换相比&#xff0c;线程之间的切换需要操作系统做的工作要少很多 线程占用的资源要比进程少很多 能充分利用多…...

keil创建单片机工程

一、创建工程 打开Keil uVision4&#xff0c;依次选择 Project—>New uVision4 Project&#xff0c;选择工程保存路径及填写工程名称&#xff0c;如下图 然后点“保存”。在Select a CPU Data Base File中选择"STC MCU Database"&#xff0c;点 "OK"&am…...

QT 串口助手 学习制作记录

QT 串口助手qt 学习制作记录 参考教程&#xff1a;​​​​​​QT初体验&#xff1a;手把手带你写一个自己的串口助手_qt设计串口助手的流程图-CSDN博客 Qt之串口编程&#xff08;添加QSerialPort模块&#xff09;_如何安装 qt串口模块教程-CSDN博客 串口调试助手&#xff1…...

Github 2024-04-13 Rust开源项目日报Top10

根据Github Trendings的统计,今日(2024-04-13统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Rust项目10CUE项目1Go项目1Tauri: 构建小型、快速和安全的桌面应用程序 创建周期:1673 天开发语言:Rust协议类型:Apache License 2.0Star数量…...

大模型日报|今日必读的10篇大模型论文

大家好&#xff0c;今日必读的大模型论文来啦&#xff01; 1.谷歌推出新型 Transformer 架构&#xff1a;反馈注意力就是工作记忆 虽然 Transformer 给深度学习带来了革命性的变化&#xff0c;但二次注意复杂性阻碍了其处理无限长输入的能力。 谷歌研究团队提出了一种新型 T…...

深度学习 Lecture 8 决策树

一、决策树模型&#xff08;Decision Tree Model) 椭圆形代表决策节点&#xff08;decison nodes)&#xff0c;矩形节点代表叶节点&#xff08;leaf nodes)&#xff0c;方向上的值代表属性的值&#xff0c; 构建决策树的学习过程&#xff1a; 第一步&#xff1a;决定在根节点…...

打包 docker 容器镜像到另一台电脑

# 提交容器为镜像 <container_id> 容器id my_migration_image 镜像名称 docker commit <container_id> my_migration_image # 保存镜像为tar文件 docker save my_migration_image > my_migration_image.tar 在另一台电脑上导入上面的镜像&#xff0c;请…...

SkyWalking 10.2.0 SWCK 配置过程

SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外&#xff0c;K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案&#xff0c;全安装在K8S群集中。 具体可参…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)

UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中&#xff0c;UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化&#xf…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...