Сайт разработчика Александр Климова

/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000

Обратный отсчет

Перед наступлением долгожданных праздников, например, Нового года, возникает желание считать, сколько дней осталось до этого события. А может даже часов, минут или секунд! Смотреть каждый день на календарь и вручную считать дни, согласитесь, не совсем удобно. Нам нужно написать приложение, которое само будет считать, сколько времени осталось до нужного события, и тогда мы не пропустим праздник! Давайте попробуем написать программку, которая будет находиться в области уведомлений и показывать оставшееся время во всплывающей подсказке, а также опционально будем выводить обратный отсчет на экране.

Использовать стандартное окно с обычным заголовком, кнопками сворачивания/закрытия окна и границами не слишком заманчиво. Вместо этого мы попробуем создать нестандартное окно. Как любое приложение, работающее из области уведомлений, при наведении мышкой на значок, у нас будет выводиться имя приложения и, конечно, обратный отсчет. Правый щелчок на значке вызывает контекстное меню с командами настройки приложения или ее закрытия.

Начнем с дизайна главного окна. Уберем кнопки Свернуть/Развернуть/Закрыть, установив значения свойства ControlBox в значение false. Чтобы убрать заголовок у окна, присвоим свойству Text пустую строку. Чтобы убрать границы у окна, нужно установить в свойстве FormBorderStyle значение None. Таким образом, мы получили небольшое окно для нашего приложения. Тут нас подстерегают две проблемы. Первая – мы не можем закрыть программу, и вторая – мы не можем двигать форму мышкой. Первая задача решается при помощи команды контекстного меню, которая будет у значка в области уведомлений. Вторая задача немного сложнее.

На самом деле перемещать форму по экрану не так сложно, просто это придется делать самому, а не полагаться на систему. Для этой цели нам нужно ловить два события: MouseDown и MouseMove. В событии MouseDown мы должны получить координаты мыши, затем для каждого события MouseMove мы устанавливаем новую позицию формы, вычисляя перемещение мыши. Иными словами, если мы щелкнули мышкой в точке (0, 0), затем событие движения сработало в координатах (10,10), то мы должны переместить форму из первоначальной позиции на +10 единиц по оси x и на +10 единиц по оси y. Смотрим код:


// Class-level declaration
private Point mouseOffset; 

...

private void countdownLabel_MouseDown(object sender, MouseEventArgs e)
{
    mouseOffset = new Point(-e.X, -e.Y);
}

private void countdownLabel_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        Point mousePos = Control.MousePosition;

        if (constrainToRight)
        {
            this.Top = Control.MousePosition.Y + mouseOffset.Y;
        }
        else
        {
            mousePos.Offset(mouseOffset.X, mouseOffset.Y);
            this.Location = mousePos;
        }
    }
}

Вы можете отслеживать события мыши из самой формы или любого элемента управления. В нашем случае форма содержит метку Label, в котором отображается строка с обратным отсчетом. Сделаем форму невидимой, оставив на экране только метку Label. Установите в свойстве TransparencyKey значение Control, и основное окно исчезнет. Не правда ли, как просто добиться такого интересного эффекта. Представьте, что в качестве фона формы вы используете замысловатую фигуру. С помощью этого эффекта вы можете получить окно приложения интересной формы.

Два дополнительных эффекта позволят приложению находиться поверх всех окон и иметь различную степень прозрачности. Устанавливая свойство TopMost в true, мы делаем окно приложения поверх всех окон. Это особенно удобно, когда мы будем пытаться двигать форму. Если наша форма будет полностью прозрачной, то необходимо щелкнуть точно на черные пиксели текста в метке. Это достаточно тяжело, если форма не будет находиться всегда поверх всех окон. Сама прозрачность формы может регулироваться от 0 до 100 при помощи свойства Opacity.

Наконец, пора заняться реализацией обратного отсчета при помощи таймера, который тикает каждую секунду. В событии Tick текущая дата сравнивается с заданной датой. Если нужная дата достигнута, то на экран выводится предупреждение в виде системной всплывающей подсказки. В остальных случаях выводится строка, состоящая из количества дней, часов, минут и секунд до события. Эта задача решается при помощи метода Append объекта StringBuilder.

Приложение готово. Вы можете добавить звуковые эффекты, картинки и другие возможности, чтобы улучшить программу.

Скачать пример

Перевод: Александр Климов

Реклама