
Использование ресурсов
Основной процесс использует ресурсы загруженной им динамической библиотеки. Ресурсы можно поместить отдельно от основной программы в динамическую библиотеку, загружая их по мере необходимости.
Наша программа вначале загружает иконку из ресурсов динамической библиотеки и устанавливает ее на окно. Если щелкать левой кнопкой мыши, направив курсор на окно, то будет вызываться процедура из динамической библиотеки, которая будет поочередно устанавливать то один, то другой значок на окно.
dll3.rc:
// идентификаторы
#define IDI_ICON1 3
#define IDI_ICON2 10
// определили иконку
IDI_ICON1 ICON "ico1.ico"
IDI_ICON2 ICON "ico2.ico"
dllex.rc:
// определение констант
#define WS_SYSMENU 0x00080000L
#define WS_MINIMIZEBOX 0x00020000L
#define WS_MAXIMIZEBOX 0x00010000L
#define DS_3DLOOK 0x0004L
// определение диалогового окна
DIAL1 DIALOG 0, 0, 340, 120
STYLE WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | DS_3DLOOK
CAPTION "Диалоговое окно с иконкой из динамической библиотеки"
FONT 8, "Arial"
{
}
dll3.asm:
; динамическая библиотека DLL3.ASM
.386P
PUBLIC SETIC
; плоская модель
IFDEF MASM
.MODEL FLAT, stdcall
ELSE
.MODEL FLAT
ENDIF
; константы
WM_SETICON equ 80h
IFDEF MASM
; MASM
; прототипы внешних процедур
EXTERN LoadIconA@8:NEAR
EXTERN PostMessageA@16:NEAR
; директивы компоновщику для подключения библиотек
includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\kernel32.lib
ELSE
; TASM
; прототипы внешних процедур
EXTERN LoadIconA:NEAR
EXTERN PostMessageA:NEAR
; директивы компоновщику для подключения библиотек
includelib c:\tasm\lib\import32.lib
LoadIconA@8 = LoadIconA
PostMessageA@16 = PostMessageA
ENDIF
;-------------------------------------------------
; сегмент данных
_DATA SEGMENT DWORD PUBLIC USE32 'DATA'
PRIZ DB 0
_DATA ENDS
; сегмент кода
_TEXT SEGMENT DWORD PUBLIC USE32 'CODE'
DLLENTRY:
MOV EAX,1
RET 12
; [EBP+8]
; [EBP+0CH]
SETIC PROC EXPORT
PUSH EBP
MOV EBP,ESP
; выбрать, какую иконку устанавливать
CMP PRIZ,0
JZ IC_1
MOV PRIZ,0
PUSH 3
JMP CONT
IC_1:
MOV PRIZ,1
PUSH 10
CONT:
; загрузить иконку из ресурсов библиотеки
PUSH DWORD PTR [EBP+0CH] ; идентификатор
; динамической
; библиотеки
CALL LoadIconA@8
; установить значок окна
PUSH EAX
PUSH 0
PUSH WM_SETICON
PUSH DWORD PTR [EBP+08H] ; дескриптор окна
CALL PostMessageA@16
POP EBP
RET 8
SETIC ENDP
_TEXT ENDS
END DLLENTRY
dllex3.asm:
; основной модуль DLLEX3.ASM, вызывающий
; процедуру из динамической библиотеки
.386P
; плоская модель
IFDEF MASM
.MODEL FLAT, stdcall
ELSE
.MODEL FLAT
ENDIF
; константы
; сообщение приходит при закрытии окна
WM_CLOSE equ 10h
WM_INITDIALOG equ 110h
WM_SETICON equ 80h
WM_LBUTTONDOWN equ 201h
; прототипы внешних процедур
IFDEF MASM
; MASM
EXTERN PostMessageA@16:NEAR
EXTERN GetProcAddress@8:NEAR
EXTERN LoadLibraryA@4:NEAR
EXTERN FreeLibrary@4:NEAR
EXTERN ExitProcess@4:NEAR
EXTERN GetModuleHandleA@4:NEAR
EXTERN DialogBoxParamA@20:NEAR
EXTERN EndDialog@8:NEAR
EXTERN LoadIconA@8:NEAR
; директивы компоновщику для подключения библиотек
includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\kernel32.lib
ELSE
; директивы компоновщику для подключения библиотек
includelib c:\tasm\lib\import32.lib
EXTERN PostMessageA:NEAR
EXTERN GetProcAddress:NEAR
EXTERN LoadLibraryA:NEAR
EXTERN FreeLibrary:NEAR
EXTERN ExitProcess:NEAR
EXTERN GetModuleHandleA:NEAR
EXTERN DialogBoxParamA:NEAR
EXTERN EndDialog:NEAR
EXTERN LoadIconA:NEAR
PostMessageA@16 = PostMessageA
LoadIconA@8 = LoadIconA
EndDialog@8 = EndDialog
GetModuleHandleA@4 = GetModuleHandleA
DialogBoxParamA@20 = DialogBoxParamA
GetProcAddress@8 = GetProcAddress
LoadLibraryA@4 = LoadLibraryA
FreeLibrary@4 = FreeLibrary
ExitProcess@4 = ExitProcess
ENDIF
;------------------------------------------------
; сегмент данных
_DATA SEGMENT DWORD PUBLIC USE32 'DATA'
LIBR DB 'DLL3.DLL',0
HLIB DD ?
HINST DD ?
PA DB "DIAL1",0
IFDEF MASM
NAMEPROC DB "_SETIC@0",0
ELSE
NAMEPROC DB "SETIC",0
ENDIF
_DATA ENDS
; сегмент кода
_TEXT SEGMENT DWORD PUBLIC USE32 'CODE'
START:
; получить дескриптор приложения
PUSH 0
CALL GetModuleHandleA@4
; создать диалог
MOV [HINST], EAX
PUSH 0
PUSH OFFSET WNDPROC
PUSH 0
PUSH OFFSET PA
PUSH [HINST]
CALL DialogBoxParamA@20
; выход
_EXIT:
PUSH 0
CALL ExitProcess@4
; процедура окна
; расположение параметров в стеке
; [EBP+014Н] ; LPARAM
; [EBP+10Н] ; WAPARAM
; [EBP+0CH] ; MES
; [EBP+8] ; HWND
WNDPROC PROC
PUSH EBP
MOV EBP,ESP
PUSH EBX
PUSH ESI
PUSH EDI
;-------------------
CMP DWORD PTR [EBP+0CH],WM_CLOSE
JNE L1
; закрыть библиотеку
; библиотека автоматически закрывается также
; при выходе из программы
PUSH HLIB
CALL FreeLibrary@4
PUSH 0
PUSH DWORD PTR [EBP+08H]
CALL EndDialog@8
JMP FINISH
L1:
CMP DWORD PTR [EBP+0CH],WM_INITDIALOG
JNE L2
; загрузить библиотеку
PUSH OFFSET LIBR
CALL LoadLibraryA@4
MOV HLIB,EAX
; загрузить иконку
PUSH 3 ; идентификатор иконки
PUSH [HLIB] ; идентификатор процесса
CALL LoadIconA@8
; установить иконку
PUSH EAX
PUSH 0 ; тип иконки (маленькая)
PUSH WM_SETICON
PUSH DWORD PTR [EBP+08H]
CALL PostMessageA@16
JMP FINISH
L2:
CMP DWORD PTR [EBP+0CH],WM_LBUTTONDOWN
JNE FINISH
; получить адрес процедуры из динамической библиотеки
PUSH OFFSET NAMEPROC
PUSH HLIB
CALL GetProcAddress@8
; вызвать процедуру с двумя параметрами
PUSH [HLIB]
PUSH DWORD PTR [EBP+08H]
CALL EAX
FINISH:
POP EDI
POP ESI
POP EBX
POP EBP
MOV EAX,0
RET 16
WNDPROC ENDP
_TEXT ENDS
END START
1.bat:
c:\masm32\bin\ml /c /coff /DMASM dllex3.asm
c:\masm32\bin\rc dllex3.rc
c:\masm32\bin\link /subsystem:windows dllex3.obj dllex3.res
pause 0
c:\masm32\bin\ml /c /coff /DMASM dll3.asm
c:\masm32\bin\rc dll3.rc
c:\masm32\bin\link /subsystem:windows /DLL /ENTRY:DLLENTRY dll3.obj dll3.res
pause 0
Рис. 6. Результат работы программы (часть 1)
Рис. 7. Результат работы программы (часть 2)