2016-03-21 6 views
0

私はC#の新機能です。アナログ時計の時刻を編集するには、そのハンドルをドラッグしてください。 https://code.msdn.microsoft.com/windowsapps/Analog-Clock-Control-0e8ffcab#contentこのコードは私を魅了しました。私は3つの単純な関数MouseDown、MouseMoveとMouseUpを持っていますが、私はDragを動作させることができません。何か提案してください?アナログ時計の時刻をリセットする方法ハンドルをドラッグしてC#

public partial class Form1 : Form 
{ 
#region Construct the clock 

public Point Start { get; set; } 
public Point End { get; set; } 

public Form1() 
{ 
    InitializeComponent(); 
    DoubleBuffered = true; 

    //Create the timer and start it 
    ClockTimer.Tick += ClockTimer_Tick; 
    ClockTimer.Enabled = true; 
    ClockTimer.Interval = 1; 
    ClockTimer.Start(); 
    Start = p1; 
    End = p2; 
} 
#endregion 

#region Update the clock 

private void ClockTimer_Tick(object sender, EventArgs e) 
{ 
    Refresh(); 
} 

private Timer ClockTimer = new Timer(); 
private Pen circle = new Pen(Color.Black, 2); 
private Pen secondHandle = new Pen(Color.Red, 1); 
private Pen minHandle = new Pen(Color.Black, 5); 
private Pen hrHandle = new Pen(Color.Black, 5); 

private Point p1; 
private Point p2; 

#endregion 

#region On paint 

protected override void OnPaint(PaintEventArgs pe) 
{ 
    base.OnPaint(pe); 

    //Clear the graphics to the back color of the control 
    pe.Graphics.Clear(BackColor); 

    //Draw the border of the clock 
    pe.Graphics.DrawEllipse(circle, 0, 0, 300, 300); 

    //Find the radius of the control by dividing the width by 2 
    float radius = (300/2); 

    //Find the origin of the circle by dividing the width and height of the control 
    PointF origin = new PointF(300/2, 300/2); 

    //Draw only if ShowMajorSegments is true; 
    if (ShowMajorSegments) 
    { 
     //Draw the Major segments for the clock 
     for (float i = 0f; i != 390f; i += 30f) 
     { 
      pe.Graphics.DrawLine(Pens.White, PointOnCircle(radius - 1, i, origin), PointOnCircle(radius - 21, i, origin)); 
     } 
    } 

    //Draw only if ShowMinorSegments is true 
    if (ShowMinorSegments) 
    { 
     //Draw the minor segments for the control 
     for (float i = 0f; i != 366f; i += 6f) 
     { 
      pe.Graphics.DrawLine(Pens.Black, PointOnCircle(radius, i, origin), PointOnCircle(radius - 10, i, origin)); 
     } 
    } 

    //Draw only if ShowSecondHand is true 
    if (ShowSecondhand) 
     //Draw the second hand 
     pe.Graphics.DrawLine(secondHandle, origin, PointOnCircle(radius, DateTime.Now.Second * 6f, origin)); 


    //Draw only if ShowMinuteHand is true 
    if (ShowMinuteHand) 
     //Draw the minute hand 
     pe.Graphics.DrawLine(minHandle, origin, PointOnCircle(radius * 0.75f, DateTime.Now.Minute * 6f, origin)); 
     minHandle.StartCap = LineCap.RoundAnchor; 
     minHandle.EndCap = LineCap.ArrowAnchor; 
     pe.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High; 
     pe.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; 


    //Draw only if ShowHourHand is true 
    if (ShowHourHand) 
     //Draw the hour hand 
     pe.Graphics.DrawLine(hrHandle, origin, PointOnCircle(radius * 0.50f, DateTime.Now.Hour * 30f, origin)); 
     hrHandle.StartCap = LineCap.RoundAnchor; 
     hrHandle.EndCap = LineCap.ArrowAnchor; 
     pe.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High; 
     pe.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; 


} 
#endregion 

#region On size changed 

protected override void OnSizeChanged(EventArgs e) 
{ 
    base.OnSizeChanged(e); 

    //Make sure the control is square 
    if (Size.Height != Size.Width) 
     Size = new Size(Size.Width, Size.Width); 

    //Redraw the control 
    Refresh(); 
} 
#endregion 

#region Point on circle 

private PointF PointOnCircle(float radius, float angleInDegrees, PointF origin) 
{ 
    //Find the x and y using the parametric equation for a circle 
    float x = (float)(radius * Math.Cos((angleInDegrees - 90f) * Math.PI/180F)) + origin.X; 
    float y = (float)(radius * Math.Sin((angleInDegrees - 90f) * Math.PI/180F)) + origin.Y; 

    return new PointF(x, y); 
} 
#endregion 

#region Show Minor Segments 

private bool showMinorSegments = true; 

public bool ShowMinorSegments 
{ 
    get 
    { 
     return showMinorSegments; 
    } 
    set 
    { 
     showMinorSegments = value; 
     Refresh(); 
    } 
} 
#endregion 

#region Show Major Segments 

private bool showMajorSegments = true; 

public bool ShowMajorSegments 
{ 
    get 
    { 
     return showMajorSegments; 
    } 
    set 
    { 
     showMajorSegments = value; 
     Refresh(); 
    } 
} 
#endregion 

#region Show Second Hand 

private bool showSecondHand = false; 

public bool ShowSecondhand 
{ 
    get 
    { 
     return showSecondHand; 
    } 
    set 
    { 
     showSecondHand = value; 
     Refresh(); 
    } 
} 
#endregion 

#region Show Minute Hand 

private bool showMinuteHand = true; 

public bool ShowMinuteHand 
{ 
    get 
    { 
     return showMinuteHand; 
    } 
    set 
    { 
     showMinuteHand = value; 
     Refresh(); 
    } 
} 
#endregion 

#region Show Hour Hand 

private bool showHourHand = true; 

public bool ShowHourHand 
{ 
    get 
    { 
     return showHourHand; 
    } 
    set 
    { 
     showHourHand = value; 
     Refresh(); 
    } 
} 
#endregion 

public float slope 
{ 
    get 
    { 
     return (((float)p2.Y - (float)p1.Y)/((float)p2.X - (float)p1.X)); 
    } 
} 
public float YIntercept 
{ 
    get 
    { 
     return p1.Y - slope * p1.X; 
    } 
} 

public bool IsPointOnLine(Point p, int cushion) 
{ 
    float temp = (slope * p.X + YIntercept); 
    if (temp >= (p.Y - cushion) && temp <= (p.Y + cushion)) 
    { 
     return true; 
    } 
    else 
    { 
     return false; 
    } 
} 

Point deltaStart; 
Point deltaEnd; 
bool dragging = false; 

private void Form1_MouseDown(object sender, MouseEventArgs e) 
{ 
    if (e.Button == System.Windows.Forms.MouseButtons.Left && IsPointOnLine(e.Location, 5)) 
    { 
     dragging = true; 
     deltaStart = new Point(p1.X - e.Location.X, p1.Y - e.Location.Y); 
     deltaEnd = new Point(p2.X - e.Location.X, p2.Y - e.Location.Y); 
    } 
} 

private void Form1_MouseMove(object sender, MouseEventArgs e) 
{ 
    if (dragging && deltaStart != null && deltaEnd != null) 
    { 
     p1 = new Point(deltaStart.X + e.Location.X, deltaStart.Y + e.Location.Y); 
     p2 = new Point(deltaEnd.X + e.Location.X, deltaEnd.Y + e.Location.Y); 
     this.Refresh(); 
    } 
} 

private void Form1_MouseUp(object sender, MouseEventArgs e) 
{ 
    dragging = false; 
} 

}

+1

「でもドラッグは動作しません」とはどういう意味ですか?あなたの描画は 'DateTime.Now'に基づいており、' Start'と 'End'変数はほとんど使われていません。あなたが望むものをより具体的にしてください。良い出発点は、マウスが現在Form1_MouseMoveにある点の角度を決定し、その角度に基づいて追加の線を描くことです。 – grek40

+0

お返事ありがとうございますgrek40、私は 'Start'と' End'変数を使用することに関するあなたの提案を実装して私の質問を編集しましたが、私はマウスがあるポイントの角度を決定するためにわずかな困難を抱えています。 – Tony

答えて

0

Iは角度が上に配置された円に基づいて、(度)の角度に配位YXの翻訳に関する部分的な答えを与えます。典型的なGUI座標の指示に従って

(コンパクトなソリューションのために下にスクロール)

は、絶対0,0点が左上に配置され、正のXの値は右方向に伸び、正のY値にストレッチボトム。

計算を単純化するために、私は円の中心に仮想0,0点を使用します。したがって、実際の描画前にすべての座標を計算前にローカルに、グローバルに変換する必要があります。

(周り0; 0円を想像)概要座標:任意の行(0; 0) - (0; -1)とライン(0; 0) - (X; Y)

円の間のクロックワイズ角度を見つけるために(X; Y)を調整するために

  (0;-1) 


(-1; 0) (0; 0) (1; 0) 


      (0; 1) 

今タスクがあります4つの四分円に分割することができ、それぞれが符号付き(X; Y)値の組み合わせをカバーします。

クォーター1角度が90°値と正X値と負Y値で表現される含有します。

クォーター2角度が180°90°値と正X値と正Y値で表現される含有します。

クォーター3角度が270°180°値と負X値と正Y値で表現される含有します。

クォーター4角度が360°270°値と負X値と負Y値で表現される含有します。コーナーケース90°180°270°360°のためにそれは本当に彼らが割り当てられている2四半期の問題ではありませんことを

注意。

このような問題を理解する最も簡単な方法は、通常の円 - >読み取りに固執することです:X; Y座標を長さ1に正規化することです。さらに、私は正の値で行く(それもせずに動作しますが、異なっ+-組み合わせでビット):

var len = Math.Sqrt(X * X + Y * Y); 
var xNorm = Math.Abs(X)/len; 
var yNorm = Math.Abs(Y)/len; 

今、逆のサイン/コサインは角度に戻す正規化座標を変換するために使用することができます(シンプルさと完全を期すために、私の計算では、いくつかの冗長性があります)値:

var angleFromX = Math.Asin(xNorm) * 180.0/Math.PI; 
var angleFromY = Math.Asin(yNorm) * 180.0/Math.PI; 

は今四半期の円領域毎に適切な角度を適用できますが

var resultAngle = 0.0; 
if (quarter_1) 
{ 
    resultAngle = 0 + angleFromX; 
    // same as 
    resultAngle = 90 - angleFromY; 
} 
if (quarter_2) 
{ 
    resultAngle = 90 + angleFromY; 
    // same as 
    resultAngle = 180 - angleFromX; 
} 
if (quarter_3) 
{ 
    resultAngle = 180 + angleFromX; 
    // same as 
    resultAngle = 270 - angleFromY; 
} 
if (quarter_4) 
{ 
    resultAngle = 270 + angleFromY; 
    // same as 
    resultAngle = 360 - angleFromX; 
} 

もちろん、quarter_1-quarter_4は説明した四分選択を表す疑似変数です。


完全なソリューションのさまざまな特性を分析すると、よりコンパクトなソリューションが見つかります。

var angleFromYAxis = Math.Asin(Y/Math.Sqrt(X * X + Y * Y)) * 180.0/Math.PI; 

var resultAngle = 0.0; 
if (X >= 0) 
{ 
    resultAngle = 90 + angleFromYAxis; 
} 
else 
{ 
    resultAngle = 270 - angleFromYAxis; 
} 
関連する問題