Обмен технологиями

«Ежедневная практика Windows API» 9.1.5. Пользовательские ресурсы

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Пользовательские ресурсы — это тип ресурса, используемый в программах Windows для хранения специфичных для приложения данных, изображений, аудио, двоичных файлов и т. д. С помощью пользовательских ресурсов разработчики могут централизованно управлять и хранить различные файлы ресурсов, необходимые приложению, для быстрого доступа и использования в программе.

Вот некоторые ключевые моменты, касающиеся пользовательских ресурсов:

●Типы пользовательских ресурсов:

1. Пользовательскими ресурсами могут быть любые данные или файлы, специфичные для приложения, такие как изображения, аудио, файлы конфигурации XML, текстовые файлы и т. д.

2. Пользовательские ресурсы можно идентифицировать с помощью идентификатора типа пользовательского ресурса, например «MY_CUSTOM_RESOURCE».

●Создавайте и редактируйте собственные ресурсы:

1. Пользовательские ресурсы обычно включаются в файл ресурсов приложения (.rc).

2. Пользовательские ресурсы можно создавать и редактировать с помощью редактора ресурсов, такого как представление ресурсов Visual Studio.

3. В файле ресурсов вы можете указать уникальный идентификатор ресурса и соответствующий путь к файлу ресурсов для каждого ресурса.

●Обратитесь к пользовательским ресурсам и используйте их:

1. При ссылке и использовании пользовательских ресурсов в коде вы можете использовать идентификаторы ресурсов для загрузки соответствующих ресурсов или доступа к ним.

2. Используйте соответствующие функции API (такие как LoadResource, FindResource, LockResource и т. д.) для загрузки и управления пользовательскими ресурсами.

3. В зависимости от типа пользовательского ресурса вы можете использовать различные функции API (например, ресурсы изображений могут использовать функции GDI, а аудиоресурсы могут использовать функции DirectSound) для обработки пользовательских ресурсов.

■Ниже приведен пример фрагмента кода, показывающий, как загрузить и использовать пользовательский ресурс:

#включать<Windows.h>

целочисленный основной()

{

HINSTANCE hInstance = GetModuleHandle(NULL); // Получаем дескриптор текущего экземпляра.

HRSRC hResource = FindResource(hInstance, MAKEINTRESOURCE(IDR_MY_RESOURCE), "MY_CUSTOM_RESOURCE"); // Найти пользовательские ресурсы

HGLOBAL hResData = LoadResource(hInstance, hResource); // Загрузка пользовательских ресурсов;

LPVOID pData = LockResource(hResData); // Блокировка пользовательских ресурсов;

// Использовать собственные ресурсы...

вернуть 0;

}

В приведенном выше примере IDR_MY_RESOURCE — это идентификатор пользовательского ресурса, а соответствующий путь к файлу ресурса определен в файле ресурса. Используйте функцию FindResource, чтобы найти пользовательский ресурс, затем используйте функцию LoadResource, чтобы загрузить пользовательский ресурс, и, наконец, используйте функцию LockResource, чтобы заблокировать пользовательский ресурс и получить указатель на данные ресурса. Впоследствии указатель pData может использоваться для последующей обработки и операций в соответствии с типом и требованиями ресурса.

Важно отметить, что способ использования настраиваемого ресурса зависит от типа ресурса и потребностей приложения. Разработчики могут выбирать подходящие типы ресурсов и соответствующие функции API для обработки пользовательских ресурсов в соответствии с фактическими потребностями.

Пользовательские ресурсы обеспечивают гибкий метод управления ресурсами для приложений. Различные данные и файлы, необходимые приложению, могут управляться единообразно, легко доступны и используются в программе. Используя пользовательские ресурсы, вы можете сделать свое приложение более модульным, удобным в обслуживании и расширяемым.

       ■в ВСДобавьте пользовательские ресурсы в

1. Добавьте ресурсы

2. Нажмите «Настроить» и заполните тип ресурса «ТЕКСТ».

3. Импортируйте ресурсы и автоматически создайте файл text1.bin, идентификатор ресурса: IDR_TEXT1.

4. В VS напрямую введите имя файла ресурсов в пользовательском компиляторе и измените идентификатор. Появится сообщение об ошибке: Невозможно загрузить внешние ресурсы — возможная причина в том, что ресурсы не импортируются.

5. Добавьте ресурсы в поле просмотра ресурсов.

6. Импортируйте файлы внешних ресурсов.

7. Повторно заполните имя и идентификатор файла ресурса. Обратите внимание, что имя идентификатора необходимо заполнить строкой в ​​кавычках «ANNABELLEE».

8. Просто сохраните настройки.

 

Существует более простой способ — напрямую изменить файл ресурсов POEPOEM.rc. Просто добавьте ресурсы под строкой ТЕКСТ.

      

9.1.6. Упражнение 57. Таблица строковых ресурсов и пользовательские ресурсы

/*------------------------------------------------------------------------

057 WIN32 API Практикуйтесь каждый день

     Пример 57 POEPOEM.C: таблица строковых ресурсов и пользовательские ресурсы

LoadString функция

LoadResource функция

FindResource функция

БлокировкаРесурса функция

AnsiСледующий Определение макроса

(с) www.bcdaren.com Программист

-----------------------------------------------------------------------*/

#включать <windows.h>

#включать "ресурс.h"

LРЕЗУЛЬТАТ ПЕРЕЗВОНИТЬ WndProc (HWND, УИНТ, WPARAM, LPARAM) ;

ПРИМЕР hInst ;

инт ВИНАПИ WinMain (ПРИМЕР hInstance, ПРИМЕР hPrevInstance,

 ПСТР szCmdLine, инт iCmdShow)

{   //Имя файла ресурса, заголовок и сообщение об ошибке

     ТЧАР szAppName[16], szПодпись[64], szErrMsg[64];

     HWND hwnd;

     MSG сообщение;

     WNDCLASS wndclass;

     //Загрузка строковых ресурсов

     LoadString(hInstance, IDS_APPNAME, szAppName,

          размер(szAppName) / размер(ТЧАР));

     LoadString(hInstance, IDS_CAPTION, szПодпись,

          размер(szПодпись) / размер(ТЧАР));

     wndclass.стиль = CS_HREDRAW | CS_VREDRAW;

     wndclass.lpfnWndProc = WndProc;

     wndclass.cbClsExtra = 0;

     wndclass.cbWndExtra = 0;

     wndclass.hInstance = hInstance;

//добавить значок

     wndclass.hИконка = ЗагрузитьИконку(hInstance, СДЕЛАЙТЕ ИНТЕРРЕСУРС(IDI_ICON1));

     //wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);

//Пользовательский указатель мыши

     wndclass.hКурсор = LoadCursor(hInstance,СДЕЛАЙТЕ ИНТЕРРЕСУРС(IDC_CURSOR1));

     wndclass.hbrПредыстория = (HЩЁТКА)ПолучитьStockObject(БЕЛАЯ_КИСТЬ);

     wndclass.lpszМенюНазвание = НУЛЕВОЙ;

     wndclass.lpszИмяКласса = szAppName;

     //hInst = hInstance;//Его нет в исходном коде, и об ошибках не будет сообщено.

     если (!RegisterClass(&wndclass))

     {

          //LoadStringA(hInstance, IDS_APPNAME, (char *)szAppName,

          // sizeof(szAppName));

          LoadStringA(hInstance, IDS_ERRMSG, (чар *)szErrMsg,

               размер(szErrMsg));

          MessageBoxA(НУЛЕВОЙ, (чар *)szErrMsg,

               (чар *)szAppName,

               MB_ICONERROR);

          возвращаться 0;

     }

     hwnd = СоздатьОкно(szAppName, szПодпись,

          WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,

          CW_USEDEFAULT, CW_USEDEFAULT,

          CW_USEDEFAULT, CW_USEDEFAULT,

          НУЛЕВОЙ, НУЛЕВОЙ, hInstance, НУЛЕВОЙ);

     Витрина(hwnd, iCmdShow);

     ОбновлениеОкна(hwnd);

     пока (ПолучитьСообщение(&сообщение, НУЛЕВОЙ, 0, 0))

     {

          ПереводСообщение(&сообщение);

          DispatchMessage(&сообщение);

     }

     возвращаться сообщение.wParam;

}

LРЕЗУЛЬТАТ ПЕРЕЗВОНИТЬ WndProc ( HWND hwnd, УИНТ сообщение, WPARAM wParam, LPARAM

lПарам)

{

     //статический символ * pText;

     статический ЛПКСТР pТекст;

     статический HGLOBAL hРесурс;//Дескриптор ресурса — дескриптор, указывающий на блок памяти.

     статический HWND hScroll;

     статический инт iPosition, cxChar, cyChar, cyClient,

          iNumLines, xПрокрутить;

     HDC hdc;

     PAINTSTRUCT пс;

     РЕКТА прям;

     ТЕКСТМЕТРИЧЕСКИЙ тм;

     выключатель (сообщение)

     {

     случай WM_CREATE:

          hdc = ПолучитьDC(hwnd);

          GetTextMetrics(hdc, &тм);

          cxChar = тм.tmAveCharWidth;

          cyChar = тм.tmHeight + тм.tmExternalLeading;

          ВыпускDC(hwnd, hdc);

//Ширина вертикальной полосы прокрутки в пикселях

          xПрокрутить = ПолучитьСистемныеМетрики(SM_CXVSCROLL);

          //Создать полосу прокрутки

          hScroll = СоздатьОкно(ТЕКСТ("полоса прокрутки"), НУЛЕВОЙ,

               WS_CHILD | WS_ВИДИМЫЙ | SBS_VERT,

               0, 0, 0, 0,

               hwnd, (ХМЕНЮ)1, hInst, НУЛЕВОЙ);

          //Получить текстовый дескриптор

          hРесурс = LoadResource(hInst,

               FindResource(hInst, ТЕКСТ("АннабельЛи"),//Убедитесь, что он имеет указанный тип и имя.

Расположение ресурса в указанном модуле

                    ТЕКСТ("ТЕКСТ")));

          //Получить указатель на указанный ресурс в памяти

          pТекст = (ЛПКСТР)БлокировкаРесурса(hРесурс);

          iNumLines = 0;//Прочитайте количество строк текста

          //Получить количество строк текста

          пока (*pТекст != '\' && *pТекст != '0')//Заканчивается на или 0

          {

               если (*pТекст == 'н')

                    iNumLines++;

                //Возвращает следующую позицию (указатель) в строке ansi, AnsiNext в 16-разрядной версии Windows.

//Определение макроса, Win32 вместо этого использует CharNext (AnsiNext может обрабатывать только символы ansi).

//String; CharNext может быть строкой в ​​формате Ansi или Unicode)

                //pText = AnsiNext(pText);

               pТекст = (ЛПКСТР)CharСледующий((LPCWSTR)pТекст);

          }

     //*pText = '0';//Исходный код здесь утверждает, что он заканчивается нулевым символом — фактический текст не заканчивается нулевым символом.

          //Установить полосу прокрутки

          УстановитьДиапазонПрокрутки(hScroll, SB_CTL, 0, iNumLines, ЛОЖЬ);

          SetScrollPos(hScroll, SB_CTL, 0, ЛОЖЬ);

          возвращаться 0;

     случай WM_SIZE:

          ПереместитьОкно(hScroll, НИЗКИЙ УОРД(lПарам) - xПрокрутить, 0,

               xПрокрутить, cyClient = HIWORD(lПарам), истинный);

          УстановитьФокус(hwnd);//Установить фокус

          возвращаться 0;

     случай WM_SETFOCUS:

          УстановитьФокус(hScroll);//Захватить фокус ползунка полосы прокрутки

          возвращаться 0;

     случай WM_VSCROLL:

          выключатель (НИЗКИЙ УОРД(wParam))  //Необходимо добавить LOWORD, поскольку код уведомления находится в младшем слове.

          {

          случай SB_TOP:

               iPosition = 0;

               перерыв;

          случай SB_BOTTOM:

               iPosition = iNumLines;

               перерыв;

          случай SB_LINEUP:

               iPosition -= 1;

               перерыв;

          случай SB_LINEDOWN:

               iPosition += 1;

               перерыв;

          случай SB_PAGEUP:

               iPosition -= cyClient / cyChar;

               перерыв;

          случай SB_PAGEDOWN:

               iPosition += cyClient / cyChar;

               перерыв;

          случай SB_THUMBTRACK:

               iPosition = HIWORD(wParam);

               перерыв;

          }

          iPosition = Макс(0, мин(iPosition, iNumLines));

          если (iPosition != GetScrollPos(hScroll, SB_CTL))

          {

               SetScrollPos(hScroll, SB_CTL, iPosition, истинный);

               InvalidateRect(hwnd, НУЛЕВОЙ, истинный);

          }

          возвращаться 0;

     случай WM_PAINT:

          hdc = BeginPaint(hwnd, &пс);

          pТекст = (чар *)БлокировкаРесурса(hРесурс);

          GetClientRect(hwnd, &прям);

          прям.левый += cxChar;//Отображение начиная со столбца 2

          прям.вершина += cyChar * (1 - iPosition);

          // Включает высоту начала внешней строки шрифта. Обычно заголовки внешних строк не включаются в высоту строки текста.

          DrawTextA(hdc, pТекст, -1, &прям, DT_EXTERNALLEADING);

          EndPaint(hwnd, &пс);

          возвращаться 0;

     случай WM_DESTRUCTION:

          FreeResource(hРесурс);

          PostQuitMessage(0);

          возвращаться 0;

     }

     возвращаться DefWindowProc(hwnd, сообщение, wParam, lПарам);

}

/******************************************************************************

LoadString Функция: загружает строковый ресурс, а затем копирует строку в буфер с завершающим нулевым символом.

Или верните указатель на сам строковый ресурс, доступный только для чтения.

*******************************************************************************

LoadResource Функция: извлекает дескриптор, который можно использовать для получения указателя на первый байт указанного ресурса в памяти.

HGLOBAL LoadResource(

HMODULE hModule,// Дескриптор модуля, исполняемый файл которого содержит ресурс.Если hModule имеет значение NULL, система загрузит ресурс из модуля, используемого для создания текущего процесса.

HRSRC hResInfo//Дескриптор ресурса для загрузки

);

*******************************************************************************

FindResource Функция: Определяет расположение ресурса указанного типа и имени в указанном модуле.

HRSRC FindResourceA(

HMODULE hModule,//Дескриптор модуля, содержащего ресурс

LPCSTR lpName,//имя ресурса

LPCSTR lpType//Тип ресурса

);

*******************************************************************************

БлокировкаРесурса Функция: получить указатель на указанный ресурс в памяти.

LPVOID БлокировкаРесурса(

HGLOBAL hResData//Дескриптор ресурса, к которому осуществляется доступ

);

*******************************************************************************

AnsiСледующий Определение макроса:

16Функция API в Windows (точнее, определение макроса), которая может обрабатывать только строки ANSI;

Позже, когда появилась Win32, Microsoft для совместимости реализовала инкапсуляцию через CharNext.

CharСледующийЭто может быть строка в формате Ansi или Unicode.

Эта функция возвращает следующую позицию (указатель) в строке ansi.

*/

Ресурс.hГоловной файл

//{{НЕТ_ЗАВИСИМОСТЕЙ}}

// Microsoft Visual C++ Созданы включаемые файлы.

// Для использования 057_POEPOEM.rc

//

#define IDS_APPNAME 1

#define IDS_Caption 2

#определить IDS_CAPTION 3

#определить IDS_ERRMSG 4

#определить IDI_ICON1 1

#определить IDC_CURSOR1 2

#определить IDR_TEXT1 107

#определить IDR_TEXT2 108

// Следующие значения по умолчанию для новых объектов

//

#ifdef APSTUDIO_INVOKED

#ifndef APSTUDIO_READONLY_SYMBOLS

#define _APS_NEXT_RESOURCE_VALUE 126

#define _APS_NEXT_COMMAND_VALUE 40002

#define _APS_NEXT_CONTROL_VALUE 1001

#определить _APS_NEXT_SYMED_VALUE 101

#endif

#endif

057_POEPOEM.rcФайлы скриптов ресурсов содержат 4 типа ресурсов:

1 . Ресурсы иконок:

// Икона

//

IDI_ICON1 ИКОНКА "D:\code\windows5.0\A ежедневно

практика\057_POEPOEM\057_POEPOEM\icon1.ico"

2 . Ресурс растрового изображения указателя мыши:

// Курсор

//

IDC_CURSOR1 КУРСОР "cursor1.cur"

3 . Таблица строковых ресурсов:

// Таблица строк

//

СТРОКОВАЯ ТАБЛИЦА

НАЧИНАТЬ

IDS_APPNAME "Поэма"

IDS_CAPTION """Аннабель Ли"" Эдгара Аллана По"

IDS_ERRMSG "Для этой программы требуется Windows NT!"

КОНЕЦ

4 . Пользовательские ресурсы:

// ТЕКСТ

//

ТЕКСТ АННАБЕЛЛИ "POEPOEM.TXT"

результат операции:

Рисунок 9-9. Таблица строковых ресурсов и пользовательские ресурсы.

 

Подведем итог

В сценарии ресурса POEPOEM.RC пользовательский ресурс указан как тип TEXT, а текстовое имя — «ANNABELLEE»: ANNABELLEE TEXT POEPOEM.TXT

При обработке сообщения WM_CREATE в WndProc дескриптор ресурса получается через FindResource и LoadResource. LockResource блокирует ресурс, а небольшая процедура заменяет конечную обратную косую черту ( ) в файле на 0. Это сделано для облегчения использования функции DrawText в последующем сообщении WM_PAINT.

[Примечание] Вместо полосы прокрутки окна мы используем элемент управления полосой прокрутки подокна. Управление полосой прокрутки подокна имеет автоматический клавиатурный интерфейс, поэтому нет необходимости обрабатывать сообщение WM_KEYDOWN в POEPOEM.

POEPOEM также использует три строки, идентификаторы которых определены в заголовочном файле RESOURCE.H. В начале программы строки IDS_APPNAME и IDS_CAPTION загружаются в память с помощью LoadString:

LoadString (hlnstance, IDS_APPNAME, szAppName,

sizeof (szAppName) /sizeof (TCHAR));

LoadString (hlnstance, IDS_CAPTION, szCaption,

размер (szCaption) /размер (TCHAR));

[Примечание] Эти два вызова предшествуют RegisterClass. Программа использует LoadStringA для загрузки строк IDS_APPNAME и IDS_ERRMSG и использует MessageBoxA для отображения пользовательского окна сообщения:

если (!RegisterClass (&wndclass))

{

LoadStringA (hInstance, IDS_APPNAME, (char *) szAppName,

sizeof (szAppName));

LoadStringA (hInstance, IDS_ERRMSG, (char *) szErrMsg,

размер (szErrMsg));

MessageBoxA (NULL, (символ *) szErrMsg,

(символ *) szAppName, MB_ICONERROR) ;

вернуть 0 ;

}

[Примечание] Принудительное преобразование строковой переменной TCHAR в указатель char.

AnsiNext — это определение макроса в 16-разрядной версии Windows. Вместо этого Win32 использует CharNext (AnsiNext может обрабатывать только строки Ansi; CharNext может обрабатывать как строки Ansi, так и строки Unicode).

pText = AnsiNext(pText);

Заменить:

pText = (LPCSTR)CharNext((LPCWSTR)pText);

Все строки, используемые POEPOEM, определены как ресурсы, поэтому переводчики могут легко преобразовать программу в неанглоязычные версии.