Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Поcобие_БЕЛОВ_Графический_интерфейс_API

.pdf
Скачиваний:
141
Добавлен:
18.03.2016
Размер:
2.75 Mб
Скачать

81

} }

case WM_DESTROY: {PostQuitMessage(0); return 0;}

}

return DefWindowProc(hwnd, msg, wParam, lParam);

}

Если нажать на кнопку «Добавить», то в буфер с именем Buf выбирается содержимое (даже пустое) однострочного редактора и содержимое буфера Buf записывается в список:

SendMessage( hEdit, EM_GETLINE, 0, (LPARAM)Buf); SendMessage( hListBox, LB_ADDSTRING, 0, (LPARAM)Buf);

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

Buf.

При двойном щелчке по строке списка определяется номер выделенного элемента: uItem=(int)SendMessage( hListBox, LB_SETCURSEL, 0, 0L);

Если код возврата uItem не равен ошибке (LB_ERR), то в буфер с именем Buf выбирается строка с номером uItem: SendMessage( hListBox, LB_GETTEXT, uItem, (LPARAM)Buf);

2.6. Комбинированный список

Комбинированный список является комбинацией однострочного редактора текста и списка и создается на базе класса «Combobox».

2.6.1. Создание комбинированного списка

Комбинированный список создается так же, как и другие элементы управления:

hComboBox = CreateWindow("ComboBox", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | CBS_AUTOHSCROLL | CBS_SIMPLE,

30, 30, 200, 200, hwnd, (HMENU) ID_COMBO, hInstance, NULL);

В стиле окон класса указывают символические имена с префиксом CBS_ (прил. 2, табл. 2.7).

2.6.2. Коды извещения

Комбинированный список посылает в функцию родительского

82

окна сообщение WM_COMMAND. При этом младшее слово параметра wParam содержит идентификатор, а параметр lParam – дескриптор списка. Старшее слово параметра wParam содержит код извещения. Приведем список некоторых кодов извещений:

Код извещения

Описание

CBN_CLOSEUP

Список исчез (стал невидим)

CBN_DBLCLK

Двойной щелчок левой клавишей мыши по строке

 

списка стиля CBS_SIMPLE

 

 

CBN_DROPDOWN

Список стал видимым

CBN_EDITCHANGE

Пользователь изменил содержимое окна

 

редактирования и изменения отображены

 

 

CBN_EDITUPDATE

Пользователь изменил содержимое окна

 

редактирования, изменения не отображены

 

 

CBN_ERRSPACE

Ошибка выделения дополнительной памяти

CBN_KILLFOCUS

Список теряет фокус ввода

CBN_SELENDCANCEL

Пользователь отменил выбор в списке

CBN_SELENDOK

Пользователь выбрал строку в списке

CBN_SELCHANGE

Изменился номер выбранной строки

CBN_SETFOCUS

Список получает фокус ввода

2.6.3. Сообщения для комбинированного списка

Для управления комбинированным списком используют набор сообщений, аналогичный сообщениям для списка и редактора текста. В следующей таблице перечислены коды некоторых сообщений:

Сообщение и параметры

Пояснение

CB_ADDSTRING, 0 и

Добавить строку lpszStr в список. Возвращает

(LPARAM)lpszStr

номер строки в списке или код ошибки

 

 

CB_DELETESTRING

Удалить строку с номером nIndex из списка.

(WPARAM)nIndex и 0L

Возвращает число оставшихся в списке строк

 

или код ошибки

 

 

CB_GETCOUNT, 0 И 0L

Определить число строк в списке. Возвращает

 

число строк в списке или код ошибки

 

 

СВ_DIR,

Заполнить список именами файлов с

(WPARAM)(UINT)uAttr и

атрибутом uAttr и шаблоном lpszFileSpec,

(LPARAM) lpszFileSpec;

именами каталогов в текущем каталоге и

 

именами дисков. Возвращает номер

 

последнего имени файла, добавленного в

 

список, или код ошибки

 

 

 

83

 

 

Сообщение и параметры

Пояснение

CB_FINDSTRING,

Начиная со строки с номером nIndexStart,

(WPARAM)nIndexStart и

искать строку с префиксом lpszStr.

(LPARAM) (LPCSTR)lpszStr

Возвращает номер определенной строки или

 

код ошибки (если строки в списке нет)

 

 

CB_GETCURSEL, 0 И 0L

Определить номер выделенной строки.

 

Возвращает номер выделенной строки или код

 

ошибки

СВ_GETDROPPEDSTATE 0 И

Определить, находится список в видимом или

0L

невидимом состоянии. Возвращает TRUE,

 

если список виден, FALSE если нет

 

 

СВ_GETLBTEXT,

Копировать текст строки с номером nIndex в

(WPARAM)nIndex и

буфер lрВ. Возвращает длину строки в байтах

(LPARAM)(int FAR *)1рВ

или код ошибки

СВ_INSERTSTRING,

Вставка строки 1рВ в список под номером

(WPARAM)nIndex и

nIndex. Возвращает номер позиции, в которую

(LPARAM)(int FAR *)1рВ

вставлена строка, или код ошибки

 

 

СВ_LIMITTEXT,

Определить сСmах как максимально

(WPARAM)cCmax и 0L

допустимое число симвлов в окне

 

редактирования. Возвращаемое значение не

 

используется

 

 

СВ_RESETCONTENT, 0 И 0L

Удалить все строки из списка. Возвращаемое

 

значение не используется

 

 

СВ_SELECTSTRING,

Начиная со строки с номером nIndexStart,

(WPARAM)nIndexStart и

определить и выделить строку с префиксом

(LPARAM)(int FAR *)1рВ

1рВ. Возвращает номер определенной строки

 

или код ошибки

 

 

СВ_SETCURSEL,

Выделить строку с номером nIndex. Если

(WPARAM)nIndex и 0L

nIndex равно -1, выделение всех строк будет

 

отменено. При этом функция SendMessage

 

вернет значение CB_ERR, что в данном случае

 

не говорит об ошибке. Возвращает код

 

ошибки (если значение nIndex не равно -1)

 

 

СВ_SHOWDROPDOWN,

Переключение списка в отображаемое или

(WPARAM)(BOOL)fExten ded

неотображаемое состояние. При

и 0L

fExtended=TRUE отображать, при FALSE –

 

нет. Возвращаемое значение всегда не равно 0

 

 

2.6.4. Пример работы с комбинированным списком

Задание. В окне приложения создать однострочный редактор, комбинированный список и кнопку «Добавить». При нажатии на

84

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

Листинг 2.8. Работа с комбинированным списком строк.

#include <windows.h>

#define ID_EDIT

1000

#define ID_COMBBOX

1001

#define ID_BUTTON

1002

BOOL RegClass(WNDPROC, LPCTSTR, UINT);

LRESULT CALLBACK WndProc(HWND,UINT,

 

WPARAM,LPARAM);

HINSTANCE hInstance;

char

szClassName[ ] = "ComboList";

char

szTitle[ ] = "Работа с комбинированным списком";

intWINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance,

LPSTR lpszCmdLine, int nCmdShow)

{ MSG msg; HWND hwnd; hInstance=hInst; if

(!RegClass(WndProc,szClassName,COLOR_WINDOW)

)

return FALSE;

if(!(hwnd = CreateWindow(szClassName, szTitle, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 50, 364,360,0, 0, hInstance, NULL)))

return FALSE;

while (GetMessage(&msg, 0, 0, 0)) { TranslateMessage(&msg); DispatchMessage(Smsg);

}

return msg.wParam; }

BOOL RegClass(WNDPROC Proc, LPCTSTR szName, UINT brBackground)

{

WNDCLASS wc; wc.style=wc.cbClsExtra=wc.cbWndExtra=0; wc.lpfnWndProc = Proc; wc.hInstance = hInstance; wc.hIcon = LoadIconfNULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW);

85

wc.hbrBackground = (HBRUSH)(brBackground + 1); wc.lpszMenuName=(LPCTSTR)NULL; wc.lpszClassName=szName;

return (RegisterClass(&wc) != 0);

}

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)

{static HWND hCombBox, hEdit, hButton, hStatic; int uItem; char Buf[80];

switch (msg) {

case WM_CREATE:

{

hStatic=CreateWindow("static",

"Введите строку для ввода в список",

WS_CHILD | WS_VISIBLE | SS_CENTER, 30,10,300,20,hWnd,(HMENU)0,hInstance,NULL);

hEdit = CreateWindow("edit", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_AUTOHSCROLL,30,40, 300,

30, hWnd,(HMENU)ID_EDIT,hInstance, NULL); hCombBox = CreateWindow("Combobox", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | CBS_SIMPLE | CBS_SORT, 30, 80, 300,200,

hWnd, (HMENU)ID_COMBBOX, hInstance, NULL); hButton = CreateWindow("button", "Добавить", WS_CHILD |

WS_VISIBLE | BS_PUSHBUTTON, 130, 290,100, 30, hWnd,(HMENU)ID_BUTTON,hInstance,NULL);

SetFocus(hEdit); return 0;

}

case WM_COMMAND: { switch (LOWORD(wParam)) {

case ID_COMBBOX: {

switch (HIWORD(wParam)) { case CBN_ERRSPACE:

{ MessageBox(hWnd, "Мало памяти”, MB_OK); return 0;

}

86

case CBN_DBLCLK:

{ uItem=(int)SendMessage(nCombBox, CB_GETCURSEL,0,0L);

if(uItem!=LB_ERR)

{ SendMessage(hCombBox, CB_GETLBTEXT, uItem, (LPARAM)Buf); MessageBox(hWnd, (LPSTR)Buf, szTitie,MB_OK);

}return 0;

}default: return 0;

}return 0;

}

case ID_BUTTON:

{ SendMessage(hEdit,EM_GETLINE,0,(LPARAM)Buf); SendMessage(hCombBox,CB_ADDSTRING,0, (LPARAM)Buf);

SetWindowText(hEdit,"\0");

SetFocus(hEdit); return 0;

}default:return 0;

}} case WM_DESTROY: { PostQuitMessage(0); return 0; }

}return DefWindowProc(hWnd, msg, wParam, lParam);

}

Текст этого приложения отличается от текста предыдущего приложения только видом используемого списка – вместо простого списка применяется комбинированный список. Отличия в тексте приложения, как видно, связаны с именами класса «Combobox», кодов извещений и сообщений.

В процессе работы со списком появляется одно существенное отличие. При выборе строки из списка простого просмотра может потребоваться много времени. Комбинированный список позволяет упростить поиск, если вы знаете хотя бы несколько первых букв префикса искомой строки. Наберите начальные буквы искомой строки в окне редактирования комбинированного списка – и необходимая строка окажется перед вашими глазами.

Окна класса «Combobox» завершают изучение определенных в системе Windows классов окон.

87

Контрольные вопросы

1.Чем отличаются окна определенных в операционной системе Windows классов от обычных окон?

2.Какие аргументы обязательны при создании элементов управления с помощью функции CreateWindow?

3.Каким образом родительское окно идентифицирует сообщения от элементов управления?

4.Чем отличается создание полосы прокрутки от создания других элементов управления?

5.Назовите способы передачи сообщений окнам и их отличия.

6.В чем заключается преимущество использования комбинированного списка по сравнению с обычным списком?

7.Каковы основные этапы создания элементов управления?

8.Что будет, если при создании комбинированного списка вторым аргументом указать на некоторую строку?

9.Какие элементы управления не используют идентификаторы?

10.Какие элементы управления и в каком случае не используют дескрипторы окон?

88

ГЛАВА 3. ВЫВОД В ОКНО

Вывод в окна обладает рядом особенностей.

1.Нельзя пользоваться функциями вывода библиотеки компилятора, так как они приспособлены для вывода в одно и единственное окно. В операционной системе Windows приложения выводят одновременно в различные окна. Система сама решает все проблемы, связанные с возможным перекрытием или перемещением этих окон. С этим обстоятельством связано то, что в окно стремятся

выводить в одном месте приложения – при обработке сообщения

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

2.Интерфейс графических устройств (Graphics Device Interface -GDI) системы открывает доступ к большому числу функций вывода. Приложения, обращаясь к функциям GDI, работают не с физическими устройствами вывода, а с логическими, т.е. описание вызова функций не зависит от физического способа отображения. Функция GDI передает указания о выводе драйверу устройства вывода. Драйвер работает непосредственно с физическим устройством и при управлении выводом учитывает его ограниченные возможности и аппаратные особенности. Благодаря этому

приложения способны работать с любым устройством вывода,

драйвер которого установлен в системе. В этой главе

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

3.Параметры вывода устанавливают в контексте отображенияс помощью функций GDI. Контекст отображения – это структура данных, которая содержит характеристики устройства вывода и указатели на выбранные инструменты рисования. Функции GDI используют только выбранные в контекст отображения параметры и инструменты рисования, например для рисования линии некоторой толщины в контекст отображения, приложение должно выбрать перо этой толщины.

4.Дескриптор контекста отображения служит первым

89

аргументом вызова всех функций, связанных с выводом в окно.

3.1. Сообщение WM_PAINT

Стремление описывать вывод в окно при обработке сообщения WM_PAINT объясняется следующим. Windows следит за изменением расположения окон и при необходимости перерисовки окна посылает функции окна сообщение WM_PAINT. Функция окна при обработке этого сообщения перерисовывает все окно или указанные части.

Сообщение WM_PAINT обрабатывают следующим образом: case WM_PAINT: { PAINTSTRUCT ps;

HDC hdc=BeginPaint(hwnd, &ps);

//Здесь настраивается контекст отображения и выводят в окно

EndPaint(hwnd, &ps); return 0; }

Структура PAINTSTRUCT описана следующим образом: typedef struct { HDC hdc;

BOOL fErase; RECT rcPaint; BOOL fRestore; BOOL fUpdate;

BYTE rgbReserved[16];

}PAINTSTRUCT;

Поля переменной ps заполняет функция BeginPaint. После ее вызова поле hdc структуры ps содержит дескриптор контекста отображения (тот же, который возвращает функция BeginPaint). Поле rcPaint содержит координаты прямоугольной области обновления. Поле fErase определяет необходимость стирания фона области обновления. Если fErase=TRUE, фон окна стирается, иначе фон окна не изменяется. Остальные поля использует операционная система, приложение не должно изменять их содержимое.

После выполнения операций вывода приложение освобождает используемые ресурсы – вызывает функцию EndPaint.

Задача. В центре рабочей области окна вывести текст. Листинг 3.1 содержит решение данной задачи.

Листинг 3.1. Вывод текста в центре рабочей области.

#include <windows.h>

BOOL RegClass(WNDPROC, LPCTSTR, UINT);

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,

90

LPARAM);

HINSTANCE hInstance; char szClass[ ]="OutputClass"; int WINAPI WinMain(HINSTANCE hInstance,

HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)

{MSG msg; HWNDhwnd;

if (!RegClass(WndProc, szClass,COLOR_WINDOW)) return FALSE;

hwnd = CreateWindow(szClass, "Вывод текста", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hInstance, NULL);

if (!hwnd) return FALSE;

ShowWindow(hwnd, SW_SHOWMAXIMIZED); UpdateWindow(hwnd); while(GetMessage(&msg, 0,0,0))

DispatchMessage(&msg); return msg.wParam;

}

BOOL RegClass(WNDPROC Proc, LPCTSTR szName, UINT brBackground)

{ WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.cbCisExtra = wc.cbWndExtra = 0; wc.lpfnWndProc = Proc; wc.hInstance = hInstance; wc.lpszClassName = szName;

wc.hIcon = LoadIcon(NULL, IDC_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(brBackground +1); wc.lpszMenuName = NULL;

return (RegisterClass(&wc) != 0);

}

LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)

{ char szText[ ]="Выводим какой-либо текст"; static short ex, cy;

switch (msg) {

case WM_SIZE: {

cx=LOWORD(lParam); cy=HIWORD(lParam); return 0;

}