Шаг 26.
Библиотека OWL.
Диалоговое окно Color (Цвет)

    На этом шаге мы рассмотрим использование диалогового окна Color.

    Хотя пользователь, вероятно, не выбирает цвета так же часто, как открывает и закрывает файлы, все же эта задача в Windows относится к числу наиболее необходимых. Многие Windows-программы используют цвета при отображении на экран и даже при выводе на внешние устройства. По этой причине в Windows диалоговое окно Color добавлено к библиотеке стандартных диалоговых окон. Диалоговое окно Color не только позволяет пользователю выбирать цвет из существующей палитры, но также смешивать уже существующие цвета.

    Как и все стандартные диалоговые окна, диалоговое окно Color является "черным ящиком". Это означает, что, независимо от сложности диалогового окна, Windows сам управляет всеми деталями. Все, что необходимо сделать вам при программировании с библиотекой OWL, так это дать несколько указаний через объект TData. Следующий пример показывает, как использовать окно диалога Color.

#include <owl\applicat.h>
#include <owl\framewin.h>
#include <owl\dc.h>
#include <owl\chooseco.h>
#include "pr26_1.rc"

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

//Класс основного окна
class TWndw : public TFrameWindow
{
  public:
	 TWndw(TWindow *parent, const char far *title);
  protected:
         TColor chosenColor;
         void CmChooseColor();
         void  Paint (TDC &paintDC, BOOL, TRect&);

	 DECLARE_RESPONSE_TABLE (TWndw);
};

DEFINE_RESPONSE_TABLE1 (TWndw, TFrameWindow)
  EV_COMMAND(CM_CHOOSECOLOR, CmChooseColor),
END_RESPONSE_TABLE;

TWndw::TWndw(TWindow *parent, const char far *title):
		  TFrameWindow(parent,title)
{
	// Добавить меню к главному окну.
	AssignMenu("MENU_1");
	// Определить расположение и размеры окна.
	Attr.X=50;
	Attr.Y=50;
	Attr.W=GetSystemMetrics(SM_CXSCREEN)/3;
	Attr.H=GetSystemMetrics(SM_CXSCREEN)/4;
}

// TWndw::CmChooseColor()
// Эта функция реагирует на команду Choose Color,
// отображая диалоговое окно "Цвет".
void TWndw::CmChooseColor()
{
  // Определить массив для сообщения об ошибке.
  char errorMsg[81];
  // Создать объект TData диалогового окна Color.
  TChooseColorDialog::TData colorData;
  // Определить начальные исходные цвета
  // диалогового окна Color. 
  static TColor customColors[16] =
  { 0x010101L, 0x101010L, 0x202020L, 0x303030L,
    0x404040L, 0x505050L, 0x606060L, 0x707070L,
    0x808080L, 0x909090L, 0xA0A0A0L, 0xB0B0B0L,
    0xC0C0C0L, 0xD0D0D0L, 0xE0E0E0L, 0xF0F0F0L
  };
  // Установить флаги таким образом, чтобы
  // диалоговое окно Color было полностью открыто и 
  // отображалось черным цветом.
  colorData.Flags = CC_FULLOPEN | CC_RGBINIT;
  // Установить выбор начального цвета. 
  colorData.Color = chosenColor;
  // Установить отображение  задаваемых цветов. 
  colorData.CustColors = customColors;
  // Создать диалоговое окно Color.
  TChooseColorDialog *dialog =
       new TChooseColorDialog (this, colorData);
  // Выполнить диалоговое окно Color. 
  int result = dialog->Execute();
  // Ответить на кнопку "OK" диалогового окна.
  if (result == IDOK)
  {
      // Сохранить цвет, выбранный пользователем.
      chosenColor = colorData.Color;
     // Заставить окно перерисоваться. 
     Invalidate();
  }
  // Если произошла ошибка... 
  else if (colorData.Error != 0)
               { //...Вывести окно сообщений об ошибке.
                 wsprintf(errorMsg,"Возникла ошибка #%ld.", colorData.Error);
                 MessageBox(errorMsg, "Ошибка",  MB_OK | MB_ICONEXCLAMATION);
               }
}

//TWndw::Paint()
// Эта функция переопределяет функцию Paint() из 
// TWindow и реагирует на сообщение WM_PAINT, которое 
// Windows посылает окну, если оно должно быть 
// повторно перерисовано.
void TWndw::Paint(TDC &paintDC, BOOL, TRect&)
{
  // Создать новые перо и кисть.
  TPen *pen = new TPen(TColor::Black, 3, PS_SOLID);
  TBrush *brush = new TBrush(chosenColor);
  // Выбрать новые перо и кисть в контекст устройства.
  paintDC.SelectObject (*pen); 
  paintDC.SelectObject (*brush);
  // Нарисовать прямоугольник выбранным цветом. 
  paintDC.Rectangle(50, 50, 200, 200);
  // Удалить новые перо и кисть. 
  delete pen; 
  delete brush; 
}

void TApp::InitMainWindow()
{
  TFrameWindow *wndw= new TWndw(0,"Диалоговое окно \"Выбор цвета\"");
  SetMainWindow(wndw);
}

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

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

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

#define CM_EXIT        24310
#define CM_CHOOSECOLOR   101


#ifdef RC_INVOKED

MENU_1 MENU
{
 POPUP "&File"
 {
  MENUITEM "E&xit", CM_EXIT
 }
 POPUP "&Color"
 {
  MENUITEM "&Choose Color...", CM_CHOOSECOLOR
 }
}

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

    При запуске этой программы вы увидите окно, показанное на рисунке 1.


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

    Это окно содержит прямоугольник, заполненный выбранным цветом, который при запуске программы был задан по умолчанию, - черным. Когда вы выбираете из пункта меню Color команду Choose Color, начинает действовать окно диалога Color среды Windows, как показано на рисунке 2.


Рис.2. Окно диалога "Цвет"

    Вы можете выбрать новый цвет, просто отметив один из цветов на левой стороне окна диалога. Вы можете смешать имеющиеся цвета с помощью окна на правой стороне окна диалога, а затем, используя строку выбора цвета, создать желаемый оттенок. Когда вы закрываете окно диалога кнопкой ОК, программа перерисовывает прямоугольник новым цветом.

    Теперь посмотрите на текст программы. Вверху расположена строка:

    #include   <owl\chooseco.h>

    CHOOSECO.H - это заголовочный файл для класса TChooseColorDialog из библиотеки OWL, который инкапсулирует диалоговое окно Color. Заголовочный файл должен быть включен в любую программу, которая использует этот класс. И снова, так как само диалоговое окно определено как часть библиотеки Windows COMMDLG.DLL, вам нет необходимости добавлять к своему проекту дополнительный файл ресурсов.

    Класс главного окна в примере включает защищенный член-данное, именуемый сhosenColor. Этот объект типа TColor содержит текущие выбранные цвета и инициализирован черным цветом в конструкторе окна, переустанавливается в соответствии с цветом, выбранным пользователем в CmChooseColor() и используется в Paint() как цвет прямоугольника.

    Когда пользователь выбирает из пункта меню Color команду Choose Color, OWL вызывает CmChooseColor(). Хотя диалоговое окно Color легко в исользовании, несколько членов-данных в связанном объекте TData предварительно должны быть проинициализированы. В CmChooseColor() функция сначала объявляет объект типа TChooseColorDialog::TData:

    TChooseColorDialog::TData  colorData;

    Затем функция определяет статический массив задаваемых по умолчанию пользовательских цветов, которые должны будут использоваться разделе Custom Colors (Дополнительные цвета) диалогового окна Color:

  static TColor customColors[16] =
  { 0x010101L, 0x101010L, 0x202020L, 0x303030L,
    0x404040L, 0x505050L, 0x606060L, 0x707070L,
    0x808080L, 0x909090L, 0xA0A0A0L, 0xB0B0B0L,
    0xC0C0C0L, 0xD0D0D0L, 0xE0E0E0L, 0xF0F0F0L
  };

    Так как класс TChooseColorDialog::TData не содержит конструктора, вы должны инициализировать необходимые члены-данные TData по одному. К счастью, их всего только три: Flags, Color и CustColors. CmChooseColor() устанавливает член-данное Flags в значение CC_FULLOPEN | CC_RGBINIT, что заставляет окно диалога Color отображаться с открытым разделом Define Custom Color (Определить дополнительные цвета), а также устанавливать цвет по умолчанию в соответствии со значением, хранящимся в члене-данном Color:

    colorData.Flags  =  CC_FULLOPEN   |   CC_RGBINIT;

    Таблица 1 приводит четыре константы, которые вы можете использовать для этих флагов.

Таблица 1. Константы флагов TChooseColorDialog::TData.Flags
Имя Описание
СС_FULLOPEN Открыть диалоговое окно с открытым разделом Define Custom Colors (Определение цветов пользователя).
СС_PREVENTFULLOPEN Блокирует кнопку Define Custom Colors (Определение цветов пользователя), что препятствует открытию пользователем раздела определения цветов пользователя.
СС_RGBINIT Открывает окно диалога с цветом, хранящимся в TData.Color в качестве определенного по умолчанию цвета.
СС_SHOWHELP Отображает кнопку "Help" окна диалога.

    После установки Flags CmChooseColor() устанавливает Color в значение chosenColor, которое позволяет открыть окно диалога Color с текущим цветом как заданным по умолчанию:

    colorData.Color   =  chosenColor;

    Накопец, функция устанавливает элемент CustColors в определенный ранее массив customColors:

    colorData.CustColors = customColors;

    После того, как CmChooseColor() определил структуру TData, он конструирует диалоговое окно Color с помощью вызова конструктора TChooseColorDialog, который получает в качестве своих двух аргументов указатель на родительское окно создаваемого диалогового окна и ссылку на объект TData диалогового окна:

    TChooseColorDialog   *dialog  =
                  new  TChooseColorDialog  (this,   colorData);

    Затем функция отображает диалоговое окно, вызывая функцию Execute():

    int result = dialog->Execute();

    Если пользователь выходит из диалогового окна, нажав кнопку ОК CmChooseColor() извлекает выбранный цвет из colorData.Color (colorData является экземпляром класса TChooseColorDialog::TData) и помещает цвет в chosenColor для сохранности. Затем вызывается Invalidate() для того, чтобы послать в окно сообщение WM_PAINT:

  if (result == IDOK)
  {
     // Сохранить цвет, выбранный пользователем.
     chosenColor = colorData.Color;
     // Заставить окно перерисоваться. 
     Invalidate();
  }

    Сообщение WM_PAINT, конечно же, обрабатывается функцией Paint () главного окна:

void TWndw::Paint(TDC &paintDC, BOOL, TRect&)
{
  // Создать новые перо и кисть.
  TPen *pen = new TPen(TColor::Black, 3, PS_SOLID);
  TBrush *brush = new TBrush(chosenColor);
  // Выбрать новые перо и кисть в контекст устройства.
  paintDC.SelectObject (*pen); 
  paintDC.SelectObject (*brush);
  // Нарисовать прямоугольник выбранным цветом. 
  paintDC.Rectangle(50, 50, 200, 200);
  // Удалить новые перо и кисть. 
  delete pen; 
  delete brush; 
}

    Эта функция сначала создает объект черное перо и новую кисть, основываясь на выбранных пользователем цветах. Затем функция выбирает объекты в контекст устройства и использует их для рисования прямоугольника в области пользовательского окна. И наконец, Paint() удаляет эти новые объекты - перо и кисть.

    На следующем шаге мы рассмотрим использование диалогового окна Font.




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