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
반응형
'Application > C# (WinForm)' 카테고리의 다른 글
[C# WinForm] Delegate, Event, Invoke, Cross Thread 사용법 (0) | 2022.12.01 |
---|---|
[C# WinForm] INI 파일 읽기 및 쓰기 (0) | 2022.11.29 |
[C# WinForm] 프로그램 광고 달기 (Ads Jumbo) (0) | 2022.11.25 |
[C# WinForm] Cross Thread 해결법 (0) | 2014.08.13 |
[C# WinForm] 마우스 커서 정보 얻기 (0) | 2014.08.13 |