Міністерство освіти та науки України
Національний університет “Львівська політехніка”
Інститут комп’ютерних наук та інформаційних технологій
Кафедра автоматизованих систем управління
ПРОГРАМУВАННЯ ЗА ДОПОМОГОЮ ФУНКЦІЙ WIN32 API (частина I)
ЗБІРНИК ЛАБОРАТОРНИХ РОБІТ
Методичні вказівки
з курсу “Сиcтемне програмування та операційні системи”
для студентів базової вищої освіти
за напрямком 97.08.04 “Комп’ютерні науки”
та курсу “Операційні системи в комп’ютерній поліграфії”
для студентів базової вищої освіти
за напрямком 97.09.27 “Видавничо-поліграфічна справа”
Львів - 2002
Програмування за допомогою функцій Win32 API. Методичні вказівки з курсу “Сиcтемне програмування та операційні системи” для студентів базової вищої освіти за напрямком 97.08.04 “Комп’ютерні науки” та курсу “Операційні системи в комп’ютерній поліграфії” для студентів базової вищої освіти за напрямком 97.09.27 “Видавничо-поліграфічна справа”, Львів, НУ “Львівська політехніка”, 2002 р.
Рецензент: Вальковський В.О., д.ф-м.н., проф.
Укладачі: Зербіно Д.Д., канд. техн. наук, доц.,
Пелешко Д.Д. канд. техн. наук, доц.,
Різник О.Я., канд. техн. наук, доц.,
Рицар В.В., канд. техн. наук, доц.,
Цимбал Ю.В., асистент.
Відповідальний за випуск: Дронюк І.М. к.ф-м.н., доц.
Лабораторна робота №1
Тема – введення в програмування за допомогою API.
Мета – навчитися використовувати функції Win32 API при програмуванні в операційній системі Windows.
ТЕОРЕТИЧНІ ПОЛОЖЕННЯ
Win32 API (розшифровується як інтерфейс прикладних програм) - це множина підпрограм-функцій, на яких побудована операційна система WINDOWS, яка використовує 32х-бітну адресацію, починаючи з WINDOWS 95 і закінчуючи WINDOWS XP. Розробники WINDOWS зробили багато зусиль щоб стандартизувати як назви функцій, так і їх параметри. Тому використовувати їх не так важко, якщо засвоїти деякі загальні концепції.
Більшість функцій доступні для програм користувача, які написані для Windows на будь-якій мові програмування (у тому числі і на асемблері). Множина цих функцій розширюється при переході до наступної версії Windows, таким чином, забезпечується сумісність розроблених раніше програм із новими версіями операційної системи. Існують і функції, які не відображені в документації, або для свого застосування вимагають від програми спеціальних прав доступу до пам’яті.
Суть функцій API зрозуміти значно легше, якщо уявити, з яких файлів вони викликаються і на які групи ці функції поділяються. Асемблер – це як раз той зручний і простий засіб, який дозволить вам звертатись безпосередньо до будь-якої функції API, що знаходиться у DLLфайлі.
Секрет пізнання операційної системи через програмування на асемблері полягає у тому, що сам асемблер не накладає жодних обмежень на програму та дані, з якими вона працює. Це повинен робити сам програміст з метою захисту операційної системи від своїх некоректних дій. Таким чином, основною метою системного програмування є написання коректних програм з необмеженими можливостями (в рамках операційної системи). Для збереження коректності ми будемо користуватися певними правилами програмування, які будуть зрозумілі на конкретних прикладах.
Типи програм. Процесори стандарту Intel можуть працювати в трьох основних режимах: реальному, віртуальному і захищеному. При включенні комп’ютера його процесор працює в реальному режимі. Після завантаження операційної системи (ОС) процесор може бути переключений програмами ОС в інші режими. В реальному та віртуальному режимах використовується 16-бітна адресація з фіксованими сегментами по 64К. У захищеному режимі використовується 32х-бітна адресація з необмеженими сегментами, і адреса до пам’яті формується (на апаратному рівні) за допомогою дескрипторних таблиць, в яких задаються початкові адреси сегментів, їх довжина, та права доступу до пам'яті і до портів для процесів, які їх використовують. Крім того, в захищеному режимі реалізоване апаратне переключення між задачами за допомогою спеціальних таблиць.
Особливості виклику функцій API. Найбільш перспективним з точки зору програмування є захищений режим, тому що він використовує всі апаратні можливості комп’ютера. Отже, функції API для Windows відіграють ту ж саму роль, що і переривання INT 21h для DOS в реальному або віртуальному режимі, але, відмінності між ними досить суттєві. Перелічимо їх:
Функції API не відміняють, а заміняють програмні переривання. Механізм обробки апаратних переривань залишається на рівні драйверів пристроїв;
Стандарт виклику функцій API оснований на передачі параметрів через стек (а не через регістри);
Значення кожної функції повертається в регістрі EAX. Якщо функція повертає структуру даних, то регістр EAX містить логічну ознаку виконання, а адресу структури необхідно передати до функції як параметр;
Функції API працюють у захищеному режимі процесора, а переривання DOS у реальному чи віртуальному режимі.
Функції API зберігаються у різних бібліотеках динамічного компонування, які знаходяться у файлах із розширенням DLL, наприклад, kernel32.dll, user32.dll, gdi32.dll та ін. Ці файли знаходяться у системному каталозі Windows (наприклад, “C:\Windows\System”). У разі необхідності, програміст може створити DLLфайл з набором своїх функцій.
Програми Windows звертаються до функцій API за допомогою команд апаратного виклику CALL, наприклад: call MessageBoxA, де MessageBoxA – 32х-бітна адреса функції. Саме ця назва функції фігурує у файлі user32.dll (подивіться редактором цей файл). Перелік можливих функцій є у файлі H:/tasm/lib/Import32.lib, який називається бібліотекою імпорту.
Параметри для виконання будь-якої функції API перед її викликом повинні засилатися в стек, починаючи з останнього параметра (див. текст програми). Тому кожний параметр є 32х-бітним числом (в якому можуть використовуватись не всі біти). Параметрами досить часто бувають спеціальні дескриптори хендли (HANDLE) та атоми.
Дескриптори (хендли та атоми) – це унікальні цілі числа, які Windows використовує для ідентифікації об’єктів, які створюються або використовуються в системі. Хендли займають по 4 байти, а атоми – по 2 байти. Хендли ідентифікують вікна, меню, блоки пам’яті, екземпляри програми, пристрої виводу, файли, аудіо та відео потоки, та інші об’єкти. Атоми ідентифікують стандартні іконки, курсори та об’єкти, які не змінюються при наступному завантаженні системи.
Більшість дескрипторів є значеннями індексів внутрішніх таблиць, які Windows використовує для доступу та керування своїми об’єктами. Звичайно, програми користувача (ужитки) в захищеному режимі не мають прав доступу до цих таблиць. Тому, коли необхідно отримати чи змінити дані, що пов’язані з певним об’єктом Windows, ужиток використовує відповідну функцію API з параметром хендла цього об’єкту. Таким чином Windows забезпечує захист своїх даних при роботі у багатозадачному режимі.
ПОРЯДОК ВИКОНАННЯ РОБОТИ
1. Створити файл tasm32.bat для компіляції програм для 32х-бітного режиму:
2. Набрати подану нижче програму для визначення імені комп’ютера (яке задається системним адміністратором при установці операційної системи), зберегти її у файлі з розширенням “.ASM ”.
3. Відкомпілювати набрану програму за допомогою командного рядка:
4. Запустити одержаний exe-файл на виконання. Записати ім’я комп’ютера, яке отримала програма.
5. Розглянути текст програми, вивчити загальну структуру програми із застосуванням функцій Win32 API. Переписати в зошит текст програми з відповідними коментарями.
6. Замінити виклик функції API GetComputerNameA на виклик однієї з наступних функцій, змінивши відповідним чином параметри:
GetUserNameA, GetWindowsDirectoryA, GetSystemDirectoryA, GetTempPathA, GetCurrentDirectoryA, GetDriveTypeA, після чого відкомпілювати і запустити програму.
Текст програми
МОЖЛИВІ ПОМИЛКИ:
рядок з коментарем не позначений символом “;”
назва функції API не визначена в команді extrn;
записана маленька буква замість великої або навпаки;
хибна послідовність параметрів функції при записі в стек;
перед викликом функції в стек записані не всі параметри;
невірний тип параметрів (word або dword);
передача змінної як параметра замість її адреси (offset).
Про параметри функцій можна дізнатися з довідкового файлу WIN32.HLP, який знаходиться в каталозі C:\Program Files\Common Files\Borland Shared\MSHelp\win32.hlp. Для отримання довідки необхідно запустити файл WIN32.HLP, вибрати розділ “index (указатель)”, набрати назву функції без останньої букви “A”. Всі параметри, які будуть вказані в довіднику, необхідно засилати в стек, починаючи з останнього. Якщо назва параметру починається з наступних букв, то його довжина вказана у таблиці:
Перші
Символи
Довжина
Параметра
Зміст параметра
H
4
Хендл об’єкту
Lp
4
Адреса об’єкту (offset)
N
4
Змінна або адреса змінної (4 байти), що містить кількість
U або B
4
Ідентифікатори типу BOOL або прапорці
W
2
Ціле 16ти бітне число
D
4
Ціле 32х бітне число
Short
2
Ціле 16ти бітне число
Long
4
Ціле 32х бітне число
Довідкова інформація по функціях API, що використані в роботі
GetComputerNameA – отримує ім’я комп’ютера з реєстру Windows
LPTSTR lpBuffer // адреса буфера для імені;
LPDWORD nSize // адреса довжини буфера.
GetCurrentDirectoryA – отримує поточний каталог
DWORD nBufferLength // довжина буфера в байтах;
LPTSTR lpBuffer // адреса буфера для імені поточного каталогу.
GetDriveTypeA – отримує інформацію про тип дискового пристрою
LpRootPathName // адреса рядка з назвою кореневого каталогу;
Результат в регістрі EAX:
0 Диск не існує;
1 Каталог не існує;
2 Пристрій для змінних дисків;
3 Пристрій для жорстких дисків;
4 Мережний диск;
5 Пристрій для читання компакт-дисків;
6 Віртуальний диск в оперативній пам’яті.
GetSystemDirectoryA – отримує повне ім’я системного каталогу
LPTSTR lpBuffer // адреса буфера для імені;
UINT uSize // довжина буфера.
GetTempPathA- отримує шлях до каталогу з тимчасовими файлами
DWORD nBufferLength // довжина буфера в байтах;
LPTSTR lpBuffer // адреса буфера для каталогу;
Результат в регістрі EAX : кількість символів, записаних у буфер.
GetUserNameA – отримує ім’я (login) поточного користувача
LPTSTR lpBuffer // адреса буфера для імені;
LPDWORD nSize // адреса довжини буфера.
GetWindowsDirectoryA - отримує повний шлях до каталогу Windows
LPTSTR lpBuffer // адреса буфера для імені;
UINT uSize // довжина буфера.
КОНТРОЛЬНІ ЗАПИТАННЯ
Що таке захищений режим процесора ?
Що таке функція API ?
Що таке дескриптори, хендли, атоми ?
Що таке бібліотека динамічного компонування (DLL) ?
Як визначити, які функції є у певному DLL-файлі ?
Яким чином передаються параметри функціям API ?
У якому регістрі знаходиться результат виконання функції ?
Яка можлива довжина кожного параметра ?
Яка загальна структура програм при програмуванні під Windows ?
Що означають ключові слова data і code ?
Що роблять функції MessageBoxA, GetComputerNameA, GetCurrentDirectoryA, GetDriveTypeA, GetSystemDirectoryA, GetTempPathA, GetUserNameA, GetWindowsDirectoryA ?
Лабораторна робота №2
Тема – структури даних для використання системних функцій.
Мета – навчитися будувати структури даних для використання функцій Win32 API при програмуванні в операційній системі Windows.
ТЕОРЕТИЧНІ ПОЛОЖЕННЯ
Для використання більш складних функцій API необхідно використовувати спеціальні структури даних. Вся концепція програмування в WINDOWS основана на чіткому впорядкуванні структур даних, пов'язаних із ними програм-функцій та констант-параметрів. Дані, що пов'язані з виконанням одної функції об'єднуються в блок певної довжини (він називається структурою). Елементами таких структур можуть бути інші структури і т.д. Існують структури загального користування, які не пов'язані з конкретною функцією API, а містять довідкову інформацію про систему, файли, користувача, тощо. Дані, що зберігаються в цих структурах постійно змінюються і деколи їх неможливо передбачити. Тому для отримання цих даних не можна користуватися звичайними командами читання з пам’яті типу “mov”. Перед користуванням такою динамічною інформацією необхідно перевірити, чи готова інформація для споживання. Щоб уникнути некоректності при умові паралельного виконання процесів кожне звернення до системної інформації необхідно регіструвати. Тому фактично існує два типа функцій API:
а) функції, які виконують будь-яку дію;
б) функції, які отримують будь-яку інформацію.
У даній лабораторній роботі треба отримати та розшифрувати одну з таких довідкових структур, яка містить інформацію про системний час. Для виклику довільної довідкової функції необхідно вказати адресу місця в пам'яті, куди буде записана довідкова структура. Цю адресу, як параметр функції, завжди перед викликом функції треба опустити в стек.
В лабораторній роботі необхідно також звернути увагу на те, що в програмі можна використовувати не лише функції API, але і функції різних мов програмування. Для цього необхідно, щоб в системі були присутні відповідні DLL-файли. Наприклад, можна викликати функцію виводу wsprintf, яка використовується в мові C. Ця функція передає управління до функції _wsprintfA, що міститься у файлі USER32.DLL. Функції такого типу можуть не звільняти після свого виконання стек. В такому випадку програміст сам повинен про це подбати. Отже, оскільки кожний параметр у стеку займає 4 байти, то після виклику такої функції необхідно записати add esp,4*N, де N – кількість параметрів для виконання функції (див. текст програми).
ПОРЯДОК ВИКОНАННЯ РОБОТИ
Набрати подану нижче програму для визначення поточної дати та місцевого часу, зберегти її у файлі з розширенням “.ASM”.
Відкомпілювати набрану програму та запустити одержаний exe-файл на виконання.
Розглянути текст програми, знайти виклик підпрограми _wsprintfA для перетворення двійкового значення в рядок десяткових цифр.
Додати до виводу значення секунд та мілісекунд.
Змінити текст програми таким чином, щоб функція API MessageBoxA виводила на екран вікно з двома кнопками: <OK> та <Cancel>. При натисненні кнопки <OK> програма повинна знову отримати системний час, а при натисненні кнопки <Cancel> - програма завершує роботу. Для цього треба знайти у файлі H:/tasm/include/win119.inc константу MB_OKCANCEL та вказати її як стиль вікна MessageBoxA. Після відповіді користувача треба порівняти регістр EAX з константою IDOK за допомогою асемблерної команди “cmp eax, IDOK”. Якщо значення однакові, то зробити перехід на початок програми по команді “jz Start”.
Текст програми
Замінити виклик функції API GetLocalTime на виклик однієї з наступних функцій (змінивши відповідним чином параметри): GetSystemTime, DeleteFileA, CopyFileA, RemoveDirectoryA, SetCurrentDirectoryA, SetVolumeLabelA, GetTempFileNameA, SetFileAttributesA, GetFileAttributesA, GetLogicalDrives, GetLogicalDriveStringsA. Для кожної функції додати відповідні дані та команди, якщо вони потрібні.
Відкомпілювати та налагодити програму для правильної роботи з кожною функцією, що вказана у попередньому пункті. В звіті відобразити всі зроблені програми.
Довідкова інформація по функціях API, що використані в роботі
CopyFileA - копіює файл
LpExistingFileName // вказівник на ім'я файлу, що копіюється;
LpNewFileName // вказівник на ім'я файлу-копії;
BOOL bFailIfExists // якщо значення - ненульове, то в разі існування файлу-копії, функція не виконується; якщо значення - нульове - файл перезаписується.
DeleteFileA - знищує заданий файл
LPCTSTR lpFileName // вказівник на ім'я файлу, який знищується.
GetFileAttributesA - отримує атрибути заданого файлу або каталогу
LPCTSTR lpFileName // адреса імені файлу або каталогу;
В результаті регістр EAX буде містити побітну інформацію про атрибути файла. Нижче наведений перелік номерів бітів і атрибутів, що їм відповідають:
0 – READONLY файл (каталог) тільки для читання;
1 – HIDDEN файл (каталог) є прихованим;
2 – SYSTEM файл (каталог) виключно використовується операційною системою;
4 – DIRECTORY "файл або каталог" є каталогом;
5 – ARCHIVE файл (каталог) є архівним. Автоматично встановлюється, якщо файл (каталог) переносився;
7 – NORMAL файл (каталог) немає інших атрибутів;
8 – TEMPORARY файл для тимчасового зберігання даних, знищується після виконання програми, яка його створює;
11 – COMPRESSED файл (каталог) є стиснутим;
12 – OFFLINE дані у файлі тимчасово є недоступними.
GetLocalTime - заповнює структуру lpSystemTime значенням місцевого часу та дати
LpSystemTime // адреса структури системного часу, яка буде заповнена (див. текст програми);
GetLogicalDrives - отримує інформацію про логічні диски, наявні в системі (0-й біт в регістрі EAX - диск A, 1-й - диск B і т.д.)
GetLogicalDriveStringsA - отримує інформацію про шляхи до кореневих каталогів логічних дисків, наявних в системі
DWORD nBufferLength // довжина буферу;
LPTSTR lpBuffer // адреса буферу для рядка імен логічних дисків, розділених символами нуля. Ім’я останнього диску закінчується двома нулями.
GetSystemTime - заповнює структуру lpSystemTime значенням поточного часу за Грінвичем (див. також функцію GetLocalTime).
GetTempFileNameA - отримує ім'я тимчасового файлу для використання програмою-ужитком
LPCTSTR lpPathName // адреса імені каталогу для тимчасового файлу;
LPCTSTR lpPrefixString // адреса префіксу імені тимчасового файлу;
UINT uUnique // число, яке з'єднується з префіксом для створення імені тимчасового файлу (0-випадкове число);
LPTSTR lpTempFileName // адреса буферу для імені тимчасового файлу.
RemoveDirectoryA - знищує заданий каталог
LPCTSTR lpPathName // адреса каталогу, який знищується.
SetCurrentDirectoryA - встановлює поточний каталог
LPCTSTR lpPathName // адреса імені нового поточного каталогу.
SetFileAttributesA - встановлює атрибути файлу (див. функцію GetFileAttributesA)
LPCTSTR lpFileName // адреса імені файлу;
DWORD dwFileAttributes // 32х-бітна константа, що задає атрибути файлу.
SetVolumeLabelA - встановлює мітку тому для диску
LPCTSTR lpRootPathName // адреса імені кореневого каталогу;
LPCTSTR lpVolumeName // адреса імені мітки.
КОНТРОЛЬНІ ЗАПИТАННЯ
На які два основні типи поділяються функції API?
Що таке структура даних у Win32 API?
Для чого існують структури даних?
Як передаються структури даних у системні функції?
Звідки беруться шаблони структур даних?
Що таке константа-параметр?
Де можна знайти перелік стандартних констант WINDOWS?
Чим і наскільки відрізняється місцевий час від системного?
Що таке файл?
Для чого використовуються тимчасові файли?
Що таке атрибут файлу?
Які ви знаєте функції для роботи з файлами та пристроями?
Що таке мітка диску?
Що таке поточний каталог?
Для чого потрібні тимчасові імена файлів і як їх отримати?
Що робить функція GetLogicalDriveStringsA і чим вона відрізняється від функції GetLogicalDrives?
Лабораторна робота №3
Тема – робота з пам’яттю.
Мета – навчитися використовувати системну пам’ять та розміщати в ній дані з файлу.
ТЕОРЕТИЧНІ ПОЛОЖЕННЯ
Пам’ять є основним ресурсом при програмуванні в багатозадачному середовищі. Множина вільних фрагментів пам’яті називається хіп (від англійського слова HEAP). Програміст може виділити для своєї програми блок пам’яті будь-якої довжини, що не перевищує загальний об’єм вільної пам’яті. В Windows пам’ять виділяється в 2 етапи:
спочатку система виділяє фрагмент віртуальної пам’яті, який отримує свій хендл, але не отримує реальної адреси;
потім система розміщує (блокує) цей фрагмент у реальній пам’яті і фрагмент отримує початкову адресу.
Після того, як програміст отримує адресу початку виділеного блоку, він може її використовувати. Комірки з адресами до початку та після кінця блоку використовувати не можна, тому що вони належать іншим програмам або системі.
Після того, як програма використала блок пам’яті, його необхідно розблокувати. Таким чином, він знову стає віртуальним, і при необхідності може бути переміщений системою в інше місце або на диск. Якщо програма довго не розблоковує блок пам’яті, то це негативно відображається на продуктивності операційної системи в цілому. Отже, якщо після розблокування пам’яті її знову заблокувати, адреса початку блоку може бути іншою. Якщо програміст взагалі відмовляється від використання виділеного блоку пам’яті, він повинен звільнити блок, що веде до знищення його хендла. Очевидно, що перед звільненням блоку пам’яті його необхідно розблокувати.
В лабораторній роботі запропонована програма, яка виділяє блок пам’яті зчитує у виділений фрагмент файл виводить його на екран та звільняє виділений блок.
Для відкриття, читання та запису файлів використовуються відповідні функції API, опис яких ви знайдете після тексту програми.
ПОРЯДОК ВИКОНАННЯ РОБОТИ
Набрати подану нижче програму, зберегти її у файлі з розширенням “.ASM”.
Відкомпілювати набрану програму та запустити одержаний exe-файл на виконання.
Розглянути текст програми, знайти функції виділення, блокування, розблокування та звільнення пам’яті.
Доповнити подану програму функцією вибору файлу GetOpenFileNameA (див. довідкову інформацію після програми).
Доповнити отриману програму фрагментом для визначення часу створення та часу останньої модифікації файлу за допомогою функції GetFileTime.
Перетворити час у зручний для сприйняття вигляд за допомогою функції FileTimeToSystemTime та вивести його за допомогою програми попередньої лабораторної роботи. Структуру даних часу time_struc розмістити у виділеному блоці пам’яті.
Після закриття файлу виконати його запуск через оболонку WINDOWS за допомогою команди ShellExecuteA.
Кожний варіант програми оформити в звіті і відповісти на контрольні запитання.
Текст програми
Довідкова інформація по функціях API, що використані в роботі
CreateFileA створення або визначення хендлу існуючого файлу
lpFileName // вказівник на ім’я файлу;
dwDesiredAccess // режим доступу:
80000000h – читання, 40000000h – запис;
dwShareMode // режим спільного доступу:
1 – по читанню, 2 – по запису;
lpSecurityAttributes // вказівник на структуру атрибутів безпеки;
dwCreationDistribution // метод створення:
1 – створювати лише тоді, коли не існує; 2 – створювати завжди новий; 3 – відкрити лише існуючий; 4 – відкрити існуючий або створити новий; 5 – обрізати існуючий до нуля;
dwFlagsAndAttributes // атрибути файлу;
HANDLE hTemplateFile // режим передачі файлу процесу.
CloseHandle закриття відкритого хендлу
hObject // хендл об’єкту, який треба закрити.
ReadFile читання файлу
hFile // хендл файлу;
lpBuffer // адреса блоку пам’яті в який попадуть дані;
nNumberOfBytesToRead // кількість байтів, що треба зчитати;
lpNumberOfBytesRead // адреса кількості зчитаних байтів;
lpOverlapped // адреса структури спільного використання або 0.
GlobalAlloc – резервування віртуальної пам’яті та отримання хендлу віртуального блоку пам’яті
UFlags // тип блоку пам’яті та його атрибути;
dwBytes // довжина блоку в байтах;
Результат в регістрі EAX: хендл віртуального блоку пам’яті.
GlobalLock – розміщення віртуального блоку за певною адресою
hMem // хендл віртуального блоку пам’яті;
Результат в регістрі EAX: адреса блоку в пам’яті.
GlobalUnlock – розблокування блоку пам’яті, дозвіл на переміщення
HMem // хендл блоку пам’яті.
GlobalFree – звільнення блоку пам’яті
HMem // хендл блоку пам’яті.
GetOpenFileNameA – функція діалогу з користувачем, в результаті якого користувач вибирає файл для відкриття
LPOPENFILENAME // адреса структури яка визначає діалог:
FSize dd 76 ; довжина цiєї структури;
Howner dd 0 ; вказiвник вiкна-власника або 0;
AppHWnd dd 0 ; вказiвник модуля-власника;
Filters dd offset filter_tab ; вказiвник на перелiк типiв файлiв;
CustFilters dd 0 ; вказiвник на перелiк типiв файлiв якi дозволенi користувачевi;
CstFltSize dd 0 ; довжина буферу на який вказує CustFilters;
CurFilter dd 3 ; iндекс вибраного фiльтру (1,2,3,...) або 0;
CurFileName dd offset openname ; вказiвник на повне iм'я файлу, наприклад, на “С:\dir1\dir2\file.ext”,0;
CurFlNmSize dd 512 ; довжина буферу вказаного в CurFileName;
CurFile dd 0 ; вказiвник на iм'я файлу з розширенням;
CurFlSize dd 0 ; довжина буферу вказаного в CurFile;
InitialDir dd offset dir ; вказiвник на каталог файлу або 0 для даного каталога;
DlgTitle dd offset titl ; вказiвник на назву вiкна;
Flags dd 00h ; тип вiкна, яке вiдкриває файл (може бути 200h);
FileOffset dw 0 ; повертає довжину повного шляху, наприклад=13 якщо користувач ввів рядок “С:\dir1\dir2\file.asm”;
ExtOffset dw 0 ; змiщення вiд початку рядка до розширення (в даному прикладi =18) або 0 якщо розширення немає;
Extension dd 0 ; вказiвник на стандартне розширення, яке буде додано до iменi, якщо розширення немає (або 0);
CustData dd 0 ; вказiвник на данi для hook-процедури;
HookProc dd 0 ; вказiвник на hook-процедуру, якщо вона дозволена у Flags;
TmplateRsc dd 0 ; вказiвник на шаблон ресурсiв, якщо вiн передбачений у Flags;
; додаткові змінні до структури:
filter_tab db "Графiчнi файли (*.BMP)",0h,"*.BMP",0
db "Текстовi файли (*.TXT)",0,"*.txt",0
db "Лабораторнi роботи (*.ASM)",0,"*.asm",0
db "Всi типи файлiв (*.*)",0h,"*.*",0,0
dir db "c:\users",0
titl db "Лабораторна робота № 3",0
GetFileTime – отримує дату і час коли файл був створений, коли останній раз був прочитаний та коли останній раз змінювався
Hfile // хендл файлу;
lpCreationTime // адреса структури creation_time (8 байт);
lpLastAccessTime // адреса структури access_time (8 байт);
lpLastWriteTime // адреса структури write_time (8 байт).
FileTimeToSystemTime – перетворює 8 байт файлового часу в системний час
lpFileTime, // адреса creation_time, access_time або write_time;
lpSystemTime // адреса структури Time_struc (див. лаб. №2)
ShellExecuteA – відкриває або виконує вказаний файл
Hwnd // хендл до вікна-власника (або 0);
lpOperation // вказівник на рядок, що містить дію (або 0);
lpFile // вказівник на папку або файл, який треба виконати;
lpParameters // вказівник на параметри виконання (або 0);
lpDirectory // вказівник на робочий каталог (або 0);
nShowCmd // прапорець показу відкриття (або 0).
КОНТРОЛЬНІ ЗАПИТАННЯ
Що таке реальна і віртуальна пам’ять ?
Як зарезервувати фрагмент віртуальної пам’яті ?
Чи можна виділити блок реальної пам’яті, якщо не резервувати віртуальну пам’ять ?
Як виділити реальну пам’ять ?
Як перемістити блок виділеної пам’яті ?
Що таке дефрагментація пам’яті ?
Як звільнити блок пам’яті ?
Які ви знаєте функції для роботи з файлами ?
Як створюються файли ?
Що означає “відкрити файл через оболонку” ?
Як працює функція GetOpenFileNameA ?
Як працюють функції GetFileTime та FileTimeToSystemTime ?
Лабораторна робота №4
Тема – стандартні класи вікон та їх типи.
Мета – зрозуміти поняття вікна в операційній системі Windows.
ТЕОРЕТИЧНІ ПОЛОЖЕННЯ
Все, що бачить користувач на екрані в системі WINDOWS є вікном. Вікно – це графічна оболонка, через яку програма може спілкуватися з користувачем. Якщо програмі не потрібно спілкуватись, то вона може і не створювати вікон. Вікно може володіти набором інших вікон, які називаються дочірніми.
Кожне вікно має як певний набір параметрів, так і може відрізнятися певною специфікою спілкування з користувачем. Такі специфічні особливості називаються класом вікна. Існують стандартні класи, наприклад, вікно–регулювач, вікно-кнопка, вікно для вводу тексту, вікно-підказка та інші, які ви знайдете в лабораторній роботі. Кожний стандартний клас має унікальну назву, яка дійсна для всіх версій операційних систем WINDOWS.
Вікно створюється за допомогою спеціальної функції CreateWindowExA. В параметрах цієї функції вказується наступна інформація:
Вказівник на MDI – структуру (або 0);
Хендл програми (отримується функцією GetModuleHandle);
Хендл меню або дочірнього вікна (або 0);
Хендл вікна-власника (або 0);
Висота вікна;
Ширина вікна;
Координата Y;
Координата X;
Прапорці стилю вікна (див. далі);
Вказівник на назву вікна (або 0);
Вказівник на назву класу (див. далі);
Прапорці властивостей вікна (див. далі).
Керувати вікном можна за допомогою внутрішнього механізму WINDOWS, який базується на понятті повідомлення (в програмі позначено WM_...). Отже, вікно – це такий об’єкт WINDOWS, який крім текстово-графічної інформації може отримувати та надсилати спеціальні структури даних, які називаються повідомленнями. Структура кожного повідомлення стандартна і складається з наступних змінних:
MsHWND dd 0 ; хендл вiкна, процедура якого отримала повiдомлення;
msMESSAGE dd 0 ; код повiдомлення (кожна подiя має свiй);
msWPARAM dd 0 ; додатковий параметр 1 (залежить вiд подiї);
msLPARAM dd 0 ; додатковий параметр 2 (залежить вiд подiї);
msTIME dd 0 ; час, коли було надiслано повiдомлення;
ptX dd 0 ; координата X миші, коли надсилалося повiдомлення;
ptY dd 0 ; координата Y миші, коли надсилалося повiдомлення.
Повідомлення сигналізує про деяку подію в системі або у вікні, наприклад, вичерпався час таймера, користувач натиснув клавішу, відпустив клавішу, порухав мишу, клацнув кнопкою, та інші.
Для того, щоб відправити повідомлення до довільного вікна (наприклад, щоб змінити його розмір) необхідно заповнити цю структуру даних та скористуватися функцією SendMessageA, а для прийому повідомлення від певного вікна необхідно вказати діапазон прийому, хендл вікна та адресу структури повідомлення і скористатися функцією GetMessageA. Коли повідомлення надійде, операційна система сама заповнить всі дані структури (див. програму).
З кожним стандартним класом вікна зв’язана певна віконна стандартна процедура WndProc, яка малює вікно та обробляє всі повідомлення, що надходять у вікно. Програміст має можливість вставити у віконну процедуру свій фрагмент програми. Такі дії називаються субкласуванням.
Саме ідеєю субкласування можна пояснити відокремлення процесів створення вікна, циклу прийому повідомлень та їх обробку у вигляді віконної процедури. Для цього ж кожна віконна процедура отримує параметри через стек за однаковим стандартом незалежно від класу та типу вікна. Цей стандарт не залежить навіть від версії WINDOWS:
Hwnd // хендл вікна, яке отримало повідомлення;
UMsg // код повідомлення;
Wparam // перший параметр повідомлення;
Lparam // другий параметр повідомлення;
В лабораторній роботі запропонована програма, в якій створюється стандартне вікно класу Button – кнопка, та утворюється цикл прийому повідомлень від цього вікна. В циклі перевіряється подія натиснення клавіші <ESC>. Якщо користувач натиснув <ESC>, то програма закінчується, інакше повідомлення передається у стандартну віконну процедуру.
В програмі використана функція GetModuleHandleA, яка необхідна для того, щоб прив’язати вікно до програмного модуля.
ПОРЯДОК ВИКОНАННЯ РОБОТИ
Відкомпілювати подану програму.
Замість стандартного класу Button ввести наступні назви класів:
ComboBox, Edit, ListBox, Message, ScrollBar, Static, SysAnimate32, SysHeader32, SysListView32, SysTabControl32, SysTreeView32, TTSubclass, ToolTips, ToolbarWindow32, msctls_hotkey32, msctls_progress32, msctls_statusbar32, msctls_trackbar32, msctls_updown32, tooltips_class32, #32768, #32769, #32770, #32771, ComboBoxEx32, SysPager, SysIPAddress32, NativeFontCtl.
Описати вікна кожного класу та їх властивості.
КОНТРОЛЬНІ ЗАПИТАННЯ
Що таке вікно і як його створити ?
Які параметри потрібно вказати щоб створити вікно ?
Що таке віконна процедура і які параметри до неї передаються ?
Що таке клас вікна та субкласування ?
Що таке повідомлення і яка його структура?
Для чого надсилаються повідомлення ?
Які існують стандартні класи вікон ?
Що таке тип (стиль) вікна ?
ФОРМА ЗВІТУ ПО РОБОТАХ
Звіт – це документ про те, що студент успішно виконав роботу.
Мета, що ставиться перед роботою;
Короткий зміст теоретичних відомостей;
Тексти всіх відлагоджених програм із коментарями;
Відповіді на контрольні запитання;
Висновки по особливостях застосування отриманих знань або зауваження по виконанню роботи та методичному забезпеченню.
ЛІТЕРАТУРА
Эпплман Д. Win32 API и Visual Basic. Для профессионалов (+CD). – СПб.: Питер, 2001. – 1120 с.: ил.
Юров В. Assembler: учебник. - СПб.: Питер, 2001. – 624 с.: ил.
Win32 Developer’s References (файл документації WIN32.HLP).