Ресурсы в традиционном приложении Windows, страница 4

Это объявление следует поместить вне всяких процедур (глобально). Кроме того, надо исправить строку кода, отвечающую за вывод текста в окно.

TextOut(hdc, gnPos, 20, buf, strlen(buf));

Теперь пора написать диалоговую процедуру. Она имеет характерную, давно устоявшуюся структуру.

BOOL WINAPI MyDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)

{

BOOL bTranslated;

UINT nPos;

switch (uMsg)

{

case WM_INITDIALOG:   // Заполняем поля диалога при его открытии

SetDlgItemInt(hDlg, IDC_XPOS, gnPos, FALSE);

return TRUE;

case WM_COMMAND:

switch(LOWORD(wParam))

{

case IDOK:

nPos = GetDlgItemInt(hDlg, IDC_XPOS, &bTranslated, FALSE);

if (bTranslated && nPos <= gnMaxPos)

{

gnPos = nPos;

EndDialog(hDlg, FALSE);

}

else

MessageBox(hDlg,"Wrong number","Input Error",MB_OK);

return TRUE;

case IDCANCEL:

EndDialog(hDlg, FALSE);

return FALSE;

}

return FALSE;

default:

return FALSE;

}

}

Первая ветвь switch-блока срабатывает при открытии диалога. вторая (WM_COMMAND) обрабатывает нажатия кнопок. При открытии диалога Windows посылает нашему приложению сообщение WM_INITDIALOG. Оно обрабатывается в первой ветви, код которой помещает в окно IDC_XPOS число, хранимое в переменной gnPos. Таким образом диалог "вспоминает" предыдущее значение переменной. Нажатие кнопок в окне диалога обрабатывается в ветви WM_COMMAND. Вместе с сообщением WM_COMMAND Windows посылает два параметра: wParam и lParam, в которые она пакует сопровождающую информацию. Мы хотим узнать какая именно из двух кнопок была нажата пользователем. Так как в Win32 идентификатор элемента управления спрятан в младших 16 битах wParam сообщения, то нам приходится распаковывать этот параметр и разветвляться в зависимости от значения идентификатора.

При нажатии кнопки OK функция API GetDlgItemInt пытается преобразовать текст из окна редактирования IDC_XPOS в число без знака (FALSE), помещаемое во временную переменную nPos. В случае, если преобразование не проходит, вспомогательный параметр bTranslated примет значение FALSE. Мы реагируем на эту ситуацию выводом сообщения об ошибке ввода. В случае успеха (bTranslated==TRUE) мы запоминаем результат в глобальной переменной gnPos.

Если мы хотим, чтобы значение gnMaxPos соответствовало действительному текущему горизонтальному размеру окна, то надо ввести обработку еще одного Windows-сообщения:

case WM_SIZE: gnMaxPos = LOWORD(lParam) - 40; break;

Здесь мы также распаковываем параметр, сопровождающий сообщение WM_SIZE, и добываем текущий горизонтальный размер клиентской области окна. Отметим, что в старшие 16 бит lParam Windows помещает вертикальный размер окна.

Вывод изображений

Вывод графического изображения на экран производится с помощью структуры языка С типа HDC (Device context — контекст устройства), которая реализует функциональность «идеального» устройства вывода. Связь с реальным устройством берет на себя операционная система. Она использует при этом модуль, называемый драйвером устройства. Одним из самых быстрых способов вывода графики на экран является копирование его из одного контекста в другой. В первый, заранее заготовленный в памяти контекст устройства (Memory DC), обычно выбирается такой инструмент GDI, как bitmap. Он должен содержать информацию о выводимом изображении. Второй контекст hdc связан с экраном (это делает функция BeginPaint). Непосредственное копирование производится функцией BitBlt (Bit Block Transfer), с именем которой связано происхождение термина "блиттинг", иногда встречаемого в литературе.

Покажем как вывести bitmap-изображение, которое мы заранее заготовим и будем хранить в ресурсах приложения. Начинать надо с создания нового ресурса типа Bitmap. Для простоты его можно скопировать из специального каталога студии ..\Microsoft Visual Studio\Common\Graphics\Bitmaps. Выбранное изображение, как и любой другой ресурс, надо идентифицировать (пусть это будет IDB_BITMAP). Теперь в оконную процедуру введем вспомогательные переменные.