Шаг 43.
Библиотека OWL.
Добавление строки сообщения

    На этом шаге мы рассмотрим алгоритм добавления к окну строки сообщения.

    Как говорилось ранее, одним из способов предоставления вашим пользователям быстрой обратной связи является предоставление текста подсказки для каждой команды из меню приложения и панели инструментов. Текст подсказки - это короткие пояснения к командам, которые автоматически появляются при их выборе. Для команд меню текст подсказки обычно появляется, когда курсор мыши проходит через команду. Для кнопок панели инструментов текст подсказки может появляться, либо если курсор мыши проходит по кнопке, либо только при нажатии этой кнопки.

    Добавление текста подсказки к стандартной программе в Windows вы можете сделать с помощью нескольких строк кода. Более того, после инсталлирования классов текста подсказки в вашей программе они берут все действия на себя, автоматически отображая текстовые подсказки, необходимые для строки сообщения или строки состояния вашей программы.

    Следующий пример показывает, как реализуется строка сообщения и текст подсказки в OWL-программе.

#include <owl\applicat.h>
#include <owl\decframe.h>
#include <owl\controlb.h>
#include <owl\buttonga.h>
#include <owl\messageb.h>
#include "pr43_1.rc"

//Класс приложения
class TApp: public TApplication
{
  public:
	 TApp():TApplication(){}
	 void InitMainWindow();
};

//Класс основного окна
class TWndw : public TDecoratedFrame
{
  public:
	  TWndw(TWindow *parent, const char far *title, 
            TWindow *client, BOOL trackMenuSelection);
  protected:
	  void CmFileNew();
	  void CmFileOpen();
	  void CmFileSave();
	  void CmMax();
	  void CmRestore();
	  // Переключатели доступности команд.
	  void CmEnableMax (TCommandEnabler &commandEnabler);
	  void CmEnableRestore (TCommandEnabler &commandEnabler);

	  DECLARE_RESPONSE_TABLE(TWndw);
};

DEFINE_RESPONSE_TABLE1 (TWndw, TDecoratedFrame)
	EV_COMMAND(CM_FILENEW, CmFileNew),
	EV_COMMAND(CM_FILEOPEN, CmFileOpen),
	EV_COMMAND(CM_FILESAVE, CmFileSave),
	EV_COMMAND(CM_MAX, CmMax),
	EV_COMMAND(CM_RESTORE, CmRestore),
	EV_COMMAND_ENABLE(CM_MAX, CmEnableMax),
	EV_COMMAND_ENABLE(CM_RESTORE, CmEnableRestore),
END_RESPONSE_TABLE;

TWndw::TWndw(TWindow *parent, const char far *title, 
       TWindow *clientWnd, BOOL trackMenuSelection):
       TDecoratedFrame(parent,title, clientWnd, trackMenuSelection)
{
  TButtonGadget *b;
  TSeparatorGadget *s;
  // Добавить меню к главному окну.
  AssignMenu("MENU_1");
  // Создать новый объект панели инструментов.
  TControlBar *cntrlBar = new TControlBar(this);
  // Добавить приспособления к панели инструментов.
  b = new TButtonGadget(BMP_NEW, CM_FILENEW);
  cntrlBar->Insert(*b);
  b = new TButtonGadget(BMP_OPEN, CM_FILEOPEN);
  cntrlBar->Insert(*b);
  b = new TButtonGadget (BMP_SAVE, CM_FILESAVE);
  cntrlBar->Insert(*b);
  s = new TSeparatorGadget(10);
  cntrlBar->Insert(*s);
  b = new TButtonGadget(BMP_MAX, CM_MAX);
  cntrlBar->Insert(*b);
  b = new TButtonGadget(BMP_RESTORE, CM_RESTORE);
  cntrlBar->Insert(*b);
  s = new TSeparatorGadget(10);
  cntrlBar->Insert (*s);
  b = new TButtonGadget(BMP_EXIT, CM_EXIT);
  cntrlBar->Insert(*b);
  // Установить режим подсказки для команды.
  cntrlBar->SetHintMode(TControlBar::EnterHints);
  // Вставить панель инструментов в окно.
  Insert(*cntrlBar, TDecoratedFrame::Top);
  // Создать новую строку сообщения.
  TMessageBar *msgbar = new TMessageBar(this);
  // Отобразить метку в строке сообщения.
  msgbar->SetText("Messages") ;
  // Добавить строку сообщения в нижнюю часть окна.
  Insert(*msgbar, TDecoratedFrame::Bottom);
  // Определить расположение и размеры окна.
  Attr.X = 50;
  Attr.Y = 50;
  Attr.W = GetSystemMetrics(SM_CXSCREEN) / 3;
  Attr.H = GetSystemMetrics(SM_CYSCREEN) / 4;
}

// TWndw::CmFileNew()
// Эта функция реагирует на сообщение CM_FILENEW,
// которое генерируется командой New из файлового
// меню или кнопкой NEW.
void TWndw::CmFileNew()
{
  MessageBox ("Выбран пункт FILENEW", "Сообщение",MB_OK);
}

// TWndw::CmFileOpen()
// Эта функция реагирует на сообщение CM_FILEOPEN,
// которое генерируется командой Open из файлового
// меню или кнопкой OPEN.
void TWndw::CmFileOpen()
{
  MessageBox ("Выбран пункт FILEOPEN", "Сообщение",MB_OK);
}

// TWndw::CmFileSave()
// Эта функция реагирует на сообщение CM_FILESAVE,
// которое генерируется командой Save из файлового
// меню или кнопкой SAVE.
void TWndw::CmFileSave()
{
  MessageBox ("Выбран пункт FILESAVE", "Сообщение",MB_OK);
}

//TWndw::CmRestore()
// Эта функция реагирует на сообщение СМ_RESTORE, которое
// генерируется кнопкой RES панели управления.
void TWndw::CmRestore()
{
  // Послать системное сообщение для восстановления размеров окна.
  SendMessage(WM_SYSCOMMAND, SC_RESTORE, 0);
}


//TWndw::CmMax()
// Эта функция реагирует на сообщение СМ_МAХ, которое
// генерируется кнопкой МАХ панели управления.
void TWndw::CmMax()
{
  // Послать системное сообщение для максимизации окна.
  SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE, 0);
}

//TWndw::CmEnableMax()
// Эта функция является переключателем доступности
// кнопки MAX панели управления.
void TWndw::CmEnableMax (TCommandEnabler &commandEnabler)
{
  // Разблокировать кнопку MAX, если окно не
  // максимизировано; в противном случае
  // заблокировать кнопку MAX.
  commandEnabler.Enable(!IsZoomed());
}

//TWndw::CmEnableRestore()
// Эта функция является переключателем доступности
// кнопки RES панели управления.
void TWndw::CmEnableRestore(TCommandEnabler &commandEnabler)
{
  // Разблокировать кнопку RES, если окно
  // максимизировано; в противном случае
  // заблокировать кнопку RES.
  commandEnabler.Enable(IsZoomed());
}

void TApp::InitMainWindow()
{
  // Окно TDecoratedFrame должно иметь окно-клиент.
  TWindow *client = new TWindow (0,0,0);
  // Сконструировать главное окно.
  TDecoratedFrame *wndw= new TWndw(0,"Создание строки сообщения",client,TRUE);
  // Установить значение указателя MainWindow приложения.
  SetMainWindow(wndw);
}

int OwlMain(int,char *[])
{
  return TApp().Run();
}

    Файл ресурсов:

#ifndef WORKSHOP_INVOKED
#include "windows.h"
#endif

#define BMP_NEW       1
#define BMP_OPEN      2
#define BMP_SAVE      3
#define BMP_MAX       4
#define BMP_RESTORE   5
#define BMP_EXIT      6
#define CM_FILESAVE   24333
#define CM_EXIT       24310
#define CM_FILEOPEN   24332
#define CM_FILENEW    24331
#define CM_MAX        201
#define CM_RESTORE    202

#ifdef RC_INVOKED

MENU_1 MENU
{
  POPUP "&File"
  {
	  MENUITEM "&New...",  CM_FILENEW
	  MENUITEM "&Open...", CM_FILEOPEN
	  MENUITEM "&Save...", CM_FILESAVE
	  MENUITEM SEPARATOR
	  MENUITEM "E&xit",    CM_EXIT
  }
}


BMP_NEW  BITMAP  "100131.bmp"
BMP_OPEN BITMAP "100143.bmp"
BMP_SAVE BITMAP "100144.bmp"
BMP_MAX BITMAP "100156.bmp"
BMP_RESTORE BITMAP "100130.bmp"
BMP_EXIT BITMAP "100139.bmp"

STRINGTABLE
{
  CM_MAX, "Развернуть окно на весь экран"
  CM_RESTORE, "Вернуть окно к нормальному размеру"
}

#endif
Текст этого приложения вместе с файлами рисунков можно взять здесь.

    Результат работы приложения:


Рис.1. Результат работы приложения

    Запустив эту программу, вы увидите окно, показанное на рисунке 1. Программа работает в точности так же, как и программа из предыдущего шага, за исключением того, что теперь внизу окна находится строка сообщения. Эта строка отображает текст подсказки, когда курсор мыши проходит по командам меню или кнопке команды в панели управления.

    В верхней части текста программы примера, кроме заголовочных файлов с теми же именами, что и в примере предыдущего шага, в программу включен файл MESSAGEB.Н, который является заголовочным файлом для класса TMessageBar. Вы должны включить этот файл в любую программу, использующую класс TMessageBar.

    Программа создает строку сообщений в конструкторе главного окна. Но прежде, чем программа создаст строку сообщений, конструктор устанавливает режим подсказки для инструментальной линейки, вызывая ее функцию-член SetHintMode():

    cntrlBar->SetHintMode(TGadgetWindow::EnterHints);

    Режим подсказки контролирует, когда OWL следует отображать подсказку в строке сообщения или строке состояния приложения. Единственным аргументом функции может быть TControlBar::PressHints, который определяется по умолчанию, если SetHintMode() не вызывается, или TControlBar::EnterHints. Первое значение заставляет библиотеку OWL отображать текст подсказки для кнопки только тогда, когда кнопка нажата. Второе значение, которое использовано в примере, заставляет OWL отображать текст подсказки для кнопки, как только курсор мыши попадает на кнопку.

    Режим PressHints имеет преимущество, состоящее в том, что подсказка не появится, пока пользователь не захочет этого. Однако пользователь не может получить текст подсказки для заблокированной кнопки, потому что заблокированная кнопка не может быть нажата.


    Замечание. Кажется странным, что режимим PressHints для TControlBar показывает подсказку только при нажатии кнопки. Разве, нажав на кнопку, пользователь не выбрал связанную с ней команду, сделав подсказку ненужной? Оказывается, нет. Windows посылает сообщение о команде только в том случае, если курсор мыши все еще находится на нажатой кнопке, тогда как левая кнопка мыши освобождена. Если пользователь нажимает кнопку, чтобы прочитать текст подсказки, и затем убирает курсор мыши с кнопки до отпускания левой кнопки мыши, команда не выполняется.

    Конструктор объекта TWndw создает строку сообщения для приложения, вызывая конструктор класса TMessageBar:

    TMessageBar *msgbar = TMessageBar(this);

    Этот конструктор принимает три аргумента, имеющие задаваемые по умолчанию значения. Первый аргумент - это указатель на родительское окно строки сообщения, второй аргумент - указатель на объект TGadgetWindowFont и третий аргумент - указатель на объект TModule. Как правило, первый аргумент - это аргумент, о котором не нужно беспокоиться. В данной программе таким аргументом является вездесущий указатель this, указывающий в рассматриваемом случае на объект TWndw, главное окно программы, и на родительское окно строки сообщения.

    Строка сообщения содержит текст заголовка, если текст подсказки не отображается. Конструктор TWndw устанавливает текст заголовка, вызывая функцию-член SetText() строки сообщения:

    msgbar->SetText("Messages");

    Эта функция имеет в качестве единственного параметра текст заголовка для строки сообщения.

    Наконец, создав строку сообщения, конструктор объекта TWndw устанавливает ее в окне, вызывая функцию-член Insert() окна, точно так же, как это делалось для панели инструментов:

    Insert(*msgbar, TDecoratedFrame::Bottom);

    Это все, что необходимо программе для установки строки сообщения. Однако вас интересует, откуда берется текст подсказки. Чтобы ответить на этот вопрос, обратите внимание на файл ресурсов программы, показанный в примере. Там вы видите следующую строковую таблицу:

STRINGTABLE
{
  CM_MAX, "Развернуть окно на весь экран"
  CM_RESTORE, "Вернуть окно к нормальному размеру"
}

    Как вы несомненно заметили, эта строковая таблица содержит ряд строк, которые появляются в виде подсказки в строке сообщения. Идентификатор каждой строки тот же самый, что и идентификатор команды, которую описывает подсказка. Сопоставляя эти идентификаторы, OWL легко может определить, какая из строк должна отображаться для каждой команды в вашей программе. Если вы пропустили строку для текста подсказки, OWL отобразит пустое приспособление-текст, когда эта команда будет выбрана.

    Где же находятся строки текста подсказки для других команд? Так как New, Open, Save и Exit представлены почти в каждом приложении, OWL задает для них текст по умолчанию. Чтобы использовать преимущества задаваемых по умолчанию строк, проверьте, чтобы идентификаторы команд были одинаковы с идентификаторами, используемыми OWL. Вы можете обнаружить эти идентификаторы в заголовочных файлах ресурса OWL, таких как WINDOW.RH, EDITFILE.RH, EDIT.RH, EDITSEAR.RH и MDI.RH. Использовать эти идентификаторы можно, включив соответствующие файлы с расширением .RH в ваше описание ресурса и программные файлы или определив их самостоятельно в файлах, которым они требуются. Таблица 1 представляет список наиболее часто используемых идентификаторов команд OWL.

Таблица 1. Идентификаторы команд OWL
Константа Значение
CM_FILENEW 24331
CM_FILEOPEN 24332
CM_FILESAVE 24333
CM_FILESAVEAS 24334
CM_FILEPRINT 24337
CM_FILEPRINTERSETUP 24338
CM_FILECLOSE 24339
CM_EXIT 24310
CM_EDITUNDO 24321
CM_EDITCUT 24322
CM_EDITCOPY 24323
CM_EDITPASTE 24324
CM_EDITDELETE 24325
CM_EDITCLEAR 24326
CM_EDITFIND 24351
CM_EDITREPLACE 24352
CM_EDITFINDNEXT 24353

    Конечно, вы можете легко определить новые строки текста подсказки даже для тех идентификаторов команд, которые имеют задаваемые по умолчанию строки. Просто добавьте строки с идентификаторами соответствующих команд к таблице строк файла ресурсов:

STRINGTABLE
{
  CM_FILENEW,  "Создание нового файла"
  CM_FILEOPEN, "Открытие файла"
  CM_FILESAVE, "Запись файла"
  CM_EXIT, "Выход"
  CM_MAX, "Развернуть окно на весь экран"
  CM_RESTORE, "Вернуть окно к нормальному размеру"
}

    На следующем шаге мы рассмотрим добавление строки состояния.




Предыдущий шаг Содержание Следующий шаг