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);
    }