1

マウス コントロールなどを処理するカスタム イベントの作成に頭を悩ませようとしてきましたが、どのチュートリアルでも対処されていないように見える特定のエラーが発生し続けています。私の作成/割り当てのロジックは正しいと確信していますが、ここで見逃している根本的な問題があるかもしれません。

まず、メソッドと同じ署名でデリゲートを作成します。

public delegate void MouseDown(object sender, MouseEventArgs e, Control control);

そして、それを自分のイベントに割り当てます。

public event MouseDown OnMouseDown;

そして最後に、イベントをサブスクライブしようとします。

public static void Init(Control control, Control container, Direction direction)
{
    control.MouseDown += OnMouseDown;

}
//ignore the parameters I'm passing, these are out of the scope of my problem.

ただし、このセクションでは、「非静的フィールド、メソッド、またはプロパティ "blah blah.OnMouseDown" には ohject 参照が必要です」というエラーが表示されます。

最後に、mouseDown でサブスクライブしようとしているメソッドを次に示します。

public void MouseDownEvent(object sender, MouseEventArgs e, Control control)
{
    Dragging = true;
    DragStart = new Point(e.X, e.Y);
    control.Capture = true;
}

どこかで見つけたヘルパー クラスを変更しようとしても、おそらく役に立たないでしょう。さらに情報が必要な場合は、お気軽にお問い合わせください。

注: このクラスの主な目的は、実行時にコントロールを移動できるようにすることです。

編集:

最初の 2 つはうまくいったと思いますが、移動するには次の方法を使用する必要があります。

public void MouseMoveEvent(object sender, MouseEventArgs e, Control control, Control container, Direction direction)
{
     if (Dragging)
    {
        if (direction != Direction.Vertical)
            container.Left = Math.Max(0, e.X + container.Left - DragStart.X);
        if (direction != Direction.Horizontal)
            container.Top = Math.Max(0, e.Y + container.Top - DragStart.Y);
    }
}

だから私は送信者として送信できない方向方向を送信する必要があります。システム全体にこれらの変更を加えている理由は、匿名のデリゲートを使用する前に動作していましたが、コントロールを再ロックしたいときにサブスクライブを解除するのが難しいことがわかったからです。

編集 2:
それをスクラッチします。正しいコントロールを渡さないと、mouseDown と mouseUp は機能しません。少なくとも以前と同じようにサブスクライブします。私はあなたの方法を試すことができましたが、私がやっていた方法は、3つのMouseControlsすべてにサブスクライブした1つのメソッドを呼び出すだけでした. 提案されているように、別の方法でサブスクライブできるか、適切なコントロールを正しく渡す必要があるようです。つまり、コントロールとしての送信者ではありません。何か案は?

現在、どこからでもこのメソッドを実行して購読しています。

helper.Init(this.Controls["btn" + i]);

そして、ボタンをマウスアップ、ダウン、ムーブにサブスクライブする前に、これらのメソッドを実行します。

public static void Init(Control control)
{
    Init(control, Direction.Any);
}

public static void Init(Control control, Direction direction)
{
    Init(control, control, direction);
}

public static void Init(Control control, Control container, Direction direction)
{
    control.MouseDown += new MouseEventHandler(FireOnMouseDown);
    control.MouseUp += new MouseEventHandler(FireOnMouseUp);
    control.MouseMove += delegate(object sender, MouseEventArgs e)
    {
        if (Dragging)
        {
            if (direction != Direction.Vertical)
                container.Left = Math.Max(0, e.X + container.Left - DragStart.X);
            if (direction != Direction.Horizontal)
                container.Top = Math.Max(0, e.Y + container.Top - DragStart.Y);
        }
    };
}

注: 3 番目のサブスクリプションは、以前の状態です (匿名デリゲート)。ただし、イベントで正しいコントロールを渡す必要があると思います。これにより、問題がより明確になりますか?

4

2 に答える 2

2

この質問への答え:

ただし、このセクションでは、「非静的フィールド、メソッド、またはプロパティ "blah blah.OnMouseDown" には ohject 参照が必要です」というエラーが表示されます。

Initメソッドは静的です。つまり、内部で使用される非ローカル変数はすべて静的でなければなりません。コードでは、public event MouseDown OnMouseDown;は静的である必要があります。

これを行うだけで問題なく動作します (デリゲートは必要ありません):

EDIT クリックされたコントロールを取得する方法については、以下のコードを参照してください。

public static void Init(Control control, Control container, Direction direction)
{
   control.MouseDown += new System.Windows.Forms.MouseEventHandler(On_MouseDown);;
}
private static void On_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)       
{     
   Control control = sender as Control;
   if(control != null){
       // Here we go, use the control to do whatever you want with it 
   } 
}
于 2012-06-08T10:38:50.977 に答える
1

あなたは書くべきです:

control.MouseDown += new MouseEventHandler(MouseDownEvent);

Control の MouseDown イベントは送信者と MouseEventArgs のみをパラメーターとして必要とするため、ここでは MouseDownEvent の署名を変更する必要があることに注意してください。

しかし、これがあなたが本当に望んでいるものかどうかはわかりません。この命令の効果は、マウスがコントロール上に置かれたときに MouseDownEvent が実行されることです。これは、あなたの望むことですか?

public event MouseDown OnMouseDown;これが表示される同じクラスのどこかに、このイベントを発生させる何かを次のように記述しない限り、この命令は不適切です。

if (OnMouseDown!= null)
   OnMouseDown(aSenderObject, aMouseEventArgs, aControl);

そして、thgis イベントをサブスクライブするには、次のように記述する必要があります (ここで hc anObj は、イベントが定義されているクラスのインスタンスです)。

anObj.OnMouseDown+= new MouseDown(MouseDownEvent);

それが役に立てば幸い。たぶん、もう少しコンテキストが役立つかもしれません。

編集:

コントロールの動きを管理するクラスを実装しようとしている場合は、以下を含むヘルパー クラスを使用できます。

public delegate void MouseDown(object sender, MouseEventArgs e, Control control);
public static event MouseDown OnMouseDown;

クラスにコントロールを「登録」できるようにしたい場合は、これがその方法です (イベントは静的であることに注意してください)。ここでは、マウスがコントロール上に置かれたときに、FireMouseDown が実行されると言います。

public static void Init(Control control, Control container, Direction direction)
    {
        control.MouseDown += new MouseEventHandler(FireOnMouseDown);
    }

FireMouseDown では、正しい引数で OnMouseEvent を起動する必要があります。

public static void FireOnMouseDown(object sender, MouseEventArgs e)
    {
        if (OnMouseDown != null)
            OnMouseDown(this, e, sender as Control);
    }

これで、ヘルパーの外部から元のメソッド OnMouseDown にサブスクライブできます。

Helper.OnMouseDown += new MouseDown(MouseDownEvent);

EDIT2:

私はそれを指定しませんでしたが、ここで起こっていることは、Init に渡されたコントロールの 1 つで MouseDown イベント (つまり、windows イベント) が発生するたびに、OnMouseDown イベントが発生するということです。つまり、OnMouseDown への登録は 1 回だけで済みます。その後、これらのコントロールのいずれかに MouseDown があるたびに、次のパラメーターを渡して MouseDownEvent が実行されます。

sender -> the Helper class
e -> the original MouseEventArgs generated by Windows
control -> the control that generated the original event

MouseMove イベントに関しては、必要なパラメーターを追加するだけで、MouseDown の場合と同様のことを行う必要があります (コンテナーは常にコントロールと等しいように見えるため、コンテナーと方向の意味が明確ではありませんが)。方向は常に Direction.Any です)。私は次のようなことを意味します:

public delegate void MouseMove(object sender, MouseEventArgs e, Control control, Control container, Direction direction);
public static event MouseMove OnMouseMove;

public static void FireOnMouseMove(object sender, MouseEventArgs e) 
{ 
    if (OnMouseMove != null) 
        OnMouseMove(this, e, sender as Control, aContainer, aDirection); 
}

ここで理解できないのは、どこから aContainer と aDirection を見つけようとしているかということです。あなたの Init を複製する必要がある場合は、 と書きますOnMouseMove(this, e, sender as Control, sender as Control, Direction.Any);が、うまくいかないと思います。

于 2012-06-08T10:44:54.877 に答える