Создание списка COMBOBOX
Приложение LISTBOX
Определение номера выделенной строки.
LB_GETCURSEL
PszBuffer - адрес буфера.
NIndex - номер строки.
Копирование текста, соответствующего заданной строке, в буфер. Если список не содержит строк (определен без стиля LBS_HASSTRING), в буфер копируется двойное слово, соответствующее указанному элементу списка.
LB_GETTEXT
LB_SETTOPINDEX
LpszBuffer - адрес буфера, содержащего образец.
Поиск строки в списке, которая начинается с символов, соответствующих образцу. Найденная строка становится выбранной.
LB_SELECTSTRING
NIndex - номер строки, о которой нужно получить информацию.
С помощью этого сообщения можно определить, выбрана ли указанная строка списка.
LB_GETSEL
Определение количества строк в списке.
LB_GETCOUNT
LB_FINDSTRINGEXACT
Поиск строки в списке.
Параметры:
wParam = (WPARAM)nIndexStart;
lParam = (LPARAM)(LPCSTR)lpszStr;
nIndexStart - номер строки, с которой начинается поиск;
lpszStr- адрес строки, которую нужно найти в списке.
Возвращаемое значение: номер найденной строки, или код ошибки (если строки в списке нет).
Параметры:
wParam = 0;
lParam = 0;
Возвращаемое значение: количество строк в списке или код ошибки.
Параметры:
wParam = (WPARAM)nIndex;
lParam = 0;
Возвращаемое значение: положительное число, если строка выбрана, 0, если не выбрана или код ошибки.
Параметры:
wParam = (WPARAM)nIndexStart;
lParam = (LPARAM)(int FAR *)lpszBuffer;
nIndexStart - номер строки, с которой начинается поиск;
Возвращаемое значение: номер найденной строки или код ошибки.
Свертка списка до тех пор, пока указанная строка не станет видимой.
Параметры:
wParam = (WPARAM)nIndex;
lParam = 0L;
nIndex - номер строки.
Возвращаемое значение:
Код ошибки.
Параметры:
wParam = (WPARAM)nIndex;
lParam = (LPARAM)(int FAR *)lpszBuffer;
Возвращаемое значение: Длина строки в байтах (с учетом двоичного нуля, закрывающего строку), или код ошибки.
Параметры:
wParam = 0;
lParam = 0L;
Возвращаемое значение: Номер выделенной строки или код ошибки.
Приложение LISTBOX (рис.) создает простейший одноколоночный список.
Главное окно приложения LISTBOX
В список добавляется несколько текстовых строк. Можно выделять строки при помощи мыши или клавиш перемещения курсора. Выделенная строка отображается в MessageBox’e.
В листинге приведён код, в котором выделенная строка отображается в MessageBox’e только после нажатия на кнопку Button.
Самостоятельно на практике_2:
Доработать код так, чтобы можно было выделять строку для отображения в MessageBox’e при помощи клавиатуры и при помощи двойного щелчка левой клавишей мыши.
Для выполнения различных операций по редактированию текста приложение может отправлять сообщения элементам управления с помощью вызова функции:
SendMessage(hwndEdit, код_сообщения, wParam, lParam);
В параметре hwndEdit указывается дескриптор элемента управления, который начинается с нуля, что соответствует самому верхнему элементу списка. Функция SendMessage может вернуть один из кодов: LB_0K (0) возвращается при нормальном завершении функции, код LB_ERRSPACE (-2) — в случае нехватки памяти для сохранения содержимого списка, LB_ERR (-1) — при возникновении любой другой ошибки.
Главный файл приложения LISTBOX приведен в листинге 2.26.
Листинг 2.26. Файл listbox\listbox.cpp
___________________________________________________
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#define STRICT 1
// Идентификатор списка
#define ID_LIST 1
// Идентификатор кнопки
#define ID_BUTTON 2
// Прототипы функций
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
// Имя класса окна
TCHAR const szClassName[] = _T("ListBoxAppClass");
// Заголовок окна
TCHAR const szWindowTitle[] = _T("ListBox Demo");
// Идентификатор копии приложения
HINSTANCE hInst;
// =====================================
// Функция WinMain
// =====================================
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
LPSTR lpszCmdLine,int nCmdShow)
{
MSG msg; // структура для работы с сообщениями
HWND hwnd; // идентификатор главного окна приложения
// Инициализируем приложение
WNDCLASS wc;
wc.style=CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
wc.cbClsExtra=wc.cbWndExtra=0;
wc.lpfnWndProc=WndProc;
wc.hInstance=hInstance;
wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wc.hCursor=LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName=(LPCTSTR)NULL;
wc.lpszClassName=szClassName;
if (!RegisterClass(&wc))
{
MessageBox(NULL,_T("Не могу зарегестрировать класс"),_T("Error"),MB_OK);
return 0;
}
// Сохраняем идентификатор копии приложения
// в глобальной переменной
hInst = hInstance;
// После успешной инициализации приложения создаем
// главное окно приложения
hwnd = CreateWindow(
szClassName, // имя класса окна
szWindowTitle, // заголовок окна
WS_OVERLAPPEDWINDOW, // стиль окна
CW_USEDEFAULT, // задаем расположение и размеры
CW_USEDEFAULT, // окна, принятые по умолчанию
CW_USEDEFAULT, //
CW_USEDEFAULT, //
0, // идентификатор родительского окна
0, // идентификатор меню
hInstance, // идентификатор приложения
NULL); // указатель на дополнительные
// параметры
// Если создать окно не удалось, завершаем приложение
if (!hwnd)
{
MessageBox(NULL,_T("Не могу создать окно"),_T("Error"),MB_OK);
return 0;
}
// Рисуем главное окно
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// Запускаем цикл обработки сообщений
while(GetMessage(&msg, 0, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
// =====================================
// Функция WndProc
// =====================================
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
// Идентификатор органа управления "listbox"
static HWND hListBox;
// Идентификатор кнопки
static HWND hButton;
switch (msg)
{
case WM_CREATE:
// Создаем список
hListBox = CreateWindow(_T("listbox"), NULL,
WS_CHILD | WS_VISIBLE | LBS_STANDARD |
LBS_WANTKEYBOARDINPUT,
30, 30, 200, 100,
hwnd, (HMENU) ID_LIST, hInst, NULL);
// Отменяем режим перерисовки списка
SendMessage(hListBox, WM_SETREDRAW, FALSE, 0L);
// Добавляем в список несколько строк
SendMessage(hListBox, LB_ADDSTRING, 0,
(LPARAM)(LPSTR)"Зеленый");
SendMessage(hListBox, LB_ADDSTRING, 0,
(LPARAM)(LPSTR)"Красный");
SendMessage(hListBox, LB_ADDSTRING, 0,
(LPARAM)(LPSTR)"Розовый");
SendMessage(hListBox, LB_ADDSTRING, 0,
(LPARAM)(LPSTR)"Пурпурный");
SendMessage(hListBox, LB_ADDSTRING, 0,
(LPARAM)(LPSTR)"Синий");
SendMessage(hListBox, LB_ADDSTRING, 0,
(LPARAM)(LPSTR)"Желтый");
SendMessage(hListBox, LB_ADDSTRING, 0,
(LPARAM)(LPSTR)"Фиолетовый");
SendMessage(hListBox, LB_ADDSTRING, 0,
(LPARAM)(LPSTR)"Черный");
SendMessage(hListBox, LB_ADDSTRING, 0,
(LPARAM)(LPSTR)"Белый");
// Включаем режим перерисовки списка
SendMessage(hListBox, WM_SETREDRAW, TRUE, 0L);
// Перерисовываем список
InvalidateRect(hListBox, NULL, TRUE);
// Создаем кнопку
hButton = CreateWindow(_T("button"),_T("OK"),WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, 250,30,50,20,hwnd,(HMENU)ID_BUTTON,hInst,NULL);
break;
// Когда главное окно приложения получает
// фокус ввода, отдаем фокус списку
case WM_SETFOCUS:
SetFocus(hListBox);
break;
case WM_COMMAND:
// Обработка извещения списка об ошибке
if(wParam == ID_LIST)
{
// Преобразуем к типу unsigned, так как
// константа LBN_ERRSPACE определена как
// отрицательное число
if(HIWORD(lParam) == (unsigned)LBN_ERRSPACE)
{
MessageBox(hwnd, "Мало памяти",
szWindowTitle, MB_OK);
}
}
// Сообщение от кнопки
else if(wParam == ID_BUTTON)
{
int uSelectedItem;
char Buffer[256];
// Определяем номер выделенной строки,
// получаем текст строки и выводим
// этот текст в окно
uSelectedItem = (int)SendMessage(hListBox,
LB_GETCURSEL, 0, 0L);
if(uSelectedItem != LB_ERR)
{
SendMessage(hListBox, LB_GETTEXT,
uSelectedItem, (LPARAM)Buffer);
MessageBox(hwnd, (LPSTR)Buffer, szWindowTitle,
MB_OK);
}
}
break;
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
Комментарии к программе:
1) функция WinMain создает главное окно приложения и запускает цикл обработки сообщений.
2) функция главного окна создает список во время обработки сообщения WM_CREATE:
hListBox = CreateWindow(_T("listbox"), NULL, WS_CHILD | WS_VISIBLE | LBS_STANDARD | LBS_WANTKEYBOARDINPUT, 30, 30, 200, 100, hwnd, (HMENU) ID_LIST, hInst, NULL);Для того чтобы родительское окно могло получать от списка клавиатурные сообщения, дополнительно к стилю LBS_STANDARD указан стиль LBS_WANTKEYBOARDINPUT.
3) после создания списка его надо заполнить строками. Отменяем режим перерисовки списка посылая списку сообщение WM_SETREDRAW со значением параметр wParam, равным FALSE:
SendMessage(hListBox, WM_SETREDRAW, FALSE, 0L);
4) добавляет в список несколько строк, посылая списку несколько раз сообщение LB_ADDSTRING:
SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)(LPSTR)"Зеленый");
5) включаем режим перерисовки, вслед за чем список перерисовывается:
SendMessage(hListBox, WM_SETREDRAW, TRUE, 0L);InvalidateRect(hListBox, NULL, TRUE);
6) при обработке сообщения WM_CREATE создаём кнопку, которая будет использована для выбора из списка выделенной строки.
7) так как для работы со списком используется клавиатура, то получив сообщение WM_SETFOCUS, функция главного окна приложения должна отдать фокус ввода списку:
case WM_SETFOCUS:{ SetFocus(hListBox); return 0;}Сообщение WM_SETFOCUS посылается окну после того, как оно получило фокус клавиатуры.8) обработчик сообщения WM_COMMAND получает управление, когда от списка приходит извещение о событии, или когда пользователь нажимает кнопку.
Если для работы списка не хватает памяти, он посылает извещение LBN_ERRSPACE. В ответ на это приложение выводит на экран диалоговую панель с сообщением об ошибке.
9) Если пользователь сделает двойной щелчок по строке списка, то приходит извещение LBN_DBLCLK.
Обработчик этого извещения должен определить номер выделенной строки (т. е. строки по которой был сделан двойной щелчок), посылая списку сообщение LB_GETCURSEL:
uSelectedItem = (int)SendMessage(hListBox, LB_GETCURSEL, 0, 0L);Для того чтобы переписать выделенную строку в буфер, списку посылается сообщение LB_GETTEXT:
SendMessage(hListBox, LB_GETTEXT, uSelectedItem, (LPARAM)Buffer);Номер строки передается через параметр wParam, адрес буфера указывается через параметр lParam.
Далее полученную строку можно выводить на экран при помощи функции MessageBox.
10) Действия, выполняемые обработчиком сообщения WM_COMMAND при получении сообщения от кнопки, полностью аналогичны действиям при обработке извещения LBN_DBLCLK. В этом случае обработчик сообщения определяет номер выделенной строки, переписывает эту строку в буфер и выводит ее на экран.
11) Чтобы при работе со списком можно было использовать клавиатру, то при создании списка необходимо указать класс LBS_WANTKEYBOARDINPUT. При этом список будет посылать в родительское окно сообщение WM_VKEYTOITEM. Параметр wParam этого сообщения содержит значение виртуального кода нажатой клавиши. Клавише <Enter> соответствует виртуальный код VK_RETURN.
case WM_VKEYTOITEM:{ if(wParam == VK_RETURN) { SendMessage(hwnd, WM_COMMAND, ID_BUTTON, 0); } return 0;}Обработчик сообщения WM_VKEYTOITEM посылает функции главного окна сообщение WM_COMMAND, имитируя выбор строки кнопкой "OK".
Список класса COMBOBOX
Орган управления COMBOBOX является комбинацией списка и однострочного редактора текста, поэтому для списка "combobox" используются стили, коды извещения и сообщения, аналогичные списку "listbox", а также некоторые сообщения от редактора текста класса "edit".
Для того чтобы создать список класса "combobox" приложение должно вызвать функцию CreateWindow, передав в качестве первого параметра указатель на строку "combobox":
hComboBox = CreateWindow(_T("ComboBox"), NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | CBS_AUTOHSCROLL | CBS_SIMPLE, 30, 30, 200, 200, hwnd, (HMENU) ID_LIST, hInst, NULL);Второй параметр функции должен быть указан как NULL.
При создании списка "combobox" указываются специальные стили списка, символические имена которых имеют префикс CBS_.