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

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

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

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

8.4. Приложение CHECK

Для демонстрации техники работы с переключателями мы подготовили исходные тексты приложения CHECK. В своем главном окне (рис. 8.3) это приложение создает кнопку и два переключателя. Первый из этих переключателей обычный, а второй - автоматический.

Рис. 8.3. Главное окно приложения CHECK

При помощи мыши вы можете изменять состояние переключателей с номерами 2 и 3 (первый номер присвоен кнопке с надписью "Переключатели"). Второй переключатель - автоматический и имеет стиль BS_AUTOCHECKBOX, третий - обычный со стилем BS_CHECKBOX.

Если после установки состояния переключателей нажать кнопку, расположенную в нижней части окна приложения, на экране появится диалоговая панель, отображающая текущее состояние переключателей. Эта панель показана на рис. 8.2.

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

Листинг 8.5. Файл check\check.c

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

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

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

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

HAB  hab;
HWND hWndFrame;
HWND hWndClient;

// Идентификаторы кнопок
HWND hWndButton1;
HWND hWndButton2;
HWND hWndButton3;

// Состояние переключателей
BOOL fButton2Checked = FALSE;
BOOL fButton3Checked = FALSE;

CHAR szAppTitle[] = "CheckBox 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[] = "BTNDEMO";

  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;
  CHAR szBuf[256];

  switch (msg)
  {
    // Создаем кнопку и два переключателя
    case WM_CREATE :
    {
      hWndButton1 = WinCreateWindow (hWnd, WC_BUTTON ,
        "Переключатели", WS_VISIBLE  | BS_PUSHBUTTON,
        0, 0, 0, 0,
        hWnd, HWND_TOP , BTN1_ID, NULL, NULL);

      // Автоматический переключатель
      hWndButton2 = WinCreateWindow (hWnd, WC_BUTTON ,
        "(2) AutoCheckBox", 
        WS_VISIBLE  | BS_AUTOCHECKBOX,
        0, 0, 0, 0,
        hWnd, HWND_TOP , BTN2_ID, NULL, NULL);

      // Обычный переключатель
      hWndButton3 = WinCreateWindow (hWnd, WC_BUTTON ,
        "(3) CheckBox", WS_VISIBLE  | BS_CHECKBOX,
        0, 0, 0, 0,
        hWnd, HWND_TOP , BTN3_ID, NULL, NULL);
      return FALSE;
    }

    // Изменяем размер и расположение органов
    // управления
    case WM_SIZE :
    {
      WinSetWindowPos (hWndButton1, HWND_TOP ,
        10, 10, 200, 50, 
        SWP _SIZE  | SWP_MOVE  | SWP_ZORDER );

      WinSetWindowPos (hWndButton2, HWND_TOP ,
        10, 70, 200, 50, 
        SWP _SIZE  | SWP_MOVE  | SWP_ZORDER );

      WinSetWindowPos (hWndButton3, HWND_TOP ,
        10, 110, 200, 50, 
        SWP _SIZE  | SWP_MOVE  | SWP_ZORDER );

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

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

      // Закрашиваем область, требующую обновление
      WinFillRect (hps, &rec, CLR_WHITE);

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

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

    // Это сообщение приходит при изменении
    // состояния переключателей
    case WM_CONTROL :
    {
      switch (SHORT1FROMMP (mp1))
      {
        // Если сообщение пришло от автоматического
        // переключателя, получаем и сохраняем его
        // текущее состояние
        case BTN2_ID:
        {
          fButton2Checked = (BOOL) 
            WinSendMsg (hWndButton2,
            BM_QUERYCHECK, MPFROMSHORT(0), NULL);
          break;
        }

        // Если сообщение пришло от обычного 
        // переключателя, изменяем его состояние 
        // и сохраняем новое состояние 
        // в переменной fButton3Checked
        case BTN3_ID:
        {
          if(fButton3Checked)
            WinSendMsg (hWndButton3, BM_SETCHECK,
              MPFROMSHORT(0), NULL);

          else
            WinSendMsg (hWndButton3, BM_SETCHECK,
              MPFROMSHORT(1), NULL);

          fButton3Checked = ~fButton3Checked;
          break;
        }

        default:
          break;
      }
      return 0;
    }

    // Когда пользователь нажимает кнопку,
    // определяем и сохраняем состояние
    // обоих переключателей
    case WM_COMMAND :
    {
      switch (COMMANDMSG(&msg) -> cmd)
      {
        case BTN1_ID:
        {
          sprintf (szBuf, "Состояние переключаталей:\n"
            "(3) третий - %d\n(2) второй - %d",
            fButton3Checked ? 1 : 0,
            fButton2Checked ? 1 : 0);

          WinMessageBox (HWND_DESKTOP, hWnd, szBuf,
           "Состояние переключателей", 0,
           MB_INFORMATION | MB_APPLMODAL |
             MB_MOVEABLE | MB_OK);
          break;
        }

        default:
          break;
      }
      return 0;
    }

    default:
      return(WinDefWindowProc (hWnd, msg, mp1, mp2));
  }
}

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

В области глобальных переменных определены переменные hWndButton1, hWndButton2 и hWndButton3, предназначенные, соответственно, для хранения идентификаторов кнопки и двух переключателей.

Состояние переключателей записывается в переменные fButton2Checked и fButton3Checked.

Функция main

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

Функция WndProc

Рассмотрим обработку сообщений, выполняемую функцией WndProc.

Сообщение WM_CREATE

Обработчик сообщения WM_CREATE создает кнопку и два переключателя. Идентификатор окна кнопки записывается в переменную hWndButton1. Идентификатор кнопки равен BTN1_ID.

Первый из создаваемых переключателей имеет стиль BS_AUTOCHECKBOX и работает автоматически. Идентификатор окна автоматического переключателя хранится в переменной hWndButton2, а идентификатор переключателя равен BTN2_ID.

Второй переключатель создается с использованием стиля BS_CHECKBOX. Идентификатор окна для него хранится в переменной hWndButton3, а идентификатор самого переключателя равен BTN3_ID.

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

Сообщение WM_SIZE

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

Сообщение WM_CONTROL

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

Внешний вид и состояние автоматического переключателя изменяется сразу после щелчка, поэтому все, что делает обработчик сообщения WM_CONTROL для автоматического переключателя - это определяет его текущее состояние. Для этого окну переключателя при помощи функции WinSendMsg посылается сообщение BM_QUERYCHECK. Полученное от этой функции состояние записывается в переменную fButton2Checked.

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

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

Обработчик сообщения WM_CONTROL в этом случае проверяет содержимое переменной fButton3Checked и выполняет включение, либо выключение переключателя. Для управления переключателем с помощью функции WinSendMsg ему посылается сообщение BM_SETCHECK. Если переключатель необходимо включить, параметр mp1 этого сообщения равен 1, если выключить - 0.

После изменения состояния переключателя обработчик сообщения WM_CONTROL соответствующим образом изменяет содержимое переменной fButton3Checked.

Сообщение WM_COMMAND

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

В ответ на это сообщение функция окна формирует текстовую строку szBuf, включая в нее состояние обоих переключателей:

sprintf (szBuf, "Состояние переключаталей:\n"
  "(3) третий - %d\n(2) второй - %d",
  fButton3Checked ? 1 : 0, fButton2Checked ? 1 : 0);

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

Файл check.h

Файл check.h (листинг 8.6) содержит определения константы ID_APP_FRAMEWND и идентификаторов органов управления BTN1_ID, BTN2_ID и BTN3_ID.

Листинг 8.6. Файл check\check.h

#define ID_APP_FRAMEWND 1
#define BTN1_ID         100
#define BTN2_ID         101
#define BTN3_ID         102

Файл check.rc

Файл описания ресурсов приложения check.rc (листинг 8.7) содержит только описание пиктограммы.

Листинг 8.7. Файл check\check.rc

#include <os2.h>
#include "check.h"
ICON ID_APP_FRAMEWND CHECK.ICO

Файл check.def

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

Листинг 8.8. Файл check\check.def

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