Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Программирование для IBM OS/2

© Александр Фролов, Григорий Фролов
Том 25, М.: Диалог-МИФИ, 1993, 286 стр.

[Назад] [Содеожание] [Дальше]

8.8. Приложение SLIDER

В приложении SLIDER мы создаем три круглых регулятора (рис. 8.7), с помощью которых можно изменять цвет окна приложения. Каждый из этих регуляторов изменяет значение цветовой компоненты (красной, зеленой или синей) в диапазоне от 0 до 255 (максимально возможное значение). Устанавливая значения компонент, вы можете выбрать любой цвет окна.

Рис. 8.7. Главное окно приложения SLIDER с регуляторами для изменения компонент цвета окна

Исходные тексты приложения приведены в листинге 8.13.

Листинг 8.13. Файл slider\slider.c

// =================================================
// Определения
// =================================================

#define INCL_WIN
#define INCL_GPI
#define INCL_WINDIALOGS
#include <os2.h>
#include "slider.h"

// Прототип функции окна приложения
MRESULT EXPENTRY WndProc(HWND, ULONG, MPARAM, MPARAM);

// =================================================
// Глобальные переменные
// =================================================

HAB  hab;
HWND hWndFrame;
HWND hWndClient;

// Идентификаторы регуляторов
HWND hWndCirc1;
HWND hWndCirc2;
HWND hWndCirc3;

// Компоненты цвета
SHORT sColorR = 255, sColorG = 255, sColorB = 255;

CHAR szAppTitle[] = "Slider Demo";

// =================================================
// Главная функция приложения main
// =================================================

int main()
{
  HMQ   hmq;
  QMSG  qmsg;
  BOOL  fRc;

  // Флаги для создания окна Frame Window
  ULONG flFrameFlags =
    FCF_SYSMENU    | FCF_TITLEBAR      | FCF_MINMAX   |
    FCF_SIZEBORDER | FCF_SHELLPOSITION | FCF_TASKLIST |
    FCF_ICON;

  // Имя класса главного окна
  CHAR  szWndClass[] = "SLIDERDEMO";

  hab = WinInitialize(0);
  if(hab == NULLHANDLE)
  {
    WinMessageBox(HWND_DESKTOP, HWND_DESKTOP,
      "Ошибка инициализации",
      "Ошибка", 0, MB_ICONHAND | MB_OK);
    return(-1);
  }

  // Создаем очередь сообщений
  hmq = WinCreateMsgQueue(hab, 0);
  if(hmq == NULLHANDLE)
  {
    WinMessageBox(HWND_DESKTOP, HWND_DESKTOP,
      "Ошибка при создании очереди сообщений",
      "Ошибка", 0, MB_ICONHAND | MB_OK);
    WinTerminate(hab);
    return(-1);
  }

  // Регистрация главного окна приложения
  fRc = WinRegisterClass(hab, szWndClass,
    (PFNWP)WndProc, 0, 0);
  if(fRc == FALSE)
  {
    WinMessageBox(HWND_DESKTOP, HWND_DESKTOP,
      "Ошибка при регистрации класса главного окна",
      "Ошибка", 0, MB_ICONHAND | MB_OK);
    WinDestroyMsgQueue(hmq);
    WinTerminate(hab);

    return(-1);
  }

  // Создаем главное окно приложения
  hWndFrame = WinCreateStdWindow (HWND_DESKTOP,
    WS_VISIBLE,
    &flFrameFlags, szWndClass, szAppTitle,
    0, 0, ID_APP_FRAMEWND, &hWndClient);
  if(hWndFrame == NULLHANDLE)
  {
    WinMessageBox(HWND_DESKTOP, HWND_DESKTOP,
      "Ошибка при создании главного окна",
      "Ошибка", 0, MB_ICONHAND | MB_OK);
    WinDestroyMsgQueue(hmq);
    WinTerminate(hab);

    return(-1);
  }

  // Запускаем цикл обработки сообщений
  while(WinGetMsg(hab, &qmsg, 0, 0, 0))
    WinDispatchMsg(hab, &qmsg);

  WinDestroyWindow(hWndFrame);
  WinDestroyMsgQueue(hmq);
  WinTerminate(hab);
  return(0);
}

// =================================================
// Функция главного окна приложения
// =================================================

MRESULT EXPENTRY
WndProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
  HPS hps;
  RECTL rec;

  switch (msg)
  {
    case WM_CREATE:
    {
      // Создаем регулятор красного цвета
      hWndCirc1 = WinCreateWindow(hWnd,
        WC_CIRCULARSLIDER,
        "Красный", WS_VISIBLE, 0, 0, 0, 0,
        hWnd, HWND_TOP, CIRCSLD1_ID, NULL, NULL);

      // Устанавливаем диапазон изменения значений
      WinSendMsg(hWndCirc1, CSM_SETRANGE,
        MPFROMLONG(0L), MPFROMLONG(255L));

      // Устанавливаем шаг для изменения позиции
      // и шаг размещения меток
      WinSendMsg(hWndCirc1, CSM_SETINCREMENT,
        MPFROMLONG(10L), MPFROMLONG(2L));

      // Устанавливаем начальное значение
      WinSendMsg(hWndCirc1, CSM_SETVALUE,
        MPFROMLONG(255L), NULL);

      // Создаем регулятор зеленого цвета
      // и настраиваем его параметры
      hWndCirc2 = WinCreateWindow(hWnd,
        WC_CIRCULARSLIDER,
        "Зеленый", WS_VISIBLE, 0, 0, 0, 0,
        hWnd, HWND_TOP, CIRCSLD2_ID, NULL, NULL);

      WinSendMsg(hWndCirc2, CSM_SETRANGE,
        MPFROMLONG(0L), MPFROMLONG(255L));

      WinSendMsg(hWndCirc2, CSM_SETINCREMENT,
        MPFROMLONG(10L), MPFROMLONG(2L));

      WinSendMsg(hWndCirc2, CSM_SETVALUE,
        MPFROMLONG(255L), NULL);

      // Создаем регулятор синего цвета
      // и настраиваем его параметры
      hWndCirc3 = WinCreateWindow(hWnd, 
        WC_CIRCULARSLIDER,
        "Синий", WS_VISIBLE, 0, 0, 0, 0,
        hWnd, HWND_TOP, CIRCSLD3_ID, NULL, NULL);

      WinSendMsg(hWndCirc3, CSM_SETRANGE,
        MPFROMLONG(0L), MPFROMLONG(255L));

      WinSendMsg(hWndCirc3, CSM_SETINCREMENT,
        MPFROMLONG(10L), MPFROMLONG(2L));

      WinSendMsg(hWndCirc3, CSM_SETVALUE,
        MPFROMLONG(255L), NULL);

      return FALSE;
    }

    // Изменяем размер и расположение регуляторов
    case WM_SIZE:
    {
      WinSetWindowPos(hWndCirc1, HWND_TOP,
        0, 0, 150, 150, 
        SWP_SIZE | SWP_MOVE | SWP_ZORDER);

      WinSetWindowPos(hWndCirc2, HWND_TOP,
        150, 0, 150, 150, 
        SWP_SIZE | SWP_MOVE | SWP_ZORDER);

      WinSetWindowPos(hWndCirc3, HWND_TOP,
        300, 0, 150, 150, 
        SWP_SIZE | SWP_MOVE | SWP_ZORDER);

      // Перерисовываем окно приложения
      WinInvalidateRect(hWnd, NULL, TRUE);
      return 0;
    }

    case WM_PAINT:
    {
      // Получаем пространство отображения
      hps = WinBeginPaint(hWnd, NULLHANDLE, &rec);

      // Переключаем таблицу цветов в режим RGB
      GpiCreateLogColorTable(hps,
        LCOL_RESET, LCOLF_RGB, 0L, 0L, NULL);

      // Закрашиваем область, требующую обновление
      WinFillRect(hps, &rec,
        (ULONG)sColorR << 16 |
        (ULONG)sColorG << 8  | (ULONG)sColorB);

      // Возвращаем пространство отображения
      WinEndPaint(hps);
      return 0;
    }

    case WM_ERASEBACKGROUND:
      return(MRFROMLONG(1L));

    case WM_CONTROL:
    {
      // Сообщение пришло от красного регулятора
      if(SHORT1FROMMP(mp1) == CIRCSLD1_ID)
      {
        // Выделяем код извещения
        if(SHORT2FROMMP(mp1) == CSN_CHANGED)
        {
           // Устанавливаем новое значение цвета
           sColorR = (SHORT)mp2;

           // Перерисовываем окно
           WinInvalidateRect(hWnd, NULL, TRUE);
        }
      }

      // Сообщение от зеленого регулятора
      else if(SHORT1FROMMP(mp1) == CIRCSLD2_ID)
      {
        if(SHORT2FROMMP(mp1) == CSN_CHANGED)
        {
           sColorG = (SHORT)mp2;
           WinInvalidateRect(hWnd, NULL, TRUE);
        }
      }

      // Сообщение от синего регулятора
      else if(SHORT1FROMMP(mp1) == CIRCSLD3_ID)
      {
        if(SHORT2FROMMP(mp1) == CSN_CHANGED)
        {
           sColorB = (SHORT)mp2;
           WinInvalidateRect(hWnd, NULL, TRUE);
        }
      }
      return 0;
    }
    default:
      return(WinDefWindowProc(hWnd, msg, mp1, mp2));
  }
}

Глобальные переменные

В глобальных переменных hWndCirc1, hWndCirc2 и hWndCirc3 хранятся идентификаторы регуляторов цвета, создаваемых при обработке сообщения WM_CREATE. Текущие значения отдельных цветовых компонент записываются в переменные sColorR (красный цвет), sColorG (зеленый цвет) и sColorB (синий цвет).

Функция main

В функции main создается очередь сообщений, регистрируется класс для главного окна приложения, создается это окно и запускается цикл обработки сообщений.

Функция WndProc

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

Сообщение WM_CREATE

Обработчик сообщения WM_CREATE создает три одинаковых регулятора, предназначенных для установки красной, зеленой и синей компоненты цвета фона окна Client Window. Все эти регуляторы создаются функцией WinCreateWindow на базе предопределенного класса окна WC_CIRCULARSLIDER.

Для каждого регулятора устанавливается диапазон изменения значений от 0 до 255. Последнее значение соответствует наиболее насыщенному цвету. Установка диапазона изменения значений выполняется при помощи сообщения CSM_SETRANGE, которое посылается по очереди окнам всех трех регуляторов.

Аналогично при помощи сообщения CSM_SETINCREMENT устанавливается шаг изменения позиции, равный 10, и шаг размещения меток, равный 2.

Начальное значение всех регуляторов устанавливается равным 255, для чего окнам регуляторов посылается сообщение CSM_SETVALUE. При этом цвет окна будет белым, так как компоненты цвета имеют максимальную насыщенность и смешиваются в равной пропорции.

Сообщение WM_SIZE

При обработке сообщения WM_SIZE устанавливаются расположение и размеры регуляторов, для чего используется функция WinSetWindowPos. Все регуляторы будут расположены рядом в нижней части окна Client Window.

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

Сообщение WM_PAINT

При обработке сообщения WM_PAINT выполняется переключение таблицы цветов, установленной для пространства отображения, в режим RGB , когда цвет определяется тремя цветовыми компонентами. Для этого вызывается функция GpiCreateLogColorTable , которая будет описана в одном из следующих томов "Библиотеки системного программиста" в разделе, посвященном графическому интерфейсу Presentation Manager.

GpiCreateLogColorTable(hps,
  LCOL_RESET, LCOLF_RGB, 0L, 0L, NULL);

Далее внутренняя область окна закрашивается функцией WinFillRect:

WinFillRect(hps, &rec,
  (ULONG)sColorR << 16 |
  (ULONG)sColorG << 8  | (ULONG)sColorB);

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

Сообщение WM_CONTROL

Обработчик сообщения WM_CONTROL прежде всего анализирует младшее слово параметра mp1, через который передается идентификатор органа управления (в нашем случае, идентификатор одного из трех регуляторов). Далее из старшего слова параметра mp1 выделяется код извещения, и если он равен SLN_CHANGE, сохраняется новое значение позиции регулятора, передаваемое через параметр mp2:

if(SHORT1FROMMP(mp1) == CIRCSLD1_ID)
{
  if(SHORT2FROMMP(mp1) == CSN_CHANGED)
  {
    sColorR = (SHORT)mp2;
    WinInvalidateRect(hWnd, NULL, TRUE);
  }
}

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

Файл slider.h

Файл slider.h (листинг 8.14) содержит определения константы ID_APP_FRAMEWND, а также идентификаторов круглых регуляторов цвета CIRCSLD1_ID, CIRCSLD2_ID и CIRCSLD3_ID.

Листинг 8.14. Файл slider\slider.h

#define ID_APP_FRAMEWND 1
#define CIRCSLD1_ID     100
#define CIRCSLD2_ID     101
#define CIRCSLD3_ID     102

Файл slider.rc

Файл описания ресурсов приложения slider.rc представлен в листинге 8.15.

Листинг 8.15. Файл slider\slider.rc

#include <os2.h>
#include "slider.h"
ICON ID_APP_FRAMEWND SLIDER.ICO

Файл slider.def

Файл определения модуля приложения slider.def приведен в листинге 8.16.

Листинг 8.16. Файл slider\slider.def

NAME        SLIDER   WINDOWAPI
DESCRIPTION 'Slider Application (C) Frolov A., 1996'
HEAPSIZE    4096
STACKSIZE   32768
EXPORTS     WndProc
[Назад] [Содеожание] [Дальше]