当前位置: 首页 > 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;请…...

贪心算法--购买股票

给你一个整数数组 prices &#xff0c;其中 prices[i] 表示某支股票第 i 天的价格。 在每一天&#xff0c;你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买&#xff0c;然后在 同一天 出售。 返回 你能获得的 最大 利润 。 示例 1&a…...

在Mac主机上连接Linux虚拟机

前言 最近醉心于研究Linux&#xff0c;于是在PD上安装了一个Debian Linux虚拟机&#xff0c;用来练练手。但是每次在mac和Linux之间切换很是麻烦&#xff0c;有没有一种方法&#xff0c;可以在mac终端直接连接我的虚拟机&#xff0c;这样在mac终端上就可以直接操控我的Linux虚…...

前端如何单独做虚拟奖金池?

公司业务需求要做一个虚拟奖金池&#xff0c;具体是需求是&#xff0c;不需要后端数据支持&#xff0c;但是又需要不同用户看到的奖金池数据每次变动都是一致的&#xff0c;并且要在给定的最小最大值中变动。 一开始看需求&#xff0c;因为需要所有登录/未登录&#xff0c;不同…...

前端md5校验文件

前端获取文件的md5值&#xff0c;与文件一同传到后端&#xff0c;后端同样对md5值进行校验。如果相同&#xff0c;则文件未被损坏&#xff08;其实这种方式优点类似于tcp、ip的差错校验&#xff0c;好像token也是这种方式&#xff09; 项目准备 前端并不可能手写一个算法来实…...

总结SQL相对常用的几个字符函数

目录 字符的截取 substr() trim()、ltrim()、rtrim() 字符串的拼接 ||、 字符的大小写转换 upper(column_name):大写 lower(column_name):小写 字符替换 replace() 搜索字符 instr(column_name, substring_to_find,start,n_appearence) charindex(substring_to_fi…...

云计算笔记

RAID的组合方式 RAID0&#xff1a;多个硬盘同时工作&#xff0c;可提供性能&#xff0c;无冗余机制 RAID1&#xff1a;数据保存多份&#xff0c;提供冗余机制&#xff0c;性能受到影响 RAID3&#xff1a;存在数据盘和单独校验盘&#xff0c;数据写入 至数据盘后需要运算且将…...

网络安全学习路线-超详细

零基础小白&#xff0c;到就业&#xff01;入门到入土的网安学习路线&#xff01; 在各大平台搜的网安学习路线都太粗略了。。。。看不下去了&#xff01; 建议的学习顺序&#xff1a; 一、网络安全学习普法&#xff08;心里有个数&#xff0c;要进去坐几年&#xff01;&#x…...

【多模态检索】Coarse-to-Fine Visual Representation

快手文本视频多模态检索论文 论文&#xff1a;Towards Efficient and Effective Text-to-Video Retrieval with Coarse-to-Fine Visual Representation Learning 链接&#xff1a;https://arxiv.org/abs/2401.00701 摘要 近些年&#xff0c;基于CLIP的text-to-video检索方法…...

VRRP——虚拟路由冗余协议

什么是VRRP 虚拟路由冗余协议VRRP&#xff08;Virtual Router Redundancy Protocol&#xff09;是一种用于提高网络可靠性的容错协议。 通过VRRP&#xff0c;可以在主机的下一跳设备出现故障时&#xff0c;及时将业务切换到备份设备&#xff0c;从而保障网络通信的连续性和可…...

隧道应急广播应该如何搭建?

隧道应急广播系统的搭建需遵循以下关键步骤&#xff0c;确保在紧急情况下能够迅速、准确地传达信息&#xff0c;保障人员安全&#xff1a; 1. 需求分析与规划设计&#xff1a; 明确目标&#xff1a;确定广播系统覆盖范围&#xff08;如隧道全长、出入口、避难所等关键位置&…...

网站qq联系怎么做/自己怎么免费做网站

关于I/O多路复用&#xff1a; I/O多路复用(又被称为“事件驱动”)&#xff0c;首先要理解的是。操作系统为你提供了一个功能。当你的某个socket可读或者可写的时候。它能够给你一个通知。这样当配合非堵塞的socket使用时&#xff0c;仅仅有当系统通知我哪个描写叙述符可读了&am…...

网页设计尺寸厘米/深圳有实力的seo公司

因为组播中的组地址是虚拟的&#xff0c;所以不可能如同单播那样&#xff0c;直接从数据源一端路由到特定的目的地址。组播应用程序将数据包发送给一组希望接收数据的接收者&#xff08;组播地址&#xff09;&#xff0c;而不是仅仅传送给一个接收者&#xff08;单播地址&#…...

建设厅网站沙场限期通知书/seo品牌优化百度资源网站推广关键词排名

今天探讨了下关于python的一个练习剪刀石头布&#xff0c;可能程序还是多少有些不足&#xff0c;欢迎各位批评指正&#xff1a; 代码如下&#xff1a; import random def main(): #将玩家和机器视为两个参量&#xff0c;机器产生随机数1-3&#xff0c;代表着1:石头,2:剪刀,3:布…...

做网站有前途吗/东莞百度推广排名

MySQL 是一种高效快速的中小型数据库系统&#xff0c;这套系统的读写速度&#xff0c;尤其是读速度可以媲美和超过很多昂贵的商业数据库系统&#xff0c;同时其功能也完全可以满足一般网络应用软件的需要&#xff0c;适合为论坛等软件构建的数据库支撑环境。Discuz! 的 MySQL 版…...

广西建设职业技术学院教育网站/厦门人才网个人版

思路&#xff1a; 啥是蓄水池算法&#xff1a; 参考链接&#xff1a;https://www.jianshu.com/p/7a9ea6ece2af 给定一个数据流&#xff0c;数据流长度N很大&#xff0c;且N直到处理完所有数据之前都不可知&#xff0c;请问如何在只遍历一遍数据&#xff08;O(N)&#xff09;的情…...

网络销售话术和技巧/外链seo招聘

JDialog 2011-08-29 15:16:33| 分类&#xff1a; JFC|字号 订阅 JDialog 用途 JDialog是创建对话框窗口的主要类&#xff0c;可以使用此类创建自定义的对话框。该类继承了AWT的Dialoglei&#xff0c;支持Swing体系结构的高级GUI属性。与JFrame类似&#xff0c;只不过JDialog…...