
- •Глава 9 Значки, курсоры, битовые образы и строки
- •Компиляция ресурсов
- •Значки и курсоры
- •Редактор изображений
- •Получение описателя значков
- •Использование значков в вашей программе
- •Использование альтернативных курсоров
- •Битовые образы: картинки в пикселях
- •Использование битовых образов и кистей
- •Символьные строки
- •Использование ресурсов-символьных строк
- •Использование ресурсов-строк в функции MessageBox
- •Ресурсы, определяемые пользователем
Ресурсы, определяемые пользователем
Ресурсы, определяемые пользователем (user-defined resourse) удобны для включения самых разнообразных данных в ваш файл с расширением .EXE и получения доступа в программе к этим данным. Данные могут содержаться в любом выбранном вами формате — текстовом или бинарном. При загрузке данных в оперативную память возвращаемым значением функций Windows, которые используются для доступа к определяемым пользователем ресурсам, является указатель на данные. С этими данными вы можете делать все, что угодно. Вы вероятно решите, что этот способ хранения и доступа к разнообразным данным удобнее, чем альтернативный, при котором данные хранятся в других файлах и доступ к ним осуществляется через функции файлового ввода.
Например, предположим, что у вас есть файл PROGHELP.TXT, в котором содержится текст "подсказок" для вашей программы. Такой файл не должен быть в чистом виде ASCII-файлом: в нем также могут содержаться бинарные данные, например, указатели, которые могли бы помочь при ссылках на различные части этого файла. Следующим образом опишите ссылку на этот файл в вашем файле описания ресурсов:
helptext TEXT proghelp.txt
Имена helptext (имя ресурса) и TEXT (тип ресурса) в этом выражении могут быть любыми. Слово TEXT написано прописными буквами просто, чтобы сделать его похожим на слова ICON, CURSOR и BITMAP. То, что мы здесь делаем, является созданием ресурса вашего собственного типа, который называется TEXT.
В процессе инициализации программы (например, при обработке сообщения WM_CREATE), можно получить описатель этого ресурса:
hResource = LoadResource (hInstance,
FindResource (hInstance, "TEXT", "helptext")) ;
Переменная hResource определяется как имеющая тип HGLOBAL. Несмотря на свое имя, функция LoadResource фактически не загружает сразу ресурс в оперативную память. Используемые вместе, так как это было показано, функции LoadResource и FindResource по существу эквивалентны функциям LoadIcon и LoadCursor. Фактически, функции LoadIcon и LoadCursor используют функции LoadResource и FindResource.
Вместо имен и типов ресурсов можно использовать числа. Числа могут быть преобразованы в дальние указатели при вызове функции FindResource с использованием MAKEINTRESOURCE. Числа, используемые в качестве типа ресурса, должны быть больше 255. (Числа от 1 до 9 при вызове функции FindResource используются в Windows для существующих типов ресурсов.)
Когда вам необходимо получить доступ к тексту, вызывайте функцию LockResource:
pHelpText = LockResource (hResource);
Функция LockResource загружает ресурс в память (если он еще не был загружен), и возвращает указатель на него. После окончания работы с этим ресурсом, вы можете освободить оперативную память, вызвав функцию FreeResource :
FreeResource (hResource);
Даже если вы не вызовите функцию FreeResource, после завершения работы программы оперативная память все равно будет освобождена.
Давайте рассмотрим пример программы, в которой используется три ресурса — значок, таблица строк и ресурс, определяемый пользователем. В программе POEPOEM, представленной на рис. 9.3, на экран, в рабочую область окна программы, выводится текст поэмы Эдгара Алана По "Annabel Lee". Ресурс, определяемый пользователем — это файл POEPOEM.ASC, в котором находится текст поэмы. Текстовый файл заканчивается символом обратной косой черты (\).
POEPOEM.MAK
#-----------------------
# POEPOEM.MAK make file
#-----------------------
poepoem.exe : poepoem.obj poepoem.res
$(LINKER) $(GUIFLAGS) -OUT:poepoem.exe poepoem.obj poepoem.res $(GUILIBS)
poepoem.obj : poepoem.c poepoem.h
$(CC) $(CFLAGS) poepoem.c
poepoem.res : poepoem.rc poepoem.ico poepoem.asc poepoem.h
$(RC) $(RCVARS) poepoem.rc
POEPOEM.C
/*-------------------------------------------------
POEPOEM.C -- Demonstrates User-Defined Resource
(c) Charles Petzold, 1996
-------------------------------------------------*/
#include <windows.h>
#include "poepoem.h"
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
char szAppName[10] ;
char szCaption[35] ;
HINSTANCE hInst ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
HWND hwnd ;
MSG msg ;
WNDCLASSEX wndclass ;
LoadString (hInstance, IDS_APPNAME, szAppName, sizeof (szAppName)) ;
LoadString (hInstance, IDS_CAPTION, szCaption, sizeof (szCaption)) ;
wndclass.cbSize = sizeof (wndclass) ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (hInstance, szAppName) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
wndclass.hIconSm = LoadIcon (hInstance, szAppName) ;
RegisterClassEx (&wndclass) ;
hInst = hInstance ;
hwnd = CreateWindow (szAppName, szCaption,
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
static char *pText ;
static HGLOBAL hResource ;
static HWND hScroll ;
static int iPosition, cxChar, cyChar, cyClient, iNumLines, xScroll ;
char szPoemRes[15] ;
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect ;
TEXTMETRIC tm ;
switch (iMsg)
{
case WM_CREATE :
hdc = GetDC (hwnd) ;
GetTextMetrics (hdc, &tm) ;
cxChar = tm.tmAveCharWidth ;
cyChar = tm.tmHeight + tm.tmExternalLeading ;
ReleaseDC (hwnd, hdc) ;
xScroll = GetSystemMetrics (SM_CXVSCROLL) ;
hScroll = CreateWindow ("scrollbar", NULL,
WS_CHILD | WS_VISIBLE | SBS_VERT,
0, 0, 0, 0,
hwnd, (HMENU) 1, hInst, NULL) ;
LoadString (hInst, IDS_POEMRES, szPoemRes, sizeof (szPoemRes)) ;
hResource = LoadResource (hInst,
FindResource (hInst, szPoemRes, "TEXT")) ;
pText = (char *) LockResource (hResource) ;
iNumLines = 0 ;
while (*pText != '\\' && *pText != '\0')
{
if (*pText == '\n')
iNumLines ++ ;
pText = AnsiNext (pText) ;
}
*pText = '\0' ;
SetScrollRange (hScroll, SB_CTL, 0, iNumLines, FALSE) ;
SetScrollPos (hScroll, SB_CTL, 0, FALSE) ;
return 0 ;
case WM_SIZE :
MoveWindow (hScroll, LOWORD (lParam) - xScroll, 0,
xScroll, cyClient = HIWORD (lParam), TRUE) ;
SetFocus (hwnd) ;
return 0 ;
case WM_SETFOCUS :
SetFocus (hScroll) ;
return 0 ;
case WM_VSCROLL :
switch (wParam)
{
case SB_TOP :
iPosition = 0 ;
break ;
case SB_BOTTOM :
iPosition = iNumLines ;
break ;
case SB_LINEUP :
iPosition -= 1 ;
break ;
case SB_LINEDOWN :
iPosition += 1 ;
break ;
case SB_PAGEUP :
iPosition -= cyClient / cyChar ;
break ;
case SB_PAGEDOWN :
iPosition += cyClient / cyChar ;
break ;
case SB_THUMBPOSITION :
iPosition = LOWORD (lParam) ;
break ;
}
iPosition = max (0, min (iPosition, iNumLines)) ;
if (iPosition != GetScrollPos (hScroll, SB_CTL))
{
SetScrollPos (hScroll, SB_CTL, iPosition, TRUE) ;
InvalidateRect (hwnd, NULL, TRUE) ;
}
return 0 ;
case WM_PAINT :
hdc = BeginPaint (hwnd, &ps) ;
pText = (char *) LockResource (hResource) ;
GetClientRect (hwnd, &rect) ;
rect.left += cxChar ;
rect.top += cyChar * (1 - iPosition) ;
DrawText (hdc, pText, -1, &rect, DT_EXTERNALLEADING) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY :
FreeResource (hResource) ;
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
}
POEPOEM.RC
/*----------------------------
POEPOEM.RC resource script
----------------------------*/
#include "poepoem.h"
poepoem ICON poepoem.ico
AnnabelLee TEXT poepoem.asc
STRINGTABLE
{
IDS_APPNAME, "poepoem"
IDS_CAPTION, """Annabel Lee"" by Edgar Allen Poe"
IDS_POEMRES, "AnnabelLee"
}
POEPOEM.ICO
POEPOEM.H
/*-----------------------
POEPOEM.H header file
-----------------------*/
#define IDS_APPNAME 0
#define IDS_CAPTION 1
#define IDS_POEMRES 2
POEPOEM.ASC
It was many and many a year ago, In a kingdom by the sea,
That a maiden there lived whom you may know
By the name of Annabel Lee;
And this maiden she lived with no other thought Than to love and be loved by me.
I was a child and she was a child
In this kingdom by the sea,
But we loved with a love that was more than love -I and my Annabel Lee --
With a love that the winged seraphs of Heaven Coveted her and me.
And this was the reason that, long ago,
In this kingdom by the sea,
A wind blew out of a cloud, chilling
My beautiful Annabel Lee;
So that her highborn kinsmen came And bore her away from me,
To shut her up in a sepulchre
In this kingdom by the sea.
The angels, not half so happy in Heaven,
Went envying her and me --
Yes! that was the reason (as all men know,
In this kingdom by the sea)
That the wind came out of the cloud by night, Chilling and killing my Annabel Lee.
But our love it was stronger by far than the love Of those who were older than we --
Of many far wiser than we --
And neither the angels in Heaven above
Nor the demons down under the sea
Can ever dissever my soul from the soul Of the beautiful Annabel Lee:
For the moon never beams, without bringing me dreams Of the beautiful Annabel Lee;
And the stars never rise, but I feel the bright eyes Of the beautiful Annabel Lee:
And so, all the night-tide, I lie down by the side Of my darling -- my darling -- my life and my bride,
In her sepulchre there by the sea --
In her tomb by the sounding sea.
[May, 1849]
Рис. 9.3. Программа POEPOEM, содержащая значок и ресурс, определяемый пользователем
В файле описания ресурсов POEPOEM.RC ресурсу, определяемому пользователем, присваивается тип TEXT и имя AnnabelLee:
AnnabelLee TEXT poepoem.asc
При обработке в WndProc сообщения WM_CREATE описатель ресурса получается с использованием функций LoadResource и FindResource. Захватывается ресурс с помощью функции LockResource, а небольшая подпрограмма заменяет символ обратной косой черты (\) в конце файла на 0. Это сделано для адаптации текста к функции DrawText, которая позже, при обработке сообщения WM_PAINT, будет отображать его на экране.
Обратите внимание на использование полосы прокрутки-элемента управления вместо полосы прокрутки окна: в полосе прокрутки-элемента управления автоматически поддерживается интерфейс клавиатуры, поэтому в программе POEPOEM не требуется обрабатывать сообщение WM_KEYDOWN.
В программе POEPOEM также используются три символьные строки, идентификаторы которых определяются в заголовочном файле POEPOEM.H. Строки IDS_APPNAME и IDS_CAPTION с помощью функции LoadString заносятся в глобальные статические переменные:
LoadString (hInstance, IDS_APPNAME, szAppName, sizeof(szAppName));
LoadString (hInstance, IDS_CAPTION, szCaption, sizeof(szCaption));
Теперь, когда мы задали все символьные строки программы POEPOEM как ресурсы, мы упростили переводчикам их задачу. Конечно, им все равно придется переводить текст поэмы "Annabel Lee", и есть подозрение, что это будет несколько более трудной задачей.