0

シーン内のグリッドの端にカーソルをスナップする機能をアプリケーションに実装しようとしています。現状では、現在のMouseMoveが提供するe.Locationを取得し、ワールド座標に変換して画面に戻すフレームワークがあります-値は一致します。以下の基本的なコードの概要を参照してください。

public void Scene_MouseMove(object sender, MouseEventArgs e)
{
    Vector2 world = ScreenToWorld(e.Location);

    ---> Check here to make sure the world coordinates returned
         fall inside my grid scene edges.
    if (world.X < Grid.Left) world.x = Grid.Left;

    Point target = WorldToScreen(world);

    // set cursr desired position
    Cursor.Position = (sender as PictureBox).PointToScreen( target );
}

私が抱えている問題は、マウスが移動した後に MouseMove が呼び出されるという事実です。そのため、グリッドの端にぶつかると、フレームのマウスのオーバーシュートが表示され、それ自体が修正されます。これにより、マウスを動かすと、カーソルがエッジを越えてジッターします。端に当たったときにカーソルがそのトラックで停止するようにしたいのですが、マウスが動く前にデータをキャプチャする方法がわかりません!

おそらく私はこれについて間違っているので、どんな提案でも大歓迎です。

参考までに - これは、実装しようとしている SnapToGrid 機能の最初の部分です。

EDIT:より簡単な例:

以下の簡単な例を実行すると、私の問題を確認できます。カーソルを動かすと、フレームごとにカーソルがちらつくことに注意してください。

bool g_Set = false;
public void Scene_MouseMove(object sender, MouseEventArgs e)
{
    // stop MouseMove from flooding the control recursively
    if(g_Set) { g_Set = false; return; }
    g_Set = true;
    Cursor.Position = new Point(400,400);
}

C# は、実際に Cursor を移動する前にMouseMoveをキャプチャするために API で何かをサポートしていますか、それとも Form.Cursorを非表示にしてレンダリングするだけの独自の Cursor クラスを実装することを検討する必要がありますか?その機能についても手がかりがありません)。

4

4 に答える 4

0

線形外挿を使用して、フレームに入る前の最後のピクセルを計算します。2つのポイントP1とP2が必要になります。入る前のポイントP0は、次のように近似できます。

P0.X = P2.X - P1.X
P0.Y = P2.Y - P1.Y
于 2013-03-07T04:11:23.053 に答える
0

それで、これを調べて良い一日を過ごした後、私は最終的に故障して Cursor クラスを書きました。ここで重要なのは、Managed DirectX を使用して PictureBox でレンダリングしていることです。

実際には、コントロールに入るとSystem.Cursorを非表示にし、各フレーム間の System.Cursor のオフセットを取得し、ロジックを適用して、「自分の」カーソルをレンダリングする場所を決定することで、独自のカーソルのレンダリングを開始します。オフセットの処理方法を以下に示します。

public bool g_RecalcCursor = false;
public Point g_Reference = new Point(400,400);
public void SceneView_MouseMove(object sender, MouseEventArgs e)
{
    // this logic avoids recursive calls into MouseMove
    if (g_RecalcCursor)
    { 
        g_RecalcCursor = false;
        return;
    }

    Point ee = (sender as PictureBox).PointToScreen(e.Location);
    Point delta = new Point(g_Reference.X - ee.X, g_Reference.Y - ee.Y);

    //------------------------------------------//
    // I can use delta now to move my cursor    //
    // and apply logic "BEFORE" it renders      //
    //------------------------------------------//

    g_RecalcCursor = true;
    Cursor.Position = g_Reference;
}

マウスの動き ( MouseMoving / MouseMove )でForm_Closing / Form_Closedのような呼び出しがないことに驚いていますが、 System.Cursorは、通常の機能に関するユーザー エクスペリエンスを低下させないために、アプリケーションによって操作されることを意図していない可能性があります。であるため、API での操作機能が制限されています。

System.Cursor を使用できるようにする提案はまだ受け付けています...

于 2013-03-07T19:43:31.833 に答える
0

UserControlシーンを持つ を作成できます。シーンを中央に配置し、周囲に既知のサイズのマージンを置きます。UserControl.BackColor = Transparent。_ イベントを処理する

private void UserControl_MouseMove(Object sender,MouseEventArgs e)
{
    // check if mouse is entering the Scene, you know the size of the margin
}

そこから、マウスがシーンに入るのを予測するロジックを考え出すことができます。

于 2013-03-07T14:59:46.360 に答える
0

エッジにスナップするには、スナップ用に少し余裕を持たせます (例: 2 ピクセル):

if (world.X - 2 < Grid.Left) world.x = Grid.Left;

コントロールの四角形内にカーソルを限定するには、例: aButton

Cursor.Clip = aButton.RectangleToScreen(aButton.ClientRectangle);

カーソルを解放するには:

Cursor.Clip = null;
于 2013-03-07T03:35:43.250 に答える