윈도우(Form)가 바탕화면 가장자리에 가까이 가면 자동으로 붙도록 만드는 것은 그다지 어렵지 않습니다.
현재 윈도우의 좌표가 바탕화면 가장자리 좌표와 일정 수준 이상 가깝게 되면 윈도우를 강제로 바탕화면 가장자리 근처로 이동시키는게 로직의 전부입니다.
그러나 C#의 기본 Form 이벤트는 윈도우가 이동이 완료된 후의 이벤트밖에 없습니다. 자석윈도우를 만들려면 윈도우가 이동중일 때의 이벤트가 필요한데 말이죠.
아래 코드는 별다른 로직은 없고 윈도우 메시지를 직접 받아서 처리하는 코드입니다.
간단히 코드를 설명하면 WndProc 함수를 오버라이드해서 WM_WINDOWPOSCHANGING(윈도우가 이동중) 메시지를 받습니다.
그리고 SetDockWindow() 함수를 호출하는데 첫번째 매개변수에는 자석윈도우로 만들 Form을 넘겨줍니다. 두번째 매개변수는 윈도우가 바탕화면 가장자리에 어느정도 가까이 가면 붙도록 할 것인지를 결정하는 수치로 픽셀단위의 정수형 값을 넘겨줍니다. 마지막 매개변수는 WndProc 함수에서 받은 Message 객체를 그대로 전달해줍니다.
SetDockWindow() 함수에서는 Screen.FromHandle()을 이용해서 현재 폼이 위치한 화면의 작업 영역을 얻어옵니다. 이렇게 함으로써 듀얼모니터 지원이 가능합니다.
나머지 코드들은 그냥 좌표 계산이 전부인데 Math.Abs() 함수를 써서 윈도우가 화면안에 있을때나 바깥에 있을 때 모두 자석효과가 가능하도록 처리해줍니다.
01 |
public const Int32 WM_WINDOWPOSCHANGING = 0x0046; |
03 |
[StructLayout(LayoutKind.Sequential)] |
04 |
public struct WINDOWPOS |
07 |
public IntPtr hwndInsertAfter; |
15 |
protected override void WndProc( ref Message m) |
19 |
case WM_WINDOWPOSCHANGING: |
20 |
SetDockWindow( this , 25, ref m); |
26 |
private void SetDockWindow(Form form, int dockMargin, ref Message message) |
29 |
Rectangle currentDesktopRect = (Screen.FromHandle(form.Handle)).WorkingArea; |
31 |
WINDOWPOS winPos = (WINDOWPOS)message.GetLParam( typeof (WINDOWPOS)); |
34 |
if (Math.Abs(winPos.x - currentDesktopRect.Left) <= dockMargin) |
36 |
winPos.x = currentDesktopRect.Left; |
40 |
if (Math.Abs(winPos.y - currentDesktopRect.Top) <= dockMargin) |
42 |
winPos.y = currentDesktopRect.Top; |
46 |
if (Math.Abs(winPos.x + winPos.cx - currentDesktopRect.Left - currentDesktopRect.Width) <= dockMargin) |
48 |
winPos.x = currentDesktopRect.Right - winPos.cx; |
52 |
if (Math.Abs(winPos.y + winPos.cy - currentDesktopRect.Top - currentDesktopRect.Height) <= dockMargin) |
54 |
winPos.y = currentDesktopRect.Bottom - form.Bounds.Height; |
57 |
Marshal.StructureToPtr(winPos, message.LParam, false ); |
58 |
message.Result = (IntPtr)0; |
(사용언어 / 제작툴 / .Net Framework버전 : C# / VS2010 / 2.0)
출처 :
http://www.gungume.com/187