[英]Prevent parent container from scrolling by the mouse wheel if a child (graphic) control is already scrolling
How to prevent the parent container from scrolling by the mouse wheel if the child (graphic) control is already focused and is scrolling?如果子(图形)控件已经聚焦并且正在滚动,如何防止父容器通过鼠标滚轮滚动?
I have a GMap.NET WinForms control embedded in a WinForms.我有一个嵌入在 WinForms 中的GMap.NET WinForms 控件。 Whenever that control is focused and scrolled via the mouse wheel, the parent form will also be scrolled.
每当该控件聚焦并通过鼠标滚轮滚动时,父窗体也将滚动。 I just want the parent form to stay put while I'm scrolling the GMap.NET control via the mouse wheel.
我只希望父窗体在我通过鼠标滚轮滚动 GMap.NET 控件时保持原状。 And when I want to scroll the parent form, I can always make GMap.NET control lose focus.
当我想滚动父窗体时,我总是可以让 GMap.NET 控件失去焦点。 How to do what I want?
如何做我想做的事?
Here's my code:这是我的代码:
partial class Form1
{
/// <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.gMapControl = new GMap.NET.WindowsForms.GMapControl();
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
this.SuspendLayout();
//
// gMapControl
//
this.gMapControl.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.gMapControl.Bearing = 0F;
this.gMapControl.CanDragMap = true;
this.gMapControl.EmptyTileColor = System.Drawing.Color.Navy;
this.gMapControl.GrayScaleMode = false;
this.gMapControl.HelperLineOption = GMap.NET.WindowsForms.HelperLineOptions.DontShow;
this.gMapControl.LevelsKeepInMemmory = 5;
this.gMapControl.Location = new System.Drawing.Point(525, 1);
this.gMapControl.MarkersEnabled = true;
this.gMapControl.MaxZoom = 2;
this.gMapControl.MinZoom = 2;
this.gMapControl.MouseWheelZoomEnabled = true;
this.gMapControl.MouseWheelZoomType = GMap.NET.MouseWheelZoomType.MousePositionAndCenter;
this.gMapControl.Name = "gMapControl";
this.gMapControl.NegativeMode = false;
this.gMapControl.PolygonsEnabled = true;
this.gMapControl.RetryLoadTile = 0;
this.gMapControl.RoutesEnabled = true;
this.gMapControl.ScaleMode = GMap.NET.WindowsForms.ScaleModes.Integer;
this.gMapControl.SelectedAreaFillColor = System.Drawing.Color.FromArgb(((int)(((byte)(33)))), ((int)(((byte)(65)))), ((int)(((byte)(105)))), ((int)(((byte)(225)))));
this.gMapControl.ShowTileGridLines = false;
this.gMapControl.Size = new System.Drawing.Size(198, 378);
this.gMapControl.TabIndex = 0;
this.gMapControl.Zoom = 0D;
//
// flowLayoutPanel1
//
this.flowLayoutPanel1.BackColor = System.Drawing.Color.Black;
this.flowLayoutPanel1.Location = new System.Drawing.Point(1, 1);
this.flowLayoutPanel1.Name = "flowLayoutPanel1";
this.flowLayoutPanel1.Size = new System.Drawing.Size(489, 885);
this.flowLayoutPanel1.TabIndex = 6;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoScroll = true;
this.ClientSize = new System.Drawing.Size(745, 533);
this.Controls.Add(this.flowLayoutPanel1);
this.Controls.Add(this.gMapControl);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
}
#endregion
private GMap.NET.WindowsForms.GMapControl gMapControl;
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
gMapControl.MapProvider = GMapProviders.GoogleTerrainMap;
gMapControl.MinZoom = 5;
gMapControl.MaxZoom = 12;
gMapControl.Zoom = 7.5;
gMapControl.ShowCenter = true;
gMapControl.DragButton = MouseButtons.Middle;
}
}
This is not just a problem of the GMap.NET for sure, I've tested with other (proprietary) graphic control and it behaves all the same.这肯定不仅仅是 GMap.NET 的问题,我已经用其他(专有)图形控件进行了测试,它的行为都是一样的。
I'm not sure if there's a better way around this but here's a hacky workaround to stop the WM_MOUSEWHEEL
message from reaching the control and still execute the zooming logic.我不确定是否有更好的方法来解决这个问题,但这里有一个 hacky 解决方法来阻止
WM_MOUSEWHEEL
消息到达控件并仍然执行缩放逻辑。
Add the following class to your project:将以下类添加到您的项目中:
public class MyGMapControl : GMapControl, IMessageFilter
{
public MyGMapControl()
{
Application.AddMessageFilter(this);
}
protected override void Dispose(bool disposing)
{
if (disposing) Application.RemoveMessageFilter(this);
base.Dispose(disposing);
}
public bool PreFilterMessage(ref Message m)
{
const int WM_MOUSEWHEEL = 0x020A;
if (m.HWnd == this.Handle && m.Msg == WM_MOUSEWHEEL)
{
Point posOnScreen = new Point(m.LParam.ToInt32());
Point pos = PointToClient(posOnScreen);
int delta = m.WParam.ToInt32();
var args = new MouseEventArgs(MouseButtons.None, 0, pos.X, pos.Y, delta);
this.OnMouseWheel(args);
return true;
}
return false;
}
}
Then, use MyGMapControl
instead of GMapControl
.然后,使用
MyGMapControl
而不是GMapControl
。
Here, we're creating a MessageFilter
to intercept the WM_MOUSEWHEEL
message and return true
in PreFilterMessage
to stop the message from reaching the control.在这里,我们创建了一个
MessageFilter
来拦截WM_MOUSEWHEEL
消息并在PreFilterMessage
返回true
以阻止消息到达控件。 Now, the scrolling won't occur but neither will the zooming logic because it's implemented inside OnMouseWheel()
which is triggered by the WM_MOUSEWHEEL
message.现在,滚动不会发生,但缩放逻辑也不会发生,因为它是在
OnMouseWheel()
内部实现的,由WM_MOUSEWHEEL
消息触发。 So, we manually call the OnMouseWheel()
method before returning true
to ensure that the zooming occurs.因此,我们在返回
true
之前手动调用OnMouseWheel()
方法以确保缩放发生。
As Jimi suggested in the comments, you could override WndProc()
of the control's parent container , check for WM_MOUSEWHEEL
, and return if the mouse cursor is over the GMapControl
:正如Jimi在评论中建议的那样,您可以覆盖控件的父容器的
WndProc()
,检查WM_MOUSEWHEEL
,如果鼠标光标位于GMapControl
上则GMapControl
:
protected override void WndProc(ref Message m)
{
const int WM_MOUSEWHEEL = 0x020A;
if (m.Msg == WM_MOUSEWHEEL)
{
if (gMapControl.Bounds.Contains(PointToClient(MousePosition))) return;
}
base.WndProc(ref m);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.