#define STRICT
#include <windows.h>
#include <time.h>

// Идентификатор таймера, который используется
// для измерения времени
#define CLOCK_TIMER 1

// Прототип функции таймера
void CALLBACK _export TimerProc(HWND, UINT, UINT, DWORD);

// Переменная для хранения идентификатора таймера,
// который используется для выдачи звукового сигнала
int nBeepTimerID;

// Внешние переменные
extern TEXTMETRIC tm;
extern int cxChar, cyChar;

// =====================================
// Функция WndProc
// =====================================

LRESULT CALLBACK _export
WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  HDC        hdc;
  PAINTSTRUCT ps;

  switch (msg)
  {
    case WM_CREATE:
    {
      // Создаем таймер, посылающий сообщения
      // функции окна примерно раз в секунду
      SetTimer(hwnd, CLOCK_TIMER, 1000, NULL);

      // Создаем таймер, который периодически
      // раз в секунду посылает сообщения в
      // функцию таймера TimerProc
      nBeepTimerID = SetTimer(hwnd, 0,  1000,
          (TIMERPROC)TimerProc);

      hdc = GetDC(hwnd);

      // Выбираем шрифт с фиксированной шириной букв
      SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));

      // Заполняем структуру информацией
      // о метрике шрифта, выбранного в
      // контекст отображения
      GetTextMetrics(hdc, &tm);

      // Запоминаем значение ширины для
      // самого широкого символа
      cxChar = tm.tmMaxCharWidth;

      // Запоминаем значение высоты букв с
      // учетом межстрочного интервала
      cyChar = tm.tmHeight + tm.tmExternalLeading;

      ReleaseDC(hwnd, hdc);
      return 0;
    }

    // Для обеспечения возможности перемещения
    // окна, не имеющего заголовка, встраиваем
    // свой обработчик сообщения WM_NCHITTEST
    case WM_NCHITTEST:
    {
      long lRetVal;

      // Вызываем функцию DefWindowProc и проверяем
      // возвращаемое ей значение
      lRetVal = DefWindowProc(hwnd, msg, wParam, lParam);

      // Если курсор мыши находится на одном из
      // элементов толстой рамки, предназначенной
      // для изменения размера окна, возвращаем
      // неизмененное значение, полученное от
      // функции DefWindowProc
      if(lRetVal == HTLEFT        ||
	 lRetVal == HTRIGHT       ||
	 lRetVal == HTTOP         ||
	 lRetVal == HTBOTTOM      ||
	 lRetVal == HTBOTTOMRIGHT ||
	 lRetVal == HTTOPRIGHT    ||
	 lRetVal == HTTOPLEFT     ||
	 lRetVal == HTBOTTOMLEFT)
      {
	return lRetVal;
      }

      // В противном случае возвращаем значение
      // HTCAPTION, которое соответствует
      // заголовку окна.
      else
      {
	return HTCAPTION;
      }
    }

    // Каждую секунду перерисовываем
    // внутреннюю область окна
    case WM_TIMER:
    {
       InvalidateRect(hwnd, NULL, FALSE);
       return 0;
    }

    case WM_DESTROY:
    {
      // Перед уничтожением окна уничтожаем
      // созданные ранее таймеры
      KillTimer(hwnd, CLOCK_TIMER);
      KillTimer(hwnd, nBeepTimerID);

      PostQuitMessage(0);
      return 0;
    }

    case WM_PAINT:
    {
      BYTE   szBuf[80];
      int    nBufSize;
      time_t t;
      struct tm *ltime;
      RECT    rc;

      hdc = BeginPaint(hwnd, &ps);

      // Определяем время и его отдельные компоненты
      time(&t);
      ltime = localtime(&t);

      // Подготавливаем буфер, заполняя его
      // строкой с текущим временем
      nBufSize = wsprintf(szBuf, "%02d:%02d:%02d",
	ltime->tm_hour,
	ltime->tm_min,
	ltime->tm_sec);

      // Выбираем шрифт с фиксированной шириной букв
      SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));

      // Получаем координаты и размер окна
      GetClientRect(hwnd, &rc);

      // Выводим время в центре окна
      DrawText(hdc, (LPSTR)szBuf, nBufSize, &rc,
	       DT_CENTER | DT_VCENTER | DT_NOCLIP | DT_SINGLELINE);

      EndPaint(hwnd, &ps);
    }
  }
  return DefWindowProc(hwnd, msg, wParam, lParam);
}

// =====================================
// Функция TimerProc
// =====================================
#pragma argsused
void CALLBACK _export
TimerProc(HWND hwnd, UINT msg, UINT idTimer, DWORD dwTime)
{
  // Просто выдаем звуковой сигнал
  MessageBeep(-1);
  return;
}

