[英]WM_LBUTTONDOWN and WM_LBUTTONUP messages are not received in the WndProc for filled rectangles
I have made a semi-transparent, borderless form with a resizable transparent panel in the middle.我制作了一个半透明、无边框的表格,中间有一个可调整大小的透明面板。 To do this, overriding the
OnPaint
, I painted dashed borders and boxes around the panel using e.Graphics.DrawLines(...)
, e.Graphics.FillRectangles(...)
, and e.Graphics.DrawRectangles(...)
methods.为此,我覆盖了
OnPaint
,使用e.Graphics.DrawLines(...)
、 e.Graphics.FillRectangles(...)
和e.Graphics.DrawRectangles(...)
...) 在面板周围绘制了虚线边框和框。 e.Graphics.DrawRectangles(...)
方法。 I then handled the WM_NCHITTEST
and WM_MOUSEMOVE
in the WndProc
as below.然后我在
WndProc
中处理了WM_NCHITTEST
和WM_MOUSEMOVE
,如下所示。
protected override void WndProc(ref Message m)
{
bool handled = false;
if (m.Msg == WM_NCHITTEST || m.Msg == WM_MOUSEMOVE)
{
if (...) // any of the boxes contains the client-point
{
m.Result = (IntPtr)HT; // HT can be HTLEFT = 10, HTRIGHT = 11, and so on
handled = true;
}
}
if (!handled)
base.WndProc(ref m);
}
So far so good—the dashed borders and the boxes filled with a white brush pass the hit test successfully.到目前为止一切顺利——虚线边框和用白色画笔填充的框成功通过了命中测试。 Now, I also need to handle the
WM_LBUTTONDOWN
and WM_LBUTTONUP
messages in the WndProc
.现在,我还需要处理
WndProc
中的WM_LBUTTONDOWN
和WM_LBUTTONUP
消息。 It seems the WndProc
receives either of these messages only when the poiner is over the borders of the panel (ie, drawn with the e.Graphics.DrawLines(...)
) or the borders of the boxes (ie, drawn with the e.Graphics.DrawRectangles(...)
) but not when the mouse pointer is over the filled area of the boxes (ie, filled with the e.Graphics.FilledRectangles(...)
).似乎
WndProc
仅在指针超出面板边界(即,使用e.Graphics.DrawLines(...)
绘制)或框的边界(即,使用e.Graphics.DrawRectangles(...)
绘制e.Graphics.DrawRectangles(...)
)但当鼠标指针位于框的填充区域上时(即,用e.Graphics.FilledRectangles(...)
填充)。 Any sggestions as why this is happening?关于为什么会发生这种情况的任何建议?
protected override void WndProc(ref Message m)
{
bool handled = false;
if (m.Msg == WM_LBUTTONDOWN || m.Msg == WM_LBUTTONUP)
{
// unreachable for the filled rectangles!?
}
if (m.Msg == WM_NCHITTEST || m.Msg == WM_MOUSEMOVE)
{
...
}
if (!handled)
base.WndProc(ref m);
}
Here is the whole code.这是整个代码。
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Microfluidic_Experiment_Assistant
{
public class FloatingPanel : Panel
{
#region __________ Declarations
public enum SizingModes
{
Normal,
GripBoxesOnly
}
#endregion
#region __________ Fields
private RectangleF TopLeftBox;
private RectangleF TopBox;
private RectangleF TopRightBox;
private RectangleF LeftBox;
private RectangleF RightBox;
private RectangleF BottomLeftBox;
private RectangleF BottomBox;
private RectangleF BottomRightBox;
private RectangleF TopBorder;
private RectangleF LeftBorder;
private RectangleF RightBorder;
private RectangleF BottomBorder;
#endregion
#region __________ Properties
public SizingModes SizingMode
{
get;
set;
}
public float BorderThickness
{
get;
set;
}
= 1F;
public int GripSize
{
get;
set;
} = 10;
#endregion
#region __________ Methods
private void RefreshBoxesAndBorders()
{
TopLeftBox = new RectangleF(0, 0, GripSize, GripSize);
TopBox = new RectangleF((this.ClientSize.Width - GripSize) / 2, 0, GripSize, GripSize);
TopRightBox = new RectangleF(this.ClientSize.Width - GripSize - BorderThickness, 0, GripSize, GripSize);
LeftBox = new RectangleF(0, (this.ClientSize.Height - GripSize) / 2, GripSize, GripSize);
RightBox = new RectangleF(this.ClientSize.Width - GripSize - BorderThickness, (this.ClientSize.Height - GripSize) / 2, GripSize, GripSize);
BottomLeftBox = new RectangleF(0, this.ClientSize.Height - GripSize - BorderThickness, GripSize, GripSize);
BottomBox = new RectangleF((this.ClientSize.Width - GripSize) / 2, this.ClientSize.Height - GripSize - BorderThickness, GripSize, GripSize);
BottomRightBox = new RectangleF(this.ClientSize.Width - GripSize - BorderThickness, this.ClientSize.Height - GripSize - BorderThickness, GripSize, GripSize);
TopBorder = new Rectangle(0, 0, this.ClientSize.Width, GripSize);
LeftBorder = new Rectangle(0, 0, GripSize, this.ClientSize.Height);
RightBorder = new Rectangle(this.ClientSize.Width - GripSize, 0, GripSize, this.ClientSize.Height);
BottomBorder = new Rectangle(0, this.ClientSize.Height - GripSize, this.ClientSize.Width, GripSize);
}
#endregion
#region __________ Event Handler
public FloatingPanel()
{
this.DoubleBuffered = true;
this.ResizeRedraw = true;
}
protected override void WndProc(ref Message m)
{
const uint WM_NCHITTEST = 0x0084;
const uint WM_MOUSEMOVE = 0x0200;
const uint WM_LBUTTONDOWN = 0x0201;
const uint WM_LBUTTONUP = 0x0202;
const uint HTLEFT = 10;
const uint HTRIGHT = 11;
const uint HTBOTTOMRIGHT = 17;
const uint HTBOTTOM = 15;
const uint HTBOTTOMLEFT = 16;
const uint HTTOP = 12;
const uint HTTOPLEFT = 13;
const uint HTTOPRIGHT = 14;
bool handled = false;
if (m.Msg == WM_LBUTTONDOWN || m.Msg == WM_LBUTTONUP)
{
}
if (m.Msg == WM_NCHITTEST || m.Msg == WM_MOUSEMOVE)
{
Dictionary<uint, RectangleF> boxes;
Point screenPoint = new Point(m.LParam.ToInt32());
Point clientPoint = this.PointToClient(screenPoint);
RefreshBoxesAndBorders();
switch (SizingMode)
{
case SizingModes.Normal:
boxes = new Dictionary<uint, RectangleF>()
{
{ HTBOTTOMLEFT, BottomLeftBox },
{ HTBOTTOMRIGHT, BottomRightBox },
{ HTTOPRIGHT, TopRightBox },
{ HTTOPLEFT, TopLeftBox },
{ HTBOTTOM, BottomBorder },
{ HTRIGHT, RightBorder },
{ HTTOP, TopBorder },
{ HTLEFT, LeftBorder }
};
break;
case SizingModes.GripBoxesOnly:
boxes = new Dictionary<uint, RectangleF>()
{
{ HTBOTTOMLEFT, BottomLeftBox },
{ HTBOTTOM, BottomBox },
{ HTBOTTOMRIGHT, BottomRightBox },
{ HTRIGHT, RightBox },
{ HTTOPRIGHT, TopRightBox },
{ HTTOP, TopBox },
{ HTTOPLEFT, TopLeftBox },
{ HTLEFT, LeftBox }
};
break;
default:
throw new NotImplementedException();
}
foreach (KeyValuePair<uint, RectangleF> 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)
{
base.OnPaint(e);
RefreshBoxesAndBorders();
Pen pen = new Pen(Color.FromArgb(255, 0, 78), 2 * BorderThickness)
{
DashPattern = new float[] { 5, 5 }
};
// Draw dashed borders
//
e.Graphics.DrawLines(pen, new PointF[]
{
new PointF(BorderThickness, BorderThickness),
new PointF(this.ClientSize.Width - BorderThickness, BorderThickness),
new PointF(this.ClientSize.Width - BorderThickness, this.ClientSize.Height - BorderThickness),
new PointF(BorderThickness, this.ClientSize.Height - BorderThickness),
new PointF(BorderThickness, BorderThickness),
});
// Fill grip boxes
//
e.Graphics.FillRectangles(new SolidBrush(Color.White), new RectangleF[] { TopLeftBox, TopBox, TopRightBox, LeftBox, RightBox, BottomLeftBox, BottomBox, BottomRightBox });
// Draw grip box borders
//
e.Graphics.DrawRectangles(new Pen(Color.Black, BorderThickness), new RectangleF[] { TopLeftBox, TopBox, TopRightBox, LeftBox, RightBox, BottomLeftBox, BottomBox, BottomRightBox });
}
#endregion
}
}
and here is how the panel look at the design time.以下是面板如何看待设计时间。
The main form properties (from the designer):主要表单属性(来自设计器):
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.Gray;
this.ClientSize = new System.Drawing.Size(350, 350);
this.Controls.Add(this.ScenePanel);
this.DoubleBuffered = true;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.Name = "MainForm";
this.Opacity = 0.7D;
this.Text = "MainForm";
this.TopMost = true;
this.TransparencyKey = System.Drawing.Color.Green;
this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
Wild guess;胡乱猜测; try WM_NCLBUTTONDOWN and WM_NCLBUTTONUP instead.
尝试WM_NCLBUTTONDOWN和WM_NCLBUTTONUP代替。
If that doesn't help, try running Spy++ to see which mouse messages are in fact sent.如果这没有帮助,请尝试运行Spy++以查看实际发送了哪些鼠标消息。 Also, handling mouse messages that do not belong to your own window (ie the
Desktop
) requires a mouse hook .此外,处理不属于您自己的 window(即
Desktop
)的鼠标消息需要鼠标钩子。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.