3

WPF キャンバスに追加された要素の MouseLeftButtonDown イベントに応答しています。クリックするとすべて正常に動作します (つまり、イベント ハンドラが正しく起動します) が、マウス ポインタの精度が高すぎます。それを機能させるには、完全に円の頂点に立つ必要があります。もう少し寛容にする必要があります。おそらく、少なくとも 1 つまたは 2 つのピクセルを許容します。キャンバス上の要素は大きな円 (画面の 4 分の 1 程度のサイズ) であるため、円自体は小さすぎませんが、それぞれの StrokeWidth は 1 であるため、細い線です。

ここでスクリーンショットを見ることができます: http://twitpic.com/1f2ci/full

ほとんどのグラフィックス アプリは、マウス ピッキングに関してそれほどうるさくありません。そのため、ユーザーに慣れ親しんだエクスペリエンスを提供したいと考えています。

もう少し寛容にするにはどうしたらいいでしょうか。

4

4 に答える 4

4

代わりに、ルートレイアウトオブジェクトのMouseLeftButtonDownイベントに接続し、次のようにしてクリックの範囲内にある要素を確認できます。

List<UIElement> hits = System.Windows.Media.VisualTreeHelper.FindElementsInHostCoordinates(Point, yourLayoutRootElement) as List<UIElement>;  

http://msdn.microsoft.com/en-us/library/cc838402(VS.95).aspx

Pointパラメーターの場合、MouseEventArgsパラメーターeを使用して、次のようにGetPositionメソッドを呼び出すことができます。

Point p = e.GetPosition(null)

FindElementsInHostCoordinatesの代わりにHitTestを使用するかどうかを思い出せません。両方試してください。
http://msdn.microsoft.com/en-us/library/ms608752.aspx

マウスの位置から4ポイントのオブジェクトを作成して偽の許容差効果を作成し、4つのポイントすべてに対してFindElementsInHostCoordinatesまたはHitTestのいずれかを呼び出すことができます。

于 2009-02-24T07:11:08.270 に答える
4

円全体をクリックできるようにするには、円を透明色で塗りつぶしてみてください...

それが失敗した場合は、他の円と同じ場所に補助円を描くこともできます。円の前景色を透明にし、ブラシの太さを数ピクセル広くして、円の周りのクリック可能な領域をより許容できるようにします。

お役に立てれば!

于 2009-02-24T15:12:46.273 に答える
1

調整できるように、楕円のストロークの厚さを増やすだけです

したがって、MouseLeftButtonDown イベントが機能します。 例: Ellipse タグの場合:

Ellipse Canvas.Left="10" Canvas.Top="133" Height="24" Name="ellipse1" Width="23" Stroke="Red" MouseLeftButtonDown="ellipse1_MouseLeftButtonDown" ToolTip="Temp Close" StrokeEndLineCap="Flat " StrokeThickness="12"

private void ellipse1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { Application curApp = Application.Current; curApp.Shutdown(); }

于 2011-02-12T11:20:30.387 に答える
1

私はそれをやったと思います(私を始めるのを手伝ってください)...

まず、移動イベントの処理を各 Ellipse ではなく Canvas に移動しました。OOPの観点からは、それは良いことでも悪いことでもあります。少なくとも、マウス イベントの処理が各ホール (ホールのビジュアルである楕円) に設定するホールパターンの責任である場合は、HolePattern の消費者がこの機能を自動的に取得できるように抽象化されます。ただし、メインの UI コードに移動することで、キャンバス マウス イベントをより高いレベルで処理できるようになりました。しかし、それも悪いことばかりではありません。この部分については何日も話し合うことができます。

ポイントは、マウスでキャンバス上で何かを選択し、選択した楕円が属する穴を読み取るときに「誤差の範囲」を作成する方法を設計したことです。次に、穴が属するHolePatternを読み取ることができますに、UI 全体 (ListView、テキストボックス、座標のグリッドビュー) はすべて既存の XAML バインディングによって更新され、キャンバスは既存のメソッドを 1 回呼び出してキャンバスを再生成することで更新されます。

正直に言うと、(もちろん、あなたの助けや他の人たちの助けもありましたが) すべてを理解できたとは信じられません。これのビジョンを持ち、それが実現するのを見るのはとてもクールな気持ちです。

ここでメインコードをチェックしてください:

void canvas1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    int ClickMargin = 2;
    Point ClickedPoint = e.GetPosition(canvas1);
    Point p1 = new Point(ClickedPoint.X - ClickMargin, ClickedPoint.Y - ClickMargin);
    Point p2 = new Point(ClickedPoint.X - ClickMargin, ClickedPoint.Y + ClickMargin);
    Point p3 = new Point(ClickedPoint.X + ClickMargin, ClickedPoint.Y + ClickMargin);
    Point p4 = new Point(ClickedPoint.X + ClickMargin, ClickedPoint.Y - ClickMargin);
    var PointPickList = new Collection<Point>();
    PointPickList.Add(ClickedPoint);
    PointPickList.Add(p1);
    PointPickList.Add(p2);
    PointPickList.Add(p3);
    PointPickList.Add(p4);

    foreach (Point p in PointPickList)
    {
        HitTestResult SelectedCanvasItem = System.Windows.Media.VisualTreeHelper.HitTest(canvas1, p);
        if (SelectedCanvasItem.VisualHit.GetType() == typeof(Ellipse))
        {
            var SelectedEllipseTag = SelectedCanvasItem.VisualHit.GetValue(Ellipse.TagProperty);
            if (SelectedEllipseTag!=null &&  SelectedEllipseTag.GetType().BaseType == typeof(Hole))
            {
                Hole SelectedHole = (Hole)SelectedEllipseTag;
                SetActivePattern(SelectedHole.ParentPattern);
                SelectedHole.ParentPattern.CurrentHole = SelectedHole;

            }
        }
    }
}
于 2009-02-24T16:38:38.563 に答える