Программирование для карманных компьютеров
Шрифт:
HWNDg_hwndB1;
9. Обеспечить помещение значения в этот идентификатор. Для этого нужно изменить вызов функции создания первой кнопки, как показано ниже.
g_hwndB1=CreateWindow(TEXT («BUTTON»), TEXT («Button»),
BS_PUSHBUTTON | BS_NOTIFY | WS_VISIBLE | WS_CHILD,
10, 20, 100,25, hWnd, (HMENU)200, g_hInst, NULL);10. Теперь первая кнопка в левом столбце может принимать сообщения. Нужно обеспечить, обработку сообщений, посланных первой кнопкой в правом столбце. Параметр hMenu этой кнопки получил значение 207, значит, нужно обеспечить «узнавание» этого значения в переключателе switch. В функции WndProc следует отыскать блок case WM_COMMAND: (именно этот тип сообщений посылают кнопки и пункты меню, когда пользователь щелкает на них) и изменить его так, как показано в листинге 4.16. Листинг 4.16
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch (wmId)
{
//Начало добавленного кода case 200:
case 200:
SendMessage (g_hwndB1, WM_SETTEXT, 0, (LPARAM)(LPSTR)L" Svoy text");
break;
case 207:
SendMessage (g_hwndB1, WM_SETTEXT, 0, (LPARAM)(LPSTR)L" Text ot 107");
break;
case 208:
MessageBox (hWnd, L" Этo тело сообщения!", L" A это заголовок", 0);
break;
//Окончание добавленного кода
case IDM_HELP_ABOUT:
DialogBox(g_hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
break;
case IDOK:
SendMessage(hWnd, WM_ACTIVATE, MAKEWPARAM(WA_INACTIVE,0), (LPARAM)hWnd);
SendMessage (hWnd, WM_CLOSE, 0, 0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);11. Теперь
12. Ветка case 207 перехватывает сообщение от первой кнопки в правом столбце и посылает первой кнопке в левом столбце команду присвоить другое значение тексту.
13. Ветка case 208 перехватывает сообщение от второй кнопки в правом столбце и выводит окно сообщения с заданным текстом и заголовком.
Окна сообщенийВсе окна сообщений выводятся на экран при помощи функции MessageBox. Эта функция несколько раз использовалась в примерах, и не нуждается в детальном рассмотрении. Оговорить надо лишь последний параметр, в котором передается константа, определяющая тип сообщения. Возможные значения приведены в следующем списке.
? МВ_0К – системная кнопка OK в правом углу сообщения.
? MBOKCANCEL – кнопки OK и Cancel.
? MBABORTRETRYIGNORE – кнопки Abort, Retry и Ignore.
? MBYESNOCANCEL – кнопки Yes, No и Cancel.
? MB_YESN0 – кнопки Yes и No.
? MB_RETRYCANCEL – кнопки Retry и Cancel.
Константы, определяющие рисунок на сообщении, приведены отдельно.
? MB_ICONHAND – красный круг с восклицательным знаком.
? MB_ICONQUESTION – белый круг с вопросительным знаком.
? MB_ICONEXCLAMATION – желтый треугольник с восклицательным знаком.
? MBICONASTERISK – белый круг с буквой I.Эти два типа констант могут быть использованы в объединении. Например, если нужно вывести сообщение с тремя кнопками и рисунком вопросительного знака, то в качестве последнего параметра следует использовать следующую конструкцию:
MB_YESNOCANCEL | MB_ICONQUESTION
Функция MessageBox возвращает значение типа int, которое соответствует номеру кнопки, которая была нажата. Например, если были отображены кнопки Yes, No и Cancel, а пользователь нажал кнопку No, то будет возвращено значение 2. Пример реакции на нажатие кнопки приведен в рассматриваемом упражнении.
Упражнение 4.3 (продолжение)
14. Изменить код реакции на нажатие кнопки с идентификатором 208, как показано в листинге 4.17.
Листинг 4.17.case 208:
msgResult = MessageBox (hWnd, L" Это тело сообщения!",
L" А это заголовок", MB_OKCANCEL|MB_ICONQUESTION);
if (msgResult==1)
SendMessage (g_hwndB1, WM_SETTEXT, 0, (LPARAM)(LPSTR)L" Да!!!");
if(msgResult==2)
SendMessage (g_hwndB1, WM_SETTEXT, 0, (LPARAM)(LPSTR)L" Нет!!!");
break;15. В начале функции WndProc нужно объявить целочисленную переменную msgResult.
16. Запустить проект. При нажатии второй кнопки в правом столбце будет выведено сообщение с кнопками OK и Cancel, и вопросительным знаком. Щелчок на кнопке OK выведет на кнопку 200 надпись Да!!! а кнопка Cancel приведет к появлению надписи Нет!!!.
17. Теперь нужно узнать, как можно получить значение состояния радиокнопки или флажка. Для этого нужно добавить объявление еще одной переменной в начало функции WndProc.wchar_t *szStr;
18. Изменить объявление переменной хэндлера и добавить переменную, которая будет хранить идентификатор еще одной кнопки.
HWNDg_hwndB1, g_hwndB2;
19. Изменить код обработки щелчка на кнопке 207, как показано в листинге 4.18. Листинг 4.18
case 207:
msgResult=SendMessage (g_hwndB2, BM_GETCHECK, 0, 0);
switch (msgResult)
{
case 0: szStr = L" UnChecked";
break;
case 1: szStr = L" Checked";
break;
case 2: szStr = L" GrayChecked";
break;
}
SendMessage (g_hwndB1, WM_SETTEXT, 0, (LPARAM)(LPSTR)szStr);
break;20. Функция SendMessage может возвращать полезные сведения, когда это поведение диктуется соответственным типом сообщения. В данном случае флажку было послано сообщение BM_GETCHECK. Это сообщение интерпретируется как запрос о его состоянии, и соответствующий компонент вернул ответ в виде целого числа.
21. Запустить проект. При нажатии правой кнопки, в левую кнопку записывается текущее состояние кнопки AutoCheck3State.
EDIT, LISTBOX и COMBOBOXЭти компоненты объединены в одном разделе потому, что орган управления ComboBox, объединяет в себе функциональность двух других, являясь комбинацией органов управления Edit и ListBox. Функциональность этих компонентов рассматривается в новом упражнении.
Упражнение 4.4
1. Создать новый проект (File ? New ? Projects ? WCE Pocket PC 2002 Application) и назвать его CombEdLi. На следующем шаге мастера нужно выбрать тип приложения A typical «Hello Word» application, после чего нажать кнопку Finish.
2. Сразу же закомментировать вызов функций LoadString и DrawText, как это было сделано в предыдущем упражнении.
3. В начале файла объявить в разделе Global Variables несколько переменных:HWNDg_hwndComB, g_hwndLnEd, g_hwndPass, g_hwndList, g_hwndMlnEd; HWNDg_hwndBtn1, g_hwndBtn2, g_hwndBtn3;
Это идентификаторы всех элементов, которые будут созданы на форме.
4. В начале функции WndProc, там, где объявляются локальные переменные, допишите объявление еще нескольких переменных, как показано в листинге 4.19.
Листинг 4.19int i;
wchar_t *mstr[]={L" Elly", L" Totoshka", L" Strashila", L" Bastinda", L" Gingema", L" Elly",
L" Totoshka", L" Strashila", L" Bastinda", L" Gingema", L" Elly", L" Totoshka",
L" Strashila", L" Bastinda", L" Gingema"};
wchar_t tmp[128];5. В этой же функции, в начале блока, помеченного комментарием Parse the menu selections, нужно разместить код, приведенный в листинге 4.20. Листинг 4.20
switch (wmId)
{
//Начало нашего кода:
case 200:
if(wmEvent == CBN_SELCHANGE)
{
SendMessage (g_hwndComB, CB_SETCURSEL, SendMessage (g_hwndComB,
CB_GETCURSEL, 0, 0), 0);
SendMessage (g_hwndComB, WM_COPY, 0, 0);
SendMessage (g_hwndMlnEd, WM_PASTE, 0, 0);
SendMessage (g_hwndMlnEd, EM_REPLACESEL, 0, (LPARAM)(LPCSTR)L"\r\n");
}
break;
case 201:
if (wmEvent == LBN_DBLCLK)
{
SendMessage (g_hwndList, LB_GETTEXT, SendMessage (g_hwndList,
LB_GETCURSEL, 0, 0), (LPARAM)(LPCTSTR)tmp);
SendMessage (g_hwndComB, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)tmp);
}
break;
case 205:
SendMessage (g_hwndPass, WM_GETTEXT, 20, (LPARAM)tmp);
SendMessage (g_hwndComB, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)tmp);
break;
case 206:
SendMessage (g_hwndLnEd, WM_GETTEXT, 20, (LPARAM)tmp);
SendMessage (g_hwndList, LB_ADDSTRING, 0, (LPARAM)(LPCSTR)tmp);
break;
case 207:
SendMessage (g_hwndMlnEd, WM_SETTEXT, 0, (LPARAM)(LPCSTR)"");
break;6. В
//Создаем ComboBox. Параметр WS_NOTIFY позволяет этому элементу
//передавать щелчки мышью в основное окно приложения
g_hwndComB = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT(«COMBOBOX»),
TEXT(""), WS_NOTIFY|CBS_AUTOHSCROLL|WS_VSCROLL |WS_BORDER |WS_VISIBLE |WS_CHILD, 10,
10, 95, 100, hWnd, (HMENU)200, g_hInst, NULL);
//Создаем ListBox.
g_hwndList = CreateWindowEx(WS_EX_DLGMODALFRAME, TEXT("LISTBOX "), TEXT(""),
LBS_NOTIFY|WS_VSCROLL |WS_BORDER| WS_VISIBLE |WS_CHILD, 135, 10, 95, 100, hWnd,
(HMENU)201, g_hInst, NULL);
//И тут же заполняем его элементами из ранее объявленного массива
//Все взаимодействия с компонентами происходят через Windows Messages
for (i = 0; i<15; i++)
{
SendMessage (g_hwndList, LB_ADDSTRING, i+1, (LPARAM)mstr[i]);
};
//Строка ввода пароля, определяется наличием параметра ES_PASSWORD
//Вводимые символы будут отображаться звездочками
g_hwndPass = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, TEXT(«EDIT»), TEXT(""), ES_PASSWORD
|WS_VISIBLE |WS_CHILD, 10, 115, 95, 25, hWnd, (HMENU)202, g_hInst, NULL);
//Простой однострочный редактор текста
g_hwndLnEd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, TEXT(«EDIT»), TEXT(""), WS_VISIBLE
|WS_CHILD, 135, 115, 95, 25, hWnd, (HMENU)203, g_hInst, NULL);
//Многострочный редактор текста с вертикальной прокруткой //(ES_MULTILINE|
ES_AUTOVSCROLL|WS_VSCROLL)
g_hwndMlnEd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, TEXT(«EDIT»), TEXT(""),
ES_NOHIDESEL| ES_MULTILINE|ES_AUTOVSCROLL|WS_VSCROLL |WS_VISIBLE |WS_CHILD, 10, 150,
220, 110, hWnd, (HMENU)204, g_hInst, NULL);
//И наконец, три самые обыкновенные кнопки
g_hwndBtn1 = CreateWindowEx(WS_EX_WINDOWEDGE, TEXT(«BUTTON»), TEXT("1"), BS_PUSHBUTTON
|WS_VISIBLE |WS_CHILD, 110, 10, 20, 40, hWnd, (HMENU)205, g_hInst, NULL);
g_hwndBtn2 = CreateWindowEx(WS_EX_WINDOWEDGE, TEXT(«BUTTON»), TEXT("2"), BS_PUSHBUTTON
|WS_VISIBLE |WS_CHILD, 110, 55, 20, 40, hWnd, (HMENU)206, g_hInst, NULL);
g_hwndBtn3 = CreateWindowEx(WS_EX_WINDOWEDGE, TEXT(«BUTTON»), TEXT("3"), BS_PUSHBUTTON
|WS_VISIBLE |WS_CHILD, 110, 100, 20, 40, hWnd, (HMENU)207, g_hInst, NULL);7. Запустить приложение. Его внешний вид показан на рис. 4.6.
8. В этом окне двойной щелчок на элементе списка ListBox копирует этот элемент в изначально пустой список ComboBox. Выбор элемента в списке ComboBox добавляет его в многострочный редактор, располагающийся в нижней части страницы. Строка, введенная в левый однострочный редактор текста будет отображаться в виде звездочек, но при щелчке на кнопке 1 будет добавлена к списку ComboBox в нормальном виде. Строка, введенная в правый однострочный редактор кода, будет добавлена в список ListBox после нажатия кнопки 2. Редакторы также позволяют выделять фрагменты текста, копировать, вырезать и вставлять этот текст из буфера обмена при помощи сочетаний клавиш Ctrl+X, Ctrl+C и Ctrl+V.
9. Теперь необходимо рассмотреть код, который был введен в обработчик события WM_COMMAND. Выбором case определяется, какой из элементов управления сгенерировал данное событие. Эта информация извлекается из младшего слова сообщения wParam, которое хранится в переменной wmId. При использовании кнопок событие WM_COMMAND означает, что пользователь нажал кнопку. С органами управления ListBox или ComboBox все не так просто. Сообщение WM_ COMMAND может поступить от разных событий. Для точного определения команды нужно воспользоваться старшим словом wParam, которое размещается в переменной wmEvent.
10. В ветке case 200 заложено достаточно много интересных действий. Прежде всего посылается сообщение CB_SETCURSEL, третьим аргументом для которого служит возвращаемый результат предварительного посланного сообщения CB_GETCURSEL. Если этого не сделать, то в ComboBox будет выбрано не то содержимое редактора, которое пользователь выбрал из списка, а предыдущее. Для проверки можно просто закомментировать эту строку. Также следует отметить, что для всех редакторов текста, в том числе для компонента Edit, входящего в состав ComboBox, работают сообщения WMCOPY, WM_PASTE и WM_CUT, осуществляющие стандартные операции редактирования. Последняя строка при помощи сообщения EM_REPLACESEL добавляет в конец только что вставленной строки «жесткий» перевод строки. На самом деле сообщение это призвано заменять выделенный фрагмент в тексте на новый, но поскольку у нас ничего не выделено, то новый фрагмент просто вставляется в позицию курсора. Обратите внимание на сочетание символов для перевода строки \г\п. Оно должно быть только таким, порядок расположения символов важен.
11. В ветви case 201 можно убедиться, что был произведен именно двойной щелчок на компоненте ListBox (wmEvent = LBN_DBLCLK). После этого в строковую переменную tmp записывается текущее строковое значение элемента, выбранного в ListBox, а сама переменная отправляется в ComboBox.
12. В ветвях case 205 и case 206 по щелчку на кнопке извлекается текущее значение текста из однострочных редакторов, которое потом добавляется в список элементов ListBox или ComboBox.
13. В целом это упражнение является достаточно полной иллюстрацией приемов работы с компонентами Edit, ListBox и ComboBox. Конечно же, в этом упражнении не были исчерпаны все возможности этих компонентов, но достаточно ясно были обозначены пути дальнейшего развития приложения.
SCROLLBAR и STATICДва этих компонента не представляют особых трудностей в использовании. Компонент SCROLLBAR можно использовать для организации полос прокрутки основного окна приложения или для создания индикатора с указателем прогресса.
При использовании компонента SCROLLBAR необходимо учитывать, что этот компонент генерирует и принимает сообщения, указанные в следующем списке.
? Сообщения WMJHSCROLL и WMJHSCROLL посылаются родительскому окну при изменении положения движка компонента.
? Сообщения SBMGETSCROLLINFO и SBMSETSCROLLINFO посылаются компоненту для установки его параметров и положения движка.
Кроме этого существуют функции API SetScrollInfo и GetScrollInfo, выполняющие те же самые действия, но без явной посылки сообщения.
Компонент STATIC позволяет вывести на определенное место формы статический текст или изображение, хранящееся в файле ресурсов. Этот компонент настолько прост, что в отдельном рассмотрении не нуждается.