2

どんな角度でも直線を作りたいと言う

public class Line : Control
{
    public Point start { get; set; }
    public Point end { get; set; }
    public Pen pen = new Pen(Color.Red);

    protected override void OnPaint(PaintEventArgs e)
    {
        e.Graphics.DrawLine(pen, start, end);
        base.OnPaint(e);
    }
}

この行は、カスタム コントロールで作成されています。

でヒットテストを実装できるように、線が作成された正確なピクセルをどのように計算できますかMouseMove

4

5 に答える 5

1

GDI 呼び出しを使用して描画される線のピクセルを列挙するための Win32 呼び出しがあります。これは、あなたが達成しようとしていることに対する最良のテクニックだと思います。LineDDAとそれに関連するコールバックLineDDAProcを参照してください。

これを C# から使用する方法を次に示します。LineDDA のドキュメントによると、エンドポイントは出力に含まれないことに注意してください。

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;

public static List<Point> GetPointsOnLine(Point point1, Point point2)
{
    var points = new List<Point>();
    var handle = GCHandle.Alloc(points);
    try
    {
        LineDDA(point1.X, point1.Y, point2.X, point2.Y, GetPointsOnLineCallback, GCHandle.ToIntPtr(handle));
    }
    finally
    {
        handle.Free();
    }
    return points;
}

private static void GetPointsOnLineCallback(int x, int y, IntPtr lpData)
{
    var handle = GCHandle.FromIntPtr(lpData);
    var points = (List<Point>) handle.Target;
    points.Add(new Point(x, y));
}

[DllImport("gdi32.dll")]
private static extern bool LineDDA(int nXStart, int nYStart, int nXEnd, int nYEnd, LineDDAProc lpLineFunc, IntPtr lpData);

// The signature for the callback method
private delegate void LineDDAProc(int x, int y, IntPtr lpData);
于 2013-06-28T18:53:31.390 に答える
0

本当にこのようにしたい場合は、コントロールを 2 回描画します。

  1. 一度スクリーンに、
  2. 一度オフスクリーンバッファに。

明らかな方法は、バッファーをコントロールのクライアントの四角形と同じサイズにすることです。

オフスクリーンでは、アンチエイリアシングをオフにして、書き込んだとおりに色の値を読み取ることができます。これで、ビットマップから簡単に読み取ることができます。複数行のヒット テストが必要な場合は、インデックス値を色に入れます。

于 2013-06-28T19:15:24.687 に答える
0

これを行うにはもっと複雑な方法がありますが、簡単な方法は、カスタム コントロールのクリック イベントを処理することです。つまり、基本クラスによって発生するMouseClickイベントのハンドラーを追加します。Controlこのようにして、Windows がすべてのヒット テストを実行します。

ユーザーがコントロールのどこかをクリックすると、MouseClickイベントが発生し、必要に応じて処理できます。それ以外の場合、イベントは発生しません。シンプルさの縮図。

MouseClickイベント ハンドラーでは、クライアント座標でポイント ( ) を取得します。これe.Locationは、位置がクライアント コントロールの左上隅に相対的であることを意味します。

テスト目的でLabel、空のフォームにコントロールを追加し、オフにして、赤AutoSizeに設定しました。BackColor次に、線のようにして、MouseClickイベントのハンドラーを追加しました。ハンドラーは次のようになります。

private void redLabel_MouseClick(object sender, MouseEventArgs e)
{
   // Fired whenever the control is clicked; e.Location gives the location of
   // the mouse click in client coordinates.
   Debug.WriteLine("The control was clicked at " + e.Location);
}

ヒット テストのこの単純な方法は、Windows に関する限り、コントロールの物理的な境界がその論理的な境界と同じであるという事実に依存しています。Sizeしたがって、カスタム コントロールで動作させるには、そのプロパティを実際の論理的な寸法 (つまり、線の幅と太さ) に設定する必要があります。

于 2013-06-28T19:47:08.397 に答える