Ім'я файлу: Шмендеренко Арістра ІПЗ-2 Курсова Робота.docx
Розширення: docx
Розмір: 744кб.
Дата: 19.12.2023
скачати


МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ

ДЕРЖАВНИЙ УНІВЕРСИТЕТ ІНФРАСТРУКТУРИ ТА ТЕХНОЛОГІЙ

ІНСТИТУТ УПРАВЛІННЯ, ТЕХНОЛОГІЙ ТА ПРАВА
ФАКУЛЬТЕТ УПРАВЛІННЯ ТА ТЕХНОЛОГІЙ
Кафедра інформаційних технологій

КУРСОВА РОБОТА

з дисципліни „Об’єктно-орієнтоване програмування”

на тему: Програмний продукт «Регулятор каналів гучності»
Студента групи ІПЗ-2 д.ф.н

Шмендеренка Арістарха Олександровича

спеціальності: Інженерія програмного забезпечення

Керівник: Овчарук І.В.

Національна шкала ________________

Кількість балів: _____ Оцінка: ECTS ___
Члени комісії:

_________ ___________

(підпис)

_________ ___________

(підпис)

_________ ___________

(підпис)
Київ – 2023
МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ

ДЕРЖАВНИЙ УНІВЕРСИТЕТ ІНФРАСТРУКТУРИ ТА ТЕХНОЛОГІЙ

ІНСТИТУТ УПРАВЛІННЯ, ТЕХНОЛОГІЙ ТА ПРАВА
Кафедра інформаційних технологій
рівень вищої освіти: перший (бакалаврський) рівень

галузь знань: 12 «Інформаційні технології»

спеціальність: 121 «Інженерія програмного забезпечення»
ЗАВДАННЯ

на курсову роботу
з дисципліни Об’єктно-орієнтоване програмування

студенту групи ІПЗ-2 д.ф.н.

Шмендеренку Арістарху Олександровичу

тема курсової роботи: Програмний продукт «Регулятор каналів гучності»

дата видачі завдання 07.02.2023

дата здачі роботи 16.05.2023
Завдання видав

керівник курсової роботи

к.т.н., доц. кафедри ІТ _________________ Овчарук І.В.

(підпис) (прізвище, ініціали)




Завдання прийняв до виконання

студент групи ІПЗ-2 д.ф.н. ___________ Шмендеренко А. О.

(підпис) (прізвище, ініціали)

ЗАТВЕРДЖУЮ

Керівник

курсової роботи

_______ Овчарук І.В.

(підпис) (ініціали, прізвище)

07лютого 2023 р.
Календарний план-графік

виконання курсової роботи
студентом ___Шмендеренко А. О._____

(прізвище, ініціали)



з/п

Назва етапів роботи та питань, які мають бути розроблені відповідно до завдання

Термін виконання

Позначки керівника про виконання завдання

1.

Вивчення та аналіз задачі

14.02.2023




2.

Розробка загальної структури програмного продукту

7.03.2023




3.

Реалізація програмного продукту

18.04 2023




4.

Захист програмного продукту

25.04.2023




5.

Оформлення пояснювальної записки

10.05.2023




6.

Дата здачі роботи

16.05.2023























































































































































Студент ________________ Шмендеренко А.О._

(підпис) (прізвище, ініціали)

АНОТАЦІЯ

Метою курсової роботи є розробка програмного продукту «Регулятор каналів гучності». Регулятор каналів гучності присутній в ОС Windows але головна ціль це розробити свій програмний продукт з додатковими можливостями в цій курсовій буде розглянутий варіант керування каналів гучності за допомогою фізичного пристрою на мікроконтроллеру ATmega328 на відладочній платі Arduino UNO для інтерфейсу зв’язку будемо використовувати Serial Port. При розробці програмного продукту будемо використовувати принципи об’єктно-орієнтовного програмування.

Розроблений програмний продукт написано в середовищі програмування Microsoft Visual Studio об’єктно-орієнтовною мовою програмування C++/CLI. Скетч для МК написано обєктно-орієнтованою мовою програмування С++. Загальний обсяг роботи ________

ANNOTATION

The purpose of the course work is to develop the software product "volume channel control". The volume channel control is present in Windows but the main goal is to develop your own software product with additional features in this course we will consider the option of controlling volume channels using a physical device on the ATmega328 microcontroller on the Arduino UNO debug board for the communication interface we will use Serial Port. When developing a software product, we will use the principles of Object-Oriented Programming.

The developed software product is written in the Microsoft Visual Studio programming environment in the Object-Oriented Programming Language C++/CLI. The sketch for MK is written in the Object-Oriented Programming Language C#. Total amount of work ________

ЗМІСТ

ВСТУП

2

1 ГОТОВІ РІШЕННЯ

3

1.1 Готові рішення.

3

1.2 Передача значень.

3

1.3 Принципова схема з’єднання для мікроконтроллеру.

4

1.4 Обробка отриманих фізичних значень

6

1.5 Обробка значень від Мікроконтроллеру

7

2 WINDOWS API

7

2.1 Вступ

7

2.2 Принцип регулювання гучності за допомогою WinAPI

14

2.3 Реалізація для отримання інтерфейсу

16

3 ПРОТОТИП ПРИСТРОЮ ТА ПРОГРАМНИЙ ПРОДУКТ

17

3.1 Загальні відомості

17

3.2 Прототип пристрою

20

3.3 Програмний продукт

20

ВИСНОВКИ

28

СПИСОК ВИКОРИСТАНОЇ ЛІТЕРАТУРИ

29











































ВСТУП

Ціль створення цієї курсової роботи це більш зручне керування каналами гучності мікшування звуків в системі без використання професіональних звукових пристроїв які для свого застосування потребують спеціальних знань а що не менше важливо займають достатньо місця на робочому місті тож нам потрібно написати програмний продукт в якого будуть відсутні ці мінуси а головне щоб як пристрій так і програмний продукт були прості в використанні та не мали необхідності володіти спеціальними знаннями.

Цей пристрій та програмний продукт може допомогти як звичайному користувачеві комп’ютеру так і геймеру програмісту та іншим користувачам які можуть одночасно мати бажання наприклад прослуховувати музику на фоні спілкуватись з близькими/друзями/командою за допомогою голосового зв’язку і буває так що потрібно зробити тихіше/гучніше канал гучності якоїсь програми то якщо використовувати стандартне програмне забезпечення ОС Windows потрібно виконувати додаткові маніпуляції (відкриття програми “sndvol”) а іноді це не зручно наприклад при веденні якоїсь конференції, в ігровому режимі і т.д. тому спеціально для цього була створена ця курсова робота а саме головне що вона буде далі розвиватися та вдосконалюватись так як на момент написання звіту програмний продукт ще має достатню купу мінусів навіть в порівнянню з стандартним програмним продуктом MS Windows “sndvol” але всі цілі які тут описані були виконані при виконанні курсової роботи були вдосконаленні навички програмування на мовах С++/CLI та C# було перше в моїй практиці використання Windows API. Та робота з елементом Serial Port в Windows Forms та стало ясно що все ж таки C++/CLI та С++ це достатньо різні мови програмування.

1. ГОТОВІ РІШЕННЯ

1.1 Готові рішення.

Після довготривалого вивчення напрямку та пошуку інформації було знайдено на GitHub проект написаний на мові програмування “GO Langue” (об’єктно-орієнтована мова програмування від компанії Google) який мав довготривалу підтримку від свого розробника проект на час написання курсової роботи не оновлювався 2 роки. Та оскільки він був реалізований за допомогою модулів які можна придбати в радіо магазині та без всяких навиків роботи з паяльником зібрати цей проект з використанням відладочної плати Arduino яка має достатньо велике поширення серед юнаків які починають вивчати мікроконтролери чи ту вже упомянуту мову програмування С#. То враховуючи всі ці фактори проект не міг залишитись без уваги то того зібравши цей достатньо простий проект ми отримуємо дійсно повністю працездатний та зручний для використання пристрій який до того-ж дуже просто налаштувати. Що стосовно самого проекту він складається з двох модулів перший це саме програмне забезпечення для персонального комп’ютера, другий це сама прошивка (скетч) для Arduino обмін даними відбувається за допомогою SerialPort.

1.2 Передача значень.

Все дуже достатньо просто запущена в фоновому режимі (треї) програма постійно чекає від налаштованого в ній SerialPort команди які узгоджені як в ПЗ що їх відправляє так і в ПЗ що їх отримує я хоч і дуже детально не вивчав програму яку було розглянуто вище але навіть при перегляді скетчу прошивки Arduino яка в цьому випадку надсилає значення для каналів гучності можна зрозуміти що ПЗ яке читає ці данні кожні 10 секунд отримує дані типу string в якій статичні 5 значень розділені символом «|» приклад функції формування даних для відправки (див рис. 1)



Рисунок 1. Вигляд ф-ції для отримання та формування даних

1.3 Принципова схема з’єднання для мікроконтроллеру.

Оскільки ми не будемо займатися виготовленням повністю готового пристрою а лише ознайомимось з набагато спростованим варіантом адже наша задача тут програмування, тому розглянемо спростований варіант схеми (див рис. 2).



Рисунок 2. Принципова схема

Тут ми можемо зрозуміти що наші повзунки які зчитують данні це звичайні резистори змінного опору з середньою точкою тобто це можливо представити як звичайний резистивний дільник (див. рис. 3)



Рисунок 3. Схема резистивного дільника

Тобто при пересуванні повзунка до верху опір резистора R1 падає а опір R2 піднімається. Отже за схемою (рис. 2) у нас на вхід резистивного дільника подається напруга а саме постійний струм 5В. опір всього дільника 100кОм повзунок по середині це виходить за формулою (див. рис. 4) по 50кОм на резистор і виходить що на виході дільника 2.5В.



Рисунок 4. Формула для розрахунку резистивного дільника

А напругу ми можемо виміряти за допомогою мікроконтроллеру оскільки ми використовуємо плату Arduino Uno то нам для цього не потрібні додаткові знання розглянемо приклад коду для отримання значень з повзунка приклад функції (див рис. 5)



Рисунок 5. Отримання значення з аналогового входу МК

1.4 Обробка отриманих фізичних значень.

Тут вже просто мікроконтроллер має в своїй прошивці стандартну функцію “loop()” (див. рис. 6) яка визивається в залежності від тактування кварцового генератора і в цій функції ми визиваємо вже функцію для отримання значень з фізичних повзунків (див. рис. 5) записуємо значення в масив після чого викликаємо функцію для формування даних на відправку (див. рис. 1) та робимо затримку в 10 секунд це потрібно для не переповнення буферу COM порту але ця незначна затримка нам ніяк не завадить і не створить проблем.



Рисунок 6. Приклад стандартної функції loop()

1.5 Обробка значень від Мікроконтроллеру

Чесно кажучи як це було реалізовано в даному випадку я не зовсім розумію так як не володію навіть базовим синтаксисом мови програмування «Go». Але маю розуміння що десь так оскільки програма не має UI інтерфейсу то все налаштування відбуваються за допомогою правки конфігу папці з проектом, програма має два потоки перший це основний другий додатковий в якому слухає та приймає значення з SerialPort при отриманні значень відправляє їх в основний поток де вже відбувається їх декодування на прилежність значення до відповідної програми а далі методами WinApi відбувається встановлення рівня гучності (Windows API розділ 2)

2. WINDOWS API

2.1 Вступ

Оскільки для роботи з звуковими сеансами нам потрібно буде використовувати Windows API так як фраймворки для розробки віконних програм не мають в своєму стандартному наборі інструментів для роботи з звуком, і цьому нам на допомогу приходить чудова річ яка носить назву API, через API можливо не лише взаємодіяти з звуком ай наприклад створювати елементи керування які відсутні в вибрану вами фраймворку отже, API – це опис способів взаємодії одного програмного продукту з іншим в нашому випадку нашого програмного продукту з ОС Windows тому розглянемо простий приклад де ми будемо викликати MessageBox без використання фраймворку взагалі тобто ми напишемо консольну програму на об’єктноорієнтованній мові програмування C++ вибір С++ тут також не з проста а все томущо приклади для використання API на MSDN (офіційна документація Windows) наведені саме на цій мові програмування. Тож пишемо програмний продукт який нам при виконанні програми виведе MessageBox з вказаними нами параметрами.

Отже для початку потрібно знайти в якому саме заготовочному файлі у нас знаходиться функція для виклику цього діалогового вікна, зробити це дуже просто робимо запит в пошукову систему наприклад Google з запитом «MessageBox msdn» знаходимо офіційну сторінку і переходимо по ній та перед нами все про MessageBox (див. рис. 7)



Рисунок 7. H файл для MessageBox (MSDN)

Тут ми бачимо що для використання нам потрібно буде під єднати до проекту H-файл “winuser.h” тому так і робимо (див. рис. 8)



Рисунок 8. Додавання H-файлу

Після чого переглядаємо синтаксис самої функції на сайті по документації (див. рис. 9)



Рисунок 9. Синтаксис функції MessageBox

Тут ми за допомогою своїх знань в об’єктно орієнтованому С++ бачимо що функція повертає значення типу Integer(Int) та також приймає 4 значення бачемо якого типу, до речі це може трішки налякати при першому знайомстві з WindowsApi але боятись не потрібно адже це звичайні Windows Data Types ми бачимо що нам потрібно будуть 3 не зрозумілі на поточний момент типи а саме (HWND|LPCSTR|UINT) трішки розберемо:

HWND (Handle to Window) є дескриптором або ідентифікатором, який використовується для ідентифікації віконного об'єкта в операційній системі Windows. Кожне вікно в системі має свій унікальний HWND, який використовується для взаємодії з цим вікном.

HWND можна розглядати як вказівник на віконний об'єкт. Він дозволяє програмам звертатися до вікон, змінювати їх розмір, положення, стиль, відправляти повідомлення, отримувати введення від користувача та інші операції, пов'язані з вікнами.

HWND зазвичай представляється як ціле число, і його можна отримати, наприклад, під час створення вікна за допомогою функції CreateWindow або під час пошуку вікон за допомогою функції FindWindow.

LPCSTR є типом даних у програмуванні для операційних систем Windows. Він є скороченням від Long Pointer to a Constant String (довгий вказівник на сталий рядок). LPCSTR використовується для передачі та роботи зі сталими рядками (рядками, які не можуть бути змінені) у функціях Windows API.

LPCSTR є псевдонімом для типу const char*. Він вказує на пам'ять, яка містить рядок символів типу char, і цей рядок є сталим, тобто його значення не можна змінювати.

Наприклад, у мові програмування C++, LPCSTR може використовуватися для передачі параметрів рядків у функції Windows API.

UINT є типом даних у програмуванні, що представляє беззнакове ціле число. Він є скороченням від Unsigned INTeger. UINT зазвичай використовується для зберігання та обробки значень, які не можуть бути від'ємними, але можуть мати додатні значення.

UINT є беззнаковим цілим типом даних, що означає, що він може мати значення від 0 до максимального значення, яке може зберігати данний тип даних. Розмір UINT залежить від архітектури платформи і зазвичай дорівнює 4 байтам (32 біта) на більшості систем.

UINT може використовуватись у різних контекстах програмування, наприклад, для зберігання кількості елементів, індексів масивів, флагів, додаткових параметрів та інших числових значень, які не можуть бути від'ємними.

Наприклад, у мові програмування C++, UINT може використовуватися для зберігання кількості елементів у масиві.

З типами даних розібралися далі дивимося які саме дані нам потрібно передати в функцію для цього користуємось знову документацією та бачимо (див. рис. 10)



Рисунок 10. Параметри для функції з MSDN

Переший параметр hWnd сюди потрібно передати дескриптор головної форми але туди можна передати пустоту NULL якщо головного вікна немає в нашому випадку будемо передавати NULL оскільки MessageBox це вікно повідомлень яке зявляється при певній дії на формі в нашому випадку форми взагалі немає програма консольна тому передамо NULL. Далі lpText це повідомлення для нашого MessageBox тип уже ми описали раніше тому сюди передамо текстове повідомлення. Потім lpCaption це той же самий тип даних але якщо в минулому випадку ми передавали повідомлення то це заголовок до нашого вікна. Ну і останнє це uType тут потрібно передати набір кнопок/Значків і тому подібного тут можна скористатися константами в H-файлі а яка саме константа нам підходить вибираємо за таблицею (див. рис 11)



Рисунок 11. Таблиця значень кнопки для параметру uType

Також можна вказати значок набір кнопок і тд. ці параметри можна поєднувати за допомогою оператора or або знака «|» добре вибераємо MB_OK (Просто кнопка «Ок») та знак оклику догори ногами це константа MB_ICONINFORMATION це все можна обрати також за таблицею



Рисунок 11. Таблиця значків для Message Box

І останнє отримуємо результат та опрацьовуємо за необхідності тут нам також допоможе таблиця (див. рис 12)



Рисунок 12. Значення які повертає MessageBox

Пам’ятаємо що в нас використовується лише одна кнопка “Ок” а це відповідає значенню IDOK тобто MessageBox після натиснення на кнопку Ок поверне 1 думаю пояснювати що замість констант можна викрасти просто числове значення не потрібно.

Ну а тепер переглянемо мною підготований варіант (див. рис. 13).

Ну так достатньо просто можна звертатися майже до будь-якого елементу Windows за допомогою її API на прикладі MessageBox ми в цьому переконалися тепер трішки складніше.



Рисунок 13. Реалізація виклику MessageBox

2.2 Принцип регулювання гучності за допомогою WinAPI

В операційній системі Windows кожна програма для своїх потреб може створити звуковий потік який наслідує інтерфейси ISimpleAudioVolume та IAudioSessionEvents.

ISimpleAudioVolume дозволяє клієнту (програмному продукту) керувати рівнем гучності звукового сеансу. Дійсний рівень гучності будь якого каналу в міксі, який буде чутно на динаміках, представляє собою результат деяких фактів рівня гучності а саме:

  • Рівень тома для кожного каналу в потоковому сеансі, яким клієнти можуть керувати за допомогою методів в інтерфейсі IAudioStreamVolume.

  • Рівень головного тома сеансу, яким клієнти можуть керувати за допомогою методів в інтерфейсі ISimpleAudioVolume.

  • Рівень тому для кожного каналу сеансу яким клієнти можуть керувати за допомогою методів в інтерфейсі IChanelAudioVolume.

  • Рівень тому на основі політики сеансу, яким система динамічно визначає сеанс глобального перечень змін.

Кожен з четверо факторів рівня тому в списку описаного вище представляє собою значення в діапазоні від 0.0 до 1.0, де 0.0 – це повна тиша, а 1.0 – це повний том(без затухання). Діючий том також представляє собою значення в діапазоні від 0.0 до 1.0 .

Базові звукові програми не змінюють рівень гучності сеансів. Замість цього програми надіються що за необхідності користувач сам змінінить гучність тому, тому такі програми розраховують на рівень гучності з програми Sndvol (Базова програма для регулювання гучності програм). SndVol змінює лише головний рівень тому, при першій активації програми вона отримую значення рівня гучності в 1.0 (максимум без затухань).

ISimpleAudioVolume – інтерфейс за допомогою якого можна відстежувати зміни в звуковому сеансі, наприклад такі як зміна рівня гучності, зміну імені і тд. На відміну від других звукових інтерфейсів в цьому розділі реалізовано системним компонентом WASAPI, клієнт WASAPI реалізує інтерфейс для отримання повідомлень про відбування, клієнт надає вказівник на його інтерфейс.

Тепер про більшість інтерфейсів вони наслідують інтерфейс IUnknown.

IUnknown інтерфейс який дозволяє отримати вказівники на другі інтерфейси за допомогою метода QueryInterface (див. рис. 14) це нам в майбутньому буде необхідно.



Рисунок 14. Синтаксис QueryInterface MSDN

Методу для запиту потрібно два параметра riid яйди інтерфейсу в с++ можна отримати за допомогою методу “__uuidof()” де потрібно передати необхідний інтерфейс, другий об’єкт це вказівник де буде інтерфейс, повертає тип HRESULT базовий Windows тип де якщо повертається константа S_OK то все добре за інших умов за таблицею первного методу при роботі з Windows API ми будемо достатньо часто бачити цей тип від може достатньо допомогти програмісту при написанні програми чи відпрацювати помилки при виконанні методів Windows API.

2.3 Реалізація для отримання інтерфейсу

Я пропоную такий метод для отримання інтерфейсу керуванням звукового потоку нам буде потрібно ISimpleAudioVolume (описано вище). Але ми можемо тільки отримати основний поток та керувати ним але нас таке не влаштовує тому створимо для свого програмного продукту свій звуковий інтерфейс потім отримаємо інтерфейс IAudioSessionEnumerator.

IAudioSessionEnumerator – це інтерфейс який в собі має перечень всіх звукових сеансів та має метод GetSession() за допомогою якого можливо отримати IAudioSessionContol() та метод GetCount() за допомогою якого можна отримати кількість звукових сесій.



Рисунок 15. Синтаксис IAudioSessionContol MSDN



Рисунок 16. Синтаксис GetCount MSDN

Але IAudioSessionEnumerator просто отримати не можливо для цього потрібно мати інтерфейс IAudioSessionManager2 де в свою чергу потрібно визвати метод GetSessionEnumerator() та передати в метод вказівник.

Для отримання інтерфейсу IAudioSessionEnumerator його можливо створити методом Activate() з інтерфейсу IMMDevice а його в свою чергу можна отримати з перечислення стандартних інтерфейсів визвавши GetDefaultAudioEndpoint(), з інтерфейсу IMMDeviceEnumerator() який вже в свою чергу можна просто взяти та спорити методом CoCreateInstance() з певними параметрами.

Але ще момент для керування рівня гучності потрібен ISimpleAudioVolume а ми отримали лише IAudioSessionControl методом GetSession з інтерфейсу IAudioSessionEnumerator, тут згадуємо про QueryInterface з інтерфейсу IUnknown який було описано вище.

3 ПРОТОТИП ПРИСТРОЮ ТА ПРОГРАМНИЙ ПРОДУКТ

3.1 Загальні відомості

Під час виконання курсової роботи було виготовлено програмний продукт та прототип пристрою все що стосовного цього описано в першому розділі.

Для прототипу було використано:

  • Відладочну плату Arduino UNO

  • Механічний датчик повороту з кнопкою

Энкодер (от англ. encode – преобразовывать) – это устройство для преобразования угловых положений или линейных перемещений в цифровой сигнал, т.е. энкодер – это датчик угла или линейного перемещения, соответственно есть крутильные и линейные энкодеры. Принцип работы энкодера заключается в преобразовании механического перемещения в электрические сигналы, у обычного инкрементального энкодера, который мы будем рассматривать, этот сигнал представляет собой два квадратных сигнала (при равномерном вращении), сдвинутых по фазе на 90 градусов.



Рисунок 17. Відображення сигналу енкодеру



Рисунок 18. Схема підєднання енкодеру

В цій схемі все чудово але ектодер механічний а це значить те що в нього є так званий дребізг це коли при повороті іноді механічні контакти будуть погано проводити сигнал і буде створено в сигналі шум який мікроконтроллер може помилково опрацювати для цього можна встановити конденсатори на силгальньні виводи як на схемі готовового модуля енкодера (див. рис. 19) резистори я не використовував а от ось конденсатори для позбавлення шуму в сигналі все ж знадобились.



Рисунок 19. Схема готового модуля енкодера

3.2 Прототип пристрою

Я зібрав все по схемах та опису в пункті один використав бібліотеки для Arduino GyverEncoder.

Ось скетч прошивки:

#include "GyverEncoder.h"

Encoder enc1(7, 2, 3);
void setup() {

  Serial.begin(9600);

  enc1.setType(TYPE2);

}
void loop() {

  enc1.tick();

  if (enc1.isRight()) Serial.println(1);

  if (enc1.isLeft()) Serial.println(2);

  if (enc1.isClick()) Serial.println(3);

  delay(10);

}

Тут у нас налаштований SerailPort на роботу з швидкістью 9600 та підключено H-файл GyverEncoder за документацією потрібно визивати в ній метод tick() я так розумію для оновлення значень після чого інтуїтивні зрозумілі методи isRight()|isLeft()|isClick() повертують bool значення true при певному значенні true прогама відсилає в SerailPort вевну цифру і це щось типу свого протоколу.

3.3 Програмний продукт

Програмний продукт написано на мною написаній бібліотекі класі де реалізовані всі API запити для виконання програми нам потрібно лише сворити об’єкт класу та користуватися його методами, методів мало але на цей момент достатньо метод GetChanelCount() повертає кількість звукових каналів, GetChanelLevel() отримує значення гучності канала він працює за методом GetMasterVolume з ISimpleAudioVolume все про це в другому пінкті, та SetChanelLevel також з ISimpleAudioVolume все описано вище. Далі простий інтерфейс на WindowsForms C++\CLI, для налаштування SerialPort (див. рис. 20)



Рисунок 20. Налаштування

Тут нічого особливого проста перевірка можливості підєднання до SerialPort. #pragma endregion

//Глобальні переменние

public: String^ comSelected;

public: String^ comStatus;
private: System::Void getComPorts() {

array^ serialPorts = nullptr;

serialPorts = SerialPort::GetPortNames();

ComName->Items->AddRange(serialPorts);

ComName->SelectedIndex = 0;

}

//Изменено вибор

private: System::Void ComName_TextChanged(System::Object^ sender, System::EventArgs^ e) {

if (Serial->IsOpen) Serial->Close();

Serial->PortName = ComName->SelectedItem->ToString();

}

//Обработчик собития нажатия

private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {

Serial->Open();
if (Serial->IsOpen) {

Status->Text = "Conected";

comStatus = "connected";

Status->BackColor = Color::Lime;

comSelected = Serial->PortName;

Serial->Close();

this->Hide();

}

else {

Status->Text = "Error";

comStatus = "error";

Status->BackColor = Color::Red;

}

}

private: System::Void COMSettings_FormClosing(System::Object^ sender, System::Windows::Forms::FormClosingEventArgs^ e) {

Serial->Open();
if (Serial->IsOpen) {

Status->Text = "Conected";

comStatus = "connected";

Status->BackColor = Color::Lime;

comSelected = Serial->PortName;

Serial->Close();

this->Hide();

}

else {

Status->Text = "Error";

comStatus = "error";

Status->BackColor = Color::Red;

}

}
Далі, головне вікно воно використовує динамічне створення елементів при запуску в залежності від кількості каналів, з відображенням каналу який регулюємо, його інтерфейс



Рисунок 21. Головне вікно програми

private: COMSettings^ stg = gcnew COMSettings(); //Обєкт налаштування COM порту
//При активації цієї форми ми ховаємо всі інші

private: Void MyForm_Activated(Object^ sender, EventArgs^ e) {

FormCollection^ frm = Application::OpenForms;

for each (Form ^ forms in frm)

{

if (forms != this) {

forms->Hide();

}

}

}

//Обработка кнопки підключення

private: Void connectBtn_Click(Object^ sender, EventArgs^ e) {

if (stg != nullptr) {

if (stg->comStatus == "connected") {

Serial->PortName = stg->comSelected;

Serial->Open();

if (Serial->IsOpen) {

connectBtn->Text = "Connected: " + Serial->PortName;

connectBtn->Enabled = false;

}

}

else {

connectBtn->Text = stg->comStatus;

connectBtn->Enabled = false;

}

}

}

//Обробка собития натиску на "Налаштування"

private: Void налаштуванняToolStripMenuItem_Click(Object^ sender, EventArgs^ e) {

if (Serial->IsOpen) {

Serial->Close();

connectBtn->Text = "Подключить";

connectBtn->Enabled = true;

}

stg->Show();

}
//Собитие для обработки принятих на COM порт значеннь

private: Void Serial_DataReceived(Object^ sender, SerialDataReceivedEventArgs^ e) {

/*

* Тут робота з потокми так як хандлер ком порта знаходиться в другому потоці то прийшлось використвувать делегат

*/

this->Invoke(gcnew Decoder(this, &MyForm::Decode), Serial->ReadLine());

}

/* Mixer class object*/

private: Mixer mx;

/*Buffer item*/

private: array^ GroupArr = gcnew array(mx.GetChanelCount());

private: array^ LabelArr = gcnew array(mx.GetChanelCount());

private: array^ TrackArr = gcnew array(mx.GetChanelCount());

//Додовання елементів в

private: Void AddContolsElement() {
int count = mx.GetChanelCount();
groupBox1->Visible = false;
GroupBox^ groupBoxBuffer;

Label^ labelBuffer;

TrackBar^ TrackBarBuffer;

float bufferLevel = 0;
for (int i = 0; i < count; i++) {

bufferLevel = mx.GetChanelLevel(i);
TrackBarBuffer = gcnew TrackBar();

TrackBarBuffer->Location = System::Drawing::Point(14, 19);

TrackBarBuffer->Maximum = 100;

TrackBarBuffer->Name = "T" + Convert::ToString(i);

TrackBarBuffer->Orientation = trackBar1->Orientation;

TrackBarBuffer->Size = trackBar1->Size;

TrackBarBuffer->TabIndex = 1 + i * 100;

TrackBarBuffer->Value = bufferLevel * 100;

TrackBarBuffer->ValueChanged += gcnew System::EventHandler(this, &MyForm::TrackValueChange);

TrackArr[i] = TrackBarBuffer;
labelBuffer = gcnew Label();

labelBuffer->AutoSize = true;

labelBuffer->Font = label1->Font;

labelBuffer->Location = System::Drawing::Point(15, 126);

labelBuffer->Name = "L" + Convert::ToString(i);

labelBuffer->Size = label1->Size;

labelBuffer->TabIndex = 1 + i * 100;

labelBuffer->Text = Convert::ToString(bufferLevel * 100);
LabelArr[i] = labelBuffer;
groupBoxBuffer = gcnew GroupBox();

groupBoxBuffer->Controls->Add(labelBuffer);

groupBoxBuffer->Controls->Add(TrackBarBuffer);

groupBoxBuffer->Location = System::Drawing::Point(2 + 72 * i, 26);

groupBoxBuffer->Name = "G" + Convert::ToString(i);

groupBoxBuffer->Size = System::Drawing::Size(70, 165);

groupBoxBuffer->TabIndex = 1 + i * 40;

groupBoxBuffer->TabStop = false;

groupBoxBuffer->Text = L"--";

GroupArr[i] = groupBoxBuffer;

this->Controls->Add(groupBoxBuffer);

}

this->Width = count * 77;

if(this->Width < 170) this->Width = 170;
}
private: int fockuse = -1;

private: int select = -1;
private: Void TrackValueChange(System::Object^ sender, System::EventArgs^ e) {

TrackBar^ trackEvent = (TrackBar^)sender;

int level = trackEvent->Value;

int index = Convert::ToInt32(Convert::ToString(trackEvent->Name[1]));
if (select != index && select != -1) UnSelect();
if(select == -1) GroupArr[index]->BackColor = Color::Gray;

LabelArr[index]->Text = Convert::ToString(level);
if (fockuse != -1 && fockuse != index) {

GroupArr[fockuse]->BackColor = SystemColors::Control;

}

fockuse = index;

mx.SetChanelLevel(index, level / 100.0);

}
delegate void Decoder(String^ commands);

void Decode(String^ command) {

int cmd = Convert::ToInt32(command);

switch (cmd)

{

case 1: //+

if (select == -1) {

if (fockuse + 1 < mx.GetChanelCount()) {

GroupArr[fockuse + 1]->BackColor = Color::Gray;

if (fockuse != -1) GroupArr[fockuse]->BackColor = SystemColors::Control;

fockuse++;

}

else {

GroupArr[0]->BackColor = Color::Gray;

if (fockuse != -1) GroupArr[fockuse]->BackColor = SystemColors::Control;

fockuse = 0;

}

}

else {

if (TrackArr[fockuse]->Value + 5 <= 100) {

TrackArr[fockuse]->Value += 5;

}

else TrackArr[fockuse]->Value = 100;

}

break;

case 2: //-

if (select == -1) {

if (fockuse - 1 >= 0) {

GroupArr[fockuse - 1]->BackColor = Color::Gray;

if (fockuse != -1) GroupArr[fockuse]->BackColor = SystemColors::Control;

fockuse--;

}

else {

GroupArr[mx.GetChanelCount() - 1]->BackColor = Color::Gray;

if (fockuse != -1) GroupArr[fockuse]->BackColor = SystemColors::Control;

fockuse = mx.GetChanelCount() - 1;

}

}

else {

if (TrackArr[fockuse]->Value - 5 >= 0) {

TrackArr[fockuse]->Value -= 5;

}

else TrackArr[fockuse]->Value = 0;

}

break;

case 3: //ok

if (select == -1) {

if (fockuse != -1) {

select = fockuse;

GroupArr[select]->BackColor = Color::Orange;

}

}

else UnSelect();

break;

}

}

private: Void UnSelect() {

fockuse = select;

GroupArr[select]->BackColor = Color::Gray;

select = -1;

}

}

ВИСНОВКИ

В курсовій роботі розроблено програмний продукт «Регулятор каналів гучності». Проведено аналіз предметної області. Розглянуто теоретичні питання, а саме:

  • програма: її поява та розвиток як предмет людської діяльності,

  • Трішки роботи з мікроконтроллером,

  • Метод зв’язку МК та персонального компютера,

  • Робота з Windows API,

  • C++/CLI.

Розроблений програмний продукт під Desktop на os Windows який представляє собою регулятор гучності та водночас являє собою аналог svdvol. Хоч

СПИСОК ВИКОРИСТАНОЇ ЛІТЕРАТУРИ
1. Страуструп Б. Мова програмування C++. Спеціальне видання. Видавництво: Біном, 2008. 1104 с.

2. Прата С. Мова програмування C++. Лекції та вправи. М.: Видавництво: ДіаСофтЮП, 2005. 1104 с.

3. Павловська Т.А. С/С++. Програмування мовою високого рівня. СПб.: Пітер, 2011. 461 с.

4. Найбільш повний та детальний онлайн-докуметація з C++: веб-сайт. URL: docs.microsoft.com/ru-ru/cpp.

5.Стивен П. Мова програмування С++ . 6 Видання. Видавництво: "Вильяме", та Unix Primer Plus. 56с.

6. Му Барбара Э., Кениг Эндрю. Ефективне програмування на С++. Практичне програмування на прикладах. Видавництво: Деалектика 2019. 66-101 ст.

7. Ю.В. Земсков Програмування на С++. Навчальне видання. Видавництво: Спб Університет ГА. 2012. 16с.

8. И. Б. Бахомов С/С++ для початківців та MS Visual C++. Видавництво Наука 2012. 56ст

9. Ю. Е. Алексеев, А. В. Куров. Практикум по програмуванню на мові С++ в середовищі VS C++. Видавництво: Попури 2007. 17с.

10. Гарберт Шилд. Повний справочник по С++. Четверте видання. Видавництво: Osborne 2012. 148 c.

11. Найбільш повний та детальний онлайн-викіпедія з C++: веб-сайт. URL: http://cppstudio.com/uk/.

12. encyclopedia.kiev.ua - Процитовано 11 травня 2023 року

13. psychologytoday.com - Процитовано 9 травня 2023 року
скачати

© Усі права захищені
написати до нас