#include <windows.h>
#include <windowsx.h>
#include "resource.h"

// -----------------------------------------------------
// Описание функций
// -----------------------------------------------------

// Функция главного окна
LRESULT WINAPI
WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

// Функция для обработки сообщения WM_CREATE
BOOL WndProc_OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct);

// Функция для обработки сообщения WM_LBUTTONDOWN
void WndProc_OnLButtonDown(HWND hWnd, BOOL fDoubleClick, 
  int x, int y, UINT keyFlags);

// Функция для обработки сообщения WM_DESTROY
void WndProc_OnDestroy(HWND hWnd);

// -----------------------------------------------------
// Глобальные переменные
// -----------------------------------------------------

// Идентификатор приложения
HINSTANCE hInst;

// Название приложения
char szAppName[] = "Window";

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

// -----------------------------------------------------
// Функция WinMain
// -----------------------------------------------------
int APIENTRY 
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
        LPSTR lpCmdLine, int nCmdShow)
{
  WNDCLASSEX wc;
  HWND hWnd;
  MSG msg;
  
  hInst = hInstance;

  // Преверяем, не было ли это приложение запущено ранее
  hWnd = FindWindow(szAppName, NULL);
  if(hWnd)
  {
  	// Если окно приложения было свернуто в пиктограмму,
	// восстанавливаем его
    if(IsIconic(hWnd))
	  ShowWindow(hWnd, SW_RESTORE);

	// Выдвигаем окно приложения на передний план
	SetForegroundWindow(hWnd);
    return FALSE;
  }

  // Регистрируем класс окна
  memset(&wc, 0, sizeof(wc));
  
  // Поля wc.cbSize	и wc.hIconSm определены в структуре
  // WNDCLASSEX, которой можно пользоваться для
  // регистрации класса окна в Windows 95
  wc.cbSize = sizeof(WNDCLASSEX);

  // Поле wc.hIconSm задает идентификатор маленькой
  // пиктограммы, которая будет отображаться в левой
  // части заголовка окна (в области системного меню).
  // Загружаем пиктограмму из ресурсов приложения при
  // помощи функции LoadImage, так как функция
  // LoadIcon может загрузить только обычную пиктограмму
  wc.hIconSm = LoadImage(hInst,
    MAKEINTRESOURCE(IDI_APPICON_SM), IMAGE_ICON, 16, 16, 0);
  
  // Завершаем заполнение структуры WNDCLASSEX
  wc.style = CS_HREDRAW | CS_VREDRAW;
  wc.lpfnWndProc = (WNDPROC)WndProc;
  wc.cbClsExtra  = 0;
  wc.cbWndExtra  = 0;
  wc.hInstance = hInst;
  
  // Для загрузки обычной пиктограммы вы можете
  // использовать функцию LoadImage
  wc.hIcon = LoadImage(hInst,
    MAKEINTRESOURCE(IDI_APPICON), IMAGE_ICON, 32, 32, 0);
  
  wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  wc.lpszMenuName = NULL;
  wc.lpszClassName = szAppName;

  // Вызываем функцию RegisterClassEx, которая выполняет
  // регистрацию окна
  if(!RegisterClassEx(&wc))

    // В случае ошибки пытаемся зарегистрировать окно
	// функцией RegisterClass
    if(!RegisterClass((LPWNDCLASS)&wc.style))
	  return FALSE;
    
  // Создаем главное окно приложения
  hWnd = CreateWindow(szAppName, szAppTitle, WS_OVERLAPPEDWINDOW,
   	 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInst, NULL);
  if(!hWnd) return(FALSE);

  // Отображаем окно
  ShowWindow(hWnd, nCmdShow);
  UpdateWindow(hWnd);

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

// -----------------------------------------------------
// Функция WndProc
// -----------------------------------------------------
LRESULT WINAPI
WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  switch(msg)
  {
    // Для сообщения WM_CREATE назначаем обработчик,
	// расположенный в функции WndProc_OnCreate
    HANDLE_MSG(hWnd, WM_CREATE, WndProc_OnCreate);

    // Для сообщения WM_LBUTTONDOWN назначаем обработчик,
	// расположенный в функции WndProc_OnLButtonDown
    HANDLE_MSG(hWnd, WM_LBUTTONDOWN, WndProc_OnLButtonDown);

    // Для сообщения WM_DESTROY назначаем обработчик,
	// расположенный в функции WndProc_OnDestroy
    HANDLE_MSG(hWnd, WM_DESTROY, WndProc_OnDestroy);

	default:
      return(DefWindowProc(hWnd, msg, wParam, lParam));
  }
}

// -----------------------------------------------------
// Функция WndProc_OnCreate
// -----------------------------------------------------
BOOL WndProc_OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct)
{
  return TRUE;
}

// -----------------------------------------------------
// Функция WndProc_OnDestroy
// -----------------------------------------------------
// Отключаем предупреждающее сообщение о том, что
// функция типа void возвращает управление при помощи
// оператора return. Этот оператор нужен для
// использования макрокоманды FORWARD_WM_LBUTTONDOWN
#pragma warning(disable: 4098)
void WndProc_OnDestroy(HWND hWnd)
{
  PostQuitMessage(0);
  return FORWARD_WM_DESTROY(hWnd, DefWindowProc);
}

// -----------------------------------------------------
// Функция WndProc_OnLButtonDown
// -----------------------------------------------------

#pragma warning(disable: 4098)
void 
WndProc_OnLButtonDown(HWND hWnd, BOOL fDoubleClick, 
  int x, int y, UINT keyFlags)
{
  MessageBox(NULL, "Hello, 32-bit world!", "Window", MB_OK);

  return FORWARD_WM_LBUTTONDOWN(hWnd, fDoubleClick, 
           x, y, keyFlags, DefWindowProc);
}
