StrangeWorker's Blog

奇妙な労働者の雑記帳

ホーム 連絡をする 同期する ( RSS 2.0 ) Login
投稿数  18  : 記事  0  : コメント  117  : トラックバック  2

書庫

日記カテゴリ

image

見た目じゃない部分を修正したので、見た目は変わりません。

修正内容の肝は一つ前のブログのコメントでご指摘いただいた、Graphicsの開放と、

スレッドの制御部分です。以下に修正版を載せます。

using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Threading;
using System.Security.AccessControl;
 
namespace ConsoleApplication93
{
    class Program
    {
        private const int MAX_SIZE = 110;
        private const int DRAW_START = 40;
        private const int DIGITAL_TIME_TOP = 65;
        private const int FONT_SIZE = 15;
        private const int LONG_SCALE = 40;
        private const int SHORT_SCALE = 35;
        private const int SCALE_LENGTH = 45;
        private const int CIRCLE_WIDTH = 3;
        private const int WINDOW_HEIGHT = 10;
        private const int WINDOW_WIDTH = 24;
        private const string FONT_NAME = "MS ゴシック";
        private const string TIME_FORMAT = "HH:mm:ss";
 
        /// <summary>
        /// メイン
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            // ウィンドウサイズを適切に設定
            Console.WindowHeight = WINDOW_HEIGHT;
            Console.WindowWidth = WINDOW_WIDTH;
 
            // 時計描画スレッド
            var manualReset = new ManualResetEvent(false);
            var thread = new Thread(DrawClock);
            thread.Start(manualReset);
 
            while (true)
            {
                Console.Write("終了しますか?[Y/N] : ");
                if ("Y" == Console.ReadLine().ToUpper())
                {
                    manualReset.Set();
                    thread.Join();
                    break;
                }
                else
                {
                    Console.CursorTop = 0;
                    Console.Clear();
                }
            }
        }
 
        /// <summary>
        /// 時計描画
        /// </summary>
        static void DrawClock(object obj)
        {
            // コンソールのウィンドウハンドルから描画クラス取得
            var process = Process.GetProcesses().ToList().Where(p => p.MainWindowTitle == Console.Title).SingleOrDefault();
            using (var g = Graphics.FromHwnd(process.MainWindowHandle))
            {
                // チラつき防止のためのバッファ領域
                var msGothicFont = new Font(FONT_NAME, FONT_SIZE, FontStyle.Bold, GraphicsUnit.Pixel);
                var fontSize = g.MeasureString(string.Empty, msGothicFont);
                var bmp = new Bitmap(MAX_SIZE + CIRCLE_WIDTH, MAX_SIZE + CIRCLE_WIDTH + DIGITAL_TIME_TOP + Convert.ToInt32(fontSize.Height));
                using (var gBuffer = Graphics.FromImage(bmp))
                {
                    // 座標系の原点を変える
                    gBuffer.TranslateTransform((MAX_SIZE + CIRCLE_WIDTH) / 2, (MAX_SIZE + CIRCLE_WIDTH) / 2, MatrixOrder.Append);
 
                    var center = new Point(0, 0);
                    var r = MAX_SIZE / 2;
                    var manualReset = obj as WaitHandle; 
 
                    while (!manualReset.WaitOne(1000))
                    {
                        var time = DateTime.Now;
 
                        // 時計の部品を描画する
                        DrawClockBase(gBuffer, time);
                        DrawSecondLine(gBuffer, time, r, center);
                        DrawMinuteLine(gBuffer, time, r, center);
                        DrawHourLine(gBuffer, time, r, center);
 
                        // 実描画
                        g.DrawImage(bmp, new Point(DRAW_START, DRAW_START));
                    }
                    manualReset.Close();
                }
            }
        }
 
        /// <summary>
        /// 秒針描画
        /// </summary>
        /// <param name="gBuffer"></param>
        /// <param name="time"></param>
        /// <param name="r"></param>
        /// <param name="center"></param>
        private static void DrawSecondLine(Graphics gBuffer, DateTime time, int r, Point center)
        {
            using (var bluePen = new Pen(Color.AliceBlue, 1))
            {
                var secAng = 2.0f * Math.PI * time.Second / 60.0f;
                var secHandLength = Convert.ToInt32(0.9f * r);
                var secHand = new Point(Convert.ToInt32(secHandLength * Math.Sin(secAng)), Convert.ToInt32(-secHandLength * Math.Cos(secAng)));
                gBuffer.DrawLine(bluePen, center, secHand);
            }
        }
 
        /// <summary>
        /// 分針描画
        /// </summary>
        /// <param name="gBuffer"></param>
        /// <param name="time"></param>
        /// <param name="r"></param>
        /// <param name="center"></param>
        private static void DrawMinuteLine(Graphics gBuffer, DateTime time, int r, Point center)
        {
            using (var greenPen = new Pen(Color.LightGreen, 2))
            {
                var minAng = 2.0f * Math.PI * (time.Minute + time.Second / 60.0f) / 60.0f;
                var minHandLength = Convert.ToInt32(0.7f * r);
                var minHand = new Point(Convert.ToInt32(minHandLength * Math.Sin(minAng)), Convert.ToInt32(-minHandLength * Math.Cos(minAng)));
                gBuffer.DrawLine(greenPen, center, minHand);
            }
        }
 
        /// <summary>
        /// 時針描画
        /// </summary>
        /// <param name="gBuffer"></param>
        /// <param name="time"></param>
        /// <param name="r"></param>
        /// <param name="center"></param>
        private static void DrawHourLine(Graphics gBuffer, DateTime time, int r, Point center)
        {
            using (var redPen = new Pen(Color.LightPink, 2))
            {
                var hourAng = 2.0f * Math.PI * (time.Hour + time.Minute / 60.0f) / 12.0f;
                var hourHandLength = Convert.ToInt32(0.5f * r);
                var hourHand = new Point(Convert.ToInt32(hourHandLength * Math.Sin(hourAng)), Convert.ToInt32(-hourHandLength * Math.Cos(hourAng)));
                gBuffer.DrawLine(redPen, center, hourHand);
            }
        }
 
        /// <summary>
        /// 時計の針以外を描画
        /// </summary>
        /// <param name="g"></param>
        static void DrawClockBase(Graphics gBuffer, DateTime time)
        {
            // 外円
            DrawCircle(gBuffer);
 
            // 目盛り
            DrawScale(gBuffer);
 
            // デジタル時計
            DrawDigitalTime(gBuffer, time);
        }
 
        /// <summary>
        /// 外円描画
        /// </summary>
        /// <param name="gBuffer"></param>
        static void DrawCircle(Graphics gBuffer)
        {
            using (var circlePen = new Pen(Color.AliceBlue, CIRCLE_WIDTH))
            {
                gBuffer.Clear(Color.Black);
                gBuffer.FillEllipse(Brushes.AliceBlue, -2.5f, -2.5f, 5f, 5f);
                gBuffer.DrawEllipse(circlePen, -MAX_SIZE / 2, -MAX_SIZE / 2, MAX_SIZE, MAX_SIZE);
            }
        }
 
        /// <summary>
        /// 目盛り描画
        /// </summary>
        /// <param name="gBuffer"></param>
        static void DrawScale(Graphics gBuffer)
        {
            var msGothicFont = new Font(FONT_NAME, FONT_SIZE, FontStyle.Bold, GraphicsUnit.Pixel);
 
            using (var scalePen = new Pen(Color.Aqua, 1))
            {
                Enumerable.Range(1, 60).ToList().ForEach(i =>
                {
                    var angle = i * 6 * (Math.PI / 180);
 
                    // 見易いように5目盛りごとに長さを変える
                    var length = 0 == i % 5 ? SHORT_SCALE : LONG_SCALE;
                    var x = Convert.ToInt32(Math.Sin(angle) * length);
                    var y = -Convert.ToInt32(Math.Cos(angle) * length);
                    var x1 = Convert.ToInt32(Math.Sin(angle) * SCALE_LENGTH);
                    var y1 = -Convert.ToInt32(Math.Cos(angle) * SCALE_LENGTH);
                    gBuffer.DrawLine(scalePen, x, y, x1, y1);
 
                    // 5目盛りごとに数字を表示
                    if (0 == i % 5)
                    {
                        var timeText = (i / 5).ToString();
                        var fontSize = gBuffer.MeasureString(timeText, msGothicFont);
                        gBuffer.DrawString(timeText, msGothicFont, Brushes.White, new PointF(x1 - fontSize.Width / 2, y1 - fontSize.Height / 2));
                    }
                });
            }
        }
 
        /// <summary>
        /// デジタル時計描画
        /// </summary>
        /// <param name="gBuffer"></param>
        /// <param name="time"></param>
        static void DrawDigitalTime(Graphics gBuffer, DateTime time)
        {
            var msGothicFont = new Font(FONT_NAME, FONT_SIZE, FontStyle.Bold, GraphicsUnit.Pixel);
            var textSize = gBuffer.MeasureString(TIME_FORMAT, msGothicFont);
            gBuffer.DrawString(time.ToString(TIME_FORMAT), msGothicFont, Brushes.White, new PointF(-textSize.Width / 2, DIGITAL_TIME_TOP));
        }
    }
}

以上です。とっちゃんさんありがとうございました。

投稿日時 : 2009年3月11日 22:08

コメント

# re: コマンドプロンプトで動くアナログ時計を作る その2 2009/03/11 22:19 StrangeWorker
さらに修正

using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Threading;
using System.Security.AccessControl;

namespace ConsoleApplication93
{
  class Program
  {
    private const int MAX_SIZE = 110;
    private const int DRAW_START = 40;
    private const int DIGITAL_TIME_TOP = 65;
    private const int FONT_SIZE = 15;
    private const int LONG_SCALE = 40;
    private const int SHORT_SCALE = 35;
    private const int SCALE_LENGTH = 45;
    private const int CIRCLE_WIDTH = 3;
    private const int WINDOW_HEIGHT = 10;
    private const int WINDOW_WIDTH = 24;
    private const string FONT_NAME = "MS ゴシック";
    private const string TIME_FORMAT = "HH:mm:ss";

    /// <summary>
    /// メイン
    /// </summary>
    /// <param name="args"></param>
    static void Main(string[] args)
    {
      // ウィンドウサイズを適切に設定
      Console.WindowHeight = WINDOW_HEIGHT;
      Console.WindowWidth = WINDOW_WIDTH;

      // 時計描画スレッド
      var manualReset = new ManualResetEvent(false);
      var thread = new Thread(DrawClock);
      thread.Start(manualReset);

      while (true)
      {
        Console.Write("終了しますか?[Y/N] : ");
        if ("Y" == Console.ReadLine().ToUpper())
        {
          manualReset.Set();
          thread.Join();
          break;
        }
        else
        {
          Console.CursorTop = 0;
          Console.Clear();
        }
      }
    }

    /// <summary>
    /// 時計描画
    /// </summary>
    /// <param name="obj"></param>
    static void DrawClock(object obj)
    {
      // コンソールのウィンドウハンドルから描画クラス取得
      var process = Process.GetProcesses().ToList().Where(p => p.MainWindowTitle == Console.Title).SingleOrDefault();
      using (var g = Graphics.FromHwnd(process.MainWindowHandle))
      using (var msGothicFont = new Font(FONT_NAME, FONT_SIZE, FontStyle.Bold, GraphicsUnit.Pixel))
      {
        // チラつき防止のためのバッファ領域
        var fontSize = g.MeasureString(string.Empty, msGothicFont);
        var bmp = new Bitmap(MAX_SIZE + CIRCLE_WIDTH, MAX_SIZE + CIRCLE_WIDTH + DIGITAL_TIME_TOP + Convert.ToInt32(fontSize.Height));
        using (var gBuffer = Graphics.FromImage(bmp))
        {
          // 座標系の原点を変える
          gBuffer.TranslateTransform((MAX_SIZE + CIRCLE_WIDTH) / 2, (MAX_SIZE + CIRCLE_WIDTH) / 2, MatrixOrder.Append);

          var center = new Point(0, 0);
          var r = MAX_SIZE / 2;
          var manualReset = obj as WaitHandle;

          while (!manualReset.WaitOne(1000))
          {
            var time = DateTime.Now;

            // 時計の部品を描画する
            DrawClockBase(gBuffer, time);
            DrawSecondLine(gBuffer, time, r, center);
            DrawMinuteLine(gBuffer, time, r, center);
            DrawHourLine(gBuffer, time, r, center);

            // 実描画
            g.DrawImage(bmp, new Point(DRAW_START, DRAW_START));
          }
          manualReset.Close();
        }
      }
    }

    /// <summary>
    /// 秒針描画
    /// </summary>
    /// <param name="gBuffer"></param>
    /// <param name="time"></param>
    /// <param name="r"></param>
    /// <param name="center"></param>
    private static void DrawSecondLine(Graphics gBuffer, DateTime time, int r, Point center)
    {
      using (var bluePen = new Pen(Color.AliceBlue, 1))
      {
        var secAng = 2.0f * Math.PI * time.Second / 60.0f;
        var secHandLength = Convert.ToInt32(0.9f * r);
        var secHand = new Point(Convert.ToInt32(secHandLength * Math.Sin(secAng)), Convert.ToInt32(-secHandLength * Math.Cos(secAng)));
        gBuffer.DrawLine(bluePen, center, secHand);
      }
    }

    /// <summary>
    /// 分針描画
    /// </summary>
    /// <param name="gBuffer"></param>
    /// <param name="time"></param>
    /// <param name="r"></param>
    /// <param name="center"></param>
    private static void DrawMinuteLine(Graphics gBuffer, DateTime time, int r, Point center)
    {
      using (var greenPen = new Pen(Color.LightGreen, 2))
      {
        var minAng = 2.0f * Math.PI * (time.Minute + time.Second / 60.0f) / 60.0f;
        var minHandLength = Convert.ToInt32(0.7f * r);
        var minHand = new Point(Convert.ToInt32(minHandLength * Math.Sin(minAng)), Convert.ToInt32(-minHandLength * Math.Cos(minAng)));
        gBuffer.DrawLine(greenPen, center, minHand);
      }
    }

    /// <summary>
    /// 時針描画
    /// </summary>
    /// <param name="gBuffer"></param>
    /// <param name="time"></param>
    /// <param name="r"></param>
    /// <param name="center"></param>
    private static void DrawHourLine(Graphics gBuffer, DateTime time, int r, Point center)
    {
      using (var redPen = new Pen(Color.LightPink, 2))
      {
        var hourAng = 2.0f * Math.PI * (time.Hour + time.Minute / 60.0f) / 12.0f;
        var hourHandLength = Convert.ToInt32(0.5f * r);
        var hourHand = new Point(Convert.ToInt32(hourHandLength * Math.Sin(hourAng)), Convert.ToInt32(-hourHandLength * Math.Cos(hourAng)));
        gBuffer.DrawLine(redPen, center, hourHand);
      }
    }

    /// <summary>
    /// 時計の針以外を描画
    /// </summary>
    /// <param name="g"></param>
    static void DrawClockBase(Graphics gBuffer, DateTime time)
    {
      // 外円
      DrawCircle(gBuffer);

      // 目盛り
      DrawScale(gBuffer);

      // デジタル時計
      DrawDigitalTime(gBuffer, time);
    }

    /// <summary>
    /// 外円描画
    /// </summary>
    /// <param name="gBuffer"></param>
    static void DrawCircle(Graphics gBuffer)
    {
      using (var circlePen = new Pen(Color.AliceBlue, CIRCLE_WIDTH))
      {
        gBuffer.Clear(Color.Black);
        gBuffer.FillEllipse(Brushes.AliceBlue, -2.5f, -2.5f, 5f, 5f);
        gBuffer.DrawEllipse(circlePen, -MAX_SIZE / 2, -MAX_SIZE / 2, MAX_SIZE, MAX_SIZE);
      }
    }

    /// <summary>
    /// 目盛り描画
    /// </summary>
    /// <param name="gBuffer"></param>
    static void DrawScale(Graphics gBuffer)
    {
      using (var msGothicFont = new Font(FONT_NAME, FONT_SIZE, FontStyle.Bold, GraphicsUnit.Pixel))
      using (var scalePen = new Pen(Color.Aqua, 1))
      {
        Enumerable.Range(1, 60).ToList().ForEach(i =>
        {
          var angle = i * 6 * (Math.PI / 180);

          // 見易いように5目盛りごとに長さを変える
          var length = 0 == i % 5 ? SHORT_SCALE : LONG_SCALE;
          var x = Convert.ToInt32(Math.Sin(angle) * length);
          var y = -Convert.ToInt32(Math.Cos(angle) * length);
          var x1 = Convert.ToInt32(Math.Sin(angle) * SCALE_LENGTH);
          var y1 = -Convert.ToInt32(Math.Cos(angle) * SCALE_LENGTH);
          gBuffer.DrawLine(scalePen, x, y, x1, y1);

          // 5目盛りごとに数字を表示
          if (0 == i % 5)
          {
            var timeText = (i / 5).ToString();
            var fontSize = gBuffer.MeasureString(timeText, msGothicFont);
            gBuffer.DrawString(timeText, msGothicFont, Brushes.White, new PointF(x1 - fontSize.Width / 2, y1 - fontSize.Height / 2));
          }
        });
      }
    }

    /// <summary>
    /// デジタル時計描画
    /// </summary>
    /// <param name="gBuffer"></param>
    /// <param name="time"></param>
    static void DrawDigitalTime(Graphics gBuffer, DateTime time)
    {
      using (var msGothicFont = new Font(FONT_NAME, FONT_SIZE, FontStyle.Bold, GraphicsUnit.Pixel))
      {
        var textSize = gBuffer.MeasureString(TIME_FORMAT, msGothicFont);
        gBuffer.DrawString(time.ToString(TIME_FORMAT), msGothicFont, Brushes.White, new PointF(-textSize.Width / 2, DIGITAL_TIME_TOP));
      }
    }
  }
}

# NaSYCSskrBdqObOezbm 2022/04/19 14:02 johnanz
http://imrdsoacha.gov.co/silvitra-120mg-qrms

Post Feedback

タイトル
名前
Url:
コメント: