Создание списка 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_.