아동 통제 아래에서 무질의 이벤트를 포착하는 방법
문제
나는 마우스 커서가 일련의 좌표 사이에 떨어지면 발사 해야하는 특정 형태의 Mouseclick 이벤트를 처리하려고 노력하고 있습니다.
나는 빈 양식이 있다면 단순히 MouseMove 이벤트에 묶을 수 있고 나가는 것을 이해합니다. 그러나 실제로 최대 10 개의 다른 중첩 컨트롤이있을 수 있으며 테스트 앱에서 MouseMove 이벤트는 커서가 실제 형태 자체에 있고 아동 통제를 통제 할 경우에만 해고됩니다.
디자인 시간에 알려지지 않은 수의 아동 컨트롤이있을 때이 이벤트를 처리하는 방법을 아는 사람이 있습니까?
내가 사용할 수있는 쉬운 1 라이너가 있습니까?
해결책
IMHO 여기에는 약간의 이진 상황이 있습니다. "하나의 라이너"는 없습니다. 내가 볼 수있는 유일한 해결책은 이벤트를 .net 컨테이너로 구현하지 않는 컨트롤을 얻는 것입니다.
컨트롤이 클릭되면 정상적인 예상 동작은 양식의 활발한 제어가 될 것입니다 (이것은 항상 this.activcecontrol에 의해 액세스 할 수 있음).
그러나 클릭 한 컨트롤이 마우스를 캡처하는 경우, .NET이 이벤트가 "버블 링"(WPF와 마찬가지로)을 구현하지 않기 때문에 이벤트를 제기해야합니다.
밀봉 된 객체의 확장 동작이나 확장 방법을 작성하는 것이 무엇이든, 제어를위한 확장을 작성하는 것을 발견했지만이 경우 도움이 될지 모르겠습니다. 불행히도 나는 지금 내 고국에서 나왔고, 비주얼 스튜디오가 없습니다.
양식의 주어진 지점이 컨트롤의 범위 내에 있는지 여부를 결정하는 데 사용할 수있는 한 가지 전략 중 하나는 양식 제어 (this.controls)를 통해 양식의 모든 제어 영역 (경계)을 열거하는 것입니다. 그러나 겹치는 컨트롤이 있다면 주어진 지점을 포함하는 둘 이상의 컨트롤 문제가 있습니다.
최고, Bill
다른 팁
이 시도:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
AddMouseMoveHandler(this);
}
private void AddMouseMoveHandler(Control c)
{
c.MouseMove += MouseMoveHandler;
if(c.Controls.Count>0)
{
foreach (Control ct in c.Controls)
AddMouseMoveHandler(ct);
}
}
private void MouseMoveHandler(object sender, MouseEventArgs e)
{
lblXY.Text = string.Format("X: {0}, Y:{1}", e.X, e.Y);
}
}
이 게시물이 꽤 오래되었음을 알고 있지만 가장 간단한 방법은 양식이 구현하는 것 같습니다. IMessageFilter
. 생성자 (또는 IN OnHandleCreated
) 당신은 전화합니다
Application.AddMessageFilter(this);
그런 다음 구현에서 모든 창의 메시지를 잡을 수 있습니다. IMessageFilter.PreFilterMessage
.
Win32 Ischild 메소드에 p/호출을 사용해야 할 것입니다.
[DllImport("user32.dll")]
public static extern bool IsChild(IntPtr hWndParent, IntPtr hWnd);
양식과 함께 Handle
올바른 메시지를 처리하는지 확인하는 속성.
컨트롤 마우스 오버 이벤트 핸들러를 사용하지 않는 이유는 무엇입니까?
나는 펀치에 조금 늦었다는 것을 알고 있지만, 패널을 제목 바로 사용할 때 오늘이 일찍이 문제를 겪고있었습니다. 텍스트, 그림 박스 및 몇 개의 버튼이 모두 패널 내에 중첩 된 라벨이 있었지만 MouseMove 이벤트를 가두어 야했습니다.
내가 결정한 것은이 작업을 수행하기 위해 재귀 적 방법 핸들러를 구현하는 것이 었습니다. 1 레벨의 중첩 컨트롤 만 있었기 때문에 말도 안되는 레벨의 중첩에 접근하기 시작할 때 과도하게 확장되지 않을 수 있습니다.
내가 한 방법은 다음과 같습니다.
protected virtual void NestedControl_Mousemove(object sender, MouseEventArgs e)
{
Control current = sender as Control;
//you will need to edit this to identify the true parent of your top-level control. As I was writing a custom UserControl, "this" was my title-bar's parent.
if (current.Parent != this)
{
// Reconstruct the args to get a correct X/Y value.
// you can ignore this if you never need to get e.X/e.Y accurately.
MouseEventArgs newArgs = new MouseEventArgs
(
e.Button,
e.Clicks,
e.X + current.Location.X,
e.Y + current.Location.Y,
e.Delta
);
NestedControl_Mousemove(current.Parent, newArgs);
}
else
{
// My "true" MouseMove handler, called at last.
TitlebarMouseMove(current, e);
}
}
//helper method to basically just ensure all the child controls subscribe to the NestedControl_MouseMove event.
protected virtual void AddNestedMouseHandler(Control root, MouseEventHandler nestedHandler)
{
root.MouseMove += new MouseEventHandler(nestedHandler);
if (root.Controls.Count > 0)
foreach (Control c in root.Controls)
AddNestedMouseHandler(c, nestedHandler);
}
그런 다음 설정하는 것은 비교적 간단합니다.
"진정한"핸들러 정의 :
protected virtual void TitlebarMouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
this.Text = string.Format("({0}, {1})", e.X, e.Y);
}
}
그런 다음 Controls 이벤트 가입자를 설정합니다.
//pnlDisplay is my title bar panel.
AddNestedMouseHandler(pnlDisplay, NestedControl_Mousemove);
사용하기가 비교적 간단하고 사실을 보증 할 수 있습니다. :)