I am implementing a screenshot in my application, with the user being able to select which part will be captured, for this purpose, i created a control to overlay a Picturebox using the example provided in this Link: Creating Custom Picturebox with Draggable and Resizable Selection Window
The control works well, doing what needs to be done, but what I'm having difficulty implementing is that when the user clicks on a button outside the control, it would no longer be moved, changing its cursor from SizeAll to Arrow, but could still be resizable.
How can I perform such a task?
This is the code I'm using now to create my control
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
}
}
}
}
Example of a screenshot using the control:

What I'm trying to do is that when the user clicks on the arrow button, the control is no longer moved around the screen, just resized by the edges and I can draw the arrow in the drawing itself (This process of drawing the arrow, I can already do it)
Add a public
boolProperty to the Custom Control, here namedCanMove, defaults totrue.Then, in the WndProc override, when the message is
WM_SETCURSOR, you evaluateCanMove: if it's the default value (true), you set the Cursor toCursors.SizeAll, otherwise toCursors.Arrow(or whatever you see fit)When the message is
WM_NCHITTEST, in the lastifcondition, if CanMove istrueyou return(IntPtr)2, otherwiseIntPtr.Zero.Add
using System.ComponentModel;on top of the FrameControl class file.The Control is still resizable when
CanMoveisfalse.So, when you click that Button, just set the
CanMoveProperty of the Framecontrol tofalse.