I found the accepted answer by @RezaAghaei in:
Creating Custom Picturebox with Draggable and Resizable Selection Window
and it's working perfectly.
However, only the Resize
event is working. No other event is working.
I am using it for another purpose. My goal is to add multiple user controls on the PictureBox. When the user clicks on any, it displays the UserControl's properties like name, image path, size, and more.
The full code is given below. Wondering only the Resize
event is working.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualBasic;
public class userControlAddImage : UserControl
{
// Constructor to set some default properties
public userControlAddImage()
{
this.BackgroundImage = Image.FromFile(@"D:\UserImportant\Desktop\New folder (8)\29927.jpg");
this.BackgroundImageLayout = ImageLayout.Zoom;
this.BorderStyle = BorderStyle.FixedSingle;
}
private void userControlAddImage_Click(object sender, EventArgs e)
{
MessageBox.Show("User Control clicked!");
}
private void userControlAddImage_DoubleClick(object sender, EventArgs e)
{
MessageBox.Show("User Control userControlAddImage_DoubleClick!");
}
private void userControlAddImage_Enter(object sender, EventArgs e)
{
MessageBox.Show("User Control userControlAddImage_Enter!");
}
private void userControlAddImage_MouseEnter(object sender, EventArgs e)
{
MessageBox.Show("User Control userControlAddImage_MouseEnter!");
}
private void userControlAddImage_Resize(object sender, EventArgs e)
{
MessageBox.Show("User Control userControlAddImage_Resize!");
}
const int WM_NCHITTEST = 0x84;
const int WM_SETCURSOR = 0x20;
const int WM_NCLBUTTONDBLCLK = 0xA3;
protected override void WndProc(ref Message m)
{
var borderWidth = 10;
if (m.Msg == WM_SETCURSOR)
{
if ((m.LParam.ToInt32() & 0xFFFF) == 0x2)
{
Cursor.Current = Cursors.SizeAll;
m.Result = (IntPtr)1;
return;
}
}
if (m.Msg == WM_NCLBUTTONDBLCLK)
{
m.Result = (IntPtr)1;
return;
}
base.WndProc(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
}
}
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle = cp.ExStyle | 0x2000000; // Turn on WS_EX_COMPOSITED
return cp;
}
}
}
I've tried many thing, but failed to trigger the Click
event or any other event.
Please share the solution or any other link, post where I fulfill my requirement.
A modified version of the original User Control.
What has been changed:
m.Result
is set to HTCLIENT (= 1)
. The original code was turning this value into HTCAPTION (= 2)
, to trigger the default functionality of the Mouse when the left Button is down: drag the window. This can be handy in some cases, but other events are not generated anymore when the Mouse pointer is, allegedly, over the Caption of a window. For example, the Click
event.HTCLIENT
location is preserved, the UserControl movement is triggered and calculated using the OnMouseDown
and OnMouseMove
methods, so all other events are working againInitializeComponent()
callClick
event, override OnClick
etc.public class UserControlAddImage : UserControl {
Point mouseDownPosition = Point.Empty;
public UserControlAddImage() {
InitializeComponent();
BackgroundImage = Properties.Resources.[SomeImageFromResources];
BackgroundImageLayout = ImageLayout.Zoom;
BorderStyle = BorderStyle.FixedSingle;
}
private void InitializeComponent() {
SuspendLayout();
Size = new Size(150, 150);
ResumeLayout(false);
}
protected override CreateParams CreateParams {
get {
CreateParams cp = base.CreateParams;
cp.ExStyle = cp.ExStyle | 0x2000000; // WS_EX_COMPOSITED
return cp;
}
}
protected override void WndProc(ref Message m) {
base.WndProc(ref m);
const int borderWidth = 10;
if (m.Msg == 0x84) { // WM_NCHITTEST
var pos = PointToClient(new Point(m.LParam.ToInt32()));
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
}
}
protected override void OnMouseDown(MouseEventArgs e) {
base.OnMouseDown(e);
if (e.Button != MouseButtons.Left) return;
mouseDownPosition = e.Location;
}
protected override void OnMouseMove(MouseEventArgs e) {
base.OnMouseMove(e);
if (e.Button != MouseButtons.Left) return;
Cursor.Current = Cursors.SizeAll;
Location = new Point(Location.X + (e.Location.X - mouseDownPosition.X),
Location.Y + (e.Location.Y - mouseDownPosition.Y));
}
protected override void OnMouseUp(MouseEventArgs e) {
Cursor.Current = Cursors.Default;
base.OnMouseUp(e);
}
protected override void OnClick(EventArgs e) {
base.OnClick(e);
Console.WriteLine("User Control clicked!");
}
protected override void OnDoubleClick(EventArgs e) {
base.OnDoubleClick(e);
Console.WriteLine("User Control DoubleClick!");
}
protected override void OnEnter(EventArgs e) {
base.OnEnter(e);
Console.WriteLine("User Control Enter!");
}
protected override void OnMouseEnter(EventArgs e) {
base.OnMouseEnter(e);
Console.WriteLine("User Control MouseEnter!");
}
protected override void OnResize(EventArgs e) {
base.OnResize(e);
Console.WriteLine("User Control Resize!");
}
}