FormBorderStyle = None 인 폼은 기본적으로 크기 조절 및 이동이 불가능합니다.
해결해야 할 것은 3가지 입니다.
1. 마우스가 테두리에 위치하여 크기를 변경 가능
2. 마우스 이동에 따른 이벤트 추가 (혹은 WndProc에서 제어도 가능!)
3. 최대화 시 작업표시줄을 가리지 않게 수정 (타이틀이 없기에 크기가 더 커집니다.)
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace MoveableForm
{
public partial class Form1 : Form
{
private int titleHeight = 32;
private int padding = 5;
private int offsetX;
private int offsetY;
private bool isMoving;
//테스트용 출력 값
private Dictionary<int, string> positionDict = new Dictionary<int, string>()
{
{0, "pass" },
//{1, "clientInner" },
//{2, "moveable and changeSize" },
{10, "left" },
{11, "right" },
{12, "top" },
{15, "bottom" },
{13, "topLeft" },
{14, "topRight" },
{16, "bottomLeft" },
{17, "bottomRight" }
};
public Form1()
{
InitializeComponent();
}
private IntPtr GetMousePosition (Point point)
{
int x = point.X;
int y = point.Y;
int width = this.ClientRectangle.Width;
int height = this.ClientRectangle.Height;
bool innerWidth = padding <= x && x < width - padding;
bool innerHeight = padding <= y && y < height - padding;
bool isTop = y <= padding / 2; //타이틀쪽 살짝 보정
bool isBottom = height - padding <= y;
bool isLeft = x <= padding;
bool isRight = width - padding <= x;
if (isLeft && innerHeight) return (IntPtr)10; //left
if (isRight && innerHeight) return (IntPtr)11; //right
if (isTop && innerWidth) return (IntPtr)12; //top
if (isBottom && innerWidth) return (IntPtr)15; //bottom
if (isTop && isLeft) return (IntPtr)13; //topLeft
if (isTop && isRight) return (IntPtr)14; //topRight
if (isBottom && isLeft) return (IntPtr)16; //bottomLeft
if (isBottom && isRight) return (IntPtr)17; //bottomRight
//1 : 클라이언트 내부인 경우.
//2 : 윈도우창 움직이거나 더블클릭이 가능.
//return y <= titleHeight ? (IntPtr)2 : (IntPtr)1;
return (IntPtr)0;
}
protected override void WndProc(ref Message m)
{
//https://learn.microsoft.com/ko-kr/windows/win32/inputdev/wm-nchittest
//WM_NCHITTEST = 0x84
if (m.Msg == 0x84)
{
Point point = new Point(m.LParam.ToInt32());
point = PointToClient(point);
m.Result = GetMousePosition(point);
label3.Text = positionDict[(int)m.Result]; //테스트용 값입니다.
return;
}
base.WndProc(ref m);
}
private void label1_Click(object sender, EventArgs e)
{
Close();
}
private void panel_title_MouseDown(object sender, MouseEventArgs e)
{
if (this.WindowState == FormWindowState.Maximized)
{
return;
}
offsetX = Cursor.Position.X - Location.X;
offsetY = Cursor.Position.Y - Location.Y;
isMoving = true;
}
private void panel_title_MouseMove(object sender, MouseEventArgs e)
{
if (isMoving)
{
Location = new Point(Cursor.Position.X - offsetX, Cursor.Position.Y - offsetY);
}
}
private void panel_title_MouseUp(object sender, MouseEventArgs e)
{
isMoving = false;
}
private void panel_title_MouseDoubleClick(object sender, MouseEventArgs e)
{
if (this.WindowState == FormWindowState.Normal)
{
//화면 최대화 시 하단의 작업표시줄을 덮지 않도록 해줍니다.
this.MaximumSize = new Size(Screen.FromControl(this).WorkingArea.Width,
Screen.FromControl(this).WorkingArea.Height);
this.WindowState = FormWindowState.Maximized;
}
else
{
this.WindowState = FormWindowState.Normal;
}
}
}
}
'C# > Windows Form' 카테고리의 다른 글
[C# Windows Form] 파일명 필터 걸기 (OpenFileDialog Filter) (0) | 2024.01.30 |
---|---|
[C# Windows Form] Properties.Resources 리소스 사용하기 (1) | 2024.01.30 |
[C# Windows Form] 로컬 프로그램 간 통신 SendMessage (0) | 2022.12.04 |
[C# Windows Form] HttpWebRequest POST 방식 통신 (0) | 2022.12.03 |
[C# Windows Form] HttpWebRequest Get 방식 통신 (0) | 2022.12.03 |