C# 无边框表单C中的自定义调整大小句柄#
我正在尝试制作从工具栏弹出的无边框窗体。我希望用户能够抓住右下角(一个“调整大小手柄”),并能够调整窗体大小,但不能以任何其他方式调整窗体大小或重新定位窗体 我听说我可以截获发送到表单的C# 无边框表单C中的自定义调整大小句柄#,c#,winforms,winapi,window-resize,C#,Winforms,Winapi,Window Resize,我正在尝试制作从工具栏弹出的无边框窗体。我希望用户能够抓住右下角(一个“调整大小手柄”),并能够调整窗体大小,但不能以任何其他方式调整窗体大小或重新定位窗体 我听说我可以截获发送到表单的WM\u nchitest消息,并将其结果设置为HTBOTTOMRIGHT,这将让操作系统处理表单的重新调整大小,就像它有一个可调整大小的框架一样。我的想法是检测鼠标指针是否输入了我在角落中定义的框,然后返回HTBOTTOMRIGHT结果 这并不像我预期的那样有效。我能够截获消息,但似乎只有当用户将鼠标光标放在
WM\u nchitest
消息,并将其结果设置为HTBOTTOMRIGHT
,这将让操作系统处理表单的重新调整大小,就像它有一个可调整大小的框架一样。我的想法是检测鼠标指针是否输入了我在角落中定义的框,然后返回HTBOTTOMRIGHT
结果
这并不像我预期的那样有效。我能够截获消息,但似乎只有当用户将鼠标光标放在表单的1px厚边框上时,消息才会被发送。这意味着它的工作方式是我想要的,如果你非常精确地将光标定位在右下角的话
这是我的WndProc
覆盖:
protected override void WndProc(ref Message m)
{
const UInt32 WM_NCHITTEST = 0x0084;
const UInt32 HTBOTTOMRIGHT = 17;
const int RESIZE_HANDLE_SIZE = 40;
bool handled = false;
if (m.Msg == WM_NCHITTEST)
{
Size formSize = this.Size;
Point screenPoint = new Point(m.LParam.ToInt32());
Point clientPoint = this.PointToClient(screenPoint);
Rectangle hitBox = new Rectangle(formSize.Width - RESIZE_HANDLE_SIZE, formSize.Height - RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE);
if (hitBox.Contains(clientPoint))
{
m.Result = (IntPtr)HTBOTTOMRIGHT;
handled = true;
}
}
if (!handled)
base.WndProc(ref m);
}
我做错了什么,还是有更好的方法来做我想做的事情
非常感谢。只需对代码稍作修改。我添加了
WM\u MOUSEMOVE
消息处理:
protected override void WndProc(ref Message m)
{
const UInt32 WM_NCHITTEST = 0x0084;
const UInt32 WM_MOUSEMOVE = 0x0200;
const UInt32 HTBOTTOMRIGHT = 17;
const int RESIZE_HANDLE_SIZE = 10;
bool handled = false;
if (m.Msg == WM_NCHITTEST || m.Msg == WM_MOUSEMOVE )
{
Size formSize = this.Size;
Point screenPoint = new Point(m.LParam.ToInt32());
Point clientPoint = this.PointToClient(screenPoint);
Rectangle hitBox = new Rectangle(formSize.Width - RESIZE_HANDLE_SIZE, formSize.Height - RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE);
if (hitBox.Contains(clientPoint))
{
m.Result = (IntPtr)HTBOTTOMRIGHT;
handled = true;
}
}
if (!handled)
base.WndProc(ref m);
}
顺便说一下,您可以使用ControlPaint.DrawSizeGrip方法绘制系统特定的窗口大小夹点我正在寻找类似的东西,Anton的代码是一个很好的基础。这就是我最终从各个方面进行调整工作的原因。我不确定一本
字典是否是存储hitbox的最佳方式,但我想这并不重要
由于我的表单中充满了使用Fill作为Dock参数的控件,因此我只需在表单中添加5px的填充即可使其正常工作
protected override void WndProc(ref Message m)
{
const UInt32 WM_NCHITTEST = 0x0084;
const UInt32 WM_MOUSEMOVE = 0x0200;
const UInt32 HTLEFT = 10;
const UInt32 HTRIGHT = 11;
const UInt32 HTBOTTOMRIGHT = 17;
const UInt32 HTBOTTOM = 15;
const UInt32 HTBOTTOMLEFT = 16;
const UInt32 HTTOP = 12;
const UInt32 HTTOPLEFT = 13;
const UInt32 HTTOPRIGHT = 14;
const int RESIZE_HANDLE_SIZE = 10;
bool handled = false;
if (m.Msg == WM_NCHITTEST || m.Msg == WM_MOUSEMOVE)
{
Size formSize = this.Size;
Point screenPoint = new Point(m.LParam.ToInt32());
Point clientPoint = this.PointToClient(screenPoint);
Dictionary<UInt32, Rectangle> boxes = new Dictionary<UInt32, Rectangle>() {
{HTBOTTOMLEFT, new Rectangle(0, formSize.Height - RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE)},
{HTBOTTOM, new Rectangle(RESIZE_HANDLE_SIZE, formSize.Height - RESIZE_HANDLE_SIZE, formSize.Width - 2*RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE)},
{HTBOTTOMRIGHT, new Rectangle(formSize.Width - RESIZE_HANDLE_SIZE, formSize.Height - RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE)},
{HTRIGHT, new Rectangle(formSize.Width - RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE, formSize.Height - 2*RESIZE_HANDLE_SIZE)},
{HTTOPRIGHT, new Rectangle(formSize.Width - RESIZE_HANDLE_SIZE, 0, RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE) },
{HTTOP, new Rectangle(RESIZE_HANDLE_SIZE, 0, formSize.Width - 2*RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE) },
{HTTOPLEFT, new Rectangle(0, 0, RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE) },
{HTLEFT, new Rectangle(0, RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE, formSize.Height - 2*RESIZE_HANDLE_SIZE) }
};
foreach (KeyValuePair<UInt32, Rectangle> hitBox in boxes)
{
if (hitBox.Value.Contains(clientPoint))
{
m.Result = (IntPtr) hitBox.Key;
handled = true;
break;
}
}
}
if (!handled)
base.WndProc(ref m);
}
受保护的覆盖无效WndProc(参考消息m)
{
const UInt32 WM_NCHITTEST=0x0084;
const UInt32 WM_MOUSEMOVE=0x0200;
const UInt32 HTLEFT=10;
常数UInt32 HTRIGHT=11;
const UInt32 HTBOTTOMRIGHT=17;
const UInt32 HTBOTTOM=15;
const UInt32 HTBOTTOMLEFT=16;
常数UInt32 HTTOP=12;
常数UInt32 HTTOPLEFT=13;
常数UInt32 HTTOPRIGHT=14;
const int RESIZE_HANDLE_SIZE=10;
bool=false;
if(m.Msg==WM|NCHITTEST | m.Msg==WM|MOUSEMOVE)
{
Size formSize=此.Size;
Point screenPoint=新点(m.LParam.ToInt32());
Point clientPoint=this.PointToClient(屏幕点);
字典框=新字典(){
{HTBOTTOMLEFT,新矩形(0,formSize.Height-RESIZE_HANDLE_SIZE,RESIZE_HANDLE_SIZE,RESIZE_HANDLE_SIZE)},
{HTBOTTOM,新矩形(RESIZE_HANDLE_SIZE,formSize.Height-RESIZE_HANDLE_SIZE,formSize.Width-2*RESIZE_HANDLE_SIZE,RESIZE_HANDLE_SIZE)},
{HTBOTTOMRIGHT,新矩形(formSize.Width-RESIZE\u HANDLE\u SIZE,formSize.Height-RESIZE\u HANDLE\u SIZE,RESIZE\u HANDLE\u SIZE,RESIZE\u HANDLE\u SIZE)},
{HTRIGHT,新矩形(formSize.Width-RESIZE\u HANDLE\u SIZE,RESIZE\u HANDLE\u SIZE,RESIZE\u HANDLE\u SIZE,formSize.Height-2*RESIZE\u HANDLE\u SIZE)},
{HTTOPRIGHT,新矩形(formSize.Width-RESIZE_HANDLE_SIZE,0,RESIZE_HANDLE_SIZE,RESIZE_HANDLE_SIZE)},
{HTTOP,新矩形(RESIZE_HANDLE_SIZE,0,formSize.Width-2*RESIZE_HANDLE_SIZE,RESIZE_HANDLE_SIZE)},
{HTTOPLEFT,新矩形(0,0,调整大小\u句柄大小,调整大小\u句柄大小)},
{HTLEFT,新矩形(0,调整大小句柄大小,调整大小句柄大小,formSize.Height-2*调整大小句柄大小)}
};
foreach(框中的KeyValuePair hitBox)
{
if(hitBox.Value.Contains(clientPoint))
{
m、 结果=(IntPtr)hitBox.Key;
已处理=正确;
打破
}
}
}
如果(!已处理)
基准WndProc(参考m);
}
安东·塞门诺夫,我不明白你的密码
不管怎样,我对Charles p的第一个密码有问题,
当我最大化窗口,然后尝试更改其大小时,它正在调整大小。
在那之后,我再也无法将其修复为正常大小,也无法使用“正常最大”按钮再次将其最大化
我解决这个问题的方法是在底部的“foreach”循环中添加条件:
受保护的覆盖无效WndProc(参考消息m)
{
const UInt32 WM_NCHITTEST=0x0084;
const UInt32 WM_MOUSEMOVE=0x0200;
const UInt32 HTLEFT=10;
常数UInt32 HTRIGHT=11;
const UInt32 HTBOTTOMRIGHT=17;
const UInt32 HTBOTTOM=15;
const UInt32 HTBOTTOMLEFT=16;
常数UInt32 HTTOP=12;
常数UInt32 HTTOPLEFT=13;
常数UInt32 HTTOPRIGHT=14;
const int RESIZE_HANDLE_SIZE=10;
bool=false;
if(m.Msg==WM|NCHITTEST | m.Msg==WM|MOUSEMOVE)
{
Size formSize=此.Size;
Point screenPoint=新点(m.LParam.ToInt32());
Point clientPoint=this.PointToClient(屏幕点);
字典框=新字典(){
{HTBOTTOMLEFT,新矩形(0,formSize.Height-RESIZE_HANDLE_SIZE,RESIZE_HANDLE_SIZE,RESIZE_HANDLE_SIZE)},
{HTBOTTOM,新矩形(RESIZE_HANDLE_SIZE,formSize.Height-RESIZE_HANDLE_SIZE,formSize.Width-2*RESIZE_HANDLE_SIZE,RESIZE_HANDLE_SIZE)},
{HTBOTTOMRIGHT,新矩形(formSize.Width-RESIZE\u HANDLE\u SIZE,formSize.Height-RESIZE\u HANDLE\u SIZE,RESIZE\u HANDLE\u SIZE,RESIZE\u HANDLE\u SIZE)},
{HTRIGHT,新矩形(formSize.Width-RESIZE\u HANDLE\u SIZE,RESIZE\u HANDLE\u SIZE,RESIZE\u HANDLE\u SIZE,formSize.Height-2*RESIZE\u HANDLE\u SIZE)},
{HTTOPRIGHT,新矩形(formSize.Width-RESIZE_HANDLE_SIZE,0,RESIZE_HANDLE_SIZE,RESIZE_HANDLE_SIZE)},
{HTTOP,新矩形(RESIZE_HANDLE_SIZE,0,formSize.Width-2*RESIZE_HANDLE_SIZE,RESIZE_HANDLE_SIZE)},
{HTTOPLEFT,新矩形(0,0,调整大小\句柄大小,调整大小_
protected override void WndProc(ref Message m)
{
const UInt32 WM_NCHITTEST = 0x0084;
const UInt32 WM_MOUSEMOVE = 0x0200;
const UInt32 HTLEFT = 10;
const UInt32 HTRIGHT = 11;
const UInt32 HTBOTTOMRIGHT = 17;
const UInt32 HTBOTTOM = 15;
const UInt32 HTBOTTOMLEFT = 16;
const UInt32 HTTOP = 12;
const UInt32 HTTOPLEFT = 13;
const UInt32 HTTOPRIGHT = 14;
const int RESIZE_HANDLE_SIZE = 10;
bool handled = false;
if (m.Msg == WM_NCHITTEST || m.Msg == WM_MOUSEMOVE)
{
Size formSize = this.Size;
Point screenPoint = new Point(m.LParam.ToInt32());
Point clientPoint = this.PointToClient(screenPoint);
Dictionary<UInt32, Rectangle> boxes = new Dictionary<UInt32, Rectangle>() {
{HTBOTTOMLEFT, new Rectangle(0, formSize.Height - RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE)},
{HTBOTTOM, new Rectangle(RESIZE_HANDLE_SIZE, formSize.Height - RESIZE_HANDLE_SIZE, formSize.Width - 2*RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE)},
{HTBOTTOMRIGHT, new Rectangle(formSize.Width - RESIZE_HANDLE_SIZE, formSize.Height - RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE)},
{HTRIGHT, new Rectangle(formSize.Width - RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE, formSize.Height - 2*RESIZE_HANDLE_SIZE)},
{HTTOPRIGHT, new Rectangle(formSize.Width - RESIZE_HANDLE_SIZE, 0, RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE) },
{HTTOP, new Rectangle(RESIZE_HANDLE_SIZE, 0, formSize.Width - 2*RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE) },
{HTTOPLEFT, new Rectangle(0, 0, RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE) },
{HTLEFT, new Rectangle(0, RESIZE_HANDLE_SIZE, RESIZE_HANDLE_SIZE, formSize.Height - 2*RESIZE_HANDLE_SIZE) }
};
foreach (KeyValuePair<UInt32, Rectangle> hitBox in boxes)
{
if (this.WindowState != FormWindowState.Maximized
&& hitBox.Value.Contains(clientPoint))
{
m.Result = (IntPtr)hitBox.Key;
handled = true;
break;
}
}
}
if (!handled)
base.WndProc(ref m);
}
this.DoubleBuffered = true;
this.ResizeRedraw = true;
const uint WM_NCHITTEST = 0x0084, WM_MOUSEMOVE = 0x0200,
HTLEFT = 10, HTRIGHT = 11, HTBOTTOMRIGHT = 17,
HTBOTTOM = 15, HTBOTTOMLEFT = 16, HTTOP = 12,
HTTOPLEFT = 13, HTTOPRIGHT = 14;
Size formSize;
Point screenPoint;
Point clientPoint;
Dictionary<uint, Rectangle> boxes;
const int RHS = 10; // RESIZE_HANDLE_SIZE
bool handled;
protected override void WndProc(ref Message m)
{
if (this.WindowState == FormWindowState.Maximized)
{
base.WndProc(ref m);
return;
}
handled = false;
if (m.Msg == WM_NCHITTEST || m.Msg == WM_MOUSEMOVE)
{
formSize = this.Size;
screenPoint = new Point(m.LParam.ToInt32());
clientPoint = this.PointToClient(screenPoint);
boxes = new Dictionary<uint, Rectangle>() {
{HTBOTTOMLEFT, new Rectangle(0, formSize.Height - RHS, RHS, RHS)},
{HTBOTTOM, new Rectangle(RHS, formSize.Height - RHS, formSize.Width - 2*RHS, RHS)},
{HTBOTTOMRIGHT, new Rectangle(formSize.Width - RHS, formSize.Height - RHS, RHS, RHS)},
{HTRIGHT, new Rectangle(formSize.Width - RHS, RHS, RHS, formSize.Height - 2*RHS)},
{HTTOPRIGHT, new Rectangle(formSize.Width - RHS, 0, RHS, RHS) },
{HTTOP, new Rectangle(RHS, 0, formSize.Width - 2*RHS, RHS) },
{HTTOPLEFT, new Rectangle(0, 0, RHS, RHS) },
{HTLEFT, new Rectangle(0, RHS, RHS, formSize.Height - 2*RHS) }
};
foreach (var hitBox in boxes)
{
if (hitBox.Value.Contains(clientPoint))
{
m.Result = (IntPtr)hitBox.Key;
handled = true;
break;
}
}
}
if (!handled)
base.WndProc(ref m);
}
protected override void OnPaint(PaintEventArgs e)
{
if (this.WindowState != FormWindowState.Maximized)
{
ControlPaint.DrawSizeGrip(e.Graphics, this.BackColor,
this.ClientSize.Width - 16, this.ClientSize.Height - 16, 16, 16);
}
base.OnPaint(e);
}