- •Глава 8 Дочерние окна управления
- •Класс кнопок
- •Создание дочерних окон
- •Сообщения дочерних окон родительскому окну
- •Сообщения родительского окна дочерним окнам
- •Нажимаемые кнопки
- •Переключатели
- •Окна группы
- •Изменение текста кнопки
- •Видимые и доступные кнопки
- •Кнопки и фокус ввода
- •Дочерние окна управления и цвета
- •Системные цвета
- •Цвета кнопок
- •Сообщение wm_ctlcolorbtn
- •Кнопки, определяемые пользователем
- •Класс статических дочерних окон
- •Класс полос прокрутки
- •Программа colors1
- •Интерфейс клавиатуры, поддерживаемый автоматически
- •Введение новой оконной процедуры
- •Закрашивание фона
- •Окрашивание полос прокрутки и статического текста
- •Класс редактирования
- •Стили класса редактирования
- •Коды уведомления управляющих окон редактирования
- •Использование управляющих окон редактирования
- •Сообщения управляющему окну редактирования
- •Класс окна списка
- •Стили окна списка
- •Добавление строк в окно списка
- •Выбор и извлечение элементов списка
- •Получение сообщений от окон списка
- •Простое приложение, использующее окно списка
- •Список файлов
- •Использование атрибутов файлов
- •Упорядочивание списков файлов
- •Утилита Head для Windows
Получение сообщений от окон списка
Когда пользователь щелкает мышью над окном списка, окно списка получает фокус ввода. Родительское окно может предоставить управляющему (listbox control) окну списка фокус ввода с помощью вызова функции:
SetFocus (hwndList);
Если окно списка имеет фокус ввода, то для выбора пунктов списка также могут использоваться клавиши управления курсором, буквенные клавиши и клавиша <Spacebar>.
Управляющее окно списка посылает сообщения WM_COMMAND своему родительскому окну. Значение параметров сообщения lParam и wParam то же, что и для кнопок управления и управляющих окон редактирования:
LOWORD (wParam) |
Идентификатор дочернего окна |
HIWORD (wParam) |
Код уведомления |
lParam |
Описатель дочернего окна |
Ниже перечисляются коды уведомления и их значения:
LBN_ERRSPACE |
—2 |
LBN_SELCHANGE |
1 |
LBN_DBLCLK |
2 |
LBN_SELCANCEL |
3 |
LBN_SELFOCUS |
4 |
LBN_KILLFOCUS |
5 |
Окно списка посылает своему родительскому окну коды LBN_SELCHANGE и LBN_DBLCLK только в том случае, если в стиль дочернего окна включен идентификатор LBS_NOTIFY.
Код LBN_ERRSPACE показывает, что превышен размер памяти, отведенный для списка. Код LBN_SELCHANGE показывает, что был изменен текущий выбор; эти сообщения имеют место, когда пользователь перемещает подсветку по списку, изменяет состояние выборки с помощью клавиши <Spacebar> или выбирает нужный элемент списка с помощью щелчка мыши. Код LBN_DBLCLK показывает, что на данном пункте списка имел место двойной щелчок мыши. (Значение кодов уведомления для LBN_SELCHANGE и LBN_DBLCLK соответствует количеству щелчков мыши.)
В зависимости от вашего приложения, вы можете использовать либо сообщения LBN_SELCHANGE, либо сообщения LBN_DBLCLK, либо оба вместе. Ваша программа будет получать много сообщений LBN_SELCHANGE, что же касается сообщений LBN_DBLCLK, то они будут случаться только при двойных щелчках мышью. Если в вашей программе используются двойные щелчки мышью, то вам понадобиться обеспечить соответствующий интерфейс клавиатуры для дублирования сообщений LBN_DBLCLK.
Простое приложение, использующее окно списка
Теперь, когда вы знаете как создать список, как заполнить его текстовыми элементами, как получать сообщения от окна списка и как извлекать строки, самое время создать приложение, использующее список. Программа ENVIRON, представленная на рис. 8.8, использует окно списка в рабочей области окна для вывода имен текущих переменных окружения MS-DOS (таких, как PATH, COMSPEC и PROMPT). При выборе переменной, имя и строка окружения выводятся в верхней части рабочей области.
ENVIRON.MAK
#-----------------------
# ENVIRON.MAK make file
#-----------------------
environ.exe : environ.obj
$(LINKER) $(GUIFLAGS) -OUT:environ.exe environ.obj $(GUILIBS)
environ.obj : environ.c
$(CC) $(CFLAGS) environ.c
ENVIRON.C
/*----------------------------------------
ENVIRON.C -- Environment List Box
(c) Charles Petzold, 1996
----------------------------------------*/
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#define MAXENV 4096
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static char szAppName[] = "Environ" ;
HWND hwnd ;
MSG msg ;
WNDCLASSEX wndclass ;
wndclass.cbSize = sizeof (wndclass) ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION) ;
RegisterClassEx (&wndclass) ;
hwnd = CreateWindow (szAppName, "Environment List Box",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
static char szBuffer[MAXENV + 1] ;
static HWND hwndList, hwndText ;
HDC hdc ;
int i ;
TEXTMETRIC tm ;
switch (iMsg)
{
case WM_CREATE :
hdc = GetDC (hwnd) ;
GetTextMetrics (hdc, &tm) ;
ReleaseDC (hwnd, hdc) ;
hwndList = CreateWindow ("listbox", NULL,
WS_CHILD | WS_VISIBLE | LBS_STANDARD,
tm.tmAveCharWidth, tm.tmHeight * 3,
tm.tmAveCharWidth * 16 +
GetSystemMetrics (SM_CXVSCROLL),
tm.tmHeight * 5,
hwnd, (HMENU) 1,
(HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),
NULL) ;
hwndText = CreateWindow ("static", NULL,
WS_CHILD | WS_VISIBLE | SS_LEFT,
tm.tmAveCharWidth, tm.tmHeight,
tm.tmAveCharWidth * MAXENV, tm.tmHeight,
hwnd, (HMENU) 2,
(HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),
NULL) ;
for (i = 0 ; environ[i] ; i++)
{
if (strlen (environ [i]) > MAXENV)
continue ;
*strchr (strcpy (szBuffer, environ [i]), '=') = '\0' ;
SendMessage (hwndList, LB_ADDSTRING, 0, (LPARAM) szBuffer) ;
}
return 0 ;
case WM_SETFOCUS :
SetFocus (hwndList) ;
return 0 ;
case WM_COMMAND :
if (LOWORD (wParam) == 1 && HIWORD (wParam) == LBN_SELCHANGE)
{
i = SendMessage (hwndList, LB_GETCURSEL, 0, 0) ;
i = SendMessage (hwndList, LB_GETTEXT, i,
(LPARAM) szBuffer) ;
strcpy (szBuffer + i + 1, getenv (szBuffer)) ;
*(szBuffer + i) = '=' ;
SetWindowText (hwndText, szBuffer) ;
}
return 0 ;
case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
}
Рис. 8.8. Программа ENVIRON
В программе ENVIRON создается два дочерних окна: окно списка стиля LBS_STANDART и статическое окно стиля SS_LEFT (текст с выравниванием по левому краю). В программе ENVIRON для получения списка строк окружения используется переменная environ (объявленная как внешняя в STDLIB.H). Программа использует сообщение LB_ADDSTRING для размещения каждой строки в окне списка.
Когда вы запускаете программу ENVIRON, то с помощью мыши или клавиатуры можете выбрать переменную окружения. Каждый раз, когда вы изменяете выбор, окно списка посылает своему родительскому окну сообщение WM_COMMAND, которое попадает в процедуру WndProc. Когда WndProc получает сообщение WM_COMMAND, она проверяет равно ли младшее слово параметра lParam (идентификатор дочернего окна) единице, и равно ли старшее слово параметра wParam (код уведомления) величине LBN_SELCHANGE. При наличии соответствующих значений она, с помощью сообщения LB_GETCURSEL, получает индекс выбранного элемента, а с помощью сообщения LB_GETTEXT — сам текст выбранного элемента, т. е. имя переменной окружения. Для получения строки, соответствующей этой переменной окружения, в программе ENVIRON используется функция языка С getenv, а функция SetWindowText используется для передачи этой строки статическому дочернему окну управления, в котором собственно и выводится на экран содержимое строки.
Обратите внимание, что в программе ENVIRON для индексирования переменной environ и получения строки нельзя использовать индекс, возвращаемый сообщением LB_GETCURSEL. Поскольку окно списка имеет стиль LBS_SORT (являющийся частью стиля LBS_STANDART), индексы не совпадают.
