在调整大小的控件上绘图

问题描述 投票:0回答:1

我正在我的应用程序中实现屏幕截图,用户可以选择要捕获的部分,为此,我使用此链接中提供的示例创建了一个控件来覆盖图片框: 创建带有可拖动和可调整大小的选择窗口的自定义图片框

该控件运行良好,做了需要做的事情,但我实现起来遇到困难的是,当用户单击控件外部的按钮时,它将不再移动,将其光标从 SizeAll 更改为 Arrow,但是仍然可以调整大小。

我如何执行这样的任务?

这是我现在用来创建控件的代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ControlSizable
{
    public partial class FrameControl: UserControl
    {
       public FrameControl()
       {
        SetStyle(ControlStyles.SupportsTransparentBackColor, true);
        DoubleBuffered = true;
        ResizeRedraw = true;
        BackColor = Color.Transparent;
    }
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        using (var p = new Pen(Color.White , 3))
        {
            p.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
            e.Graphics.DrawRectangle(p, 0, 0, Width - 1, Height - 1);
        }
    }
    const int WM_NCHITTEST = 0x84;
    const int WM_SETCURSOR = 0x20;
    const int WM_NCLBUTTONDBLCLK = 0xA3;
    protected override void WndProc(ref Message m)
    {
        int borderWidth = 10;
        if (m.Msg == WM_SETCURSOR)  /*Setting cursor to SizeAll*/
        {
            if ((m.LParam.ToInt32() & 0xffff) == 0x2 /*Move*/)
            {
                Cursor.Current = Cursors.SizeAll;
                m.Result = (IntPtr)1;
                return;
            }
        
        }
        if ((m.Msg == WM_NCLBUTTONDBLCLK)) /*Disable Mazimiz on Double click*/
        {
            m.Result = (IntPtr)1;
            return;
        }
        base.WndProc(ref m);
        if (m.Msg == WM_NCHITTEST)
        {
            var pos = PointToClient(new Point(m.LParam.ToInt32() & 0xffff,
                m.LParam.ToInt32() >> 16));
            if (pos.X <= ClientRectangle.Left + borderWidth &&
                pos.Y <= ClientRectangle.Top + borderWidth)
                m.Result = new IntPtr(13); //TOPLEFT
            else if (pos.X >= ClientRectangle.Right - borderWidth &&
                pos.Y <= ClientRectangle.Top + borderWidth)
                m.Result = new IntPtr(14); //TOPRIGHT
            else if (pos.X <= ClientRectangle.Left + borderWidth &&
                pos.Y >= ClientRectangle.Bottom - borderWidth)
                m.Result = new IntPtr(16); //BOTTOMLEFT
            else if (pos.X >= ClientRectangle.Right - borderWidth &&
                pos.Y >= ClientRectangle.Bottom - borderWidth)
                m.Result = new IntPtr(17); //BOTTOMRIGHT
            else if (pos.X <= ClientRectangle.Left + borderWidth)
                m.Result = new IntPtr(10); //LEFT
            else if (pos.Y <= ClientRectangle.Top + borderWidth)
                m.Result = new IntPtr(12); //TOP
            else if (pos.X >= ClientRectangle.Right - borderWidth)
                m.Result = new IntPtr(11); //RIGHT
            else if (pos.Y >= ClientRectangle.Bottom - borderWidth)
                m.Result = new IntPtr(15); //Bottom
            else
                m.Result = new IntPtr(2); //Move
        }
    }
}

}

使用该控件的屏幕截图示例:

我想做的是,当用户单击箭头按钮时,控件不再在屏幕上移动,只是按边缘调整大小,我可以在绘图本身中绘制箭头(绘制箭头的过程箭头,我已经可以做到了)

c# .net winforms custom-controls
1个回答
0
投票

向自定义控件添加公共

bool
属性,此处名为
CanMove
,默认为
true

然后,在 WndProc 重写中,当消息为

WM_SETCURSOR
时,您评估
CanMove
:如果它是默认值 (
true
),则将光标设置为
Cursors.SizeAll
,否则设置为
Cursors.Arrow
(或其他值)你觉得合适)

当消息为

WM_NCHITTEST
时,在最后一个
if
条件下,如果 CanMove 为
true
,则返回
(IntPtr)2
,否则
IntPtr.Zero

在 FrameControl 类文件顶部添加

using System.ComponentModel;

CanMove
false
时,控件仍可调整大小。

因此,当您单击该按钮时,只需将 Framecontrol 的

CanMove
属性设置为
false

using System.ComponentModel;

public class FrameControl : Control {
    public FrameControl() { // [...]}

    [DefaultValue(true)] 
    public bool CanMove { get; set; } = true;

    // [...]

    protected override void WndProc(ref Message m) {
        if (m.Msg == WM_SETCURSOR)  /*Setting cursor to SizeAll*/
        {
            if ((m.LParam.ToInt32() & 0xffff) == 0x2 /*Move*/) {
                Cursor.Current = CanMove ? Cursors.SizeAll : Cursors.Arrow;
                m.Result = (IntPtr)1;
                return;
            }
        }
        // [...]
        base.WndProc(ref m);

        if (m.Msg == WM_NCHITTEST) {
            // [...]
            if (pos.X <= ClientRectangle.Left + borderWidth &&
                pos.Y <= ClientRectangle.Top + borderWidth)
                m.Result = new IntPtr(13); //TOPLEFT
            // [...]
            else
                m.Result = CanMove ? new IntPtr(2) : IntPtr.Zero;
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.