// ----------------------------------------
// Демонстрация стилей окна
// ----------------------------------------

#define STRICT
#include <windows.h>
#include <windowsx.h>
#include <mem.h>

// Прототипы функций

BOOL Register(HINSTANCE);
LRESULT CALLBACK _export MainWndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK _export ChildWndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK _export PopUpWndProc(HWND, UINT, WPARAM, LPARAM);

// Имя класса для главного окна приложения
char const szMainClassName[]    = "WStyleAppClass";

// Имя класса для дочерних окон
char const szChildClassName[]   = "WStyleAppChildClass";

// Имя класса для временных окон
char const szPopUpClassName[]   = "WStyleAppPopUpClass";

// Заголовок главного окна приложения
char const szMainWindowTitle[]  = "WStyle Application";

// Заголовок дочернего окна
char const szChildWindowTitle[] = "Окно Child";

// Заголовок временного окна
char const szPopUpWindowTitle[] = "Окно PopUp";

// =====================================
// Функция WinMain
// =====================================
#pragma argsused

int PASCAL
WinMain(HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR     lpszCmdLine,
	int       nCmdShow)
{
  MSG  msg;
  HWND MainHwnd;   // идентификатор главного окна приложения
  HWND ChildHwnd;  // идентификатор дочернего окна
  HWND PopUpHwnd;  // идентификатор временного окна
  HWND OwnedHwnd;  // идентификатор окна, которым владеет
                   // главное окно приложения

  // Регистрируем классы окон
  if(!Register(hInstance))
      return FALSE;

  // Создаем главное окно приложения
  MainHwnd = CreateWindow(
    szMainClassName,     // имя класса окна
    szMainWindowTitle,   // заголовок окна
    WS_OVERLAPPEDWINDOW, // стиль окна
    CW_USEDEFAULT,       // задаем размеры и расположение
    CW_USEDEFAULT,       // окна, принятые по умолчанию 
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    0,                   // идентификатор родительского окна
    0,                   // идентификатор меню
    hInstance,           // идентификатор приложения
    NULL);               // указатель на дополнительные
			 // параметры

  // Если создать окно не удалось, завершаем приложение
  if(!MainHwnd)
    return FALSE;

  // Делаем окно видимым
  ShowWindow(MainHwnd, nCmdShow);

  // Посылаем в окно сообщение WM_PAINT
  UpdateWindow(MainHwnd);

  // Создаем перекрывающееся окно, которое
  // принадлежит главному окну приложения
  OwnedHwnd = CreateWindow(
    szMainClassName,        // имя класса окна
    "Перекрывающееся окно", // заголовок окна
    WS_OVERLAPPEDWINDOW,    // стиль окна
    20,                     // задаем размеры и расположение
    200,                    // окна
    300,
    100,
    MainHwnd,            // идентификатор родительского окна
    0,                   // идентификатор меню
    hInstance,           // идентификатор приложения
    NULL);               // указатель на дополнительные
			 // параметры

  // Если создать окно не удалось, завершаем приложение
  if(!OwnedHwnd)
    return FALSE;

  // Делаем окно видимым
  ShowWindow(OwnedHwnd, nCmdShow);

  // Посылаем в окно сообщение WM_PAINT
  UpdateWindow(OwnedHwnd);

  // Создаем дочернее окно
  ChildHwnd = CreateWindow(
    szChildClassName,     // имя класса окна
    "Дочернее окно",      // заголовок окна
    WS_CHILDWINDOW | WS_VISIBLE |
    WS_CAPTION,           // стиль окна
    300,                  // задаем размеры и расположение
    20,                   // окна
    200,
    100,
    MainHwnd,            // идентификатор родительского окна
    0,                   // идентификатор меню
    hInstance,           // идентификатор приложения
    NULL);               // указатель на дополнительные
			 // параметры

  // Если создать окно не удалось, завершаем приложение
  if(!ChildHwnd)
    return FALSE;

  // Создаем временное окно
  PopUpHwnd = CreateWindow(
    szPopUpClassName,       // имя класса окна
    "Временное окно",      // заголовок окна
    WS_POPUPWINDOW | WS_CAPTION | WS_VISIBLE,  // стиль окна
    100,                    // задаем размеры и расположение
    100,                    // окна
    200,
    100,
    MainHwnd,            // идентификатор родительского окна
    0,                   // идентификатор меню
    hInstance,           // идентификатор приложения
    NULL);               // указатель на дополнительные
			 // параметры

  // Если создать окно не удалось, завершаем приложение
  if(!PopUpHwnd)
    return FALSE;

  // Запускаем цикл обработки сообщений
  while(GetMessage(&msg, 0, 0, 0))
  {
    DispatchMessage(&msg);
  }
  return msg.wParam;
}

// =====================================
// Функция Register
// Выполняет регистрацию классов окна,
// используемых приложением
// =====================================

BOOL
Register(HINSTANCE hInstance)
{
  ATOM aWndClass; // атом для кода возврата
  WNDCLASS wc;    // структура для регистрации
                  // класса окна

  memset(&wc, 0, sizeof(wc));

// --------------------------------------------------
// Регистрируем класс окна для главного
// и перекрывающегося окна
// --------------------------------------------------
  wc.style = 0;
  wc.lpfnWndProc   = (WNDPROC) MainWndProc;
  wc.cbClsExtra    = 0;
  wc.cbWndExtra    = 0;
  wc.hInstance     = hInstance;
  wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
  wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  wc.lpszMenuName  = (LPSTR)NULL;
  wc.lpszClassName = (LPSTR)szMainClassName;

  aWndClass = RegisterClass(&wc);
  if(aWndClass == 0) return FALSE;

// --------------------------------------------------
// Регистрируем класс окна для 
// дочернего окна
// --------------------------------------------------

  wc.lpfnWndProc   = (WNDPROC) ChildWndProc;
  wc.hCursor       = LoadCursor(NULL, IDC_SIZE);
  wc.hbrBackground = GetStockBrush(GRAY_BRUSH);
  wc.lpszClassName = (LPSTR)szChildClassName;

  aWndClass = RegisterClass(&wc);
  if(aWndClass == 0) return FALSE;

// --------------------------------------------------
// Регистрируем класс окна для
// временного окна
// --------------------------------------------------

  wc.lpfnWndProc   = (WNDPROC) PopUpWndProc;
  wc.hCursor       = LoadCursor(NULL, IDC_CROSS);
  wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  wc.lpszClassName = (LPSTR)szPopUpClassName;

  aWndClass = RegisterClass(&wc);
  if(aWndClass == 0) return FALSE;

  return TRUE;
}

// =====================================
// Функция MainWndProc
// Используется главным окном приложения
// и созданным дополнительно
// перекрывающимся окном 
// =====================================

LRESULT CALLBACK _export
MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  HDC hdc;             // индекс контекста устройства
  PAINTSTRUCT ps;      // структура для рисования

  switch (msg)
  {
    case WM_PAINT:
    {
      hdc = BeginPaint(hwnd, &ps);
      TextOut(hdc, 10, 20, "WM_PAINT", 8);
      EndPaint(hwnd, &ps);
      return 0;
    }

    case WM_LBUTTONDOWN:
    {
      hdc = GetDC(hwnd);
      TextOut(hdc, 10, 40, "WM_LBUTTONDOWN", 14);
      ReleaseDC(hwnd, hdc);
      return 0;
    }

    case WM_DESTROY:
    {
      PostQuitMessage(0);
      return 0;
    }
  }
  return DefWindowProc(hwnd, msg, wParam, lParam);
}

// =====================================
// Функция ChildWndProc
// Используется дочерним окном
// =====================================

LRESULT CALLBACK _export
ChildWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  HDC hdc;             // индекс контекста устройства
  PAINTSTRUCT ps;      // структура для рисования

  switch (msg)
  {
    case WM_PAINT:
    {
      hdc = BeginPaint(hwnd, &ps);
      TextOut(hdc, 10, 20, "WM_PAINT", 8);
      EndPaint(hwnd, &ps);
      return 0;
    }

    case WM_LBUTTONDOWN:
    {
      hdc = GetDC(hwnd);
      TextOut(hdc, 10, 40, "WM_LBUTTONDOWN", 14);
      ReleaseDC(hwnd, hdc);
      return 0;
    }

    case WM_RBUTTONDOWN:
      {
	MessageBeep(-1); // звуковой сигнал
	return 0;
      }
  }
  return DefWindowProc(hwnd, msg, wParam, lParam);
}

// =====================================
// Функция PopUpWndProc
// Используется временным окном
// =====================================

LRESULT CALLBACK _export
PopUpWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  HDC hdc;             // индекс контекста устройства
  PAINTSTRUCT ps;      // структура для рисования

  switch (msg)
  {
    case WM_PAINT:
    {
      hdc = BeginPaint(hwnd, &ps);
      TextOut(hdc, 10, 20, "WM_PAINT", 8);
      EndPaint(hwnd, &ps);
      return 0;
    }

    case WM_LBUTTONDOWN:
    {
      hdc = GetDC(hwnd);
      TextOut(hdc, 10, 40, "WM_LBUTTONDOWN", 14);
      ReleaseDC(hwnd, hdc);
      return 0;
    }
  }
  return DefWindowProc(hwnd, msg, wParam, lParam);
}
