// ----------------------------------------
// Создание меню без использования шаблона
// Динамическое изменение меню
// ----------------------------------------

#define STRICT
#include <windows.h>
#include <mem.h>
#include "dmenu.hpp"

// Прототипы функций
BOOL InitApp(HINSTANCE);
LRESULT CALLBACK _export WndProc(HWND, UINT, WPARAM, LPARAM);

// Имя класса окна
char const szClassName[]   = "DMenuClass";

// Заголовок окна
char const szWindowTitle[] = "Menu Demo";

// Идентификатор меню верхнего уровня
HMENU hmenu;

// Идентификаторы временных меню
HMENU hmenuFile; // "File"
HMENU hmenuEdit; // "Edit"
HMENU hmenuHelp; // "Help"

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

int PASCAL
WinMain(HINSTANCE hInstance, 
	HINSTANCE hPrevInstance,
	LPSTR     lpszCmdLine, 
	int       nCmdShow)
{
  MSG  msg;   // структура для работы с сообщениями
  HWND hwnd;  // идентификатор главного окна приложения

  // Инициализируем приложение
  if(!InitApp(hInstance))
      return FALSE;

  // После успешной инициализации приложения создаем
  // главное окно приложения
  hwnd = CreateWindow(
    szClassName,         // имя класса окна
    szWindowTitle,       // заголовок окна
    WS_OVERLAPPEDWINDOW, // стиль окна
    CW_USEDEFAULT,       // задаем размеры и расположение
    CW_USEDEFAULT,       // окна, принятые по умолчанию
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    0,                   // идентификатор родительского окна
    0,                   // идентификатор меню
    hInstance,           // идентификатор приложения
    NULL);               // указатель на дополнительные
                         // параметры

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

  // Рисуем главное окно
  ShowWindow(hwnd, nCmdShow);
  UpdateWindow(hwnd);

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

// =====================================
// Функция InitApp
// Выполняет регистрацию класса окна
// =====================================

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

  // Записываем во все поля структуры нулевые значения
  memset(&wc, 0, sizeof(wc));

  wc.lpszMenuName  = NULL;
  wc.style         = 0;
  wc.lpfnWndProc   = (WNDPROC) WndProc;
  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.lpszClassName = (LPSTR)szClassName;

  // Регистрация класса
  aWndClass = RegisterClass(&wc);

  return (aWndClass != 0);
}

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

LRESULT CALLBACK _export
WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  switch (msg)
  {
    case WM_CREATE:
    {
      // Создаем пустое меню верхнего уровня
      hmenu = CreateMenu();

      // Подключаем меню к главному окну приложения
      SetMenu(hwnd, hmenu);

      // Создаем два временных меню - "File" и "Help"
      hmenuFile = CreatePopupMenu();
      hmenuHelp = CreatePopupMenu();

      // Добавляем строки к меню "File"
      AppendMenu(hmenuFile, MF_ENABLED | MF_STRING,
         CM_FILENEW,    "&New");
      AppendMenu(hmenuFile, MF_ENABLED | MF_STRING,
         CM_FILEOPEN,   "&Open");
      AppendMenu(hmenuFile, MF_GRAYED | MF_STRING,
         CM_FILECLOSE,  "&Close");
      AppendMenu(hmenuFile, MF_GRAYED | MF_STRING,
         CM_FILESAVE,   "&Save");
      AppendMenu(hmenuFile, MF_GRAYED | MF_STRING,
         CM_FILESAVEAS, "Save &as...");

      // Добавляем разделительную линию
      AppendMenu(hmenuFile, MF_SEPARATOR, 0, NULL);

      AppendMenu(hmenuFile, MF_GRAYED | MF_STRING,
         CM_FILEPRINT,         "&Print");
      AppendMenu(hmenuFile, MF_GRAYED | MF_STRING,
         CM_FILEPAGE_SETUP,    "Page Se&tup");
      AppendMenu(hmenuFile, MF_GRAYED | MF_STRING,
         CM_FILEPRINTER_SETUP, "P&rinter Setup");

      AppendMenu(hmenuFile, MF_SEPARATOR, 0, NULL);

      AppendMenu(hmenuFile, MF_DISABLED | MF_STRING,
         CM_FILEDEMO, "&Demo Version");

      AppendMenu(hmenuFile, MF_SEPARATOR, 0, NULL);

      AppendMenu(hmenuFile, MF_ENABLED | MF_STRING,
         CM_FILEEXIT, "E&xit");

      // Отмечаем галочкой строку "Demo Version"
      CheckMenuItem(hmenuFile, CM_FILEDEMO,
         MF_BYCOMMAND | MF_CHECKED);

      // Добавляем строки к меню "Help"
      AppendMenu(hmenuHelp, MF_GRAYED | MF_STRING,
         CM_HELPINDEX, "&Index\tF1");
      AppendMenu(hmenuHelp, MF_GRAYED | MF_STRING,
         CM_HELPKEYBOARD, "&Keyboard");
      AppendMenu(hmenuHelp, MF_GRAYED | MF_STRING,
         CM_HELPCOMMANDS, "&Commands");
      AppendMenu(hmenuHelp, MF_GRAYED | MF_STRING,
         CM_HELPPROCEDURES, "&Procedures");
      AppendMenu(hmenuHelp, MF_GRAYED | MF_STRING,
         CM_HELPUSING_HELP, "&Using help");

      AppendMenu(hmenuHelp, MF_SEPARATOR, 0, NULL);

      AppendMenu(hmenuHelp, MF_ENABLED | MF_STRING,
         CM_HELPABOUT, "&About...");

      // Добалвяем временные меню к меню верхнего уровня
      AppendMenu(hmenu, MF_ENABLED | MF_POPUP,
         (UINT)hmenuFile, "&File");
      AppendMenu(hmenu, MF_ENABLED | MF_POPUP,
         (UINT)hmenuHelp, "&Help");

      // Перерисовываем меню
      DrawMenuBar(hwnd);

      // Записываем в идентификатор меню "Edit" значение
      // NULL. Если это меню не будет создано, мы не будем
      // вызывать функцию DestroyMenu для его уничтожения
      hmenuEdit = NULL;

      return 0;
    }

    case WM_COMMAND:
    {
      switch (wParam)
      {
        // Сообщения от меню
	case CM_HELPUSING_HELP:
        case CM_HELPPROCEDURES:
        case CM_HELPCOMMANDS:
        case CM_HELPKEYBOARD:
        case CM_HELPINDEX:
        case CM_EDITPASTE:
        case CM_EDITCOPY:
        case CM_EDITCUT:
        case CM_EDITUNDO:
        case CM_FILEPRINTER_SETUP:
        case CM_FILEPAGE_SETUP:
        case CM_FILEPRINT:
        case CM_FILESAVEAS:
        case CM_FILESAVE:
	{
          // Выводим сообщение об ошибке
	  MessageBox(hwnd, "Функция не реализована",
	          NULL, MB_OK);
          return 0;
	}

        // Выбрали строку "About..." в меню "Help"
	case CM_HELPABOUT:
	{
	  MessageBox(hwnd, "Приложение DMENU\n(C) Фролов А.В., 1994",
		  szWindowTitle, MB_OK | MB_ICONINFORMATION);
          return 0;
	}

	// Выбрали строки "Open" или "New" в меню "File"
	case CM_FILEOPEN:
	case CM_FILENEW:
	{
          // Создаем временное меню "Edit"
	  hmenuEdit = CreatePopupMenu();

          // Добавляем строки в меню "Edit"
	  AppendMenu(hmenuEdit, MF_GRAYED  | MF_STRING,
	     CM_EDITUNDO,  "&Undo\tCtrl+Z");
	  AppendMenu(hmenuEdit, MF_ENABLED | MF_STRING,
	     CM_EDITCUT,   "&Cut\tCtrl+X");
	  AppendMenu(hmenuEdit, MF_ENABLED | MF_STRING,
	     CM_EDITCOPY,  "&Copy\tCtrl+C");
	  AppendMenu(hmenuEdit, MF_ENABLED | MF_STRING,
	     CM_EDITPASTE, "&Paste\tCtrl+V");

          // Вставляем меню "Edit" между меню "File" и меню "Help"
	  InsertMenu(hmenu, 1, MF_BYPOSITION | MF_ENABLED | MF_POPUP,
	     (UINT)hmenuEdit, "&Edit");

          // Разблокируем строки "Save", "Save as..." и "Close" в меню "File"
	  EnableMenuItem(hmenuFile, CM_FILESAVE,
	     MF_ENABLED | MF_BYCOMMAND);
	  EnableMenuItem(hmenuFile, CM_FILESAVEAS,
	     MF_ENABLED | MF_BYCOMMAND);
	  EnableMenuItem(hmenuFile, CM_FILECLOSE,
	     MF_ENABLED | MF_BYCOMMAND);

          // Блокируем строки "New" и "Open" в меню "File"
	  EnableMenuItem(hmenuFile, CM_FILENEW,
	     MF_GRAYED | MF_BYCOMMAND);
	  EnableMenuItem(hmenuFile, CM_FILEOPEN,
	     MF_GRAYED | MF_BYCOMMAND);

          // Перерисовываем меню
	  DrawMenuBar(hwnd);
	  return 0;
	}

        // Выбрали строку "Close" из меню "File"
	case CM_FILECLOSE:
	{
          // Уничтожаем временное меню "Edit"
	  DestroyMenu(hmenuEdit);

	  hmenuEdit = NULL;

	  // Удаляем соответствующую строку в меню
          // верхнего уровня
	  RemoveMenu(hmenu, 1, MF_BYPOSITION);

          // Блокируем строки "Save", "Save as..." и "Close" в меню "File"
	  EnableMenuItem(hmenuFile, CM_FILESAVE,
	     MF_GRAYED | MF_BYCOMMAND);
	  EnableMenuItem(hmenuFile, CM_FILESAVEAS,
	     MF_GRAYED | MF_BYCOMMAND);
	  EnableMenuItem(hmenuFile, CM_FILECLOSE,
	     MF_GRAYED | MF_BYCOMMAND);

	  // Разблокируем строки "New" и "Open" в меню "File"
	  EnableMenuItem(hmenuFile, CM_FILENEW,
	     MF_ENABLED | MF_BYCOMMAND);
	  EnableMenuItem(hmenuFile, CM_FILEOPEN,
	     MF_ENABLED | MF_BYCOMMAND);

	  // Перерисовываем меню
	  DrawMenuBar(hwnd);
	  return 0;
	}

	// Завершаем работу приложения
        case CM_FILEEXIT:
        {
	  DestroyWindow(hwnd);
          return 0;
        }

        default:
          return 0;
      }
    }

    case WM_DESTROY:
    {
      // Если было создано меню "Edit",
      // уничтожаем его
      if(hmenuEdit != NULL)
      {
        DestroyMenu(hmenuEdit);
      }

      // Уничтожаем созданные ранее меню
      DestroyMenu(hmenuFile);
      DestroyMenu(hmenuHelp);
      DestroyMenu(hmenu);

      PostQuitMessage(0);
      return 0;
    }

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