Шаг 36.
Язык описания ресурсов. Строки

    На этом шаге мы рассмотрим использование строк из файла ресурсов.

    Чтобы задать строку или несколько строк, используется ключевое слово STRINGTABLE. Ниже представлен текст файла ресурса, задающий две строки.

#define IDI_ICON1 1 
#define IDI_CUR1  2
#define IDI_BIT1  3
#define IDI_STR1  4
#define IDI_STR2  5

IDI_ICON1 ICON "help.ico"
IDI_CUR1  CURSOR  "3dsmove.cur"
IDI_BIT1  BITMAP  "bitmap.bmp"
STRINGTABLE
{
IDI_STR1,  "Сообщение"
IDI_STR2,  "Версия программы 1.01"
}

    Для загрузки строки в программу используется функция LoadString. С помощью нее строка загружается в буфер, после чего с ней можно работать, как с обычной строкой. Отметим, что строки, задаваемые в файле ресурсов, могут играть роль констант.

    Изменим текст программы из шага 19, осуществляющего вывод строки в окно. Теперь строки, выводимые в окно, будут браться из файла ресурсов.


    Заголовочный файл для приложения, содержащий определения констант, внешних процедур и структур (его имя pr36_1.asm).
;Константы.
;Сообщение приходит при  закрытии окна.
WM_DESTROY	equ 2
;Сообщение приходит при создании окна.
WM_CREATE	equ  1
;Сообщение приходит при  перерисовке окна.
WM_PAINT        equ 0Fh
;Свойства окна.
CS_VREDRAW	    equ 1h
CS_HREDRAW	    equ 2h
CS_GLOBALCLASS      equ 4000h
WS_OVERLAPPEDWINDOW equ 000CF0000h
stylcl              equ CS_HREDRAW+CS_VREDRAW+CS_GLOBALCLASS
DX0                 equ 300
DY0                 equ 200
;Компоненты цветов.
RED                 equ 50
GREEN               equ 50
BLUE                equ 255
RGBW                equ (RED or (GREEN shl 8)) or (BLUE shl 16)
RGBT                equ 255 ;Красный.
;Режим показа окна - нормальный.
SW_SHOWNORMAL	  equ  1

;Прототипы внешних процедур.
EXTERN  CreateWindowExA@48:NEAR
EXTERN  DefWindowProcA@16:NEAR
EXTERN  DispatchMessageA@4:NEAR
EXTERN  ExitProcess@4:NEAR
EXTERN  GetMessageA@16:NEAR
EXTERN  GetModuleHandleA@4:NEAR
EXTERN  LoadCursorA@8:NEAR
EXTERN  LoadIconA@8:NEAR
EXTERN  PostQuitMessage@4:NEAR 
EXTERN  RegisterClassA@4:NEAR
EXTERN  ShowWindow@8:NEAR
EXTERN  TranslateMessage@4:NEAR
EXTERN  UpdateWindow@4:NEAR
EXTERN  BeginPaint@8:NEAR
EXTERN  EndPaint@8:NEAR
EXTERN  TextOutA@20:NEAR
EXTERN  GetStockObject@4:NEAR
EXTERN  CreateSolidBrush@4:NEAR
EXTERN  SetBkColor@8:NEAR
EXTERN  SetTextColor@8:NEAR
EXTERN  LoadStringA@16:NEAR
;Структуры
;Структура сообщения.
MSGSTRUCT  STRUC	
           MSHWND     DD ? ;Идентификатор окна, получающего сообщение.
           MSMESSAGE  DD ? ;Идентификатор сообщения.
           MSWPARAM   DD ? ;Доп. информация о сообщении.
           MSLPARAM   DD ? ;Доп. информация о сообщении.
           MSTIME     DD ? ;Время посылки сообщения.
           MSPT       DD ? ;Положение курсора во время посылки сообщения.
MSGSTRUCT ENDS	
;-----------------------
WNDCLASS  STRUC	
           CLSSTYLE     DD ? ;Стиль окна.
           CLWNDPROC    DD ? ;Указатель на процедуру окна.
           CLSCBCLSEX   DD ? ;Информация о доп. байтах для данной структуры.
           CLSCBWNDEX   DD ? ;Информация о доп. байтах для окна.
           CLSHINST     DD ? ;Дескриптор приложения.
           CLSHICON     DD ? ;Идентификатор иконки окна.
           CLSHCURSOR   DD ? ;Идентификатор курсора окна.
           CLBKGROUND   DD ? ;Идентификатор кисти окна.
           CLMENNAME    DD ? ;Имя-идентификатор меню.
           CLNAME       DD ? ;Специфицирует имя класса окон.
WNDCLASS  ENDS 
;-------------------------------- 
PAINTSTR  STRUC
    hdc     DWORD 0 
    fErase  DWORD 0
    left    DWORD 0
    top     DWORD 0
    right   DWORD 0
    bottom  DWORD 0
    fRes    DWORD 0
    fIncUp  DWORD 0
    Reserv DB 32 dup(0)
PAINTSTR  ENDS
Текст этого модуля, а также исходный файл ресурсов, файлы с пиктограммой, курсором и битовой картинкой можно взять здесь.


    Основной файл приложения, содержит подключение файла pr36_1.asm (его имя pr36_2.asm).
.386P
;Плоская модель.
.MODEL FLAT, STDCALL
include pr36_1.asm
;Директивы компоновщику для подключения библиотек.
includelib c:\masm32\lib\user32.lib 
includelib c:\masm32\lib\kernel32.lib
includelib c:\masm32\lib\gdi32.lib
;------------------------------------------------
;Сегмент данных. 
_DATA SEGMENT DWORD PUBLIC USE32 'DATA'
     NEWHWND     DD 0
     MSG         MSGSTRUCT <?>
     WC          WNDCLASS <?>
     PNT         PAINTSTR <?>
     HINST       DD 0 ;Здесь хранится дескриптор приложения.
     TITLENAME   DB 'Текст в окне',0
     NAM         DB 'CLASS32',0
     XT          DWORD 30
     YT          DWORD 30
     TXT         DWORD ?
     TEXT        DB 25 DUP(0) ;Буфер для выводимого текста.
_DATA ENDS 
;Сегмент кода.
_TEXT SEGMENT DWORD PUBLIC USE32 'CODE'
START: 
;Получить дескриптор приложения.
     PUSH  0
     CALL  GetModuleHandleA@4
     MOV   [HINST], EAX
REG_CLASS:
;Заполнить структуру окна.
;Стиль.
     MOV [WC.CLSSTYLE],stylcl 
;Процедура обработки сообщений.
     MOV   [WC.CLWNDPROC], OFFSET WNDPROC
     MOV   [WC.CLSCBCLSEX], 0
     MOV   [WC.CLSCBWNDEX], 0
     MOV   EAX, [HINST]
     MOV   [WC.CLSHINST], EAX
;------------ пиктограмма окна
;    PUSH    IDI_APPLICATION
;    PUSH    0
;    CALL    LoadIconA@8
;    MOV    [WC.CLSHICON], EAX
    PUSH  1   ;Идентификатор пиктограммы (см. файл resu.rc).
    PUSH  [HINST] ;Идентификатор процесса.
    CALL  LoadIconA@8
    MOV   [WC.CLSHICON], EAX
;------------ курсор окна
;    PUSH   IDC_ARROW
;    PUSH   0
;    CALL   LoadCursorA@8
;    MOV    [WC.CLSHCURSOR], EAX
    PUSH  2   ;Идентификатор курсора (см. файл resu.rc).
    PUSH  [HINST] ;Идентификатор процесса.
    CALL   LoadCursorA@8
    MOV    [WC.CLSHCURSOR], EAX
;------------
    PUSH   RGBW ;Цвет кисти.
    CALL   CreateSolidBrush@4;Создать кисть.
    MOV    [WC.CLBKGROUND],EAX 
    MOV    DWORD PTR [WC.CLMENNAME],0
    MOV    DWORD PTR [WC.CLNAME], OFFSET  NAM
    PUSH   OFFSET WC
    CALL   RegisterClassA@4
;Создать окно зарегистрированного класса.
    PUSH   0
    PUSH   [HINST]
    PUSH   0
    PUSH   0
    PUSH   DY0      ; DY0 - высота окна.
    PUSH   DX0      ; DX0 - ширина окна.
    PUSH   100      ; Координата Y.
    PUSH   100      ; Координата X.
    PUSH   WS_OVERLAPPEDWINDOW
    PUSH   OFFSET TITLENAME  ;Имя окна.
    PUSH   OFFSET NAM        ;Имя класса.
    PUSH   0
    CALL   CreateWindowExA@48
;Проверка на ошибку.
    CMP    EAX,0
    JZ    _ERR
    MOV   [NEWHWND], EAX  ;Дескриптор окна.
;------------------------------------
    PUSH  SW_SHOWNORMAL
    PUSH  [NEWHWND]
    CALL  ShowWindow@8    ;Показать созданное окно.
;------------------------------------
    PUSH  [NEWHWND]
    CALL UpdateWindow@4   ;Команда перерисовать видимую
                          ;часть окна, сообщение WM_PAINT.
;Цикл обработки сообщений 
MSG_LOOP:
    PUSH 0
    PUSH 0
    PUSH 0
    PUSH OFFSET MSG
    CALL GetMessageA@16
    CMP  EAX, 0
    JE   END_LOOP
    PUSH OFFSET MSG
    CALL TranslateMessage@4
    PUSH OFFSET MSG
    CALL DispatchMessageA@4
    JMP  MSG_LOOP 
END_LOOP: 
;Выход из программы (закрыть процесс).
    PUSH [MSG.MSWPARAM]
    CALL ExitProcess@4
_ERR:
    JMP  END_LOOP
;-----------------------------------------
;Процедура окна.
;Расположение параметров в стеке: 
;[ЕВР+14Н] LPARAM 
;[ЕВР+10Н] WPARAM 
;[ЕВР+0СН] MES 
;[ЕВР+08H] HWND 
WNDPROC PROC
        PUSH EBP
        MOV  EBP, ESP
        PUSH EBX
        PUSH ESI
        PUSH EDI
        CMP  DWORD PTR [EBP+0CH], WM_DESTROY
        JE   WMDESTROY
        CMP  DWORD PTR [EBP+0CH], WM_CREATE
        JE   WMCREATE
        CMP  DWORD PTR [EBP+0CH], WM_PAINT
        JE   WMPAINT
        JMP  DEFWNDPROC
WMPAINT:
;--------------------------
        PUSH OFFSET PNT
        PUSH DWORD PTR [EBP+08H]
        CALL BeginPaint@8
        PUSH EAX ;Сохранить контекст (дескриптор)
;------------------------ цвет фона = цвет окна
        PUSH RGBW
        PUSH EAX
        CALL SetBkColor@8
;------------------------ контекст
        POP EAX
        PUSH EAX
;------------------------ цвет текста (красный)
        PUSH RGBT
        PUSH EAX
        CALL SetTextColor@8
;------------------------ cохранить контекст
        POP EAX
        MOV TXT, EAX
;------------------------ загрузить 1-ю строку
        PUSH 25           ;Длина буфера.
        PUSH OFFSET TEXT  ;Начальный адрес буфера.
        PUSH 4            ;Идентификатор строки.
        PUSH [HINST]      ;Дескриптор приложения.
        CALL LoadStringA@16 
;------------------------ вывести 1-ю строку
        PUSH OFFSET TEXT
        CALL LENSTR
        PUSH EBX         ;Длина строки.
        PUSH OFFSET TEXT ;Адрес строки.
        PUSH YT          ;Y
        PUSH XT          ;X
        PUSH TXT         ;Контекст окна.
        CALL TextOutA@20
;------------------------ загрузить 2-ю строку
        PUSH 25
        PUSH OFFSET TEXT
        PUSH 5
        PUSH [HINST]
        CALL LoadStringA@16 
;------------------------ вывести 2-ю строку
        PUSH OFFSET TEXT
        CALL LENSTR
        PUSH EBX         ;Длина строки.
        PUSH OFFSET TEXT ;Адрес строки.
        ADD  YT,20       ;Вторая строка выводится ниже.
        PUSH YT          ;Y
        PUSH XT          ;X
        PUSH TXT         ;Контекст окна.
        CALL TextOutA@20
;------------------------ закрыть
        PUSH OFFSET PNT
        PUSH DWORD PTR [EBP+08H]
        CALL EndPaint@8 
        MOV EAX, 0 
        JMP FINISH 
WMCREATE:
        MOV EAX, 0 
        JMP FINISH 
DEFWNDPROC:
        PUSH DWORD PTR [EBP+14H]
        PUSH DWORD PTR [EBP+10H]
        PUSH DWORD PTR [EBP+0CH]
        PUSH DWORD PTR [EBP+08H]
        CALL DefWindowProcA@16
        JMP  FINISH
WMDESTROY:	
        PUSH 0                   ;MB_OK
        CALL PostQuitMessage@4   ;Сообщение WM_QUIT.
        MOV  EAX, 0
FINISH:	
        POP  EDI
        POP  ESI
        POP  EBX
        POP  EBP
        RET  16
WNDPROC ENDP
;---------------- ФУНКЦИЯ -----------------------
;Длина строки, [ЕВР+08Н] - указатель на строку.
LENSTR  PROC
        PUSH EBP
        MOV  EBP,ESP
        PUSH ESI
        MOV  ESI,DWORD PTR [EBP+8]
        XOR  EBX,EBX
LBL1:
        CMP  BYTE PTR [ESI],0 
        JZ   LBL2 
        INC  EBX 
        INC  ESI 
        JMP  LBL1
LBL2:
        POP  ESI
        POP  EBP
        RET  4
LENSTR  ENDP 
_TEXT   ENDS 
        END START
Текст этой программы можно взять здесь.

    Результат работы программы представлен на рисунке 1:


Рис.1. Результат работы приложения

    На следующегм шаге мы рассмотрим создание и использование диалоговых окон.




Предыдущий шаг Содержание Следующий шаг