Главная Посты Курсы Связь О сайте

Аналоговые часы на C#



Привет! Сегодня сделаем аналоговые часы на языке программировании C#.


Запускаем Visual Studio. Выбираем Создание проекта->Приложение Windows Forms (.NET Framework)->Создать.


Для самого окна сделаем размер: 350px на 350px в окне свойств.



Размер окна для аналоговых часов



Свойство FormBorderStyle для окна формы поставим в значение None, чтобы убрать границу у окна нашей программы.


Добавим на форму из Панели элементов PictureBox. Поставим так же размеры для PictureBox 350 и 350.


Свойство SizeMode для PictureBox установим в Zoom. Это растянет нашу картинку на всё окно формы. Свойство Dock установим в Fill. Это означает, что наша картинка будет размещена по центру окна формы.


Уже можно загрузить саму картинку циферблата. Будем использовать вот это изображение формата gif:



Циферблат для аналоговых часов на C#

Загружаем данное изображение в свойство Image для PictureBox. Выбираем Локальный ресурс->Импорт.


Теперь, если мы запустим наш проект, то мы увидим, что мы не можем переносить мышкой наше окно. Чтобы исправить ситуацию, заходим в код нашей программы, нажав клавишу F7.


Настраиваем перемещение окна с помощью мыши.


C помощью команды using подключим пространство имён System.Runtime.InteropServices


...
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.Runtime.InteropServices; // Подключаем новое пространство имён
...

Подключаем функции из библиотеки user32.dll, которые помогут нам переносить окно с помощью мышки, кликая в любой точки этого окна.


...

    public partial class Form1 : Form
    {
        [DllImport("user32", CharSet = CharSet.Auto)]
        internal extern static bool PostMessage(IntPtr hWnd, uint Msg, uint WParam, uint LParam);

        [DllImport("user32", CharSet = CharSet.Auto)]
        internal extern static bool ReleaseCapture();

...


А так же подключим обработчик события MouseDown (нажатия клавиши мыши) для нашей PictureBox. Кликаем на вкладку конструктор, выбираем в свойствах именно форму и нажимаем кнопку со значком молния. Там ищем событие MouseDown и кликаем два раза на поле, которое напротив слова MouseDown.



Событие MouseDown на C#

В появившийся функции обработчика события пропишем следующий код:


private void PictureBox1_MouseDown(object sender, MouseEventArgs e)
{
   const uint WM_SYSCOMMAND = 0x0112;
   const uint DOMOVE = 0xF012;

   ReleaseCapture();
   PostMessage(this.Handle, WM_SYSCOMMAND, DOMOVE, 0);
}

Запустим программу и увидим, что теперь можно перемещать окно, кликая по любой точке картинки.




Настраиваем прозрачность окна.


Чтобы у нас была только картинка циферблата, и не было видно самого окна, настроим прозрачность окна.


Пропишем код:


...
public Form1()
        {
            InitializeComponent();

            this.BackColor = Color.AliceBlue;  
            this.TransparencyKey = this.BackColor;
...

Прозрачность окна на C#

Формируем таймер и стрелки.


Заведём необходимые переменные:


...
    public partial class Form1 : Form
    {
        int cx = 175, cy = 175; // Центр картинки.

        int secHAND = 100, minHAND = 90, hrHAND = 75;

        Timer t = new Timer();
...

secHAND, minHAND, hrHAND - это длина в пикселях секундной стрелки, минутной и часовой соответственно.


Так же завели таймер t.


Перейдём в обработчик события Load (загрузка) для самой формы (по аналогии, как мы делали обработчик события MouseDown).


Настроим таймер:


private void Form1_Load(object sender, EventArgs e)
{
    t.Interval = 1000;  //В миллисекундах
    t.Tick += new EventHandler(this.t_Tick);
    t.Start();
}

Теперь каждую секунду будет запускаться функция t_Tick(), которую мы пропишем ниже.


Стрелки будут идти от центра картинки. Центр имеет координаты x=175 (350/2), y=175 (350/2). Начало координат находится в верхнем левом углу.


Напишем функцию msCoord, которая будет получать количество секунд (или минут) и длину стрелки, а возвращать координаты конца секундной(минутной) стрелки.


private int[] msCoord(int val, int hlen)
{
    int[] coord = new int[2];
    val *= 6;  

    if (val >= 0 && val <= 180)
    {
        coord[0] = cx + (int)(hlen * Math.Sin(Math.PI * val / 180));
        coord[1] = cy - (int)(hlen * Math.Cos(Math.PI * val / 180));
    }
    else
    {
        coord[0] = cx - (int)(hlen * -Math.Sin(Math.PI * val / 180));
        coord[1] = cy - (int)(hlen * Math.Cos(Math.PI * val / 180));
    }
    return coord;
}

При отклонении на 1 секунду (или минуту), стрелка отклоняется на 6 градусов (360/60). В начале, функция узнаёт на сколько градусов отклоняется стрелка от начального положения (цифры 12).



Координаты стрелок аналоговых часов на С#

Если прошло 5 секунд, стрелка отклонилась на 30 градусов. Тогда координата x=cx+l*sin(30), a y=cy-l*cos(30), где l-длина стрелки, cx и cy - центр картинки. Градусы нужно указывать в радианах (умножаем на пи и делим на 180 градусов угол отклонения).


В функции так же учтены знаки для синуса и косинуса для разных четвертей окружности. Так же учтено, когда нужно вычитать от сx и cy, а когда прибавлять.


Напишем функцию для получения координат конца часовой стрелки.


private int[] hrCoord(int hval, int mval, int hlen)
{
    int[] coord = new int[2];
    int val = (int)((hval * 30) + (mval * 0.5)); 

    if (val >= 0 && val <= 180)
    {
        coord[0] = cx + (int)(hlen * Math.Sin(Math.PI * val / 180));
        coord[1] = cy - (int)(hlen * Math.Cos(Math.PI * val / 180));
    }
    else
    {
        coord[0] = cx - (int)(hlen * -Math.Sin(Math.PI * val / 180));
        coord[1] = cy - (int)(hlen * Math.Cos(Math.PI * val / 180));
    }
    return coord;
}

Эта функция принимает и часы и минуты. Для часовой стрелки: 1 час - это 30 градусов (360/12), а одна минута - это 0.5 градусов.


1 час - 30 градусов
1/60 часа (1 минута) - x градусов

x = 1/60*30 = 0.5 градусов.

В остальном работает так же, как предыдущая функция.


Напишем главную функцию t_Tick.


private void t_Tick(object sender, EventArgs e)
{
    //Берём время.
    int s = DateTime.Now.Second;
    int m = DateTime.Now.Minute;
    int h = DateTime.Now.Hour;

    int[] handCoord = new int[2];

    Graphics g = pictureBox1.CreateGraphics();

    // Стираем предыдущее положения секундной стрелки
    handCoord = msCoord(s, secHAND + 4);
    g.DrawLine(new Pen(Color.White, 45f), new Point(cx, cy), new Point(handCoord[0], handCoord[1]));

    // Стираем предыдущее положение минутной стрелки
    handCoord = msCoord(m, minHAND + 4);
    g.DrawLine(new Pen(Color.White, 40f), new Point(cx, cy), new Point(handCoord[0], handCoord[1]));

    // Стираем предыдущее положение часовой стрелки
    handCoord = hrCoord(h % 12, m, hrHAND + 4);
    g.DrawLine(new Pen(Color.White, 20f), new Point(cx, cy), new Point(handCoord[0], handCoord[1]));


    //Отрисовка стрелки часов.
    handCoord = hrCoord(h % 12, m, hrHAND);
    g.DrawLine(new Pen(Color.Gray, 4f), new Point(cx, cy), new Point(handCoord[0], handCoord[1]));


    //Отрисовка минутной стрелки
    handCoord = msCoord(m, minHAND);
    g.DrawLine(new Pen(Color.Black, 2f), new Point(cx, cy), new Point(handCoord[0], handCoord[1]));

    // Отрисовка секундной стрелки.
    handCoord = msCoord(s, secHAND);
    g.DrawLine(new Pen(Color.DarkOrange, 2f), new Point(cx, cy), new Point(handCoord[0], handCoord[1]));
}

В начале функции берём системное время (часы, минуты, секунды). Создаём объект g типа Graphics, который позволит рисовать на нашей картинке (циферблате).


Узнаём координаты для секундной, минутной и часовой стрелки, и в начале проводим "толстые линии" белого цвета, которые должны стереть предыдущее изображение стрелок. Т.к для линий подобрана нужная толщина, то получается полностью закрасить предыдущее положение стрелок.


Функция DrawLine в C#

Затем уже, рисуем линии стрелок часов с нормальной толщиной и нужными нами цветами.


Каждую секунду стрелки прорисовываются заново. Для часов подставляем остаток от деления на 12 (h % 12), чтобы учесть, что 22-это 10 часов.


Аналоговые часы на C#

На этом всё! Будьте здоровы!


Скачать проект




06-08-2021 в 10:09:51






Оставить коментарий:



Напишите email, чтобы получать сообщения о новых комментариях (необязательно):


Задача против робота. Расположите картинки горизонтально: