问题描述
我试图使该弹出一个工具栏的边框少的形式。我希望用户能够在右下角抢(一个调整手柄),并能够调整的形式,但不能够调整或重新定位的形式以任何其他方式。
I'm attempting to make border-less forms that pop out of a tool bar. I want the user to be able to grab at the bottom-right corner (a "resize handle") and be able to resize the form, but not be able to resize or reposition the form in any other way.
我听说,我可以拦截发送到形式 WM_NCHITTEST
消息,并设置其结果 HTBOTTOMRIGHT
这将让操作系统处理的形式的重新调整大小,就好像它有一个相当大的帧。我当时的想法是,以检测是否鼠标指针进入了一个盒子我在角落里规定,如果没有则返回 HTBOTTOMRIGHT
的结果。
I've heard that I can intercept the WM_NCHITTEST
message sent to the form and set its result to HTBOTTOMRIGHT
which will let the operating system handle the re-sizing of the form, just as if it had a sizable frame. The idea I had was to detect if the mouse pointer had entered a box I defined in the corner and if it did then return the HTBOTTOMRIGHT
result.
这确实如我所料它不是那么回事。我能够拦截的消息,但它似乎在用户定位上形式的1px的厚边框的鼠标光标只发送的消息。这意味着,它的工作原理如何我想,如果你很precisely将光标置于右下角边缘。
This doesn't quite work as I expected it to. I'm able to intercept the message, but it seems the message is only sent when the user positions the mouse cursor on the 1px thick border of the form. That means it works how I want to, if you very precisely position your cursor on the bottom-right edges.
下面是我的的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);
}
我是不是做错了什么,还是有更好的方法做我想要做什么?
Am I doing something wrong or is there a better way to do what I'm trying to do?
很多的感谢。
推荐答案
我一直在寻找类似的东西和安东的code是一个伟大的基地。这是我最后有来自各方面的调整大小的工作。我不能确定一个词典
是存储hitboxes最佳方式,但我想这并不重要,所有的东西。
I was looking for something similar and Anton's code was a great base. This is what I ended up to have resize work from all sides. I'm unsure a Dictionary
was optimal way to store the hitboxes, but I guess it doesn't matter all that much.
此外,由于我的形式充满了使用填充为码头的参数控制,我只是一个5像素填充添加到表格
为它很好地工作。
And since my form is filled with controls using Fill as Dock parameters, I just had to add a 5px padding to the Form
for it to work nicely.
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);
}
这篇关于自定义调整处理边境少表格C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!