Работа с селекторными кнопками

В этом разделе описываются селекторные кнопки* (radio buttons), использующиеся для представления в окне множества опций, из которых можно выбрать только одну. Селекторная кнопка состоит из небольшой круглой кнопки и текста с описанием селекторной кнопки. Если кнопка заполнена, опция установлена, если нет – опция сброшена. Windows поддерживает два типа селекторных кнопок – устанавливаемые вручную (ручные) и автоматические. Ручные селекторные кнопки (как и ручные контрольные переключатели) требуют, чтобы все действия по управлению ими выполняла программа. Управление автоматическими селекторными кнопками выполняет сама Windows. Поскольку управление селекторными кнопками более сложно, чем управ­ление контрольными переключателями, и поскольку автоматические селекторные кноп­ки используются наиболее часто, рассмотрим только этот тип селекторных кнопок.

Как и другие элементы управления, селекторные кнопки описываются в файле ресурсов при определении диалога. Для создания автоматических селекторных кно­пок используется оператор AUTORADIOBUTTON:

AUTORADIOBUTTON "строка", ID, X, Y,

Width, Height[,стиль]

Здесь "строка" задает текст, a ID – идентификатор селекторной кнопки. Коорди­наты верхнего левого угла задаются параметрами X и Y, a ширина и высота – параметрами Width и Height. Стиль задает вид селекторной кнопки. Если этот параметр не указан, стиль устанавливается по умолчанию, то есть строка отображается справа от маленькой кнопки и пользователь может переключаться к селекторной кнопке с помощью клавиши [Tab].

Как уже упоминалось, селекторные кнопки используются для представления группы опций, из которых можно выбрать только одну. Если в такой группе используются автоматические селекторные кнопки, Windows управляет ими таким образом, чтобы в каждый момент времени была выбрана только одна из них. То есть, если пользователь выбирает одну из селекторных кнопок, ранее выбранная кнопка автоматически очи­щается, и поэтому невозможно выбрать более одной селекторной кнопки одновременно.

Селекторная кнопка (в том числе и автоматическая) может быть установлена в нужное состояние программно, если направить ей сообщение BM_SETCHECK, используя функцию API SendDlgItemMessage(). Значение wParam при этом опреде­ляет будущее состояние кнопки: если оно равно 1, то кнопка выбрана, если 0 – то нет. По умолчанию все кнопки изначально очищены.

С помощью функции SendDlgItemMessage() можно выбрать более одной селек­торной кнопки одновременно либо сбросить все селекторные кнопки. Однако нормальный стиль использования селекторных кнопок в Windows предполагает, что в каждый момент времени может быть выбрана одна, и только одна, селекторная кнопка. Нарушать это правило не рекомендуется.



Состояние селекторной кнопки можно определить при помощи сообщения BM_GETCHECK. Если при этом селекторная кнопка возвращает 1, она выбрана, а если 0 – нет.

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

GROUPBOX "Селекторы", ID_GT2, 62, 1, 53, 34

AUTORADIOBUTTON "Селектор 1", ID_RB1, 64, 10, 50, 12

AUTORADIOBUTTON "Селектор 2", ID_RB2, 64, 22, 50, 12

Пример 7-4. Ниже приводится измененный текст программы предыдущего примера, в кото­ром добавлен фрагмент работы с двумя селекторными кнопками. Поскольку эти кнопки автоматические, изменений в программе немного. Заметьте, что состояние селекторных кнопок сохраняется во внешних переменных rstatus1 и rstatus2. Значе­ния этих переменных используются и для установки состояний селекторных кнопок при активизации диалога, и для отображения их состояния по команде меню Статус.

// Демонстрация селекторных переключателей

// (радиокнопок)

#include

#include

#include

#include "Mydialog.h"

LRESULT CALLBACK WindowFunc(HWND,UINT,WPARAM,LPARAM);

BOOL CALLBACK DialogFunc(HWND,UINT,WPARAM,LPARAM);

char szWinName[]="МоеОкно"; // Имя класса окна

HINSTANCE hInst;

int cbstatus1=0; // Для хранения состояния

int cbstatus2=0; // контрольных переключателей

int rbstatus1=0; // Для хранения состояния

int rbstatus2=0; // селекторных кнопок

int WINAPI WinMain(HINSTANCE hThisInst,

HINSTANCE hPrevInst,

LPSTR lpszArgs,

int nWinMode)

{

HWND hwnd;

MSG msg;

WNDCLASS wcl;

HACCEL hAccel;

// Определить класс окна

wcl.hInstance=hThisInst; // Дескриптор приложения

wcl.lpszClassName=szWinName; // Имя класса окна



wcl.lpfnWndProc=WindowFunc; // Функция окна

wcl.style=0; // Стиль по умолчанию

wcl.hIcon=LoadIcon(NULL,IDI_APPLICATION); // Иконка

wcl.hCursor=LoadCursor(NULL,IDC_ARROW); // Курсор

wcl.lpszMenuName="MYMENU"; // Меню

wcl.cbClsExtra=0; // Без дополнительной

wcl.cbWndExtra=0; // информации

wcl.hbrBackground= // Белый фон

(HBRUSH)GetStockObject(WHITE_BRUSH);

if(!RegisterClass(&wcl)) // Зарегистр. класс окна

return 0;

hwnd=CreateWindow(szWinName, // Создать окно

"Работа с селекторными кнопками",

WS_OVERLAPPEDWINDOW, // Стиль

CW_USEDEFAULT, // Х-координата

CW_USEDEFAULT, // Y-координата

CW_USEDEFAULT, // Ширина

CW_USEDEFAULT, // Высота

HWND_DESKTOP, // Нет родит. окна

NULL, // Нет меню

hThisInst, // Дескрип. приложения

NULL); // Без дополн. аргументов

hInst=hThisInst; // Дескрип. текущ. приложения

// Загрузить акселераторы

hAccel=LoadAccelerators(hThisInst,"MYMENU");

ShowWindow(hwnd,nWinMode); // Показать окно

UpdateWindow(hwnd); // Перерисовать содержимое

while(GetMessage(&msg,NULL,0,0))

{ // Запустить цикл обработки сообщений

if(!TranslateAccelerator(hwnd,hAccel,&msg))

{

TranslateMessage(&msg); // Исп. клавиатуры

DispatchMessage (&msg); // Возврат к Windows

}

}

return msg.wParam;

}

// Следующая функция вызывается операционной системой

// Windows и получает в качестве параметров сообщения

// из очереди сообщений данного приложения

LRESULT CALLBACK WindowFunc(HWND hwnd,

UINT message,

WPARAM wParam,

LPARAM lParam)

{

char str[255];

switch(message)

{

case WM_COMMAND:

switch(LOWORD(wParam))

{

case ID_DIALOG1:

DialogBox(hInst,"MYDB",

hwnd,DialogFunc);

break;

case ID_STATUS: // Состояние переключат.

if(cbstatus1)

strcpy(str,

"Переключатель 1 выбран\n");

else

strcpy(str,

"Переключатель 1 не выбран\n");

if(cbstatus2)

strcat(str,

"Переключатель 2 выбран\n");

else

strcat(str,

"Переключатель 2 не выбран\n");

if(rbstatus1)

strcat(str,

"Селектор 1 выбран\n");

else

strcat(str,

"Селектор 1 не выбран\n");

if(rbstatus2)

strcat(str,

"Селектор 2 выбран\n");

else

strcat(str,

"Селектор 2 не выбран\n");

MessageBox(hwnd,str,"",MB_OK);

break;

case IDM_HELP:

MessageBox(hwnd,"Помощь","",MB_OK);

break;

}

break;

case WM_DESTROY: // Завершение программы

PostQuitMessage(0);

break;

default:

// Все сообщения, не обрабатываемые в данной

// функции, направляются на обработку по

// умолчанию

return DefWindowProc(hwnd,message,

wParam,lParam);

}

return 0;

}

// Простая функция диалога

BOOL CALLBACK DialogFunc(HWND hdwnd,

UINT message,

WPARAM wParam,

LPARAM lParam)

{

switch(message)

{

case WM_INITDIALOG: // Инициализация диалога;

// установить состояние

// контрольн. переключателей

// и селектторных кнопок

SendDlgItemMessage(hdwnd,ID_CB1,

BM_SETCHECK,cbstatus1,0);

SendDlgItemMessage(hdwnd,ID_CB2,

BM_SETCHECK,cbstatus2,0);

SendDlgItemMessage(hdwnd,ID_RB1,

BM_SETCHECK,rbstatus1,0);

SendDlgItemMessage(hdwnd,ID_RB2,

BM_SETCHECK,rbstatus2,0);

return 1;

case WM_COMMAND:

switch(LOWORD(wParam))

{

case IDCANCEL:

EndDialog(hdwnd,0);

return 1;

case IDOK:

// Обновить значения переменных,

// содержащих статус переключателей

cbstatus1=SendDlgItemMessage

(hdwnd,ID_CB1,

BM_GETCHECK,0,0);

// Выбран ли переключатель?

cbstatus2=SendDlgItemMessage

(hdwnd,ID_CB2,

BM_GETCHECK,0,0);

// Выбран ли переключатель?

// Обновить значения переменных,

// содержащих статус селекторных кнопок

rbstatus1=SendDlgItemMessage

(hdwnd,ID_RB1,

BM_GETCHECK,0,0);

// Выбран ли селектор?

rbstatus2=SendDlgItemMessage

(hdwnd,ID_RB2,

BM_GETCHECK,0,0);

// Выбран ли селектор?

EndDialog(hdwnd,0);

return 1;

case ID_CB1:

// Это ручной переключатель

// Пользователь его выбрал

// Поэтому нужно изменить его состояние

if(!SendDlgItemMessage(hdwnd,ID_CB1,

BM_GETCHECK,0,0))

SendDlgItemMessage(hdwnd,ID_CB1,

BM_SETCHECK,1,0);

else // Очистить его

SendDlgItemMessage(hdwnd,ID_CB1,

BM_SETCHECK,0,0);

return 1;

}

}

return 0;

}

Диалог, создаваемый этой программой, будет выглядеть так, как показано на рис. 7.3.


1549405556336521.html
1549429823269128.html
    PR.RU™