Application/C# (WinForm)

[C# WinForm] 자석 효과 구현

devsalix 2014. 8. 13. 15:46
728x90

부모폼에 착착 달라붙는 자석효과 자식폼 생성하기

 


//Snap Class 부분
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

class CSnap
{
     [StructLayout(LayoutKind.Sequential)]
     private struct WINDOWPOS
     {
		 public IntPtr hwnd;
		 public IntPtr hwndInsertAfter;
		 public Int32 x;
		 public Int32 y;
		 public Int32 cx;
		 public Int32 cy;
		 public UInt32 flags;
     };

	 bool bDock = false;
	 private Form Owner;
     private Form Child;
	 private Point ChildPos;
	 private const int WM_WINDOWPOSCHANGING = 0x0046;
     private const int WM_WINDOWPOSCHANGED = 0x0047;
	 
	 public CSnap(Form Owner, Form thisForm)
     {
		 this.Owner = Owner;
		 this.Child = thisForm;
		 Owner.Move += new EventHandler(Owner_Move);
		 Child.Move += new EventHandler(Child_Move);
     }

	 private void Owner_Move(object sender, EventArgs e)
     {
		 if (Child != null)
		 if (bDock)
		 {
			Child.Location = new Point(Owner.Location.X + ChildPos.X, Owner.Location.Y + ChildPos.Y);
		}
     }

	 private void Child_Move(object sender, EventArgs e)
     {
		 if (bDock)
		 {
			ChildPos = new Point(Child.Location.X - Owner.Location.X, Child.Location.Y - Owner.Location.Y);
		 }
     }

	 public void OnWindowPosChanging(IntPtr lParam, Int32 Gap)
     {
		 WINDOWPOS wndpos = (WINDOWPOS)Marshal.PtrToStructure(lParam, typeof(WINDOWPOS));
		 
		 if ((wndpos.x + wndpos.cx <= Owner.Location.X + Gap &&
			 wndpos.x + wndpos.cx >= Owner.Location.X - Gap) &&
			 (wndpos.y + wndpos.cy >= Owner.Location.Y &&
			 wndpos.y <= Owner.Location.Y + Owner.Size.Height))
		 {
			wndpos.x = Owner.Location.X - wndpos.cx;
		 }
		 else if ((wndpos.x) <= (Owner.Location.X + Owner.Size.Width + Gap) &&
				 (wndpos.x) >= (Owner.Location.X + Owner.Size.Width - Gap) &&
				 (wndpos.y + wndpos.cy >= Owner.Location.Y &&
				 wndpos.y <= Owner.Location.Y + Owner.Size.Height))
		 {
			wndpos.x = Owner.Location.X + Owner.Size.Width;
		 }

		 if ((wndpos.y + wndpos.cy <= Owner.Location.Y + Gap &&
			 wndpos.y + wndpos.cy >= Owner.Location.Y - Gap) &&
			 (wndpos.x + wndpos.cx >= Owner.Location.X &&
			 wndpos.x <= Owner.Location.X + Owner.Size.Width))
		 {
			wndpos.y = Owner.Location.Y - wndpos.cy;
		 }
		 else if ((wndpos.y) <= (Owner.Location.Y + Owner.Size.Height + Gap) &&
				 (wndpos.y) >= (Owner.Location.Y + Owner.Size.Height - Gap) &&
				 (wndpos.x + wndpos.cx >= Owner.Location.X &&
				 wndpos.x <= Owner.Location.X + Owner.Size.Width))
		 {
			wndpos.y = Owner.Location.Y + Owner.Size.Height;
		 }
		 
		 Marshal.StructureToPtr(wndpos, lParam, true);
     }

	 public void OnWindowPosChanged(IntPtr lParam, Int32 Gap)
     {
		 WINDOWPOS wndpos = (WINDOWPOS)Marshal.PtrToStructure(lParam, typeof(WINDOWPOS));
		 
		 bDock = false;
		 
		 if ((wndpos.x + wndpos.cx <= Owner.Location.X + Gap &&
			 wndpos.x + wndpos.cx >= Owner.Location.X - Gap) &&
			 (wndpos.y + wndpos.cy >= Owner.Location.Y &&
			 wndpos.y <= Owner.Location.Y + Owner.Size.Height))
		 {
			bDock = true;
		 }
		 else if ((wndpos.x) <= (Owner.Location.X + Owner.Size.Width + Gap) &&
				 (wndpos.x) >= (Owner.Location.X + Owner.Size.Width - Gap) &&
				 (wndpos.y + wndpos.cy >= Owner.Location.Y &&
				 wndpos.y <= Owner.Location.Y + Owner.Size.Height))
		 {
			bDock = true;
		 }
		 
		 if ((wndpos.y + wndpos.cy <= Owner.Location.Y + Gap &&
			 wndpos.y + wndpos.cy >= Owner.Location.Y - Gap) &&
			 (wndpos.x + wndpos.cx >= Owner.Location.X &&
			 wndpos.x <= Owner.Location.X + Owner.Size.Width))
		 {
			bDock = true;
		 }
		 else if ((wndpos.y) <= (Owner.Location.Y + Owner.Size.Height + Gap) &&
				 (wndpos.y) >= (Owner.Location.Y + Owner.Size.Height - Gap) &&
				 (wndpos.x + wndpos.cx >= Owner.Location.X &&
				 wndpos.x <= Owner.Location.X + Owner.Size.Width))
		 {
			bDock = true;
		 }
		 
		 Marshal.StructureToPtr(wndpos, lParam, true);
     }

	 public int Get_WM_WINDOWPOSCHANGING
     {
		 get
		 {
			return WM_WINDOWPOSCHANGING;
		 }
	}

     public int Get_WM_WINDOWPOSCHANGED
     {
		 get
		 {
			return WM_WINDOWPOSCHANGED;
		 }
		 }
}

//부모폼 부분
private void btn_Click(object sender, EventArgs e)
{
      f2 = new Form2();
      f2.Owner = this;
      f2.Show();
}  

//자식폼 부분 
private CSnap _CSnap;
private int iDockGap = 30;

private void Form2_Load(object sender, EventArgs e)
{
      _CSnap = new CSnap(this.Owner, this);
}  

protected override void WndProc(ref Message m)
{
      if (this._CSnap != null)
      {
		  if (m.Msg == _CSnap.Get_WM_WINDOWPOSCHANGING)
		  {
			_CSnap.OnWindowPosChanging(m.LParam, iDockGap);
		  }
		  else if (m.Msg == _CSnap.Get_WM_WINDOWPOSCHANGED)
		  {
			_CSnap.OnWindowPosChanged(m.LParam, iDockGap);
		  }
      }
	  
      base.WndProc(ref m);
} 

 

 


제 글이 도움이 되셨다면 댓글 & 공감 부탁드려요 😀

 

 
728x90
반응형