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));
}
}
}