//===================================================== 
// Приложение Status
// (c) Frolov G.V., 1996
// E-mail: frolov@glas.apc.org
//===================================================== 

// Включаемые файлы для MFC
#include <afxwin.h>
#include <afxext.h> 
#include <afxcmn.h>

// Включаемый файл для ресурсов приложения и идентификаторов
#include "resource.h"

//===================================================== 
// Класс CStateApp - главный класс приложения 
//===================================================== 
class CStateApp : public CWinApp
{
public:
   // Мы будем переопределять метод InitInstance,
   // предназначенный для инициализации приложения
   virtual BOOL InitInstance();
};
 
// Создаем объект приложение класса CStateApp
CStateApp StateApp;
 
//===================================================== 
// Класс CStateWindow - представляет главное окно 
//===================================================== 
class CStateWindow : public CFrameWnd
{

protected:  
   CStatusBar  m_wndStatusBar;   // панель состояния
   BOOL  bIndicatorTEXT;         // флаг для управления 
                                 // индикатором
                                 // ID_INDICATOR_TEXT
     
protected:
   // Метод для создания окна приложения и панели состояния
   afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

public:
   // Объявляем конструктор класса CStateWindow
   CStateWindow();

   // Объявляем методы для обработки команд меню
   afx_msg BOOL OnMenuDirectADD_SUB(UINT nID);
   afx_msg void OnMenuProcessBar();
   afx_msg void OnMenuDisableADD_SUB();
   afx_msg void OnMenuSwitchTEXT();
   afx_msg void OnMenuExit();
   
   // Метод для обработки команды ON_UPDATE_COMMAND_UI
   // от индикатора ID_INDICATOR_TEXT
   afx_msg void OnUpdateTEXT(CCmdUI* pCmdUI);
   
   // Макрокоманда необходима, так как класс 
   // CStateWindow обрабатывает сообщения
   DECLARE_MESSAGE_MAP()    
}; 

//===================================================== 
// Таблица сообщений класса CStateWindow
//===================================================== 
BEGIN_MESSAGE_MAP(CStateWindow, CFrameWnd)
   
   // Макрокоманда вызывает метод OnCreate
   ON_WM_CREATE()

   // Обработчик сообщения ON_UPDATE_COMMAND_UI 
   ON_UPDATE_COMMAND_UI(ID_INDICATOR_TEXT, OnUpdateTEXT)
   
   // Обработчики команд меню Work
   ON_COMMAND(ID_WORK_PROCESS, OnMenuProcessBar)
   ON_COMMAND(ID_WORK_DISABLE_ADDSUB, OnMenuDisableADD_SUB)
   ON_COMMAND(ID_WORK_ON_SWITCH_TEXT, OnMenuSwitchTEXT)
   
   ON_COMMAND_EX(ID_WORK_DIRECT_ADD, OnMenuDirectADD_SUB)
   ON_COMMAND_EX(ID_WORK_DIRECT_SUB, OnMenuDirectADD_SUB)

   ON_COMMAND(ID_WORK_EXIT, OnMenuExit)
   
END_MESSAGE_MAP()

// Индикаторы панели управления. Порядок идентификаторов 
// соответствует порядку индикаторов в панели состояния
// (до тех пор, пока он не изменен методом SetPaneInfo)
static UINT indicators[] =
{
	ID_SEPARATOR,           // Самый первый индикатор
   ID_INDICATOR_OVR,       // Индикатор OVR
	ID_INDICATOR_PROGRESS,  // Резервирование места для 
                           // progress bar
   ID_INDICATOR_CAPS,      // Индикатор клавиши <Caps Lock>
	ID_INDICATOR_NUM,       // Индикатор клавиши <Num Lock>
   ID_INDICATOR_SCRL,      // Индикатор клавиши <Scroll Lock>
   ID_INDICATOR_TEXT,      // Индикатор TEXT/PIC
   ID_INDICATOR_ADD,       // Индикатор ADD/SUB (начальное 
                           // состояние START)
};

//===================================================== 
// Метод InitInstance класса CStateApp
// Создает главное окно приложения и отображает его на экране
//===================================================== 
BOOL CStateApp::InitInstance()
{
   m_pMainWnd = new CStateWindow();
   m_pMainWnd -> ShowWindow(m_nCmdShow);
   m_pMainWnd -> UpdateWindow();

   return TRUE;
}

//===================================================== 
// Конструктор класса CStateWindow
//===================================================== 
CStateWindow::CStateWindow()
{ 
   // Создаем окно приложения, соответствующее 
   // данному объекту класса CStateWindow
   Create(NULL, "Status Bar Sample", WS_OVERLAPPEDWINDOW,
      rectDefault, NULL, MAKEINTRESOURCE(IDR_MENU)); 
   
   // Устанавливаем значение флага bIndicatorTEXT
   bIndicatorTEXT = TRUE;
}

//===================================================== 
// Метод OnMenuProcessBar класса CStateWindow
//===================================================== 
void CStateWindow::OnMenuProcessBar()
{
    // Определяем координары индикаатора ID_INDICATOR_PROGRESS
    RECT rectProgress;
    
    m_wndStatusBar.GetItemRect(
       m_wndStatusBar.CommandToIndex(ID_INDICATOR_PROGRESS), 
         &rectProgress);

   // Создаем полосу progress bar. Рамещаем ее 
   // на месте индикаатора ID_INDICATOR_PROGRESS
   CProgressCtrl ctrlProgressBar;

   if(!ctrlProgressBar.Create(WS_CHILD | WS_VISIBLE, 
                              rectProgress, &m_wndStatusBar, 1))
	{
      // Ошибка при создании progress bar
		TRACE0("Failed to create progress bar\n");
		return;
	}

   // Устанавливаем границы для progress bar
   ctrlProgressBar.SetRange(0, 100);

   // Устанавливаем шаг приращения для progress bar
   ctrlProgressBar.SetStep(1);
 
   // Плавно увеличиваем положение progress bar
   for(int i=0;i<100;i++)
   {
      // Выполняем короткую задержку
      Sleep(10);
      
      // Выполняем шаг приращения progress bar
      ctrlProgressBar.StepIt();
   }
   
   // По завершении,отображаем текст в самом первом 
   // индикаторе панели состояния
   m_wndStatusBar.SetWindowText("Process completed");
}

//===================================================== 
// Метод OnMenuDirectADD_SUB класса CStateWindow
//===================================================== 
BOOL  CStateWindow::OnMenuDirectADD_SUB(UINT nID)
{
   // Определяем индекс индикатора ID_INDICATOR_ADD
   int nIndex = m_wndStatusBar.CommandToIndex(ID_INDICATOR_ADD);

   // Устанавливаем нормальный режим отображения этого индикатора
   m_wndStatusBar.SetPaneStyle(nIndex, SBPS_NORMAL);

   // Из меню Work выбрана строка Direct set ADD
   if(nID == ID_WORK_DIRECT_ADD)
   {
      // Выводим текст ADD
      m_wndStatusBar.SetPaneText(nIndex, "ADD");
   }

   // Из меню Work выбрана строка Direct set SUB
   else if(nID == ID_WORK_DIRECT_SUB)
   {
      // Изменяем внешний вид индикатора
      m_wndStatusBar.SetPaneStyle(nIndex, SBPS_POPOUT);

      // Выводим текст SUB
      m_wndStatusBar.SetPaneText(nIndex, "SUB");
   }

   return TRUE;
}   

//=====================================================
// Метод OnMenuDisableADD_SUB класса OnMenuDisableADD_SUB
//=====================================================
void CStateWindow::OnMenuDisableADD_SUB()
{
   // Определяем индекс индикатора ID_INDICATOR_ADD   
   int nIndex = m_wndStatusBar.CommandToIndex(ID_INDICATOR_ADD);
   
   // Блокируем индикатор
   m_wndStatusBar.SetPaneStyle(nIndex, SBPS_DISABLED);
}   

//===================================================== 
// Метод OnUpdateTEXT класса CStateWindow
//===================================================== 
void CStateWindow::OnMenuSwitchTEXT()
{
   // Изменяем состояние флага bIndicatorTEXT,
   // который используется методом OnUpdateTEXT
   bIndicatorTEXT = !bIndicatorTEXT;
}

//===================================================== 
// Метод OnMenuExit класса CStateWindow
//===================================================== 
void CStateWindow::OnMenuExit()
{
   // Завершаем приложение
   DestroyWindow();
   return;
}

//===================================================== 
// Метод OnCreate класса CStateWindow
// Вызывается во время создания окна приложения
//===================================================== 
int CStateWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
   // Вызываем метод OnCreate базового класса
   if(CFrameWnd::OnCreate(lpCreateStruct) == -1)
      return -1;
   
   // Создаем панель состояния 
	if(!m_wndStatusBar.Create(this))
	{
      // Ошибка при создании панели состояния
		TRACE0("Failed to create status bar\n");
		return -1;   
	}

   // Отображаем индикаторы панели состояния
   if(!m_wndStatusBar.SetIndicators(indicators,
		                sizeof(indicators)/sizeof(UINT)))
	{
      // Ошибка при установке индикаторов
		TRACE0("Failed to set indicators\n");
		return -1;   
	}
   
   // Устанавливаем характеристики индикатора ID_INDICATOR_PROGRESS
   m_wndStatusBar.SetPaneInfo( 
      m_wndStatusBar.CommandToIndex(ID_INDICATOR_PROGRESS), 
      ID_INDICATOR_PROGRESS, 
      SBPS_DISABLED |   // текст не отображается
      SBPS_NOBORDERS,   // рамка вокруг индикатора отсутствует
      150 );            // ширина индикатора 150 пикселов

   return 0;
}

//===================================================== 
// Метод OnUpdateTEXT класса CStateWindow
// Обрабатывает сообщение ON_UPDATE_COMMAND_UI 
// от индикатора ID_INDICATOR_TEXT
//===================================================== 
void CStateWindow::OnUpdateTEXT(CCmdUI* pCmdUI)
{
   // В зависимости от сосотяния флага bIndicatorTEXT
   // отображаем в индикаторе ID_INDICATOR_TEXT
   // строку TEXT или PIC
   if(bIndicatorTEXT)
  	   pCmdUI->SetText("TEXT"); // отображаем строку TEXT

   else
      pCmdUI->SetText("PIC");  // отображаем строку PIC

   // Разрешаем отображение текста в индикаторе
	pCmdUI->Enable();
}
