- •Методические рекомендации
- •План лекции
- •Интерфейс графического устройства
- •Программирование, основанное на ресурсах
- •Управления памятью
- •Документы и их представление
- •Контрольные вопросы
- •Редактирование функций.
- •Изучение работы приложения.
- •Самостоятельная работа.
- •Добавление своего класса.
- •Домашняя работа.
- •Лекция 2. Основы программирования. Работа с классом Вид. Методические рекомендации:
- •Интерфейс графического устройства
- •Работа с gdi объектами
- •Пример создания нового gdi объекта
- •Режимы преобразования координат
- •Режимы преобразования координат с постоянным масштабом
- •Режимы преобразования координат с переменным масштабом
- •Замечание
- •Координатные пространства mfc
- •Пример использования режимов преобразования координат
- •Работа с окнами, содержащими полосы прокрутки
- •Линейки прокрутки
- •Различные способы прокрутки
- •Прием ввода с клавиатуры
- •Контрольные вопросы
- •Обработка сообщений от мыши.
- •Задание для самостоятельной домашней разработки.
- •Лекция 3. Меню. Панели инструментов и строки состояния Методические рекомендации
- •Меню Windows
- •Обновление командного пользовательского интерфейса
- •Класс cMenu
- •Создание контекстных меню
- •Панели элементов управления и каркас приложений
- •Панель инструментов
- •Растровое изображение панели инструментов
- •Состояния кнопок Любая кнопка может находиться в следующих состояниях
- •Всплывающие подсказки
- •Строка состояния
- •Определение секций в строке состояния
- •Строка сообщений
- •Индикатор состояния
- •Управление строкой состояния
- •Контрольные вопросы:
- •Добавление переменных-членов.
- •Добавление функции OnMouseMove.
- •Программирование команд контекстного меню.
- •Программирование команд главного меню.
- •Домашняя работа.
- •Лекция 4. Диалоговые окна и стандартные элементы управления Методические рекомендации
- •Работа с модальным диалоговым окном
- •Стандартные элементы управления
- •Работа с немодальными диалоговыми окнами
- •Пользовательские сообщения
- •Принадлежность диалогового окна
- •Контрольные вопросы
- •Создание класса “диалогового окна”.
- •Добавление переменных-членов класса вашего диалогового окна.
- •Написание инициализирующего кода
- •Присваивание переменным начальных значений.
- •Самостоятельная работа.
- •Домашнее задание.
- •Лекция 5. Обработка сообщений Windows и программирование многопоточных приложений Методические рекомендации
- •Обработка сообщений в однопоточной программе
- •Передача управления
- •Таймеры
- •Обработка в периоды простоя
- •Программирование многопоточных приложений
- •Функция рабочего потока и запуск потока
- •Общение основного потока с рабочим
- •Общение рабочего потока с основным
- •Синхронизация потоков с использованием событий
- •Блокировка потоков
- •Критические секции
- •Потоки пользовательского интерфейса
- •Контрольные вопросы
- •Домашнее задание.
- •Задание для самостоятельной работы
- •Управление процессом Пример 1.
- •2. Замена образа процеса Пример 2. Использование функции exec.
- •Пример 3. Использование неименованного канала.
- •Пример 4. Создание именованного канал с именем "fifo".
- •3. Сигналы.
- •Пример 5. Использование сигналов.
- •Пример 6. Сообщения.
- •Пример 7. Сообщения.
- •Пример 8. Разделение памяти.
- •Пример 9. Использование семафоров.
- •Пример 10. Создание процесса вWindows.
- •Пример 11. Использование неименованного канала.
- •Пример 12. Использование именованного канала.
- •Пример 13. Использование разделяемой памяти File Mapping.
- •Пример 14. Использование Mailslot.
- •Пример 15. Использование событий.
Пример 15. Использование событий.
Приложение использует событийный объект, чтобы предохранить несколько нитей от чтения разделенной памяти, в то время как основная нить пишет в этот буфер. Сначала основная нить, используя функцию CreateEvent создаёт массив событийных объектов. Она определяет событие, которое не возникает, когда основная нить пишет в разделяемую память, и возникает по окончании записи.Затем основная нить создаёт несколько читающих из разделяемой памяти нитей. Каждая нить-читатель устанавливает своё событие, чтобы сигнализировать когда она закончит читать из разделяемой памяти.
#include <vcl.h>
#include <stdio.h>
#pragma hdrstop
#pragma argsused
#define NUMTHREADS 4
void ThreadFunction(LPVOID lpParam);
void CreateEventsAndThreads(void);
void WriteToBuffer(void);
HANDLE hGlobalWriteEvent;
HANDLE hReadEvents[NUMTHREADS], hThread;
HANDLE hfilemap;
DWORD IDThread;
unsigned char *pwrite,i;
int main(int argc, char* argv[])
{
LPMSG msg;
CreateEventsAndThreads();
WriteToBuffer();
while (GetMessage(msg, NULL, 0, 0))
DispatchMessage(msg);
}
/* Создаёт событие, которое активизируется при окончании записи в память*/
void CreateEventsAndThreads(void){
hGlobalWriteEvent = CreateEvent(
NULL, // Security_Attributes
TRUE, // программный вызов события
TRUE, // статус инициализации события - активно
"WriteEvent" // имя объекта
);
if (hGlobalWriteEvent == NULL)
{GetLastError(); exit;}
/* Создаёт множество нитей и события для каждой с автосбросом.
Каждая нить устанавлмвает событие в активное, когда не читает из памяти
*/
for(i = 0; i < NUMTHREADS; i++)
{
// Создаёт массив автматических дезактивирующихся событий для читателей.
hReadEvents[i] = CreateEvent(
NULL, // Security_Attributes
FALSE, // автосброс события
TRUE, // статус инициализации события - активно
NULL); // неименованное событие
if (hReadEvents[i] == NULL)
{GetLastError(); exit;}
hThread = CreateThread(
NULL, // Security_Attributes
0, // Размер буфера
(LPTHREAD_START_ROUTINE) ThreadFunction, // Исполняемая функция
&hReadEvents[i], // Передача хендла события
0, // Флаги создания
&IDThread); // Идентификатор нити
if (hThread == NULL)
{GetLastError(); exit; }
}
}
VOID WriteToBuffer(VOID)
{
DWORD dwWaitResult, i;
// Сбрасывает событие hGlobalWriteEvent в неактивное, блокируя чтение.
if (!ResetEvent(hGlobalWriteEvent) )
{GetLastError(); exit;}
//Ожидает пока все нити закончат чтение.
dwWaitResult = WaitForMultipleObjects(
NUMTHREADS, // число хендлов в массиве событий читателей
hReadEvents, // массив хендлов событий читателей
TRUE, // ожидать пока все события не активизируются
INFINITE); // бесконечное ожидание
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
printf(" /nMainthread: All read-event were signaled");
// Создаёт разделяемую память и пишет в неё 10 чисел
hfilemap=CreateFileMapping(NULL,NULL,PAGE_READWRITE,0,10,"shmem");
pwrite=(unsigned char *)MapViewOfFile(hfilemap,FILE_MAP_ALL_ACCESS,0,0,0);
printf("\n Mainthread write to share memory ");
for (i = 1; i<=10; i++)
{*pwrite=i; printf("%d ",*pwrite); pwrite++;}
break;
// An error occurred.
default:
printf("Wait error: %d\n", GetLastError());
ExitProcess(0);
}
// Устанавливает hGlobalWriteEvent в активное состояние.
if (! SetEvent(hGlobalWriteEvent) )
{GetLastError(); exit;}
// Set all read events to signaled.
for(i = 1; i <= NUMTHREADS; i++)
if (! SetEvent(hReadEvents[i]) )
{GetLastError(); exit;}
}
VOID ThreadFunction(LPVOID lpParam)
{
DWORD dwWaitResult;
HANDLE hEvents[2];
unsigned char *pread,i;
hEvents[0] = *(HANDLE*)lpParam; // нить читает хендл своего события
hEvents[1] = hGlobalWriteEvent; // событие на запись
dwWaitResult = WaitForMultipleObjects(
2, // число хендлов в массиве
hEvents, // массив хендловсобытий
TRUE, // ожидать пока все соьытия не активизируются
INFINITE); // бесконечное ожидание
switch (dwWaitResult)
{
// Оба события активны
case WAIT_OBJECT_0:
HANDLE hMapFile;
hMapFile = OpenFileMapping(FILE_MAP_READ, FALSE,"shmem");
pread=(unsigned char*)MapViewOfFile(
hMapFile, // Handle to mapping object.
FILE_MAP_ALL_ACCESS, // Read/write permission.
0, // Max. object size.
0, // Size of hFile.
0);
if (pread==NULL) // Map entire file.
{GetLastError();
ExitThread(0);}
printf("\nThread read from share memory \n");
for (i=1;i<=10;i++)
printf("%d ",*pread++);
break;
default:
printf("Wait error: %d\n", GetLastError());
ExitThread(0);
}
// Set the read event to signaled.
if (! SetEvent(hEvents[0]) )
{
// Error exit.
}
}