Ano*_*ser 5 c# wndproc winforms
编辑: tl;博士去第一条评论.
这个问题源于另一个问题,当鼠标在表格边框上下降时,我的获取MouseDown事件?
在那个问题中,当用户在表单边框上按下鼠标左键(准备拖动)时,我需要有一个表单触发事件,这非常有效.问题是当用户完成此操作时,通过放开鼠标左键,我还想要触发一个事件.
为此,我将此代码生成为"基本形式"类,其他形式将从中派生.我已经删除了FireMouseButton...()
简洁的方法; 他们解雇自定义事件.
const int WM_NCLBUTTONUP = 0xA2;
const int WM_NCLBUTTONDWN = 0xA1;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_NCLBUTTONUP)
FireMouseButtonUp();
if (m.Msg == WM_NCLBUTTONDWN)
FireMouseButtonDown();
base.WndProc(ref m);
}
Run Code Online (Sandbox Code Playgroud)
这个问题是WM_NCLBUTTONUP
消息没有像我预期的那样发送.在查看了描述后,WM_NCLBUTTONUP
我可以看到为什么,
当用户在窗口的非客户区域内释放鼠标左键时,会发布[WM_NCLBUTTONUP].此消息将发布到包含光标的窗口.如果窗口捕获了鼠标,则不会发布此消息.
因为表单在拖动时捕获了鼠标,所以它不会收到WM_NCLBUTTONUP
消息.(如果形式最大化的话会这样).这个问题解释得更好一个窗口未最大化时丢失的WM_NCLBUTTONUP消息的奇怪问题.
这个问题的答案有点帮助,但对我来说却引起很多困惑.在下面的代码中我有一个小的SSCCE,它实现了从上面的答案的解决方案给出的一些代码,检查WMNCHITTEST
消息以查看鼠标是否已被释放;
这个想法是WM_NCHITTEST
当鼠标在表单中移动时应该发送.因此,一旦拖动停止,此消息应与DragStartPoint
WndProc消息参数中的鼠标位置一起发送; 其中DragStartPoint
所述当记录WM_NCLBUTTONDOWN
被接收的消息.
但问题是,在WM_NCHITTEST
拖动开始后并不总是发送,只有在顶部边框的远端开始拖动时(见下图).在WM_NCLBUTTONDOWN
顶部边框(从不为两侧或底部),单击后始终发送消息.所以这很好,但WM_NCHITTEST
正如所指出的那样WM_NCLBUTTONUP
,但有时只会发送.
如何让WM_NCHITTEST
"测试"在下面的代码中工作,以便在用户停止拖动表单后通知我?("测试"正在检查DragStartPoint
if语句中WM_NCHITTEST
)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace MouseEventTest
{
public partial class Form1 : Form
{
Random rand = new Random();
public Form1()
{
InitializeComponent();
}
const int WM_NCHITTEST = 0x84;
const int WM_NCLBUTTONUP = 0xA2;
const int WM_NCLBUTTONDWN = 0xA1;
public Point DragStartPoint { get; set; }
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_NCLBUTTONUP)
{
label1.Text = "Mouse Up On Border";
}
if (m.Msg == WM_NCLBUTTONDWN)
{
label1.Text = "Mouse Down On Border";
Point pos = lParamToPoint(m.LParam);
DragStartPoint = this.PointToClient(pos);
Console.Out.WriteLine("DragStartPoint: " + DragStartPoint);
}
if(m.Msg == WM_NCHITTEST)
{
Point pos = lParamToPoint(m.LParam);
Console.Out.WriteLine("HtTestPnt: " + this.PointToClient(pos));
if (DragStartPoint == this.PointToClient(pos))
{
label1.Text = "Mouse Up HitTest";
}
}
base.WndProc(ref m);
}
private Point lParamToPoint(IntPtr lParamIn)
{
int x = lParamIn.ToInt32() & 0x0000FFFF;
int y = (int)((lParamIn.ToInt32() & 0xFFFF0000) >> 16);
return new Point(x, y);
}
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(42, 30);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(91, 13);
this.label1.TabIndex = 0;
this.label1.Text = "99999999999999";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(185, 75);
this.Controls.Add(this.label1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label1;
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1062 次 |
最近记录: |