Міністерство освіти, науки,
культури та спорту України
Національний університет “Львівська політехніка”
Інститут комп’ютерних наук та інформаційних технологій
Кафедра автоматизованих систем управління
МЕТОДИ СИСТЕМНОГО ПРОГРАМУВАННЯ
ЗБІРНИК ЛАБОРАТОРНИХ РОБІТ
Методичні вказівки
з курсу “операційні системи”
для студентів базової вищої освіти
за напрямком 05.01.01 “Комп’ютерні науки”
та курсу “Сиcтемне програмування та операційні системи в комп’ютерній поліграфії”
для студентів базової вищої освіти
за напрямком 05.15.01 “Видавничо-поліграфічна справа”
Львів - 2011
Методи системного програмування. Методичні вказівки з курсу “операційні системи” для студентів базової вищої освіти за напрямком 05.01.01 “Комп’ютерні науки” та курсу “ Сиcтемне програмування та операційні системи в комп’ютерній поліграфії” для студентів базової вищої освіти за напрямком 05.15.01 “Видавничо-поліграфічна справа”, Львів, НУ “Львівська політехніка”, 2011 р.
Укладачі: Зербіно Д.Д., канд. техн. наук, доц.,
Цимбал Ю.В., канд. техн. наук, доц.
Відповідальний за випуск: Шпак З.Я. канд. техн. наук, доц.
Лабораторна робота №1
Тема ( Робота з компонентами ActiveX.
Мета ( На прикладі роботи з об’єктами ActiveX навчитись викликати методи COM-об’єктів.
ТЕОРЕТИЧНІ ПОЛОЖЕННЯ
Ідея технології ActiveX полягає в тому, щоб зв’язати WEB-технологію з компонентами, які встановлені на комп’ютері у користувача. Таким чином, компонент може бути активізований і керуватися через WEB-сторінки, якщо в них є посилання на ці об’єкти. Другий варіант ActiveX – це можливість керування компонентом з віддаленого WEB-сервера, або робота компонента під управлінням цього сервера.
Технологія ActiveX побудована на методах OLE і використовує стандартні функції реєстрації та створення COM-об’єктів. Для роботи з COM-об’єктом необхідно створити екземпляр його інтерфейсу за допомогою API функції CoCreateInstance (див. програму далі). Після створення екземпляру об’єкту (інтерфейсу) його необхідно відповідним чином ініціалізувати (див. програму далі). Уникнути ініціалізації можна, якщо створювати екземпляр інтерфейсу більш спеціалізованими функціями (наприклад, функцією OleLoadPicture для інтерфейсу IPicture, якою ви користувалися в попередній лабораторній роботі).
В даній лабораторній роботі розглядається керування одним з таких об’єктів як Microsoft Agent. Цей компонент був створений для підтримки дружнього інтерфейсу з користувачем і виглядає як казковий персонаж, що керується певними командами. Компоненти Microsoft Agent входять в склад операційних систем Windows, починаючи з версії 2000. На інші системи ці компоненти можна інсталювати з сервера фірми Microsoft (http://www.microsoft.com/msagent). Персонажі можуть виглядати по-різному, але всі вони підтримують один стандартний набір команд.
Технологія ActiveX не залежить ні від мови програмування, ні від платформи; тому її можна віднести до одної з технологій системного програмування. Для підтвердження сказаного наведемо приклад WEB-сторінки, яка посилається на компонент Microsoft Agent. Вам лише необхідно скопіювати нижче поданий фрагмент у текстовий файл і поміняти розширення на “.htm”:
<html> <body bgcolor=#000000>
<h2> <Font Face=Times Color=#d1d1c8> Site News </Font></h2>
<OBJECT id=Agent height=0 width=0
classid=CLSID:F5BE8BD2-7DE6-11D0-91FE-00C04FD701A5></OBJECT>
<SCRIPT language=javascript> <!--
var Merlin;
var X,Y;
function LoadAgent()
{ Agent.Characters.Load ("Default");
Merlin = Agent.Characters.Character("Default");
Merlin.MoveTo(200, 200);
Merlin.Show();
Merlin.Play("DoMagic1");
Merlin.Play("DoMagic2");
Merlin.MoveTo(300,300);
Merlin.Play("Greet");
Merlin.Play("Explain");
Merlin.Speak('Hello! This site will tell you about our Company.')
Merlin.MoveTo(400, 450);
Merlin.Play("LookUpBlink");
Merlin.Play("Read");
Merlin.Speak("You are welcome!");
Merlin.Play("Congratulate");
Merlin.Play("GestureLeft");
Merlin.Play("GestureRight");
Merlin.MoveTo(400, 500);
Merlin.Speak("Please read the news of the site...");
Merlin.Play("GestureUp");
Merlin.Play("Search");
Merlin.Play("LookLeftBlink");
Merlin.Play("LookRightBlink");
Merlin.Play("LookLeftBlink");
Merlin.Play("Searching");
}
function SayAnat(s)
{ X = window.event.screenX;
Y = window.event.screenY;
Merlin.MoveTo(X+50, Y-30);
Merlin.GestureAt(X,Y);
s="\\Pit=18400\\\\Spd=500\\"+s;
Merlin.Speak(s);
Merlin.Play("StartListening");
Merlin.Play("Wave");
Merlin.Play("Write");
}
function Stop()
{ Merlin.Play("Pleased");
Merlin.StopAll();
}
function UnLoadAgent()
{ Merlin.Play("Searching");
Agent.Characters.Unload("Default");
}
//--> </SCRIPT>
<SCRIPT language=VBSCRIPT>
If HaveAgent() Then
document.write "<body onload=""LoadAgent()"" onunload=""UnLoadAgent()"">"
document.write "<h2><A onMouseOver=""SayAnat('Our History')"" onMouseOut=""Stop()"" HREF=""http://www.yandex.ru/""> History of the Company</A></h2><br>"
document.write "<h2><A onMouseOver=""SayAnat('Our Partners')"" onMouseOut=""Stop()"" HREF=""http://www.yandex.ru/"">Partners</A></h2><br>"
document.write "<h2><A onMouseOver=""SayAnat('Here our Programming Laboratory')"" onMouseOut=""Stop()"" HREF=""http://www.yandex.ru/"">Laboratory</A></h2><br>"
document.write "<h2><A onMouseOver=""SayAnat('Please review our suggestions!')"" onMouseOut=""Stop()"" HREF=""http://www.yandex.ru/""> Suggestions</A></h2>"
Else
document.write "<h2 align=center><A HREF=""http://www.microsoft.com/msagent/""> Microsoft Agent control was not found on your computer! </A></h2>"
End If
Function HaveAgent()
Dim agent
HaveAgent = False
On Error Resume Next
Set agent = CreateObject("Agent.Control.1")
HaveAgent = IsObject(agent)
End Function
</SCRIPT> </body> </html>
Оскільки керуючі елементи ActiveX можуть виконувати в системі клієнта довільні дії, то не можна допускати, щоб WEB-клієнт міг загрузити довільний об’єкт ActiveX. Ці компоненти можна лише завантажувати з сервера Microsoft.
Якщо проглянути вище поданий текст, то можна побачити застосування наступних методів до активізованого об’єкта “Microsoft agent”: MoveTo, Play, Speak. На низькому рівні методи організовані як таблиця з адресами підпрограм, які їх реалізовують. У таблиці 1 подані символічні назви методів, їх адреси, кількість параметрів. Назва методів та їх порядок у таблиці подаються в довідкових файлах *.h, які додаються до компілятора С++.
Таблиця 1
№
Адреса в
Таблиці
Назва методу
Параметри
Зміст параметрів
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
0h
04h
08h
0Ch
10h
14h
18h
1Ch
20h
24h
28h
2Ch
30h
34h
38h
3Ch
40h
44h
48h
4Ch
50h
54h
58hl
5Ch
60h
64h
68h
6Ch
70h
74h
78h
7Ch
80h
84h
88h
8Ch
90h
94h
98h
9Ch
0A0h
0A4h
0A8h
0ACh
0B0h
0B4h
0B8h
0BCh
0C0h
0C4h
0C8h
0CCh
0D0h
0D4h
0D8h
0DCh
0E0h
0E4h
0E8h
0Ech
0F0h
QueryInterface
AddRef
Release
GetTypeInfoCount
GetTypeInfo
GetIDsOfNames
Invoke
GetVisible
SetPosition
GetPosition
SetSize
GetSize
GetName
GetDescription
GetTTSSpeed
GetTTSPitch
Activate
SetIdleOn
GetIdleOn
Prepare
Play
Stop
StopAll
Wait
Interrupt
Show
Hide
Speak
MoveTo
GestureAt
GetMoveCause
GetVisibilityCause
HasOtherClients
SetSoundEffectsOn
GetSoundEffectsOn
SetName
SetDescription
GetExtraData
ShowPopupMenu
SetAutoPopupMenu
GetAutoPopupMenu
GetHelpFileName
SetHelpFileName
SetHelpModeOn
GetHelpModeOn
SetHelpContextID
GetHelpContextID
GetActive
Listen
SetLanguageID
GetLanguageID
GetTTSModeID
SetTTSModeID
GetSRModeID
SetSRModeID
GetGUID
GetOriginalSize
Think
GetVersion
GetAnimationNames
GetSRStatus
in, out
-
-
out
in, in, out
in, in, in, in, out
in,in,in,in,i/o,out
out
in, in
out, out
in, in
out, out
out
out
out
out
in
in
out
in, in, in, out
in, out
in
in
in, out
in, out
in, out
in, out
in, in, out
in, in, in, out
in, in, out
out
out
out
in
out
in
in
out
in, in
in
out
out
in
in
out
in
out
out
in
in
out
out
in
out
in
out
out, out
in, out
out, out
out
out
Адр. ідентиф., Адр.хендлу
-
-
Адр. буферу
Тип, ID, Адр. буферу
IID, Size, Name, ID, Адр. буф.
ID,IID,ID,Flg,Адр.буф,Адр.буф
Адреса ідентифікатора
Координати X,Y
Адреса координат X,Y
Ширина, висота
Адреса ширини, висоти
Адреса буферу
Адреса буферу
Адреса змінної
Адреса змінної
Значення початкового стану
Значення-прапорець
Адреса змінної
Тип, Ім’я, Черга, Адр. ідентиф.
Адреса буферу, Адр. ідентифік.
Ідентифікатор
Тип дії
Ідентифікатор, Адр. ідентифік.
Ідентифікатор, Адр. ідентифік.
Швидкість, Адр. ідентифік.
Швидкість, Адр. ідентифік.
Адр.тексту, Адр.файлу, Адр.ID.
X, Y, Швидкість, Адр. ідентиф.
X, Y, Адр. ідентифік.
Адреса буферу
Адреса буферу
Адреса змінної
Значення-прапорець
Адреса змінної
Адреса буферу
Адреса буферу
Адреса буферу
X, Y
Прапорець
Адреса прапорця
Адреса імені
Адреса імені
Прапорець
Адреса прапорця
Адреса IID
Адреса рядка
Адреса прапорця
Прапорець
Ідентифікатор
Адр. Ідентифікатора
Адреса рядка
Адр. Ідентифікатора
Адреса рядка
Адреса рядка
Адреса рядка
Адреса X, Адреса Y
Адр. рядка, Адр. ідентиф.
Адр. ідентиф., Адр. ідентиф.
Адреса буферу
Адреса прапорця
Для виклику довільного методу використовується три команди асемблера:
mov edx, хендл інтерфейсу об’єкта
mov edx, [edx]
call [edx+ адреса метода в таблиці], хендл інтерфейсу об’єкта, параметри
Кожна таблиця методів містить на початку стандартні спеціалізовані методи QueryInterface, AddRef, Release, які будуть розглянуті в наступній лабораторній роботі.
Для деяких методів (наприклад, Speak) необхідно виділяти системну область пам’яті. Пам’ять з програми користувача для них не підходить. Для цього існує функція SysAllocString, яка резервує фрагмент системної пам’яті і одразу ж копіює в нього рядок з пам’яті користувача, який закінчується двома нулями (див. далі текст програми). Після використання цей фрагмент знищується за допомогою функції SysFreeString, параметром якої є адреса цього фрагменту.
Всі керуючі дії для об’єктів ActiveX (так само як і для об’єктів мережі) необхідно передавати в юнікодах. Для перетворення рядка в юнікод в програмі використана функція MultiByteToWideChar.
Нижче наведена програма для демонстрації всіх рухів персонажу “Microsoft Agent”.
.486
.model flat,stdcall
extrn ExitProcess:Proc, MessageBoxA:Proc, CoInitialize:Proc
extrn CoCreateInstance:Proc, MultiByteToWideChar:Proc
extrn SysAllocString:Proc, SysFreeString:Proc, OpenFile:Proc
VT_BSTR equ 8
OF_EXIST equ 4000h
.data
; HKEY_CLASSES_ROOT\CLSID\{D45FD2FC-5C6E-11D1-9EC1-00C04FD7081F} [по умолчанию] = Microsoft Agent Server 2.0
CLSID_AgentServer dd 0d45fd2fch
dw 5c6eh, 11d1h
db 9Eh,0C1h, 00h, 0C0h,4Fh,0D7h,08h,1Fh
;--------------------------------------------------------------------------------------------------------------
; HKEY_CLASSES_ROOT\Interface\{48D12BA0-5B77-11D1-9EC1-00C04FD7081F} [по умолчанию] = IAgentEx
; HKEY_LOCAL_MACHINE\Software\CLASSES\Interface\{48D12BA0-5B77-11D1-9EC1-00C04FD7081F} [по умолчанию] = IAgentEx
IID_IAgentEx dd 48d12ba0h
dw 5b77h,11d1h
db 9Eh,0C1h, 00h,0C0h,4Fh,0D7h,08h,1Fh
TITLE1 db "Виконує дiю:",0
;--------------------------------------
GESTURES: ; Прокоментуйте стандартнi жести персонажа:
db "Wave",0, "Acknowledge",0, "Alert",0, "Announce",0, "Blink",0, "Confused",0
db "Congratulate",0, "Decline",0, "DoMagic1",0, "DoMagic2",0, "DontRecognize",0
db "Explain",0, "GestureDown",0, "GestureLeft",0, "GestureRight",0, "GestureUp",0
db "GetAttention",0, "GetAttentionContinued",0, "GetAttentionReturn",0, "Greet",0
db "LookDown",0,"LookDownReturn",0,"LookLeft",0,"LookLeftReturn",0,"LookRight",0
db "LookRightReturn",0, "LookUp",0, "LookUpReturn",0, "MoveDown",0, "MoveLeft",0
db "MoveRight",0, "MoveUp",0, "Pleased",0, "Process",0, "Processing",0, "Read",0
db "ReadContinued",0,"ReadReturn",0,"Reading",0,"RestPose",0,"Sad",0,"Search",0
db "Searching",0, "Show",0, "StartListening",0, "StopListening",0, "Suggest",0
db "Surprised",0,"Think",0,"Thinking",0,"Uncertain",0,"Write",0,"WriteContinued",0
db "WriteReturn",0, "Writing",0, "Idle1_1",0, "Idle1_2",0, "Idle1_3",0, "Idle1_4",0
db "Idle2_1",0, "Idle2_2",0, "Idle3_1",0, "Idle3_2",0, "Hide",0, "Hearing_1",0
db "Hearing_2",0, "Hearing_3",0, "Hearing_4",0, "Animation",0
end_GESTURES db 0
;----------------------------------------------------------------------------------------------------------
hAgent dd 0
hAgentObject dd 0
IChrID dd 0
IReqID dd 0
hAgentChar dd 0
Var1 dd 0
ADR1 dd 0
TYPE_AGENT dd 0
; Параметри дискретизацiї звуку та швидкостi вимовляння фрази:
BUF1 db "\Pit=18400\\Spd=150\ Hello Dear Students of National University L'vivska Politechnica!",0
Index dd 0
ACS db "robby.acs",0 ; Варiант агента
.data?
OFSTRUCT db 8 dup(?)
FullName db 260 dup(?)
BUF2 dw 500 dup(?)
;-----------------------------------------------------------------------------------------------------------
.code
Start:
Call CoInitialize,0 ; Initializes the COM library on the current thread
Call CoCreateInstance, offset CLSID_AgentServer, 0, 5, offset IID_IAgentEx, offset hAgentObject
test eax, eax
js STOP
call OpenFile,offset ACS,offset OFSTRUCT,OF_EXIST
cmp eax,-1
jz NOT_ACS
call MessageBoxA,0,offset FullName,offset ACS,0
Call MultiByteToWideChar,0,0,offset FullName,-1,offset BUF2,500
Call SysAllocString,offset BUF2
mov ADR1,eax
mov TYPE_AGENT,VT_BSTR
NOT_ACS:
mov edx,hAgentObject
mov edx,[edx] ; Load Agent:
call [edx+1Ch],hAgentObject,TYPE_AGENT,0,ADR1,0,offset IChrID,offset IReqID
Call SysFreeString,ADR1
test eax, eax
js STOP
mov edx,hAgentObject
mov edx,[edx]
; 2ch = Get the Agent Character
call [edx+2Ch],hAgentObject,IChrID,offset hAgentChar ; Get the Agent Character
test eax, eax
js STOP
;====================================================
mov edx,hAgentChar
mov edx,[edx]
; 0c4h = SetLanguageID ; 409-English, 419-Russian, 422-Ukrain
call [edx+0C4h],hAgentChar,409h ; Set Language
test eax, eax
js STOP
;------------------------------
mov edx,hAgentChar
mov edx,[edx]
call [edx+28h],hAgentChar,250, 270 ; SetSize
;--------------------------------
mov edx, hAgentChar
mov edx,[edx]
call [edx+64h],hAgentChar,0,offset Var1 ; show
;--------------------------------
mov edx, hAgentChar
mov edx,[edx]
call [edx+70h],hAgentChar,200,200,1,offset Var1 ; MoveTo X,Y,Speed,Id
;--------------------------------
Call MultiByteToWideChar,0,0,offset BUF1,-1,offset BUF2,500
Call SysAllocString,offset BUF2
mov ADR1,eax
mov edx,hAgentChar
mov edx,[edx]
call [edx+6Ch],hAgentChar,eax,0,offset Var1 ; speak
Call SysFreeString,ADR1
;--------------------------------
L_Index1:
Call Do_Gesture,Index ; PlayVal
call MessageBoxA,0,edi,offset TITLE1,0
inc Index
cmp Index,69
jc L_Index1
;--------------------------------
mov edx,hAgentChar
mov edx,[edx]
call [edx+68h],hAgentChar,0,offset Var1 ; hide
call MessageBoxA,0,offset BUF1,offset BUF1,0
STOP: call ExitProcess,0
;===============================================
Do_Gesture Proc Number:dword
push ds
pop es
;-----------------------------------------------------------
mov edx,hAgentChar
mov edx,[edx]
call [edx+58h],hAgentChar,1 ; Stop play
;-----------------------------------------------------------
mov edi,offset GESTURES
mov ecx,offset end_GESTURES
sub ecx,edi ; esi = size of GESTURES
cmp Number,0
jz FOUND_OK
L_NUM1: xor al,al
repnz scasb
or ecx,ecx
jz ERR1
dec Number
jnz L_NUM1
FOUND_OK:
push edi
Call MultiByteToWideChar,0,0,edi,-1,offset BUF2,1000
Call SysAllocString,offset BUF2
mov ADR1,eax
mov edx,hAgentChar
mov edx,[edx]
call [edx+50h],hAgentChar,eax,offset Var1 ; gesture
Call SysFreeString,ADR1
pop edi
ERR1: ret
endp Do_Gesture
end Start
ПОРЯДОК ВИКОНАННЯ РОБОТИ
Запустити поданий в лабораторній роботі HTML-файл. Дослідити рухи персонажу Microsoft Agent.
Створити файл для компіляції, у якому замінити шлях до файлу Import32.lib на шлях до аналогічного файлу з каталогу CBUILDER5, що має довжину 710K і 2000-й рік створення.
Відкомпілювати та запустити подану в роботі програму. Дослідити рухи персонажу Microsoft Agent.
Переписати в каталог з програмою файл ROBBY.ACS та знову запустити програму.
Отримати від викладача завдання стосовно сценарію поведінки персонажу Microsoft Agent та реалізувати заданий сценарій.
Скласти та захистити звіт по лабораторній роботі. В звіті дати свої коментарі до основних фрагментів програми. Зробити висновки.
ВАРІАНТИ ЗАВДАНЬ
Скласти програму, яка активізує агента, коли пересувається миша, і змушує його летіти за мишею. Для цього використати в циклі метод MoveTo та функції GetCursorPos та Sleep (див. документацію).
Скласти програму, яка пересуває агента по краях екрану та виконує випадкову анімацію.
Скласти програму, яка робить презентацію студентської групи та автора програми за допомогою об’єкту Microsoft Agent. Методи Speak та MoveTo оформити та викликати як окремі підпрограми.
КОНТРОЛЬНІ ЗАПИТАННЯ
Яка основна концепція ActiveX?
Які параметри має функція CoCreateInstance?
Як викликається метод?
Які стандартні методи є в кожній таблиці методів?
Які методи викликаються в програмі?
Яка функція перетворює рядок в юнікод?
Яка функція виділяє буфер в системній області?
Лабораторна робота №2
Тема ( Компіляція ресурсних даних.
Мета ( Оволодіти правилами компіляції ресурсних даних.
ТЕОРЕТИЧНІ ПОЛОЖЕННЯ
Ресурсні дані (в подальшому – ресурси) включаються в програмний модуль як окрема секція даних, яка завантажується в оперативну пам’ять по частинах по мірі необхідності за допомогою функцій LoadResource, LoadAcceleratorsA, LoadBitmapA, LoadCursorA, LoadIconA, (або LoadImageA), LoadMenuA, LoadStringA.
Для включення певних даних у виконуючий файл їх необхідно описати у спеціальному текстовому файлі з таким самим іменем та розширенням “.rc”. Цей файл складається з окремих рядків, кожний з яких описує фрагмент ресурсних даних, які після компіляції будуть включені exe-модуль. Наприклад, якщо ви бажаєте включити у файл PROG.EXE іконку ABCD.ICO, то необхідно створити текстовий файл з іменем PROG.RC, в який треба записати наступне:
Файл ABCD.ICO повинен бути в цьому ж каталозі. Ключове слово ICON вказує на тип ресурсних даних, які будуть приєднані до exe-модуля. Name1 – це внутрішній ідентифікатор, по якому можна буде знайти вказані дані в секції ресурсів.
Після цього файл PROG.RC необхідно відкомпілювати за допомогою програми H:\tasm\bin\BRCC32.EXE (або будь-яким іншим компілятором ресурсів). Результатом компіляції RC-файлу PROG.RC завжди буде RES-файл PROG.RES. Файл PROG.RES буде використаний для лінкування модуля за допомогою Tlink32.exe.
Отже, для компіляції програм, які містять ресурси, необхідно користуватись наступним BAT-файлом (compile32res.bat):
В ньому “%1” буде замінятися на назву програми. Не забувайте створювати разом з програмою файл опису ресурсів з розширенням “.rc”, який повинен мати таке ж саме ім’я як і програма, інакше в exe-модуль будуть включені випадкові дані.
В наступній таблиці наведені ключові слова для різних типів ресурсних даних, які можна включити в exe-модуль:
Таблиця 2
Ключове слово
в файлі .rc
Тип ресурсних даних
ICON
Файл з малюнком типу “Іконка”
AVI
Анімована іконка (AVI-файл)
ACCELERATORS
Таблиця гарячих клавіш
STRINGTABLE
Таблиця рядків
STRING
Текстовий рядок
DIALOG
Опис діалогового вікна
CONTROL
Вікно стандартного класу
MENU
Опис горизонтального меню вікна
POPUP
Опис спадаючого меню
MENUITEM
Опис одного пункту меню
CURSOR
Файл, що містить зображення курсору
BITMAP
Файл типу “.BMP”
RCDATA
Опис бінарних даних
WAVE
Звуковий файл типу “.WAV”
HTML
Файл типу “.HTM”
ANICURSOR
Файл анімованого курсору
FONT
Файл шрифту
VXD
Файл драйвера пристрою
Наведемо приклад файлу ресурсів (знайдіть в ньому опис меню).
Banana2 CURSOR "TEST1.CUR"
Face5 ICON "TEST2.ICO"
Back1 BITMAP "TEST3.bmp"
sss1 WAVE "Test4.wav"
dgg1 DIALOG 26, 25, 200, 90 CAPTION "About GDIDEMO" STYLE 2160590848
BEGIN
CONTROL "Лабораторна №2", 1, "static", 1073741825, 50, 35, 100, 8
CONTROL "Прiзвище", 2, "Edit", 1073741825, 50, 43, 100, 8
CONTROL "OK", 1, "Button", 1073807360, 50, 54, 100, 17
END
mm1 MENU
{
POPUP "&Програма"
{
MENUITEM "&Автор\tF1", 123
MENUITEM SEPARATOR
MENUITEM "&Exit\tAlt-F4", 456
}
POPUP "&Файл"
{
MENUITEM "&Завантажити\tCtrl-L", 789
MENUITEM "Зберегти\tCtrl-S", 555
}
}
У цьому RC-файлі описано:
1) курсор, 2) піктограму, 3) зображення, 4) звуковий файл, 5) діалогове вікно, 5) меню.
Для того, щоб користуватись кожним типом ресурсів існує своя функція:
LoadCursorA, LoadIconA, LoadBitmapA, PlaySoundA, CreateDialogParamA, LoadMenuA. Курсор, іконка і меню вказуються в структурі класу вікна.
Наприклад, перед тим як користуватись меню його необхідно завантажити за допомогою функції LoadMenuA з двома параметрами: хендл програми, адреса рядка “mm1”. Кожний пункт меню має свій ідентифікатор (наприклад, 123 в пункті “Автор”). Цей ідентифікатор буде передаватись у віконну процедуру разом з повідомленням WM_COMMAND (111h) як значення lParam.
Для активізації діалогового вікна необхідно викликати функцію CreateDialogParamA, яка має наступні параметри: хендл програми, адреса рядка “dgg1”, хендл вікна-власника, адреса діалогової процедури, параметр користувача.
Якщо під час компіляції цього файлу у поточному каталозі не знайдеться будь-якого з заданих файлів (TEST1.CUR, TEST2.ICO, TEST3.BMP, TEST4.WAV), то файл “.RES” не створиться, а EXE-програма не буде працювати. Тому перед запуском програми перевірте наявність RES-файлу у поточному каталозі.
Нижче наведена програма для утворення ярлика на робочому столі.
.486
.model flat,stdcall
extrn MultiByteToWideChar:Proc
extrn ExitProcess:Proc
extrn lstrcat:Proc
extrn CoInitialize:Proc
extrn CoUninitialize:Proc
extrn CoCreateInstance:Proc
extrn SHGetSpecialFolderLocation:Proc
extrn SHGetPathFromIDList:Proc
; IPersistFile STRUCT DWORD
; IPersistFile_QueryInterface comethod3 0
; IPersistFile_AddRef comethod1 4
; IPersistFile_Release comethod1 8
; IPersistFile_GetClassID comethod2 0Ch
; IPersistFile_IsDirty comethod1 10h
; IPersistFile_Load comethod3 14h
; IPersistFile_Save comethod3 18h
; IPersistFile_SaveCompleted comethod2 1Ch
; IPersistFile_GetCurFile comethod2 20h
; IPersistFile ENDS
.data
DESKTOP db 260 dup(0),0
PROG_PATH db "C:\Program Files\Far\Far.exe",0
WORK_DIR db "C:\WINNT\Temp",0
LINKNAME db "\Far1.lnk",0
BUF1 db 520 dup(0)
CLSID_Shortcut:
dd 00021401h ; HKEY_CLASSES_ROOT\CLSID\{00021401-0000-0000-C000-000000000046} = Shortcut
dw 0000h,0000h
db 0C0h,00h
db 00h,00h,00h,00h,00h,46h ; {000214EE-0000-0000-C000-000000000046}
IID_IShellLink:
dd 000214EEh ; HKEY_CLASSES_ROOT\Interface\{000214EE-0000-0000-C000-000000000046} = IShellLinkA
dw 0000h,0000h
db 0C0h,00h
db 00h,00h,00h,00h,00h,46h
IID_IPersistFile:
dd 0000010Bh ; HKEY_CLASSES_ROOT\Interface (IPersistFile)
dw 0000h, 0000h
db 0C0h, 00h
db 00h,00h,00h,00h,00h,046h
DIRECTORY_ID dd 0 ; хендл папки;
Result dd 0
INTERFACE dd 0
PSL dd 0
.code
Start:
; Отримуємо шлях до каталогу "DESKTOP":
call SHGetSpecialFolderLocation,0,0,offset DIRECTORY_ID
call SHGetPathFromIDList,DIRECTORY_ID,offset DESKTOP
call lstrcat,offset DESKTOP,offset LINKNAME
; Перетворюємо шлях до DESKTOP з кодування ANSI в UNICODE:
Call MultiByteToWideChar,0,0,offset DESKTOP,-1,offset BUF1,520
; Iнiциалiзуємо роботу з бiблiотекою COM (Component Object Model)
call CoInitialize,0
; Створюємо об'єкт та отримуємо вказiвник на його iнтерфейс (IShellLink),
; та записуємо вказiвник в змiнну PSL.
Call CoCreateInstance, offset CLSID_Shortcut, 0, 1, offset IID_IShellLink, offset PSL
mov Result, eax
test eax, eax
js STOP
; Запросити у інтерфейсу IShellLink вказiвник на iнтерфейс IPersistFile.
; Iншими словами, викликаємо метод QueryInterface (змiщення 0h в таблицi методiв),
; який налаштовує IShellLink на використання iнтерфейсу IPersistFile.
; В результатi отримуємо хендл INTERFACE, який вказує
; на таблицю методiв IPersistFile для роботи з IShellLink.
mov edx,PSL
mov edx, [edx]
call [edx],PSL,offset IID_IPersistFile,offset INTERFACE
mov Result, eax
test eax, eax
js Err1 ; В разi помилки треба знищити об'єкт
; Виклик методу SetPath з iнтерфейсу IShellLink
; для встановлення шляху до програми на яку ми збираємось створити ярлик.
; Метод SetPath (50h) має 1 параметр:
mov edx,PSL
mov edx, [edx]
call [edx+50h],PSL,offset PROG_PATH
mov Result, eax
; Виклик методу SetIconLocation з iнтерфейсу IShellLink
; для встановлення шляху до iконки яка буде вiдображатися на ярлику.
; Метод SetIconLocation (44h) має 2 параметри:
mov edx,PSL
mov edx, [edx]
call [edx+44h],PSL,offset PROG_PATH,0
mov Result, eax
; Виклик методу SetWorkingDirectory з iнтерфейсу IShellLink:
; для встановлення шляху до робочого каталогу, в якому буде працювати програма.
; Метод SetWorkingDirectory (24h) має 1 параметр:
mov edx,PSL
mov edx, [edx]
call [edx+24h],PSL,