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




Поскольку при создании список не содержит элементов, его необходимо ини­циализировать при первом отображении содержащего его диалога. Это довольно просто, поскольку при активизации диалога его оконная функция получает сообще­ние WM_INITDIALOG, так что в DialogFunc() нужно добавить обработку этого сообщения:

 

case WM_INITDIALOG: // Инициализация списка

SendDlgItemMessage(hdwnd,ID_LB1,LB_ADDSTRING,

0,(LPARAM)"Яблоко");

SendDlgltemMessage(hdwnd,ID_LB1,LB_ADDSTRING,

0,(LPARAM)"Апельсин");

SendDlgltemMessage(hdwnd,ID_LB1,LB_ADDSTRING,

0,(LPARAM)"Груша");

SendDlgltemMessage(hdwnd,ID_LB1,LB_ADDSTRING,

0,(LPARAM)"Виноград");

return 1;

 

Этот фрагмент программы заносит в список элементы Яблоко, Апельсин, Груша и Виноград. Каждый вызов функции SendDlgItemMessage() добавляет новую строку в список. Функция SendDlgItemMessage() направляет списку команду LB_ADDSTRING. Указатель на добавляемую строку содержится в параметре lParam (тип указателя надо преобразовать к LPARAM). В данном случае строки добавляются в список в том порядке, в котором передаются. В зависимости от типа списка добавляемые элементы могут сортироваться в алфавитном порядке. Если количество включаемых в список элементов превышает число элементов, которые можно отобразить в списке, к окну списка автоматически добавляется линейка прокрутки.

 

Выбор элементов списка. После инициализации список готов к работе с ним. Существует два способа эыбора элементов в списке. Во-первых, это можно сделать двойным щелчком мыши на выбираемом элементе. В этом случае оконной функции диалога будет направлено сообщение WM_COMMAND, в котором LOWORD(wParam) будет содержать иден­тификатор окна списка, a HIWORD(wParam) – сообщение LBN_DBLCLK. Двойной щелчок мыши обычно означает, что программа должна обработать выбор сразу же. Во-вторых, пользователь может просто изменить выбранный элемент списка, исполь­зуя клавиатуру или мышь. В этом случае сообщение в программу не посылается, выбранный элемент запоминается, так что программа может запросить у списка номер этого элемента. Оба подхода иллюстрируются в приведенном ниже примере.

Если выбран какой-нибудь элемент списка, можно определить его номер, послав списку сообщение LB_GETCURSEL. В ответ список возвратит номер выбранного элемента. Если никакой элемент не выбран, список возвращает LB_ERR(-1).

Чтобы продемонстрировать процедуру обработки выбора элементов списка, добавьте во вложенный оператор switch в функции DialogFunc() следующий фрагмент.

 

case ID_LB1: // Обработка сообщения LBN_DBLCLK списка

// Если это, конечно, LBN_DBLCLK

if(HIWORD(wParam) == LBN_DBLCLK)

{ // Получить индекс выбранного элемента

i = SendDlgItemMessage(hdwnd,ID_LB1,

LB_GETCURSEL, 0, 0L);

sprintf(str,"Индекс выбранного элемента %d", i);

MessageBox(hdwnd, str,"Сделан выбор", МВ_ОК);

}

return 1;

case IDD_SELFRUIT: // Нажата кнопка "Выбери фрукт"

{

i = SendDlgItemMessage(hdwrtd, ID_LB1,

LBJ3ETCURSEL, 0, 0L);

if(i > -1)

sprintf(str,"Индекс выбранного элемента %d", i);

else

sprintf(str,"Фрукт не выбран");

MessageBox(hdwnd, str, "Сделан выбор", МВ_ОК);

return 1;

 

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

 

Пример 5-2. Для удобства приведем полный текст программы отображения диалога со списком. (Не забудьте внести соответствующие изменения а файлы Mydialog.h и Mydialog.rc).

 

// Демонстрация списка

#include <Windows.h>

#include <String.h>

#include <Stdio.h>

#include "Mydialog.h"

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

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

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

HINSTANCE hInst;

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)

{

switch(message)

{

case WM_COMMAND:

switch(LOWORD(wParam))

{

case IDM_DIALOG1:

DialogBox(hInst,"MYDB",hwnd,

DialogFunc);

break;

case IDM_DIALOG2:

MessageBox(hwnd,

"Этого диалога пока нет",

"", 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)

{

long i;

char str[80];

switch(message)

{

case WM_COMMAND:

switch(LOWORD(wParam))

{

case IDCANCEL:

EndDialog(hdwnd,0);

return 1;

case IDD_RED:

MessageBox(hdwnd,

"Выбран Красный",

"Красный",MB_OK);

return 1;

case IDD_GREEN:

MessageBox(hdwnd,

"Выбран Зеленый",

"Зеленый",MB_OK);

return 1;

case ID_LB1: // Сообщение от списка, если

// это, конечно, LBN_DBLCLK

if(HIWORD(wParam) == LBN_DBLCLK)

{ // Получ. индекс выбран. элемента

i=SendDlgItemMessage(hdwnd, ID_LB1,

LB_GETCURSEL,

0, 0L);

sprintf

(str,

"Индекс выбранного элемента %d",

i);

MessageBox(hdwnd,str,"Сделан выбор",

MB_OK);

}

return 1;

case IDD_SELFRUIT: //Кнопка "Выбери фрукт"

i=SendDlgItemMessage(hdwnd,ID_LB1,

LB_GETCURSEL,

0, 0L);

if(i > -1)

sprintf

(str,

"Индекс выбранного элемента %d",

i);

else

sprintf(str,"Фрукт не выбран");

MessageBox(hdwnd,str,"Сделан выбор",

MB_OK);

return 1;

}

case WM_INITDIALOG: // Инициализация списка

SendDlgItemMessage(hdwnd, ID_LB1,

LB_ADDSTRING,

0, (LPARAM)"Яблоко");

SendDlgItemMessage(hdwnd, ID_LB1,

LB_ADDSTRING,

0, (LPARAM)"Апельсин");

SendDlgItemMessage(hdwnd, ID_LB1,

LB_ADDSTRING,

0, (LPARAM)"Груша");

SendDlgItemMessage(hdwnd, ID_LB1,

LB_ADDSTRING,

0, (LPARAM)"Виноград");

return 1;

}

return 0;

}

 

Пример работы этой программы показан на рис. 5.2.

 

Окно ввода

 

Окно ввода будет последним элементом управления, который мы добавим в диалог в этой главе. Окна ввода применяются для ввода текстовых строк. Перед добавлением окна ввода в программе необходимо описать его в файле ресурсов. В данном случае следует изменить Mydialog.rc так, чтобы описание диалога выглядело следующим образом:

 

MYDB DIALOG 18, 18, 142, 92

CAPTION "Первый диалог"

STYLE DS_MODALFRAME|WS_POPUP|WS_CAPTION|WS_SYSMENU

{

DEFPUSHBUTTON "Красный", IDD_RED, 57, 45, 36, 14,

WS_CHILD|WS_VISIBLE|WS_TABSTOP

PUSHBUTTON "Зеленый", IDD_GREEN, 95, 45, 36, 14,

WS_CHILD|WS_VISIBLE|WS_TABSTOP

PUSHBUTTON "Сброс", IDCANCEL, 52, 65, 37, 14,

WS_CHILD|WS_VISIBLE|WS_TABSTOP

PUSHBUTTON "Выбери фрукт", IDD_SELFRUIT,

2, 45, 50, 14, WS_CHILD|WS_VISIBLE|WS_TABSTOP

PUSHBUTTON "Конец ввода", IDOK, 68, 22, 60, 14,

WS_CHILD|WS_VISIBLE|WS_TABSTOP

LISTBOX ID_LB1, 2, 10, 47, 28, LBS_NOTIFY|WS_CHILD|

WS_VISIBLE|WS_BORDER|WSJVSCROLL|WS_TABSTOP

EDITTEXT ID_EB1, 68, 8, 72, 12, ES_LEFT|

ES_AUTOHSCROLL|WS_CHILD|WS_VISIBLE|WS_BORDER|

WS_TABSTOP

 

 

Рис. 5.2. Пример диалога со списком

 

В этой версии файла ресурсов добавлена кнопка Конец ввода, нажатие которой означает окончание ввода текста. Кроме того, добавлено само окно ввода.

Оператор EDITTEXT создает окно ввода в диалоге:

 

EDITTEXT ID, X, Y, Width, Height[, стиль]

 

Здесь ID задает идентификатор элемента управления, Х и Y – координаты его верхнего левого угла, Width и Height – размеры, а стиль определяет его внешний вид (стили, которые могут быть использованы, приведены в табл. 5.1).

Затем в Mydialog.h нужно добавить следующее макроопределение:

 

#define ID_ED1 107

 

Окна ввода могут не только принимать сообщения, но и генерировать их. Однако в нашем примере обработка всех сообщений не требуется. Вы увидите, что окна ввода автоматически выполняют все необходимые действия для редактирования текста, так что в процессе ввода текста Вашей программе не нужно будет взаимодействовать с окном ввода, – ей потребуется просто решить, когда следует получить текущее содержимое окна ввода. Для этого следует использовать функцию API GetDlgItemText():

 

UINT GetDlgltemText(HWND hdwnd, int nID,

LPSTR lpstr, int nMax);

 

Эта функция копирует содержимое окна ввода в строку-буфер, указатель на которую передается в параметре lpstr. При этом копируется не более nMax символов. Параметр hdwnd передает дескриптор окна диалога, a nID – идентификатор окна ввода.

Чтобы добавить в программу работу с окном ввода, дополните вложенный оператор switch в DialogFunc() приведенным ниже фрагментом кода. При нажатии кнопки Конец ввода откроется окно сообщения, содержащее текущий текст окна ввода.

 

case IDOK: // Нажата кнопка "Конец ввода",

// показать содержимое окна ввода

GetDlgItemText(hdwnd,ID_EB1,str,80);

MessageBox(hdwnd, str, "Содержимое окна ввода",

MB_OK);

return 1;

 

Макроимя IDOK было ранее определено в Windows.h.

 

Пример 5-3. С помощью сравнительно небольшой модификации программа, приведенная в примере 2, превращается в приложение с окном ввода. Проделайте эти изменения самостоятельно. На рис. 5.3 представлен результат работы программы с окном ввода.

 



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2017-03-31 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: