Курсовая на тему Розробка програми для демонстрації автомобільного руху через залізнодорожний переїзд
Работа добавлена на сайт bukvasha.net: 2015-07-01Поможем написать учебную работу
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Міністерство освіти і науки України
Вінницький національний технічний університет
Інститут інформаційних технологій та комп’ютерної інженерії
Кафедра захисту інформації
Розробка програми для ДЕМОНСТРАЦІЇ АВТОМОБІЛЬНОГО РУХУ ЧЕРЕЗ ЗАЛІЗНОДОРОЖНІЙ ПЕРЕЇЗД
Вінниця 2008
Анотація
Даний курсовий проект призначений для демонстрування автомобільного руху через залізнодорожній переїзд . Програма демонструє рух автомобіля через переїзд, та наслідки, які можуть виникнути внаслідок неуважності працівника переїзду. Для досягнення поставленої задачі використовується програмне середовище Visual C++ 8.0 з використанням Win32 API функцій. Програма реалізує діалоговий інтерфейс користувача, який включає головне меню, що викликає потрібні користувачеві дії: запуск програми, виклик вікон для виконання потрібних дій.
ЗМІСТ
ВСТУП 5
1 Розробка структури програмного забезпечення
1.1 Обгрунтування структури програмного забезпечення
1.2 Розробка головного меню програми
1.3 Розробка структури програми
1.4 Створення ресурсів
1.5 Алгоритм роботи додатку
1.6 Розробка загальної схеми функціонування програми
2 Програмна реалізація задачі
2.1 Підбір програмних засобів
2.2 Реалізація інтерфейсу
2.3 Реалізація виведення графічних зображень
2.4 Програмна реалізація вікна
2.5 Програмна реалізація загальних елементів керування та музики
2.6 Програмна реалізація роботи з шлагбаумом
3 Аналіз результатів роботи програми
3.1 Інструкція з технічного обслуговування
3.2 Інструкція системного програміста
3.3 Інструкція програміста
3.4 Інструкція оператора
ВИСНОВКИ
ПЕРЕЛІК ВИКОРИСТАНИХ ДЖЕРЕЛ
Додаток. Лістинг програми
Вступ
Основною ідеєю структурного програмування є розділення складної задачі на декілька менших задач, і це ділення треба продовжувати до тих пір поки задачі не стануть простими для розуміння. Основною ідеєю сучасного програмування є створення окремих елементів, придатних до складання конкретних програм.
На відміну від бібліотек стандартних підпрограм, в яких теж використовується повторні модулі об’єктно-орієнтований підхід дозволяє створити ще ієрархію вкладених один в одного модулів. Модель об’єктно-орієнтованого програмування базується на декількох основних принципах: абстрагуванні даних, інкапсуляції, наслідувані та поліморфізмі.
Абстракція даних – це можливість визначати нові типи даних, з якими можна працювати майже так само, як і з основними. Такі типи називають абстрактними, хоча більш точною назвою є “типи даних, що визначаються користувачем”.
Інкапсуляція – це механізм, який об’єднує дані і код, що працює з цими даними і захищає перше та друге від зовнішнього втручання або неправильного використання.
Наслідування – це процес, за допомогою якого один об’єкт може отримати властивості іншого.
Поліморфізм – це властивість програми вести себе по-різному, в залежності від ситуації, що виникає в момент виконання. Ця властивість полягає у принципі перевантаження функцій, тобто в не однократній об’яві функції з різними типами аргументів. Всі вони базуються на використанні класів.
Об’єктно-орієнтоване програмування є дуже потужним засобом програмування, який є одним з передових підходів до програмування. Однією з найдосконаліших програмних реалізацій цієї мови є програмний пакет Microsoft Visual C++ 8.0, за допомогою якого і буде реалізована дана курсова робота.
Розробка структури програмного забезпечення
Обґрунтування структури програмного забезпечення
Оскільки данна програма буде використовуватись в середовищі MS Windows, потрібно створити, просте та зручне для користувача, меню.
Для демонстрації автомобільного руху через переїзд необхідно використати зрозумілий інтерфейс та зробити зрозумілою роботу самої програми. Меню буде створене з простими та зручними пунктами.
Меню має складатись з таких пунктів: “Старт Поїзда”, “Керування Шлагбаумом”, “Сервіс”, “Вихід”. В пункті меню “Сервіс будуть: відомості про розробника програми, саме завдання та допомога по використанню програмного продукту.
Самим головним пунктом меню програми буде “Старт Поїзда”. Який наглядно покаже рух автомобіля (рух автомобіля керується за допомогою шлагбаума), поїзда, та приклад аварії.
Розробка головного меню програми
Меню повинно містити два основні та два додаткових розділи: Старт Поїзда та Керування шлагбаумом, Сервіс та Вихід, в яких буде реалізовано доступ користувача до всіх можливостей програмного продукту.
Розглянемо кожен пункт меню детальніше:
Старт поїзда – початок руху поїзда.
Керування Шлагбаумом:
Підняти Шлагбаум;
Опустити Шлагбаум;
Сервіс:
Завдання Курсової – варіант та зміст задачі;
Інфо –відомості про виконавця;
Допомога – допомога.
Вихід – завершення роботи програми .
Розробка структури програми
Розглянемо структуру програми. Після запуску програми, на екрані з’явиться головне вікно додатку. У ньому буде реалізовано фоновий малюнок, на якому буде відбуватись власне й рух автомобіля та поїзда. Рух буде показаний у вигляді чотирьох малюнків, завантажених у проект (детальніше при програмній реалізації): дорога і переїзд (Background..bmp), шлагбаум (Shlagbaym.bmp), поїзд (train.bmp), автомобіль (car2.bmp).Для того, щоб програма була зручною для користувача, потрібно створити дружній і зручний інтерфейс. Це може бути свій оригінальний курсор, іконка, екранна заставка і т.п.
Кнопки Завдання Курсової, Інфо, Допомога будуть представленні у вигляді діалогових вікон.
Підсумовуючи вище сказане, можна зробити висновок, що майбутній програмний продукт буде складатися з однієї віконної та чотирьох діалогових процедур, що забезпечить створення зручного для стороннього користувача інтерфейсу.
Створення ресурсів
Для підключення іконки та курсору необхідно підключити до проекту створений файл ресурсів. Назвемо його l3.rc. Добавимо курсор: IDC_CURSOR1, (рис. 1.1), далі іконки: IDI_ICON1, IDI_ICON2 (рис. 1.2).
Рисунок 1.1 – Вигляд курсору
Рисунок 1.2 – Вигляд іконок
Для підключення ресурсів потрібно на початку програми написати таку стрічку: #include «resource.h», та вказати курсор, меню та іконку при реєстрації вікна:
RegClass(WndProc,szMainClass,COLOR_APPWORKSPACE,IDI_ICON1,IDC_CURSOR1,
IDR_MENU1)
Завдання курсової (рис. 1.3), інформація про виконавця (рис. 1.4), допомога (рис. 1.5) потрібно оформити діалоговими вікнами, щоб зробити стиль програми більш гарнішимзручнішим.
Рисунок 1.3 – Вигляд діалогового вікна «Завдання Курсової роботи»
Рисунок 1.4 – Вигляд діалогового вікна «Інфо»
Рисунок 1.5 - Вигляд діалогового вікна «Допомога»
Алгоритм роботи додатку
При натисненні на пункт меню «Старт Поїзда» буде рухатись поїзд, при цьому машина рухається залежно від положення шлагбауму. При натисненні на «Керування Шлагбаумом» ->«Підняти Шлагбаум» - шлагбаум піднімається, і автомобіль продовжує рух, «Керування Шлагбаумом» ->«Опустити Шлагбаум» - шлагбаум опускається і автомобіль зупиниться, коли під`їде до нього. Нижче наведено алгоритм, за яким працює додаток (рис. 1.6).
Рисунок 1.6 – Алгоритм дорожнього руху
Розробка загальної схеми функціонування програми
При завантаженні програми відкриється вікно з меню. Алгоритм, представлений у вигляді схеми, наведений нижче (рис. 1.7).
Рисунок 1.7 – Загальна схема програми
Програмна реалізація задачі
Підбір програмних засобів
В даному програмному продукті потрібно наглядно показати, як підключити і працювати з ресурсами при використанні API-функцій. Програма складається з однієї віконної та чотирьох діалогових функцій, що викликаються в залежності від команд користувача. Для кожного вікна потрібно реалізувати прийнятний для користувача інтерфейс. Для цього потрібно показати як реалізується графічне представлення програми, як потрібно створити і працювати з різними типами вікон.
Для більш цікавішої роботи програми потрібно підключити загальні елементи керування та доповнити рух певними звуками. Рухомість графічних зображень додасть програмі динамічності.
Реалізацію кожного елемента програми розглянемо в окремих пунктах.
Реалізація інтерфейсу
Як було сказано у попередніх розділах головне меню знаходиться в головному вікні. Воно складається з розділів: Старт Поїзда, Керування Шлагбаумом, Сервіс та Вихід. При натисненні на «Вихід» вилетить текстове повідомлення, яке буде просити відповіді. Це повідомлення являє собою функцію MessageBox, яка створює, відображає, забезпечує роботу та закриває вікно повідомлення:
int WIAPI MessageBox(HWND hWnd, LPCTSTR Text, LPCTSTR lpCaption,
UINT uType );
Якщо hWnd=NULL, вікно повідомлення не має батьківського вікна. При lpCaption = NULL, в заголовок виводиться рядок “Помилка”. Параметр uType визначає зміст та поводження вікна повідомлень. Також передбачена можливість видачі звукових повідомлень, при визові функції MessageBeep. Синтаксис цієї функції:
BOOL MessageBeep(UINT uType);
У даній курсовій роботі MessageBox використовується при виході із програми в такому вигляді:
MessageBox(hWnd,
"Ви впевнені?",
"?",
MB_OKCANCEL|MB_ICONQUESTION|MB_SYSTEMMODAL);
Інші пункти меню розглянемо під наступними розділами.
Реалізація виведення графічних зображень
Даний програмний продукт має доволі багато графічної інформації, що на думку виконавця повинно надавати програмі кращого вигляду.
Виведення графічної інформації відбувається при обробці повідомлення системи WM_PAINT за допомогою об’єкту типу HDC, за допомогою функції BeginPaint().
Так в головному вікні виводиться фоновий малюнок, значок університету та текст. Малюнок та значок являють собою растрові зображення, для їх виводу використовують тип BITMAP. Ці об’єкти потрібно загрузити з файлу в пам’ять, визначити розміри вікна і розташувати по своїм місцям у вікні.
Програмний код, що реалізує виведення фонового малюнку представлений нижче.
PAINTSTRUCT ps; // структура для параметрів контексту
hdc = BeginPaint(hWnd, &ps); // отримуємо хендл контексту пристрою
hBmpBckGrnd = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP1));
GetObject ( hBmpBckGrnd, sizeof(BITMAP),&bitmap);// отримали розміри зображення
hCompDC = CreateCompatibleDC ( hdc );
oBitmap = (HBITMAP)SelectObject ( hCompDC, hBmpBckGrnd );
// ввели наше зображення у контекст в пам’яті
// і запам’ятали те, що витіснили звідти
StretchBlt (hdc, r.left, r.top, r.right, r.bottom, // куди
hCompDC, 0, 0, bitmap.bmWidth, bitmap.bmHeight, // звідки
SRCCOPY); // як
// “натягнули” зображення в пам’яті на екран
SelectObject ( hCompDC, oBitmap ); // повернули в контекст в пам’яті попередній //вміст
DeleteObject ( hBmpBckGrnd ); // знищили об’єкт
Програмна реалізація вікна
Вікно повинне мати свою віконну функцію:
hWnd = CreateWindow (szMainClass,// Створюється вікно нашого класу
szTitle, // Заголовок створюємого вікна
WS_OVERLAPPED|WS_SYSMENU|WS_MINIMIZEBOX|
WS_VISIBLE|WS_BORDER|WS_DLGFRAME|
TBSTYLE_TOOLTIPS, //Тип вікна
CW_USEDEFAULT, //стандартне
//гориз. разміщення
CW_USEDEFAULT, // стандартное
//вертикальне розміщення
1000, //стандартна ширина вікна
600, // стандартна висота вікна
NULL, // дескриптор батьківського вікна
NULL, // меню у вікна відсутнє
hInstance, // дескриптор программы */
NULL // покажчик на данні вікна(для MDI-вікон));
if (!hWnd) return NULL;
Кожного разу вікно потрібно показати та обновити у пам’яті:
ShowWindow(hWnd,nCmdShow);
UpdateWindow(hWnd);
Щоб зареєструвати вікно потрібно використати API-функцію RegisterClass(&wc).
if(!RegClass(WndProc,szMainClass,COLOR_APPWORKSPACE,IDI_ICON1,IDC_CURSOR1,IDR_MENU1)) return FALSE;
Для створення діалогового вікна потрібна наявність трьох компонентів:
шаблону діалогу (описує форму і розміщення самого діал. вікна і всіх його внутрішніх елементів керування на екрані);
програмного коду, який утворює і відображає його на екрані;
діалогової процедури, яка обслуговує взаємодію користувача з блоком діалогу.
Діалогова процедура потрібна для обробки повідомлень, пов’язаних з обміном даних у діалоговому вікні.
Для дочірніх та діалогових вікон потрібно об’явити прототип віконної функції:
BOOL CALLBACK DlgProg(HWND hdWnd,UINT mes,WPARAM wParam,LPARAM lParam);
BOOL CALLBACK DlgProg2 (HWND hdWnd,UINT mes,WPARAM wParam,LPARAM lParam);
BOOL CALLBACK DlgProg3 (HWND hdWnd,UINT mes,WPARAM wParam,LPARAM lParam);
BOOL CALLBACK DlgProg4 (HWND hdWnd,UINT mes,WPARAM wParam,LPARAM lParam);
Програмна реалізація діалогового вікна, що містить завдання:
BOOL CALLBACK DlgProg2(HWND hdWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CLOSE:
{
EndDialog(hdWnd, 0);
return 1;
}
}
return 0;
}
Програмна реалізація загальних елементів керування та музики
Для того, щоб показати свої вміння більш обширного використання ресурсів мови програмування VС++, я використав два загальних елементи керування: Стрічки стану та акселератори.
Щоб додати до проекту будь – який елемент керування потрібно зробити такі додаткові дії:
#include <commctrl.h>
Project Setting Link Object\Library modules : comctl32.lib
Підключаємо до проекту бібліотеку <commctrl.h>, яка містить бази даних для роботи з загальними елементами керування та дописуємо по вище написаному напрямку рядок comctl32.lib.
Добавлення рядка стану має такий вигляд:
#define ID_STATUS 120
...
LRESULT CALLBACK Window (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
static HWND hStatus;
switch(msg)
{
case WM_CREATE:
{
hStatus = CreateStatusWindow (WS_CHILD|WS_VISIBLE,
"Готово", hWnd, ID_STATUS);
return 0;
}
...
}
Рядок стану – це дочірнє вікно з певними параметрами. Для того, щоб розбити цей рядок на декілька областей потрібно:
static int parts[2];
...
parts[0]=cx/2; parts[1]=cx;
SendMessage(hStatus,SB_SETPARTS,2,(LPARAM)parts);
...
Для підключення акселераторів ( комбінація клавіш ) потрібно:
Insert Resource Accelerator
Описати потрібний набір клавіш для пунктів меню
Або в самій програмі потрібно написати:
HACCEL CreateAccelTable(void)
{ //Масив акселераторов
ACCEL Accel[4];
// Старт
Accel[0].fVirt=FVIRTKEY|FCONTROL;
Accel[0].key=0x53;//"S"
Accel[0].cmd=IDM_START;
//Шлагбаум
Accel[1].fVirt=FVIRTKEY|FCONTROL;
Accel[1].key=0x57;// "W"
Accel[1].cmd=IDM_EDIT;
//Инфо
Accel[2].fVirt=FVIRTKEY|FCONTROL;
Accel[2].key=0x49;//"I"
Accel[2].cmd=IDM_INFO;
//Выход
Accel[3].fVirt=FVIRTKEY|FCONTROL;
Accel[3].key=0x45;//"E"
Accel[3].cmd=IDM_EXIT;
return CreateAcceleratorTable((LPACCEL)Accel,4);
}
int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
HACCEL hAccel=CreateAccelTable();
}
...
while(GetMessage(&msg,NULL,0,0))
{
if (!TranslateAccelerator(hWnd,hAccel,&msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
DestroyAcceleratorTable(hAccel);
...
Для додання до проекту звуку потрібно зробити такі додаткові дії:
Project Setting Link Object\Library modules : winmm.lib
Для того, щоб грав звук потрібно написати таку функцію:
PlaySound (“train”, hInstance, SND_RESOURCE | SND_ASYNC)
Перший параметр відповідає за назву звуку.
Програмна реалізація роботи з шлагбаумом
Спочатку необхідно об’явити змінні, які будуть відповідати за рух машини та поїзда. Оскільки цих два об’єкти являють собою малюнки їх необхідно завантажити у ресурси, а потім завантажувати з ресурсів у програму.
Програмна реалізація зображення машини:
hBmpCar1 = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP4));
DrawTransparentBitmap(hdc, // кінцевий DC.
hBmpCar1, // Бітмап, який буде намальований
X2, // координата X.
Y2, // координата Y.
0x00FFFFFF); // Колір для прозорих
// пикселів (в данном випадку білий
DeleteObject ( hBmpCar1 ); // знищили об’єкт
Програмна реалізація зображення поїзда:
hBmpTrain = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP4));
DrawTransparentBitmap(hdc, // кінцевий DC.
hBmpTrain, // Бітмап, який буде намальований
X, // координата X.
Y, // координата Y.
0x00FFFFFF); // Колір для прозорих
// пикселів (в данном випадку білий
DeleteObject (hBmpTrain ); // знищили об’єкт
Для того, щоб машина та поїзд рухались необхідно змінювати значення змінних X2 та Y2 – для машини, X – для поїзда (оскільки поїзд рухається горизонтально, координата Y залишається сталою), які відповідають за поточне місце на фоні . Над цією задачею працює таймер:
case WM_TIMER:
{
if ((shlagbaym==0)||(Y2<330)||(Y2>350))
{
if (car==0)
{
Y2-=13;
InvalidateRect(hWnd, &car1, FALSE);
}
if (car==1)
{
if (wham==0)
{
PlaySound("wham", hInstance,
SND_RESOURCE|SND_ASYNC);
wham++;
}
X2+=13;
InvalidateRect(hWnd, &car1, FALSE);
}
if ((Y2<-200)||(X2>1000))
{
Y2=800;
X2=450;
}
}
if (par==1)
{
X+=10;
InvalidateRect(hWnd, &train, FALSE);
if(X<=(X2+45)&&(X+538)>=(X2-1)
&&(Y+118)>=(Y2+1)&&(Y<=Y2+85))
car=1;
if (X>1001)
{
X2=450;
par=0;
car=0;
wham=0;
}
}
return 0;
}
Для запуску таймера необхідно записати таку функцію:
int Speed=10;
…………….
SetTimer(hWnd,1,Speed,NULL);
Перший параметр вказує дескриптор вікна, другий – номер таймера, третій – швидкість. Останній пов’язаний з системою, за замовчуванням рівний нулю.
Шлагбаум теж потрібно намалювати:
if(shlagbaym==0)
{
SendMessage(hStatus, SB_SETTEXT, 1, (LONG)"Увага!
Шлагбаум відкрито!");
if (w==0)
{
InvalidateRect(hWnd, &shlagbm, FALSE);
w++;
}
hBmpShlagbaym = LoadBitmap(hInstance,
MAKEINTRESOURCE(IDB_BITMAP9));
DrawTransparentBitmap(hdc,hBmpShlagbaym,X3,Y3,0x00FFFFFF);
DeleteObject ( hBmpShlagbaym ); // знищили об’єкт
}
if(shlagbaym==1)
{
SendMessage(hStatus, SB_SETTEXT, 1, (LONG)"Увага! Шлагбаум
закрито!");
if (w==1)
{
InvalidateRect(hWnd, &shlagbm, FALSE);
w--;
}
hBmpShlagbaym = LoadBitmap(hInstance,
MAKEINTRESOURCE(IDB_BITMAP5));
DrawTransparentBitmap(hdc,hBmpShlagbaym,X3,Y3,0x00FFFFFF);
DeleteObject ( hBmpShlagbaym );
}
В залежності від змінної shlagbaym , шлагбаум знаходить або в опущеному або у піднятому стані.
При натисненні на «Керування Шлагбаумом» ->«Підняти Шлагбаум» шлагбаум піднімається, і автомобіль продовжує рух, «Керування Шлагбаумом» ->«Опустити Шлагбаум» шлагбаум опускається і автомобіль зупиниться, коли під`їде до нього. Щоб уникнути ДТП потрібно вчасно закрити шлагбаум, якщо не встигли – далі все залежить від випадку. Фрагмент коду, що описує все це наведемо нижче:
{
if ((shlagbaym==0)||(Y2<330)||(Y2>350))
{
if (car==0)
{
Y2-=13;
InvalidateRect(hWnd, &car1, FALSE);
}
if (car==1)
{
if (wham==0)
{
PlaySound("wham", hInstance, SND_RESOURCE|SND_ASYNC);
wham++;
}
X2+=13;
InvalidateRect(hWnd, &car1, FALSE);
}
if ((Y2<-200)||(X2>1000))
{
Y2=800; //Збиваємо значення на початкові
X2=450;
}
}
if (par==1)
{
X+=10;
InvalidateRect(hWnd, &train, FALSE);
if(X<=(X2+45)&&(X+538)>=(X2-1)&&(Y+118)>=(Y2+1)&&(Y<=Y2+85))
car=1;
if (X>1001)
{
X2=450; //Збиваємо значення на початкові
par=0;
car=0;
wham=0;
}
}
return 0;
}
Аналіз результатів роботи програми
Програмний продукт _-=Мій Курсовий Проект=-_ наглядно показує регулювання автомобільного руху через залізнодорожній переїзд, при використанні шлагбауму. Розроблений програмний продукт необхідно перевірити на конкретність роботи і підготувати інструкцію по роботі з ним.
3.1 Інструкція з технічного обслуговування
Вступ.
Дана інструкція призначена для технічного обслуговування програми, тобто встановлення її на комп’ютер та експлуатації.
Загальні вказівки.
Програма встановлюється на комп’ютер який відповідає вимогам технічних засобів поданих нижче.
Вимоги до технічних засобів.
Мінімальні системні вимоги:
Pentium III 1.5 ГГц;
128 MБ RAM;
12 MБ вільного місця на жорсткому диску;
Вмонтована звукова карта;
Windows ME, XP.
Рекомендовані системні вимоги:
Pentium III 2.0 ГГц;
128 MБ RAM;
15 MБ вільного місця на жорсткому диску;
Вмонтована звукова карта;
Windows МЕ або XP.
Опис функцій.
Основне призначення програми _-=Мій Курсовий Проект=-_ наглядно показати регулювання автомобільного руху через залізнодорожній переїзд, при використанні шлагбауму. Для перевірки працездатності програми потрібно скористатись інструкцією системного програміста.
3.2 Інструкція системного програміста
Загальні відомості про програму.
Основне призначення програми _-=Мій Курсовий Проект=-_ наглядно показати регулювання автомобільного руху через залізнодорожній переїзд, при використанні шлагбауму.
Структура програми.
Для початку роботи необхідно дану програму скопіювати на комп’ютер в окрему папку. Сама програма складається одного файлу (рис. 3.1):
My_Kursach.exe – завантажувальний файл програми.
Рисунок 3.1 – Вигляд компонентів програми
Програма використовує 8024 Кбайт оперативної пам’яті.
Займає 5 885 952 байт пам’яті на жорсткому диску.
Перевірка програми.
Для того, щоб перевірити правильність роботи шлагбауму по регулюванню дорожнього руху потрібно виконати таку послідовність дій:
Виконати таку послідовність дій «Керування Шлагбаумом» ->«Опустити Шлагбаум»
Натиснути лівою кнопкою миші на пункт меню “Старт поїзда”
ДТП не повинне виникнути.
Виконати таку послідовність дій «Керування Шлагбаумом» ->«Підняти Шлагбаум»
Натиснути лівою кнопкою миші на пункт меню “Старт поїзда”
ДТП повинне виникнути в залежності від випадку, якщо ж таки автомобілю «повезе» проскочити перед поїздом, тоді пункт №5 повторити ще раз.
Якщо під час виконання усіх шести пунктів все пройшло так як пояснювалось у пункті №3 (ДТП не відбулось, хіба що шлагбаум був закритий запізно) і №6 (ДТП відбулось, при відкритому шлагбаумі) – програма правильно виконує свою роботу.
3.3 Інструкція програміста
Призначення і умови застосування програми.
Основне призначення програми _-=Мій Курсовий Проект=-_ наглядно показати регулювання автомобільного руху через залізнодорожній переїзд, при використанні шлагбауму.
Програма використовує 8024 Кбайт оперативної пам’яті.
Займає 5 885 952 байт пам’яті на жорсткому диску.
Характеристика програми.
Режим роботи визначається пунктами меню. (детальніше в інструкціях оператора). При наявності помилок в роботі шлагбауму закрити вікно додатку і перезавантажити програму. Якщо помилка не виправилась потрібно переустановити програмний продукт.
Звернення до програми.
Повний лістинг програми наведений в додатку. Робота окремих модулів наведена в другому розділі. Для внесення будь-яких в роботі програми необхідно відкоригувати потрібний код програми та виконати компіляцію.
3.4 Інструкція оператора
Призначення програми.
Основне призначення програми _-=Мій Курсовий Проект=-_ наглядно показати регулювання автомобільного руху через залізнодорожній переїзд, при використанні шлагбауму.
Умови виконання програми.
Програма буде працювати при складі апаратних і програмних засобів, які вказані в інструкціях з технічного обслуговування.
Виконання програми.
Для правильного функціонування даного програмного продукту ці файли повинні міститись в одній папці, бажано окремій (рис. 3.2):
Рисунок 3.2 – Вигляд папка з проектом
Для запуску програми треба запустити на виконання My_Kursаch.exe Після чого відбувається відкриття головного вікна програми (рис. 3.3).
Рисунок 3.3 – Загальний вигляд вікна
Якщо ви звернете увагу на самий низ вікна, ви побачите стрічку стану. При появі вікна, у ньому зразу буде рухатись автомобіль (рис 3.4).
Рисунок 3.4 – Загальний вигляд вікна з автомобілем
Натиснувши пункт меню «Старт поїзда» – почне рухатись поїзд(рис 3.5).
Рисунок 3.5 – Загальний вигляд вікна з автомобілем та потягом
Завдяки курсору миші користувач може маніпулювати рухом автомобіля і запускати рух поїзда. Керування автомобілем та запуск поїзда здійснюється завдяки натисканню лівої кнопки миші на пункті меню «Керування шлагбаумом» «Підняти шлагбаум» чи «Опустити шлагбаум», запустити потяг - «Старт поїзда», або за допомогою гарячих клавіш: Ctrl+W – Керування шлагбаумом, Ctrl+S – Старт поїзда (рис 3.6).
Рисунок 3.6 – Керування шлагбаумом та Старт поїзда
Рисунок 3.7 – Вигляд опущеного шлагбауму та поїзда в русі
Скориставшись меню Допомога (рис 3.8) отримаємо допомогу як керувати шлагбаумом та Запускати поїзд.
Рисунок 3.8 – Вигляд діалогового вікна “Допомога”
Для отримання відомостей про розробника програми використовуємо клавішу – акселератор Ctrl+I – це є пункт меню Інфо (рис 3.9).
Рисунок 3.9 – Вигляд діалогового вікна “Автор”
Для отримання відомостей про завдання роботи використовуємо пункт меню «Сервіс» «Завдання Курсової» (рис 3.10).
Рисунок 3.10 – Вигляд діалогового вікна “Завдання”
Для виходу з програми використовуємо «Вихід» або комбінацію клавіш Ctrl + E – для швидкого доступу до даного пункту меню (рис 3.11).
Рисунок 3.14 – Вигляд вікна повідомлення при виході з програми
При невірному виконанні роботи програми чи виникненні певних проблем у користуванні звертатися до розробника програмного продукту.
Висновки
В даній курсовій роботі було розроблено та реалізовано за допомогою мови програмування VС++ програмний продукт для демонстрації регулювання автомобільного руху через залізнодорожній переїзд з використанням шлагбауму.
При програмній реалізації були використані всі основні принципи об’єктно-орієнтованого програмування, тобто абстракція, наслідування, поліморфізм та інкапсуляція, оскільки мова програмування VС++ базується саме на цих принципах. Значною перевагою мови програмування VС++ відносно мов програмування, заснованих на принципах структурного та процедурного програмування, є те, що вона дозволяє правильно користуватись вже розробленими раніше функціями, об’єктами даних, не знаючи їх опису і об’яви. Це значно спрощує процес програмування і підвищує можливості даної мови. Так розробка ресурсів і використання стандартних панелей та елементів керування системи Windows в даній курсовій роботі відбувалося без знання, яким саме чином написані функції, які використовуються. Головне – це той результат, який повертає та чи інша функція.
Головним недоліком об’єктно-орієнтованого програмування є те, що проблема реалізації рішення тієї чи іншої задачі, полягає у проблемі пошуку потрібної функції, та інформації щодо її використання. Але пошук даної функції може зайняти навіть більше часу, ніж написання її аналогу програмістом. Крім того через незнання елементарних функцій, таких як АРІ-функції робить написання цього аналогу неможливим.
Отже мова програмування С++, як і інші мови, засновані на принципі об’єктно-орієнтованого програмування, не є досконалою, проте вона набагато більше відкрита для удосконалення, ніж мови, що засновані на інших принципах програмування. Тому вже зараз вона вважається найкращою для написання комерційних програм зі зручним інтерфейсом.
Перелік використаних джерел
Поляков А. Ю., Брусенцев В. А. Методы и алгоритмы компьютерной графики в примерах на Visual C++, 2-е изд., перераб. и доп. – СПб.: БХВ-Петербург, 2003. – 560 с.
Либерти Джесс. Освой самостоятельно С++ за 21 день, 4-е издание. : Пер. с англ. – М. : Издательский дом "Вильямс", 2003. – 832 с.
Глушаков С. В., Коваль А. В., Черепкин С. А. Програмирование на Visual C++ 6.0, Харьков: Фолио, 2002. – 726 с.
Семеренко В. П. Програмування мовами С та С++ в середовищі Windows. Навчальний посібник. – Вінниці: УНІВЕРСУМ – Вінниця, 2003. – 128 с.
Холзнер С. Visual C++ 6.: Учебный курс-СПб.: Питер, 2001. – 576 с.
Ганеев. Р. М. Проектирование интерфейса пользователя средствами Win32 API. .: Питер, 2001. – 350 с.
Конспект лекцій з дисципліни ,,Програмування’’ за перший та другий курси.
Павловская Т.А.. С/С++. Программирование на языке высокого уровня – СПб. : Питер, 2004. – 461 с.
Методичка.
Додаток
Лістинг програми
#include <windows.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <commctrl.h>
#include "resource.h"
#define ID_STATUS 200
/* Прототипы функций */
BOOL RegClass(WNDPROC,LPCSTR,UINT,UINT,UINT,UINT);
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK DlgProg(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK DlgProg2(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK DlgProg3(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK DlgProg4(HWND, UINT, WPARAM, LPARAM);
HACCEL CreateAccelTable(void);
void DrawTransparentBitmap(HDC, HBITMAP, short,short, COLORREF);
HINSTANCE hInstance;
char szMainClass[]="Головний клас";
char szTitle[]="_-=Мій Курсовий Проект=-_";
int X=-400, Y;
int X2=450, Y2=800;
int X3=460, Y3=120;
int Speed=50;
int par=0;
int car=0;
int shlagbaym=0, w=0;
int wham=0;
static TBBUTTON but[4];
HACCEL CreateAccelTable(void)
{ //Масив акселераторов
ACCEL Accel[4];
// Старт
Accel[0].fVirt=FVIRTKEY|FCONTROL;
Accel[0].key=0x53;//"S"
Accel[0].cmd=IDM_START;
//Шлагбаум
Accel[1].fVirt=FVIRTKEY|FCONTROL;
Accel[1].key=0x57;// "W"
Accel[1].cmd=IDM_EDIT;
//Инфо
Accel[2].fVirt=FVIRTKEY|FCONTROL;
Accel[2].key=0x49;//"I"
Accel[2].cmd=IDM_INFO;
//Выход
Accel[3].fVirt=FVIRTKEY|FCONTROL;
Accel[3].key=0x45;//"E"
Accel[3].cmd=IDM_EXIT;
return CreateAcceleratorTable((LPACCEL)Accel,4);
}
int WINAPI WinMain (
HINSTANCE hInst,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{
MSG msg; /* Структура для хранения сообщений */
static HWND hWnd; /* Дескриптор окна */
BOOL bRet; // for return value of GetMessage
hInstance=hInst;
if(!RegClass(WndProc,szMainClass,COLOR_APPWORKSPACE,IDI_ICON1,IDC_CURSOR1,IDR_MENU1))
return FALSE;
hWnd = CreateWindow (
szMainClass, /* Создается окно нашего класса */
szTitle, /* Заголовок создаваемого окна */
WS_OVERLAPPED|WS_SYSMENU|WS_MINIMIZEBOX|WS_VISIBLE|WS_BORDER|WS_DLGFRAME|
TBSTYLE_TOOLTIPS, /* Стандартный тип окна */
CW_USEDEFAULT, // стандартн. горизонтальное размещение
CW_USEDEFAULT, // стандартное вертикальное
1000, //стандартная ширина окна
600, // стандартная высота окна
NULL, // дескриптор родительского окна
NULL, // меню у окна отсутствует
hInstance, // дескриптор экземпляра программы */
NULL // указатель на данные окна (для MDI-окон)
);
if (!hWnd) return NULL;
but[0].iBitmap=STD_FILESAVE;
but[0].idCommand=IDM_START;
but[0].fsState=TBSTATE_ENABLED;
but[0].fsStyle=TBSTYLE_GROUP;
but[1].iBitmap=STD_CUT;
but[1].idCommand=IDM_EDIT;
but[1].fsState=TBSTATE_ENABLED;
but[1].fsStyle=TBSTYLE_BUTTON;
but[2].iBitmap=STD_COPY;
but[2].idCommand=IDM_INFO;
but[2].fsState=TBSTATE_ENABLED;
but[2].fsStyle=TBSTYLE_BUTTON;
but[3].iBitmap=STD_FILEOPEN;
but[3].idCommand=IDM_EXIT;
but[3].fsState=TBSTATE_ENABLED;
but[3].fsStyle=TBSTYLE_BUTTON;
CreateToolbarEx(hWnd,
WS_CHILD|WS_VISIBLE|WS_DLGFRAME|TBSTYLE_TOOLTIPS,
IDR_TOOLBAR1,
0,
HINST_COMMCTRL,
IDB_STD_SMALL_COLOR,
but,
4,
0,0,0,0,
sizeof(TBBUTTON));
ShowWindow(hWnd,nCmdShow); // функцiя вiдображення вiкна
UpdateWindow(hWnd); // функцiя оновлення вiкна
HACCEL hAccel=CreateAccelTable();
while ((GetMessage(&msg, NULL, 0, 0))!= 0)
{
if (!TranslateAccelerator( hWnd, // handle to receiving window
hAccel, // handle to active accelerator table
&msg)) // message data
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
DestroyAcceleratorTable(hAccel);
return msg.wParam;
}
BOOL RegClass(WNDPROC Proc, LPCSTR szName,UINT brBackground,UINT ic,UINT cur,UINT menu)
{
WNDCLASS wc; /* Структура класса окна */
wc.lpszClassName = szName, /* имя класса */
wc.lpfnWndProc = Proc; /* оконная процедура класса */
wc.style = CS_HREDRAW | CS_VREDRAW|CS_BYTEALIGNCLIENT;
wc.cbClsExtra=wc.cbWndExtra=0; /* стиль окна */
wc.hInstance = hInstance; /* дескриптор экземпляра программы */
wc.hIcon = LoadIcon( hInstance, (LPCSTR)ic );
wc.hCursor = LoadCursor( hInstance, (LPCSTR)cur );
wc.hbrBackground = (HBRUSH)(brBackground+1);
wc.lpszMenuName = (LPCSTR) menu;
return(RegisterClass(&wc)!=0); /* Регистрируем класс окна */
}
/* Оконная процедура */
LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam )
{
HDC hCompDC, hdc; // хендли контекстів пристрою
HBITMAP hBmpBckGrnd, hBmpTrain, oBitmap, hBmpCar1, hBmpShlagbaym;
// хендли нашого зображення і старого
BITMAP bitmap; // для зберігання розмірів зображення
RECT r; // для зберігання розмірів екрану
RECT train, car1, shlagbm;
static HWND hStatus;
int pParts[2];
SetTimer(hWnd,1,Speed,NULL);
GetClientRect(hWnd, &r);
pParts[0]=500;
pParts[1]=1000;
shlagbm.top=Y3;
shlagbm.left=X3;
shlagbm.bottom=Y3+215;
shlagbm.right=X3+215;
car1.left=X2;
car1.top=Y2;
car1.right=X2+96+13;
car1.bottom=Y2+168+13;
train.left=X-10;
train.top=Y;
train.right=X+538;
train.bottom=Y+118;
Y=85;
switch(msg)
{
case WM_CREATE:
{
hStatus=CreateStatusWindow(WS_CHILD|WS_VISIBLE, "Готово", hWnd, ID_STATUS);
SendMessage(hStatus, SB_SETPARTS, 2, (LPARAM)pParts);
return 0;
}
case WM_NOTIFY:
{
LPTOOLTIPTEXT t;
t=(LPTOOLTIPTEXT)lParam;
if (t->hdr.code!=TTN_NEEDTEXT)
return 0;
switch (t->hdr.idFrom)
{
case IDM_START:
t->lpszText="Старт поїзда";
break;
case IDM_EDIT:
t->lpszText="Керування шлагбаумом";
break;
case IDM_INFO:
t->lpszText="Інформація про виконавця";
break;
case IDM_EXIT:
t->lpszText="Вихід";
break;
}
}
case WM_PAINT:
{
PAINTSTRUCT ps; // структура для параметрів контексту
hdc = BeginPaint(hWnd, &ps); // отримуємо хендл контексту пристрою
hBmpBckGrnd = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP1));
GetObject ( hBmpBckGrnd, sizeof(BITMAP),&bitmap); // отримали розміри зображення
hCompDC = CreateCompatibleDC ( hdc );
oBitmap = (HBITMAP)SelectObject ( hCompDC, hBmpBckGrnd );
// ввели наше зображення у контекст в пам’яті
// і запам’ятали те, що витіснили звідти
StretchBlt (hdc, r.left, r.top, r.right, r.bottom, // куди
hCompDC, 0, 0, bitmap.bmWidth, bitmap.bmHeight, // звідки
SRCCOPY); // як
// “натягнули” зображення в пам’яті на екран
SelectObject ( hCompDC, oBitmap );// повернули в контекст в пам’яті попередній вміст
DeleteObject ( hBmpBckGrnd ); // знищили об’єкт
if (car==0)
{
hBmpCar1 = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP4));
DrawTransparentBitmap(hdc,// Конечный DC.
hBmpCar1,// Битмап, который будет нарисован.
X2, // координата X.
Y2, // координата Y.
0x00FFFFFF); // Цвет для прозрачных
// пикселей (в данном случае белый
DeleteObject ( hBmpCar1 ); // знищили об’єкт
}
if (car==1)
{
hBmpCar1 = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP10));
DrawTransparentBitmap(hdc, // Конечный DC.
hBmpCar1, // Битмап, который будет нарисован.
X2, // координата X.
Y2, // координата Y.
0x00FFFFFF); // Цвет для прозрачных
// пикселей (в данном случае белый
DeleteObject ( hBmpCar1 ); // знищили об’єкт
}
if(par==1)
{
SendMessage(hStatus, SB_SETTEXT, 0, (LONG)"Увага!!!Їде Поїзд!!!");
hBmpTrain = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2));
DrawTransparentBitmap(hdc, // Конечный DC.
hBmpTrain, // Битмап, который будет нарисован.
X, // координата X.
Y, // координата Y.
0x00FFFFFF); // Цвет для прозрачных
// пикселей (в данном случае
DeleteObject ( hBmpTrain ); // знищили об’єкт
}
else
SendMessage(hStatus, SB_SETTEXT, 0, (LONG)"Поїзд ще далеко :)");
if(shlagbaym==0)
{
SendMessage(hStatus, SB_SETTEXT, 1, (LONG)"Увага! Шлагбаум відкрито!");
if (w==0)
{
InvalidateRect(hWnd, &shlagbm, FALSE);
w++;
}
hBmpShlagbaym = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP9));
DrawTransparentBitmap(hdc, // Конечный DC.
hBmpShlagbaym,// Битмап, который будет нарисован.
X3, // координата X.
Y3, // координата Y.
0x00FFFFFF); // Цвет для прозрачных
// пикселей (в данном случае белый
DeleteObject ( hBmpShlagbaym ); // знищили об’єкт
}
if(shlagbaym==1)
{
SendMessage(hStatus, SB_SETTEXT, 1, (LONG)"Увага! Шлагбаум закрито!");
if (w==1)
{
InvalidateRect(hWnd, &shlagbm, FALSE);
w--;
}
hBmpShlagbaym = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP5));
DrawTransparentBitmap(hdc, // Конечный DC.
hBmpShlagbaym,// Битмап, который будет нарисован.
X3, // координата X.
Y3, // координата Y.
0x00FFFFFF); // Цвет для прозрачных
// пикселей (в данном случае белый
DeleteObject ( hBmpShlagbaym ); // знищили об’єкт
}
DeleteDC ( hCompDC );
EndPaint(hWnd, &ps); // знищуємо контекст пристрою
return 0;
}
case WM_TIMER:
{
if ((shlagbaym==0)||(Y2<330)||(Y2>350))
{
if (car==0)
{
Y2-=13;
InvalidateRect(hWnd, &car1, FALSE);
}
if (car==1)
{
if (wham==0)
{
PlaySound("wham", hInstance, SND_RESOURCE|SND_ASYNC);
wham++;
}
X2+=13;
InvalidateRect(hWnd, &car1, FALSE);
}
if ((Y2<-200)||(X2>1000))
{
Y2=800;
X2=450;
}
}
if (par==1)
{
X+=10;
InvalidateRect(hWnd, &train, FALSE);
if(X<=(X2+45)&&(X+538)>=(X2-1)&&(Y+118)>=(Y2+1)&&(Y<=Y2+85))
car=1;
if (X>1001)
{
X2=450;
par=0;
car=0;
wham=0;
}
}
return 0;
}
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case IDM_EXIT:
{
int k=MessageBox(hWnd, "Ви впевнені?","Вихід?",
MB_OKCANCEL|MB_ICONQUESTION|MB_SYSTEMMODAL);
if (k==IDOK) DestroyWindow(hWnd);
break;
}
case IDM_VARIANT:
{
DialogBox (hInstance, MAKEINTRESOURCE(IDD_DIALOG2), hWnd, DlgProg2);
return 0;
}
case IDM_INFO:
{
DialogBox (hInstance, MAKEINTRESOURCE(IDD_DIALOG3), hWnd, DlgProg3);
return 0;
}
case IDM_EDIT:
{
int i=0;
i=1;
DialogBox (hInstance, MAKEINTRESOURCE(IDD_DIALOG1), hWnd, DlgProg);
InvalidateRect(hWnd, &shlagbm, FALSE);
return 0;
}
case IDM_HELP:
{
DialogBox (hInstance, MAKEINTRESOURCE(IDD_DIALOG4), hWnd, DlgProg4);
return 0;
}
case IDM_START:
{
PlaySound("train", hInstance, SND_RESOURCE|SND_ASYNC);
InvalidateRect(hWnd, &r, FALSE);
X=-500;
par=1;
car=0;
X2=450;
wham=0;
return 0;
}
}
return 0;
}
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc (hWnd, msg, wParam, lParam);
}
BOOL CALLBACK DlgProg(HWND hdWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CLOSE:
{
EndDialog(hdWnd, 0);
return 1;
}
case WM_COMMAND:
{
switch (wParam)
{
case IDC_UPBUTTON:
{
if (par!=1)
{
shlagbaym=0;
}
EndDialog(hdWnd, 0);
return 1;
}
case IDC_DOWNBUTTON:
{
shlagbaym=1;
EndDialog(hdWnd, 0);
return 1;
}
}
return 1;
}
}
return 0;
}
BOOL CALLBACK DlgProg2(HWND hdWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CLOSE:
{
EndDialog(hdWnd, 0);
return 1;
}
}
return 0;
}
BOOL CALLBACK DlgProg3(HWND hdWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_COMMAND:
{
switch (wParam)
{
case IDOK:
{
EndDialog(hdWnd, 0);
return 1;
}
}
return 1;
}
case WM_CLOSE:
{
EndDialog(hdWnd, 0);
return 1;
}
}
return 0;
}
BOOL CALLBACK DlgProg4(HWND hdWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_COMMAND:
{
switch (wParam)
{
case IDOK:
{
EndDialog(hdWnd, 0);
return 1;
}
}
return 1;
}
case WM_CLOSE:
{
EndDialog(hdWnd, 0);
return 1;
}
}
return 0;
}
void DrawTransparentBitmap(HDC hdc, HBITMAP hBitmap, short xStart,
short yStart, COLORREF cTransparentColor)
{
BITMAP bm;
COLORREF cColor;
HBITMAP bmAndBack, bmAndObject, bmAndMem, bmSave;
HBITMAP bmBackOld, bmObjectOld, bmMemOld, bmSaveOld;
HDC hdcMem, hdcBack, hdcObject, hdcTemp, hdcSave;
POINT ptSize;
hdcTemp = CreateCompatibleDC(hdc);
SelectObject(hdcTemp, hBitmap); // Выбираем битмап
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
ptSize.x = bm.bmWidth; // Получаем ширину битмапа
ptSize.y = bm.bmHeight; // Получаем высоту битмапа
DPtoLP(hdcTemp, &ptSize, 1); // Конвертируем из координат
// устройства в логические
// точки
// Создаём несколько DC для хранения временных данных.
hdcBack = CreateCompatibleDC(hdc);
hdcObject = CreateCompatibleDC(hdc);
hdcMem = CreateCompatibleDC(hdc);
hdcSave = CreateCompatibleDC(hdc);
// Создаём битмап для каждого DC.
// Монохромный DC
bmAndBack = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);
// Монохромный DC
bmAndObject = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);
bmAndMem = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y);
bmSave = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y);
// В каждом DC должен быть выбран объект битмапа для хранения
// пикселей.
bmBackOld = (HBITMAP)SelectObject(hdcBack, bmAndBack);
bmObjectOld = (HBITMAP)SelectObject(hdcObject, bmAndObject);
bmMemOld = (HBITMAP)SelectObject(hdcMem, bmAndMem);
bmSaveOld = (HBITMAP)SelectObject(hdcSave, bmSave);
// Устанавливаем режим маппинга.
SetMapMode(hdcTemp, GetMapMode(hdc));
// Сохраняем битмап, переданный в параметре функции, так как
// он будет изменён.
BitBlt(hdcSave, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY);
// Устанавливаем фоновый цвет (в исходном DC) тех частей,
// которые будут прозрачными.
cColor = SetBkColor(hdcTemp, cTransparentColor);
// Создаём маску для битмапа путём вызова BitBlt из исходного
// битмапа на монохромный битмап.
BitBlt(hdcObject, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0,
SRCCOPY);
// Устанавливаем фоновый цвет исходного DC обратно в
// оригинальный цвет.
SetBkColor(hdcTemp, cColor);
// Создаём инверсию маски.
BitBlt(hdcBack, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0,
NOTSRCCOPY);
// Копируем фон главного DC в конечный.
BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdc, xStart, yStart,
SRCCOPY);
// Накладываем маску на те места, где будет помещён битмап.
BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, SRCAND);
// Накладываем маску на прозрачные пиксели битмапа.
BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND);
// XOR-им битмап с фоном на конечном DC.
BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT);
// Копируем на экран.
BitBlt(hdc, xStart, yStart, ptSize.x, ptSize.y, hdcMem, 0, 0,
SRCCOPY);
// Помещаем оригинальный битмап обратно в битмап, переданный в
// параметре функции.
BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcSave, 0, 0, SRCCOPY);
// Удаляем битмапы из памяти.
DeleteObject(SelectObject(hdcBack, bmBackOld));
DeleteObject(SelectObject(hdcObject, bmObjectOld));
DeleteObject(SelectObject(hdcMem, bmMemOld));
DeleteObject(SelectObject(hdcSave, bmSaveOld));
// Удаляем DC из памяти.
DeleteDC(hdcMem);
DeleteDC(hdcBack);
DeleteDC(hdcObject);
DeleteDC(hdcSave);
DeleteDC(hdcTemp);
}