2

私はWPFにまったく慣れていないので、このほとんどを難しい(しかし楽しい)方法で学んでいます。HSVのようなカラーピッカーユーザーコントロールを作成しています。「セレクター」が楕円形の領域(実際には円)に限定されているため、使用する親指の動作を取得したいと思います。外に移動するときは、セレクターは横に固定され、まったく移動しないようにする必要があります。これが最も一般的なGUIの動作であると私は信じているので、それがどのように動作するかです。より良い行動を提案してください!

これに対する一般的で既知の推奨される解決策はありますか、それとも毎回車輪の再発明を行うのは全員の責任ですか?

これを解決する方法についての良いアイデアはありますか?

コードビハインド:

public partial class HSVColorPicker : UserControl
{
    public HSVColorPicker()
    {
        InitializeComponent();
    }

    void onDragDelta(object sender, DragDeltaEventArgs e)
    {
        Canvas.SetLeft(thumb, Canvas.GetLeft(thumb) + e.HorizontalChange);
        Canvas.SetTop(thumb, Canvas.GetTop(thumb) + e.VerticalChange);
    }
}

XAML:

<Grid>
    <Canvas x:Name="canvas">
        <Image x:Name="wheel" Source="colorwheel.png" Width="300" Margin="5,5,0,0"/>
        <Thumb Name="thumb" DragDelta="onDragDelta" Canvas.Left="104" Canvas.Top="68" Template="{StaticResource thumbTemplate}" />
    </Canvas>
</Grid>

私がここにいる間、親指は常にカーソルの後ろをドラッグしていますが、これを作成する別の方法はありますか?私が言ったように、私はWPFとGUIの作成にまったく慣れていないので、私には思いつかなかった明らかな解決策があるかもしれません;)

4

2 に答える 2

1

いくつかの再考を行い、代わりにダミーの円(thumbという名前)を使用してThumbを完全に削除しました。今、キャンバス上でマウスダウン、マウスアップ、マウスムーブを聞いて、何が可能で何が不可能かを判断します。これには、マウスが領域の外に出たときに親指がカラーホイールの端にくっつくという優れた機能がありますが、領域はカラーホイールよりも少し大きいため、境界線上のポイントを簡単に取得できます。完全ではありませんが、質問は解決したので、現時点ではそのまま投稿します。

    private bool mousePressed { get; set; }
    private bool mouseWithinArea { get; set; }
    private Point circleMiddlePoint { get; set; }
    private int margin;
    private double mPX;
    private double mPY;
    private double localXpos;
    private double globalXpos
    {
        get
        {
            return localXpos + mPX;
        }
        set
        {
            localXpos = value - mPX;
            Canvas.SetLeft(thumb, value);
        }
    }
    private double localYpos;
    private double globalYpos
    {
        get
        {
            return mPY - localYpos;
        }
        set
        {
            localYpos = mPY - value;
            Canvas.SetTop(thumb, value);
        }
    }

    public HSVColorPicker()
    {
        InitializeComponent();
        wheel.Width = 300;
        margin = 15;
        mPX = 150+margin;
        mPY = 150+margin;
        circleMiddlePoint = new Point(mPX, mPY);
    }

    private void CalcPosition(double X, double Y)
    {
        double radius = wheel.Width / 2.0;
        double vectorX = X - mPX;
        double vectorY = Y - mPY;
        double distance = Math.Sqrt(vectorX * vectorX + vectorY * vectorY);
        if (distance > radius)
        {
            double factor = radius / distance;
            vectorX *= factor;
            vectorY *= factor;
        }
        globalXpos = vectorX + mPX;
        globalYpos = vectorY + mPY;
    }

    private void wheel_MouseDown(object sender, MouseButtonEventArgs e)
    {
        if (mouseWithinArea)
        {
            mousePressed = true;
            Point mousePoint = e.GetPosition(this);
            CalcPosition(mousePoint.X, mousePoint.Y);
        }
    }

    private void wheel_MouseMove(object sender, MouseEventArgs e)
    {
        Point mousePoint = e.GetPosition(this);
        double relX = mousePoint.X - mPX;
        double relY = mPY - mousePoint.Y;
        if (mouseWithinArea)
        {
            if (Math.Sqrt(relX * relX + relY * relY) > 150+margin)
            {
                mouseWithinArea = false;
            }
            else
            {
                if (mousePressed)
                {
                    CalcPosition(mousePoint.X, mousePoint.Y);
                }
            }
        }
        else
        {
            if (Math.Sqrt(relX * relX + relY * relY) < 150+margin)
            {
                mouseWithinArea = true;
                if (mousePressed)
                {
                    CalcPosition(mousePoint.X, mousePoint.Y);
                }
            }
        }
    }

    private void wheel_MouseUp(object sender, MouseButtonEventArgs e)
    {
        mousePressed = false;
    }
}

<Canvas x:Name="canvas" Background="Transparent" MouseDown="wheel_MouseDown" MouseMove="wheel_MouseMove" MouseUp="wheel_MouseUp" Width="330" Height="330">
        <Image x:Name="wheel" Source="colorwheel.png" Width="300" Margin="15,15,0,0"  />
        <Ellipse Margin="0,0,0,0"
                x:Name="outerEll"
                Stroke="Silver"
                StrokeThickness="15" 
                Width="330"
                Height="330"/>
        <Ellipse Name="thumb" Stroke="Black" Fill="Silver" Canvas.Left="150" Canvas.Top="150" Width="15" Height="15" Margin="-12" />
    </Canvas>
于 2012-04-17T12:06:23.863 に答える
0

親指の中心をカラーホイール内に配置します。

したがって、親指の中心とカラーホイールの中心(つまり、キャンバスの中心)の間の距離は、カラーホイールの半径(つまり、キャンバスの側面の半分)以下である必要があります。 )。

テストされていないc#コード:

void onDragDelta(object sender, DragDeltaEventArgs e)
{
    double radius = canvas.RenderSize.Width / 2.0;
    double thumbCenterX = Canvas.GetLeft(thumb) - thumb.RenderSize.Width + e.HorizontalChange;
    double thumbCenterY = Canvas.GetTop(thumb) - thumb.RenderSize.Height + e.VerticalChange;
    double colorWheelCenterX = canvas.RenderSize.Width / 2.0;
    double colorWheelCenterY = canvas.RenderSize.Height / 2.0;
    double vectorX = thumbCenterX - colorWheelCenterX;
    double vectorY = thumbCenterY - colorWheelCenterY;
    double distance = Math.Sqrt(vectorX * vectorX + vectorY * vectorY);
    if(distance > radius) {
        double factor = radius / distance;
        vectorX *= factor;
        vectorY *= factor;
    }
    Canvas.SetLeft(thumb, colorWheelCenterX + vectorX - thumb.RenderSize.Width / 2.0);
    Canvas.SetTop(thumb, colorWheelCenterY + vectorY - thumb.RenderSize.Height / 2.0);
}
于 2012-04-13T11:42:14.813 に答える