3

ほぼ完成したメトロノームアプリケーションを開発しようとしています。

私が残した唯一の部分は、腕の画像(時計の分針を考えてください)を時間の前後に回転させる必要があるセカンダリビジュアルです。

画像を中心点を中心に回転させずに回転させるにはどうすればよいですか。私が書いているシナリオでは、下の境界線の中央にある点を中心に画像を回転できるようにする必要があります。

また、画像をXからYにnミリ秒で回転させ、アニメーションで簡単に出し入れできるようにしたいと思います。これはC#には遠すぎる橋であり、この高度なタイプの物理アニメーションを実現するのに役立つライブラリはありますか。

どうもありがとう

ダン

4

3 に答える 3

2

あなたが求めたものではありませんが、:

1秒間に何度もプロセッサを集中的に使用する操作を行う代わりに、静止画像のセットをめくることを検討する必要があります。

于 2012-06-08T18:40:26.173 に答える
2

拡張返信

ちらつきは一切ありません。ctorのSetStyleがそれを処理します。「ちらつき」と表示されるのは、次の3つの要因によるアーティファクトの原因です。

  1. 更新レートはわずか10/秒です。それを20または30に増やしてみてください。
  2. 方向の値はコースです。時間/加速に基づく必要があります。それはあなたに残された運動です。
  3. 安っぽい「手」の画像には、硬いエイリアシングされたエッジがあります。更新の速度やアニメーションの速度に関係なく、ぎくしゃくしたように見えます。繰り返しになりますが、アンチエイリアス処理されたブレンドグラフィックス処理を行うことは演習として残されています。

コードをもっと注意深く見てください。これは「フォームにペイント」されたものではなく、カスタムコントロールです。からどのようにMetronomeControl派生するかを参照してくださいControl?MetronomeControlを追加してフォームを作成した方法をご覧ください。

画像ボックスは静止画像を表示するためのものであり、カスタムコントロール用ではありません。

更新する方法は、タイマーを作成することです。タイマーのTickイベントが発生すると、角度と方向が更新されます。より一般的には、コントロールの状態が更新されます。Invalidateを呼び出すと、オペレーティングシステムに、「ねえ、塗り直しが必要です。都合のよいときにWM_PAINTメッセージを送信してください」と通知されます。OnPaintオーバーライドは、コントロールの現在の状態をペイントするだけです。

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;

class MetronomeControl : Control
{
    private Bitmap hand;
    private float angle = 0;
    private float direction = 2;
    private Timer timer = new Timer { Enabled = true, Interval = 30 };

    public MetronomeControl()
    {
        SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.Opaque | ControlStyles.AllPaintingInWmPaint, true);
        hand = CreateCrappyHandBitmap();
        timer.Tick += new EventHandler(timer_Tick);
    }

    void timer_Tick(object sender, EventArgs e)
    {
        if (angle < -45 || angle > 45)
            direction = -direction;
        angle += direction;
        Invalidate();
    }

    private static Bitmap CreateCrappyHandBitmap()
    {
        Bitmap bitmap = new Bitmap(100, 300, PixelFormat.Format32bppArgb);
        using (Graphics graphics = Graphics.FromImage(bitmap))
        {
            graphics.Clear(Color.Transparent);
            graphics.FillRectangle(Brushes.LightGray, 50 - 5, 0, 10, 300);
            graphics.FillPolygon(Brushes.LightSlateGray, new Point[] { new Point(50 - 30, 40), new Point(50 + 30, 40), new Point(50 + 20, 80), new Point(50 - 20, 80) });
            graphics.FillEllipse(Brushes.LightSlateGray, 0, 200, 100, 100);
        }
        return bitmap;
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        // Erase background since we specified AllPaintingInWmPaint
        e.Graphics.Clear(Color.AliceBlue);

        e.Graphics.DrawString(Text, Font, Brushes.Black, new RectangleF(0, 0, ClientSize.Width, ClientSize.Height), new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });

        // Move the 0,0 point to the just below the bottom-center of our client area
        e.Graphics.TranslateTransform(ClientSize.Width / 2, ClientSize.Height + 40);
        // Rotate around this new 0,0
        e.Graphics.RotateTransform(angle);
        // Turn on AA to make it a bit less jagged looking
        e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
        // Draw the image so that the center of the ellipse is at 0,0
        e.Graphics.DrawImage(hand, 0 - hand.Width / 2, 0 - hand.Height + 50);

        // Reset the transform for other drawing
        e.Graphics.ResetTransform();

        base.OnPaint(e);
    }
}

static class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form
        {
            Text = "Metronome Control Demo",
            ClientSize = new Size(640, 480),
            Controls =
            {
                new MetronomeControl
                {
                    Location = new Point(10, 10),
                    Size = new Size (340, 300),
                    Font = new Font(FontFamily.GenericSansSerif, 24),
                    Text = "Metronome Control Demo",
                }
            }
        });
    }
}
于 2012-06-08T21:45:18.420 に答える
0

このサンプルコードが役立つかもしれません:

Graphics x=Graphics.FromImage(m);
x.TranslateTransform(m.Width / 2, m.Height / 2);
x.RotateTransform(30);
SizeF textSize = x.MeasureString("hi", font);
x.DrawString("hi", font, Brushes.Red, -(textSize.Width / 2), -(textSize.Height / 2);
于 2012-06-08T18:34:59.387 に答える