2. Понятие контекста устройства, применение контекстов устройства, обработка сообщений WM_СHAR, WM_PAINT
В широком смысле контекст устройства является путем, по которыму Windows-программа, используя соответствующий драйвер, выводит информацию в рабочую область окна. Контекст устройства является структурой, которая полностью определяет состояние этого драйвера и способ вывода информации.
Прежде чем программа начнет выводить информацию в рабочую область окна, она должны получить контекст устройства. Пока это не сделано, нет связи между программой и окном, предназначенным для вывода.
В традиционных Windows-программах контекст устройства получают вызовом функции GetDC(), а освобождают с помощью ReleaseDC(). Поскольку Windows может предоставить лишь небольшое количество контекстов, важно, чтобы программа освободила контекст после окончания работы с ним. MFC имеет соответствующие классы, способные руководить этим процессом. В частности, при создании экземпляра объекта типа CClientDC программе предоставляется контекст устройства. Если этот объект необходимо изъять, вызывается функция ReleaseDC() и контекст устройства автоматически освобождается. Конструктор класса СClientDC записывается в виде:
СClientDC (CWnd *Windows);
где параметр Windows является указателем на окно, которому предоставляется контекст устройства. Для активного окна можно указать ключевое слово this.
Вывод в клиентскую область окна программы может обеспечиваться с помощью функции TextOut():
virtual BOOL CDC::TextOut(int X, int Y, LPCSTR lpszStr, int Length);
где X, Y – координаты точки начала вывода в пикселях (относительно левого верхнего угла окна программы), lpszStr – указатель на строку, которая выводится, а Length – его длина. Пример иллюстрирует возможный вариант реализации обработчика нажатия клавиш клавиатуры - в точку (1, 1) окна программы.
Пример обработчика нажатия клавиш клавиатуры
char str [80]; // строка символов для вывода
void CMainWin::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{CClientDC dc(this); // получение контекста окна
dc.TextOut(1,1," ", 3); // удаление старого текста
wsprintf(str,"%с", ch); // формирование строки с кодом клавиши
dc.TextOut(1, 1, str, strlen(str)); // вывод строки в координату (1, 1)
}
Таким образом, каждый раз, когда необходимо вывести информацию в рабочую область окна, необходимо получить контекст устройства с помощью CClientDC. Частным случаем является применения сообщения WM_PAINT.
Обновление содержимого рабочей области окна программы
Для обновления содержимого рабочего окна программы необходимо отослать сообщение WM_PAINT. Вне его применения содержимое окна может не отображаться. Т.е. каждый раз, когда есть потребность выводить информацию в окно программы, следует обращаться к этому сообщению.
Сообщению WM_PAINT отвечает макрокоманда ON_WM_PAINT(), а макрокоманде – обработчик OnPaint(). Этот обработчик может выглядеть следующим образом:
Пример обработчика сообщения WM_PAINT
void CMainWin::OnPaint()
{CPaintDC dc(this); // получение контекста окна
dc.TextOut(1,1, str, strlen(str)); // отображение символа
}
В примере приведен обработчик OnPaint(), который обеспечивает вывод на экран символа, введенного с клавиатуры пользователем соответственно обработчику OnChar(), записанному в предыдущем примере. Видно, что для получения контекста устройства здесь использован объект другого типа, а именно CPaintDC. В отличие от CClientDC, который работает только с клиентской частью окна программы, CPaintDC обеспечивает роботу со всей плоскостью окна.
В программе желательным было бы, чтобы Windows самостоятельно решала, когда ей вызвать сообщение WM_PAINT. Это так и происходит, например, когда пользователь программы минимизирует окно, максимизирует, движет экраном, изменяет размеры окна и т.п.. Но иногда необходимо проводить обновление окна принудительно. Для того, чтобы прислать сообщение WM_PAINT, программа вызывает функцию InvalidateRect() – член класса CWnd, которая имеет следующий прототип:
void CWnd::InvalidateRect(LPCRECT lpRegion, BOOL Erase=TRUE);
где lpRegion – указатель на область окна, которую необходимо обновить, Erase – флаг, который в значении TRUE устанавливает изъятие предыдущего содержимого окна. Если указать первому параметру значения NULL, произойдет полное обновление окна. Вызов функции InvalidateRect() обеспечивает принудительную посылку сообщения WM_PAINT и выполнение обработчика OnPaint().
Полное обновление окна, как например:
InvalidateRect(NULL);
занимает много ресурсов системы, которая визуально может выглядеть мерцанием рабочего окна программы. Этого можно избегнуть, задав отдельно область обновления, например:
СRect region(10,10,100,100);
InvalidateRect(region);
в таком случае будет обновляться лишь область, ограниченная прямоугольником с левым верхним углом (10,10) и нижним правым углом (100,100). Такой вариант обновления становится особенно интересным, если необходимо обеспечить подвижность отдельных элементов окна, а этого можно достичь с одновременным применением обработки сообщения таймера WM_TIMER.
... в Win32 позволила реализовать так называемые многопотоковые приложения (multithread application). При этом выделяют два новых понятия — процесс (proccess) и поток (thread). Процессы в Win32 API примерно эквивалентны приложениям в Windows API. Для каждого процесса выделяются определенные системные ресурсы — адресное пространство, приоритеты и права доступа к разделяемым ресурсам и прочее, но не ...
... предприятия. Для дальнейшего развития Системы необходимо рассчитать экономическую эффективность проекта. Для этого необходимо выбрать направление распространения Системы. Заказчиком системы выступало закрытое акционерное общество "Белгородский бройлер". Произведем расчет экономической эффективности проекта с точки зрения заказного проекта. Структура экономической части при создании программного ...
... доступа с записью равной байту. Такие файлы называются двоичными. Файлы прямого доступа незаменимы при написании программ, которые должны работать с большими объемами информации, хранящимися на внешних устройствах. В основе обработке СУБД лежат файлы прямого доступа. Кратко изложим основные положения работы с файлами прямого доступа. 1). Каждая запись в файле прямого доступа имеет свой номер ...
0 комментариев