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

#include "toolbar.hpp"


LRESULT CALLBACK _export
  ToolbarWndProc(HWND, UINT, WPARAM, LPARAM);

void DrawButton(LPDRAWITEMSTRUCT lpInfo);
void DrawBitmap(HDC hDC, int x, int y, HBITMAP hBitmap);

// Определяем члены статического класса TbMain
HBITMAP   TbMain::hbmpUp[20];
HBITMAP   TbMain::hbmpDown[20];
HBITMAP   TbMain::hbmpGrayed[20];
HWND      TbMain::hwndParent;
HINSTANCE TbMain::hInst;
int       TbMain::nFirstId = 0;

// ======================================================
// Конструктор класса Toolbar
// ======================================================
Toolbar::Toolbar(HINSTANCE hInstance, HWND hwndParentWindow, int nFirstId)
{
  // Сбрасываем признак ошибки
  errno = 0;

  // Сохраняем идентификатор копии приложения,
  // идентификатор родительского окна, создавшего
  // TOOLBAR, и идентификатор первой кнопки в
  // органе управления TOOLBAR
  TbMain::hInst = hInstance;
  TbMain::hwndParent = hwndParentWindow;
  TbMain::nFirstId = nFirstId;

  // Определяем размеры внутренней области
  // родительского окна
  GetClientRect(TbMain::hwndParent, &rcParent);

  // Определяем размеры дочернего окна, которое
  // будет использовано для создания органа TOOLBAR
  GetRect();

  // Регистрируем класс для дочернего окна TOOLBAR
  if(!RegisterWndClass())
  {
    errno = 1;
    return;
  }

  // Создаем дочернее окно TOOLBAR
  CreateTbWindow();

  if(hwndToolbar == NULL)
  {
    errno = 2;
    return;
  }
}

// ======================================================
// Деструктор класса Toolbar
// ======================================================
Toolbar::~Toolbar()
{
  // Уничтожаем дочернее окно TOOLBAR
  DestroyWindow(hwndToolbar);
}

// ======================================================
// Функция окна ToolbarWndProc для дочернего окна TOOLBAR
// ======================================================

LRESULT CALLBACK _export
ToolbarWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  switch (msg)
  {
     // Передаем сообщение WM_COMMAND от кнопок в
     // родительское окно
     case WM_COMMAND:
     {
       SendMessage(TbMain::hwndParent, WM_COMMAND, wParam, lParam);
       return 0;
     }

     // Это сообщение приходит при изменении состояния
     // дочернего окна органа управления, когда окно
     // нужно перерисовать
     case WM_DRAWITEM:
     {
       // Перерисовываем кнопку
       DrawButton( (LPDRAWITEMSTRUCT)lParam );
       break;
     }
  }
  return DefWindowProc(hwnd, msg, wParam, lParam);
}

// ======================================================
// Функция DrawButton
// Перерисовывает кнопку
// ======================================================

void DrawButton(LPDRAWITEMSTRUCT lpInfo)
{
   HBITMAP hbm;

   // Обрабатываем сообщение WM_DRAWITEM
   // только если оно поступило от кнопки 
   if(lpInfo->CtlType != ODT_BUTTON)
     return;

   hbm = TbMain::hbmpUp[(lpInfo->CtlID) - TbMain::nFirstId];

   // Если кнопка выбрана, рисуем ее в нажатом
   // состоянии
   if (lpInfo->itemState & ODS_SELECTED)
   {
     hbm = TbMain::hbmpDown[(lpInfo->CtlID) - TbMain::nFirstId];
   }

   // Если кнопка неактивна, загружаем идентификатор
   // изображения кнопки в неактивном состоянии
   else if (lpInfo->itemState & ODS_DISABLED)
   {
     hbm = TbMain::hbmpGrayed[(lpInfo->CtlID) - TbMain::nFirstId];
   }

   // При ошибке ничего не рисуем
   if(!hbm) return;

   // Если кнопка выбрана и ее надо целиком
   // перерисовать, вызываем функцию DrawBitmap
   if((lpInfo->itemAction & ODA_DRAWENTIRE) ||
      (lpInfo->itemAction & ODA_SELECT))
   {
     // Рисуем кнопку
     DrawBitmap(lpInfo->hDC,
       (lpInfo->rcItem).left,
       (lpInfo->rcItem).top , hbm);
   }
}
